Skip to navigation

Changelog

4.23.2

(fix): Fix InputStream upload overloads on multipart endpoints that have non-file form fields. The overloads now take the generated request object and serialize every companion multipart field alongside the streamed file, instead of silently dropping them. The unused File-typed parameter (including Optional<File>) is also removed from these signatures. When the file property is inlined onto the request object (inline-file-properties: true) and companion fields exist, the stream overloads are no longer generated, since the file cannot be separated from the request object.

4.23.1

(chore): Bump bundled @fern-api/generator-cli to 0.10.3. When the hosted auto-version analysis of the full SDK diff fails, generator-cli now retries chunk-by-chunk instead of silently applying a PATCH bump; any remaining unavailable or incomplete analysis adds a “Version bump not verified” notice to the SDK PR body and disables automerge.

4.22.3

(fix): Honor package-prefix and package-layout for local-file-system output when the CLI requests a full project (e.g. --generate-tests, --package, or self-hosted SDKs). Previously these were dropped when converting the local-file-system config, so the root package fell back to com.<org>.<api> instead of the configured prefix. Full-project local output now also writes sources at their full package path (src/main/java/com/acme/...) instead of stripping the prefix from the directory.

4.23.0

(feat): XML-encoded (TwiML) types now carry inline Javadoc on their user-facing API: the class itself gets the type description, every Builder setter overload gets the property description, and child appenders (say.break_(...), response.say(...)) document the child element plus @param/@return.

4.22.2

(fix): RetryInterceptor now applies the client timeout to each attempt individually instead of to the whole retry loop. Previously a Retry-After wait as long as the timeout (e.g. Retry-After: 60 with the default 60s timeout) cancelled the call during the backoff sleep and surfaced IOException: Canceled instead of retrying or returning the received 429. The call timeout is paused while waiting for the backoff and restarted for each retry attempt, so a call that retries may now take up to timeout * (maxRetries + 1) plus the backoff waits.

4.22.1

(fix): Closing the root client (or ClientOptions.close()) now disconnects any WebSocket clients that are still connected before the SDK-owned OkHttp dispatcher is shut down, so they stop reconnecting cleanly instead of failing asynchronously with InterruptedIOException: executor rejected. ClientOptions exposes isClosed(); WebSocket connect/reconnect attempts made after close, as well as OkHttpWebSocketFactory.create(...) when constructed with a closed-check, fail fast with IllegalStateException("root client has been closed").

4.22.0

(feat): Generate the shared WebhooksHelper from the API-wide api.settings.webhook-signature setting in generators.yml (IR sdkConfig.webhookSignatureVerification). The helper is emitted even when the API definition models no webhooks; webhook-specific signature overrides still produce their own named helpers.

(fix): Fix the generated ReconnectingWebSocketListener connection-timeout message, which was missing the closing parenthesis after the retry attempt number (e.g. ... milliseconds (retry attempt #2).

4.21.2

(fix): RetryInterceptor no longer discards an API response it has already received (e.g. a 429) when a later retry attempt fails, such as when the call timeout expires mid-retry. The previous response is buffered and returned instead of surfacing a generic IOException.

4.21.1

(chore): Bump bundled @fern-api/generator-cli to 0.10.1. Auto-versioned MAJOR/MINOR bumps no longer produce a version-only changelog.md block when the AI analysis returns an empty changelog entry; the PR description, version bump reason, or commit message body is used instead.

4.21.0

(feat): Generated root clients (sync and async) now implement AutoCloseable. close() shuts down the underlying OkHttpClient’s dispatcher executor and evicts its connection pool, but only when the SDK created that OkHttpClient itself — a client supplied via Builder.httpClient(...) is left running, since the caller owns its lifecycle. This lets short-lived applications (e.g. CLIs, or code that finishes after using WebSockets) release the client’s background threads instead of relying on JVM shutdown.

4.20.0

(feat): Object types with xml encoding metadata (e.g. TwiML defined via OpenAPI xml objects) now implement XmlSerializable with toXml() and a static fromXml(String) parser, backed by new core XmlWriter/XmlReader utilities. Builders gain per-child-element methods (e.g. Response.builder().say(...)) and undiscriminated child unions dispatch fromXml by element name. Builder.fromXml(String) returns a populated builder, unknown child elements are preserved as XmlElements (readable via getAdditionalChildren(), addable via addChild(...)) and round-tripped by toXml(), and very large objects that use a builder-based constructor also get fromXml. Types without xml metadata are unchanged.

4.19.3

(fix): Generated ReconnectingWebSocketListener now acknowledges peer-initiated close frames by overriding onClosing, so OkHttp completes the close handshake and onClosed (and the public disconnect lifecycle) fires for server-initiated closes. A no-status close (local sentinel 1005) is acknowledged with 1000, since 1005 is not a wire-valid close code. The reconnect decision is exposed as a protected boolean shouldReconnectAfterClose(WebSocket, int, String) hook (default unchanged: code != 1000) so resource-specific subclasses can treat a protocol-established terminal close as final. Adds send(String, Consumer<WebSocket>) / sendBinary(ByteString, Consumer<WebSocket>) overloads that report which socket directly accepted a message (not invoked for queued or dropped messages).

4.19.2

(fix): Respect custom OAuth token headers and prefixes for client credentials authentication.

4.19.1

(fix): Honor an endpoint’s retries: {disabled: true} configuration (the x-fern-retries OpenAPI extension). A call to such an endpoint tags its request with a max-retries override of zero, so it bypasses automatic retries regardless of the client-wide ClientOptions.maxRetries or a per-request RequestOptions.maxRetries. Endpoints without the configuration are unchanged.

4.19.0

(fix): With respect-optional-request-body enabled, a call that leaves out an optional request body now passes a null body to OkHttp instead of an empty one, so the request carries no body at all. The methods OkHttp requires a body for (POST, PUT, PATCH) still send an empty body, which is what endpoints with no request body at all already send.

(feat): Add a respect-optional-request-body option. When enabled, an endpoint whose request body the API does not require also gets an overload without the body parameter, and calling that overload sends no body. The body parameter keeps its own type, so alpha(String id, Body body) gains a sibling alpha(String id) rather than becoming alpha(String id, Optional<Body> body). Examples that supply no body render as client.alpha(id). That call also leaves out the Content-Type header, which now only goes out when a body does. The option defaults to false, so existing signatures and snippets are unchanged.

4.18.2

(fix): Build an empty request body in snippets for an endpoint example that omits a body the wrapped request requires, instead of leaving the builder’s required body stage unset.

4.18.1

(fix): Fix the generated OAuth token supplier when the get-token request has required properties other than the client credentials. The builder calls are now ordered by the request’s required properties, so the staged builder’s stages are satisfied in order, and hardcoded values (such as grant_type) are written using the property’s type, which means an enumerated grant_type gets the generated enum constant instead of a string literal.

4.18.0

(feat): Add support for the FERN_JAVA_SKIP_FORMATTING environment variable. When set to a truthy value (1, true, yes, or on), the generator skips the ./gradlew :spotlessApply pass that normally runs after code generation, so generation makes no Gradle invocation at all. This unblocks restricted networks that cannot reach the Gradle distribution or plugin repositories, and shortens generation time.

4.17.1

(fix): Fixed wire tests generated for APIs with auth: any combining Basic and OAuth schemes. Tests no longer assert both a Bearer and a Basic Authorization header on the same request; only the OAuth Bearer assertion is emitted since the client sends the OAuth token when OAuth credentials are configured.

4.17.0

(feat): Add opt-in allowUserAgentAppInfo config. When enabled, the generated client’s builder exposes an appInfo(name, version, comment) option whose product token is appended to the User-Agent header the SDK would otherwise send ({sdk}/{version} ... {name}/{version} ({comment})), following RFC 9110. Disabled by default, so existing generated output is unchanged, and it composes with includePlatformHeaders, the runtime-version jar-manifest path, the configured user-agent template value, and the default {coordinate}/{version}. Caller-supplied values are trimmed and sanitized (name/version percent-encoded to RFC 7230 tchars; comment delimiters, control characters and any non-ASCII characters percent-encoded as UTF-8 bytes so OkHttp’s header validation never rejects them), so untrusted values cannot inject header content. Still overridable by an explicit User-Agent and suppressed by omit-fern-headers.