Changelog

3.83.0

(feat): Add support for webhook body-hash binding in the generated verifySignature helper. When a webhook’s signature declares a body-hash binding, the helper now hashes the raw request body and compares it to the hash transmitted separately as a query parameter on the notification URL (e.g. Twilio’s bodySHA256) before verifying the HMAC signature. Both checks must pass. The body-hash algorithm and encoding are independent of the outer HMAC’s.

3.82.3

(fix): Fix server URL variable interpolation to render the selected environment’s URL template instead of always using the first environment’s template. When a client is constructed with both an environment and server URL variable values (e.g. region), the base URL is now built from the selected environment’s template(s); for multi-host environments every host’s template is formatted. An explicitly provided baseUrl or custom environment value is no longer overridden.

3.82.2

(fix): Generated endpoint JSDoc now documents all thrown error paths: in addition to the errors declared in the API definition, each method’s @throws annotations include the base API error class (thrown for any undeclared HTTP error status code) and the timeout error class (thrown when the request times out).

3.82.1

(fix): Send grant_type: "client_credentials" in the OAuth token request when the token endpoint models grant_type as a plain (non-literal) string. Previously the generated OAuthAuthProvider omitted grant_type entirely, so token requests against OpenAPI-imported specs (where grant_type is an optional string rather than a literal) failed. A required non-literal grant_type is no longer surfaced as a user-supplied client-credentials option; it is synthesized automatically.

3.82.0

(feat): Add automatic idempotency-key generation, driven by the centralized idempotencyKeyGeneration config in the IR. When enabled, the generated SDK attaches a UUIDv4 idempotency-key header (default Idempotency-Key) to requests whose HTTP method is listed in the IR (default POST/PUT). A caller-supplied key in request options still takes precedence.

3.81.0

(feat): Add support for server URL variables (e.g. region/edge routing). Server variables defined on the API’s environments are now exposed as optional string options on the client constructor and interpolated into the base URL(s) at request time. Reserved option names are de-collided by prefixing with serverUrl (e.g. a variable named environment is exposed as serverUrlEnvironment).

3.80.2

(fix): Fix compile errors in the generated OAuthAuthProvider when the serde layer is disabled: the token endpoint method is now called with the same camelCase name that the generated client exposes (previously the original casing, e.g. CreateOauth2Token, was used). Also guard against optional access_token response properties so the token refresh path satisfies its Promise<string> return type instead of string | undefined.

3.80.1

(fix): Make the structured User-Agent (emitted when includePlatformHeaders is enabled) comply with the RFC 7230 token grammar. The npm package name is now percent-encoded in the product token so the @ and / of a scoped package are escaped (e.g. @dummy/sdk/0.0.1 becomes %40dummy%2Fsdk/0.0.1); the original name can be recovered by URL-decoding. The architecture label is also normalized so the 64-bit x86 aliases (x64, amd64, x86_64) all report as the canonical x86_64.

3.80.0

(feat): Add opt-in support for a structured User-Agent header of the form {sdkName}/{version} ({os}; {arch}) {runtime}/{runtimeVersion}, matching the Twilio helper-library shape. This is gated behind the includePlatformHeaders config option and is disabled by default, so existing generated output is unchanged. When enabled, the platform + runtime information is consolidated into the User-Agent and the discrete X-Fern-Runtime / X-Fern-Runtime-Version headers are omitted. The platform group and runtime segment are dropped gracefully in environments where they cannot be determined (e.g. browsers), and the header remains subject to omitFernHeaders.

3.79.2

(fix): Pin the npm toolchain used by the generated publish workflow. The .github/workflows/ci.yml publish job now runs on a pinned Node LTS (node-version: "lts/Krypton") and calls npm publish directly instead of npx -y npm@latest publish. Relying on npm@latest pulled whatever npm release was newest at publish time, so a broken npm release could break publishing. The pinned Node LTS bundles an npm that supports OIDC trusted publishing. The npx semver invocation used for backport detection is also pinned to semver@7.8.1.

3.79.1

(fix): Generated snippets now use baseUrl instead of environment when no environments are defined in the API spec, matching the actual constructor parameter users should provide.

3.79.0

(feat): Add a defaultTimeout custom config option, expressed in milliseconds, which is idiomatic for JavaScript/TypeScript (setTimeout, AbortSignal.timeout(ms)). Use "infinity" to disable the timeout. The seconds-based defaultTimeoutInSeconds and timeoutInSeconds keys are now deprecated but continue to work: their values are converted to milliseconds (× 1000). Precedence is defaultTimeout > defaultTimeoutInSeconds > timeoutInSeconds. Generated SDK output is unchanged for existing configs.

3.78.2

(fix): Fix a regression where | undefined was dropped from the value type of generated Record types backed by optional map values (e.g. optional additionalProperties). Optional map values now correctly generate Record<string, T | undefined> with serialization record(string(), T.optional()), while unknown/any map values keep the redundant | undefined stripped (Record<string, unknown>).

3.78.1

(fix): Fix TypeError: Cannot use 'in' operator to search for 'path' in undefined crash when null or undefined is passed to a file upload parameter at runtime. The error is now a clear TypeError describing the expected types instead of a cryptic in operator failure.

3.78.0

(feat): Add an additionalBodyParameters request option that spreads additional parameters into an endpoint’s JSON request body. Caller-supplied properties override matching keys in the endpoint body, matching the behavior of the Python, Swift, and Ruby SDKs. Omitting the option leaves the request body unchanged and never fabricates a body for bodyless requests.

3.77.3

(fix): Revert the automatic renaming of inlined path parameters that collide with request body properties (introduced in 3.77.1). These collisions are now rejected at the CLI level: fern check errors and asks the user to deconflict the names (e.g. via x-fern-parameter-name).

3.77.2

(fix): Fix ESM spec violations for extensionless imports in generated SDKs. The rename-to-esm-files.js script now resolves bare directory imports (e.g. from "./oauth"from "./oauth/index.mjs") and extensionless file imports (e.g. from "./client"from "./client.mjs"), which previously broke Node’s ESM loader and Turbopack (Next 16). Also sets moduleResolution: "bundler" in tsconfig.esm.json for correct ESM semantics.

3.77.1

(fix): When an inlined path parameter (inlinePathParameters: true) shares its property name with an inlined request-body property (e.g. a {idType} path parameter and an idType body field), the request wrapper now keeps both fields by renaming the path parameter with a PathParam suffix (e.g. idTypePathParam). Previously the two values were collapsed into a single shared field, which made it impossible to send different values for the URL path and the request body.

3.77.0

(feat): Implement SSE stream auto-reconnection for resumable endpoints. When an SSE stream drops mid-connection and the endpoint is marked resumable: true, the SDK now automatically reconnects using the Last-Event-ID header, honoring server-sent retry directives clamped to 30 seconds. Reconnection respects reconnectionEnabled and maxReconnectionAttempts options.

3.76.0

(feat): Add React Query hooks generation support via the generateReactQueryHooks config flag. When enabled, generates a react-query/ directory with a tRPC-style namespace object that mirrors the SDK client hierarchy (e.g. seedApi.user.list.useQuery()). Each query endpoint exposes useQuery, useSuspenseQuery, getQueryKey, getQueryOptions (for SSR/RSC), and invalidate. Mutation endpoints expose useMutation. Hierarchical cache invalidation at endpoint, service, and SDK levels. Per-service file splits with wildcard subexports for tree-shaking. All exports available via a ./react-query package.json subexport with optional peer dependencies on react and @tanstack/react-query.