Changelog
1.58.0
(feat): Add the enableNestedRequestBodyPagination configuration option, which extends
enableRequestBodyPagination to page properties that live inside nested request objects, e.g.
offset: $request.options.offset. Such endpoints previously generated without a pager, so the
option defaults to false to preserve their existing return types.
1.57.13
(fix): Calling a SetXxx setter on a value copy of a request or model type no longer
changes the JSON of the value it was copied from. The private explicitFields
bitmask is reached through a pointer, so a plain struct assignment aliased it and
require mutated it in place, making every explicit-field bit set on one copy
visible in all of them (e.g. copied.SetOptions(...) added "options":null to
the original’s body). The bitmask is now replaced rather than mutated, so each
copy gets its own on first write.
1.57.12
(fix): The retrier no longer waits out a Retry-After/backoff delay after its final
attempt. Previously the sleep happened before the attempt budget was checked,
so a client with retries disabled (or MaxAttempts: 1) still blocked for the
full Retry-After on a 429/5xx, and the default two-attempt retrier paid two
delays for one retry. Retrier exhaustion now returns immediately.
1.57.11
(fix): Fix HandleExplicitFields silently corrupting the JSON body of types that have
date/date-time fields. When any SetXxx setter was called on such a type, the
generated MarshalJSON wrapper (embedded struct plus date shadow fields) was not
recognized as the embed pattern, so the explicit-field bits were applied to the
wrapper’s fields instead of the embedded type’s fields and the embedded struct
itself was dropped from the output (e.g. req.SetCount(&n) produced
{"end_date":null} instead of {"count":7}). This also caused offset-based
auto-pagination to loop forever. Shadow fields are now preserved and
omitempty is stripped from the shadow field when the shadowed date field is
explicitly set, so SetStartDate(nil) emits "start_date":null.
1.57.10
(fix): Optional idempotency headers are no longer sent with a Go expression prefix
prepended to their value. An optional<string> idempotency header was sent
with a literal * in front of the caller’s value, and an
optional<base64> one with a literal base64.StdEncoding.EncodeToString(,
because the dereference/encode prefix used to build the value expression was
also interpolated into the fmt.Sprintf format string. Required headers were
unaffected.
1.57.9
(fix): Retry backoff now waits on the request context, so a cancelled or expired
context interrupts the wait instead of sleeping through it (previously a
Retry-After of up to 60s could hold a call well past its deadline).
(fix): option.WithoutRetries() is now honored when passed to the client
constructor. Previously the flag was dropped by NewRetrier and only worked
per call. Request-scoped WithMaxAttempts still overrides it.
1.57.8
(fix): Honor endpoint-level retry configuration (x-fern-retries: { disabled: true }, or retries: { disabled: true }
in a Fern definition). Endpoints that disable retries are now issued exactly once, regardless of the
client-level and per-request retry options.
1.57.7
(fix): Fixed generated WireMock stubs for OAuth client credentials APIs whose token endpoint is
itself marked as authenticated: the token (and refresh) endpoint stub no longer requires
an Authorization header, since the token request is made to obtain the token and cannot
carry one yet.
1.57.6
(fix): An empty string terminates cursor pagination when the cursor is a named type that resolves to an
optional string (e.g. type Cursor = *string), matching an inline optional string. Optionality
is now resolved through aliases, so both spellings of the same type generate the same
termination check. Required string, uuid, int, and datetime cursors are unchanged.
1.57.5
(fix): Fixed generated wire tests for OAuth client credentials APIs: the test client is now
constructed with client credentials so requests carry the Authorization header the
WireMock stubs require, instead of failing with Header is not present.
1.57.4
(fix): Fix several issues in the generated README:
- The Request Options example now renders the auth options the SDK actually
generates (e.g.,
option.WithSecretfor header auth,option.WithBasicAuthfor basic auth) instead of always assumingoption.WithToken. - The Errors example now passes a pointer to
errors.Asso the snippet compiles and doesn’t panic. - The Pagination section is now emitted whenever the API has an endpoint with a generated paginated client, by selecting such an endpoint for the example, rather than relying on the default endpoint being paginated. The section is omitted entirely when no paginated client is generated (e.g. custom, URI, and path pagination), so the example no longer references an iterator that doesn’t exist.
- The Request Options section now documents the environment variables the generated client reads credentials from when they aren’t explicitly provided.
1.57.3
(fix): Omit global headers (declared under api.headers) from requests when they are
left unset, instead of sending them with an empty value. This matches the
behavior of auth scheme headers, which were already guarded. This applies to
string, UUID, bytes, date, datetime, and enum headers; boolean and numeric
headers are unchanged, since false and 0 are meaningful values that
cannot be distinguished from an unset field. Unset UUID, date, and datetime
headers are no longer sent as 00000000-0000-0000-0000-000000000000 and
0001-01-01 either.
1.57.2
(fix): Fix JSON deserialization of date and datetime values nested in containers.
Lists, sets, and string-keyed maps of dates (including optional containers and
aliases of containers) are now unmarshaled through the internal date wrappers,
so date-only values such as "2002-08-28" no longer fail with
parsing time "2002-08-28" as "2006-01-02T15:04:05Z07:00".
1.57.1
(fix): Cursor pagination now stops when a string cursor is an empty string, in addition to null. Previously an
optional string cursor was only terminal when it was null, so an API that signals the last page with
"next_cursor": "" caused an extra request, or looped indefinitely when it also kept returning results.
This matches the TypeScript, Python, and C# generators. Non-string cursors (e.g. uuid, int) are unchanged.
1.57.0
(fix): Snippets for examples that omit an optional request body now pass nil for the body
parameter instead of dropping the argument, which produced snippets that did not compile.
(feat): Add a respectOptionalRequestBody option. When enabled, an endpoint whose request body the API
does not require sends no body and no Content-Type header once the caller leaves that body out,
including when the request wrapper is passed with a nil Body. Examples that supply no body stop
rendering an empty body such as Body: &acme.RefundRequest{}. The option defaults to false, so
existing SDKs send exactly what they always have.
1.56.1
(fix): Fix the initial offset for offsetSemantics: item-index. Item-index offsets address records
rather than pages, so pagination now starts at 0 instead of 1, which previously skipped the
first record of every collection. This applies to both query-parameter and request-body offsets.
Page-index semantics continue to start at 1.
(fix): Fix offset pagination emitting code that does not compile. With offsetSemantics: item-index
and a step, the pager read results before declaring it (undefined: results), and the
offset increment now matches the page type (int, int64, float64). Endpoints whose offset
is a required (non-optional) query parameter also emitted an invalid assignment to a request
field (request.Offset := ...) under either offset semantics, and now seed the initial offset
from the request (next := request.Offset).
1.56.0
(feat): Add the enableRequestBodyPagination configuration option, which generates auto-pagination for
endpoints whose cursor or offset is a top-level request body property (e.g.
cursor: $request.cursor). These endpoints previously generated a regular method that returned
the response body, so the option defaults to false to preserve the existing return types.
1.55.1
(fix): Fixed WireMock stubs for wire tests of APIs with auth: any combining Basic and
OAuth/Bearer schemes: stubs now accept either Authorization form instead of
requiring the exact Basic header the client may not send.
(fix): Fixed generated OAuth wire tests failing to compile when the OAuth token
endpoint lives in a subpackage: the pointer helper (String) is now
referenced from the root package instead of the request type’s package.
1.55.0
(feat): Add opt-in allowUserAgentAppInfo config. When enabled, generated clients expose an
option.WithUserAgentAppInfo(name, version, comment string) client option whose sanitized
product token is appended to whatever User-Agent the SDK would otherwise send
({sdk}/{version} ... {product}/{product-version} ({comment})), following RFC 9110.
Disabled by default, so existing generated output is byte-identical, and it composes with
includePlatformHeaders, the configured user-agent template value, and the default
{package}/{version} value. Caller-supplied values are trimmed before the blank check and
before encoding (blank name/version/comment are dropped rather than encoded into whitespace
tokens), then name/version are percent-encoded to RFC 7230 tchar and comment delimiters
(, ), \ and control characters (incl. CR/LF) are escaped, so untrusted values cannot
inject header content. Still overridable by an explicit User-Agent header and suppressed
by omitFernHeaders. The AppInfo type, the AppInfoOption, and the emitted
appendAppInfoToUserAgent helper are only generated when the flag is on, so the shared
core-utilities are never modified. No IR change.
1.54.0
(feat): Add the applyQueryDefaultsOnNilRequest option, which applies query parameter defaults
when a request is nil. internal.QueryValuesWithDefaults returns early for a nil
request, so defaults declared via x-fern-default are silently dropped and the request is
sent without them. When the option is enabled, a nil request behaves like a zero-value
request struct, which matters most for paginated endpoints whose response shape depends on
a defaulted query parameter. The option defaults to false to preserve today’s behavior.