Query Params & Multipart Forms
Relevant source files
The following files were used as context for generating this wiki page:
The Anthropic Go SDK utilizes specialized internal modules to handle complex data serialization for HTTP requests. Specifically, it manages the conversion of Go structures into URL query parameters for GET requests (such as listing batches or skills) and into multipart/form-data for requests involving binary uploads (such as creating skills with associated files).
These systems are designed to handle nested structures, slices, and unions while respecting specific formatting requirements dictated by the Anthropic API. The serialization logic is driven by struct tags and configurable settings that determine how arrays and nested objects are represented in the final request.
Query Parameter Serialization
The SDK uses an internal apiquery package to transform Go structs into url.Values. This is primarily used for pagination and filtering in "List" endpoints.
Serialization Logic and Settings
The conversion process is governed by QuerySettings, which define the format for arrays and nested objects.
| Format Type | Supported Options | Description |
|---|---|---|
| Array Format | Comma, Brackets, Repeat | Determines if slices are joined by commas (a=1,2), use brackets (a[]=1&a[]=2), or repeated keys (a=1&a=2). |
| Nested Format | Brackets, Dots | Determines if nested structs use bracket notation (a[b]=c) or dot notation (a.b=c). |
Sources: [internal/apiquery/query_test.go:134-165](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiquery/query_test.go#L134-L165), [messagebatch.go:503-508](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/messagebatch.go#L503-L508)
Struct Tags for Queries
Field serialization is controlled via two primary struct tags:
query: Defines the parameter name and behavior (e.g.,omitzero,inline).format: Specifies specific data formats likedateordate-time.
Sources: [internal/apiquery/tag.go:10-43](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiquery/tag.go#L10-L43)
Data Flow for Query Generation
The following diagram illustrates how a parameter struct (like MessageBatchListParams) is converted into a URL query string.
Sources: [internal/apiquery/query_test.go:275-300](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiquery/query_test.go#L275-L300), [betamessagebatch.go:487-492](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/betamessagebatch.go#L487-L492)
Multipart Form Data
Multipart forms are utilized when requests require a combination of JSON-like fields and binary data, such as file uploads for Skills.
Binary Uploads in Skills
The BetaSkillNewParams struct implements a custom MarshalMultipart method. This method uses the apiform internal package to write various fields into a multipart.Writer.
func (r BetaSkillNewParams) MarshalMultipart() (data []byte, contentType string, err error) {
buf := bytes.NewBuffer(nil)
writer := multipart.NewWriter(buf)
err = apiform.MarshalRoot(r, writer)
// ... handles extra fields and closing writer
return buf.Bytes(), writer.FormDataContentType(), nil
}
Sources: [betaskill.go:281-296](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/betaskill.go#L281-L296)
Form Formatting Options
Similar to query parameters, form serialization supports different array indices styles. Tests indicate support for indices:dots and bracket-based nested structures.
| Feature | implementation Example |
|---|---|
| Primitive Slices | f.0, f.1 or f[] |
| Nested Objects | child.name or child[name] |
| File Handling | Content-Disposition: form-data; name="file"; filename="..." |
Sources: [internal/apiform/form_test.go:214-250](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiform/form_test.go#L214-L250), [internal/apiform/form_test.go:160-175](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiform/form_test.go#L160-L175)
Multipart Construction Flow
The sequence of creating a multipart request for a skill upload involves iterating through fields and writing binary parts for io.Reader types.
Sources: [betaskill.go:281-296](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/betaskill.go#L281-L296), [internal/apiform/form_test.go:120-135](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiform/form_test.go#L120-L135)
Parameter Handling Features
The SDK implements several robust features for both Query and Form serialization:
- Omitting Zero Values: Using the
omitzerotag option, fields that contain their Go zero value are excluded from the output to keep requests clean. Sources:[internal/apiquery/tag.go:30](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiquery/tag.go#L30),[internal/apiquery/query_test.go:94](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiquery/query_test.go#L94). - Inlining: The
inlinetag allows fields of a nested struct or union to be serialized at the same level as the parent, which is essential for supporting complex API unions. Sources:[internal/apiquery/query_test.go:107-115](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiquery/query_test.go#L107-L115). - Time Formatting: Specific formatting for
time.Timeobjects is supported via theformattag, ensuring dates conform to2006-01-02or RFC 3339. Sources:[internal/apiquery/query_test.go:195-202](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiquery/query_test.go#L195-L202),[internal/apiform/form_test.go:265-275](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiform/form_test.go#L265-L275). - Additional Properties: Support for
map[string]anyfields (tagged withinlineorapi:"extrafields") allows the SDK to pass through parameters not explicitly defined in the struct. Sources:[internal/apiquery/query_test.go:204-213](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiquery/query_test.go#L204-L213),[internal/apiform/form_test.go:277-293](https://github.com/ajit216/anthropic-sdk-go/blob/HEAD/internal/apiform/form_test.go#L277-L293).
Conclusion
The SDK's handling of query parameters and multipart forms provides a flexible bridge between strongly-typed Go structures and the Anthropic API's requirements. By leveraging internal apiquery and apiform packages, the SDK ensures that complex types like nested maps, binary readers, and polymorphic unions are correctly encoded for network transmission.