Changelog
5.22.1
(fix): Loosen the generated httpx-aiohttp optional dependency constraint from an exact
pin (0.1.8) to a caret range (^0.1.8, i.e. >=0.1.8,<0.2.0). This lets the
aiohttp extra coexist with other packages that require a newer 0.1.x of
httpx-aiohttp (e.g. >0.1.9) without introducing a breaking major bump.
5.22.0
(feat): Add support for per-endpoint auth routing. When the API-level auth requirement is
ENDPOINT_SECURITY, each endpoint now applies only the auth scheme(s) it declares in
its IR security field (OR across the list of requirements, AND within a requirement,
and no auth when security is empty), instead of applying every configured credential
to every request. Behavior for the ALL and ANY auth requirements (the common cases)
is unchanged.
Inferred (token-endpoint) auth is now also wired under ENDPOINT_SECURITY when other
schemes are present, and generated wire tests assert per endpoint that only the declared
scheme’s header is sent.
5.21.0
(feat): Add webhook body-hash binding support to verify_signature. When a webhook’s HMAC
signature declares a bodyHashBinding in the IR, the generated helper first recomputes
the raw request body’s hash (using the binding’s own algorithm/encoding), extracts the
configured query parameter from the notification URL, and timing-safe-compares them
(failing closed on a missing or mismatched hash) before performing the existing HMAC
verification over the verbatim notification URL. Adds stdlib-only compute_hash (unkeyed
digest) and read-only get_webhook_query_parameter core utilities. Output is unchanged
when no body-hash binding is present.
5.20.2
(fix): When a client is constructed with both an environment and server URL
variables (e.g. region), the generated client now renders the selected
environment’s URL template instead of always using the default (first)
environment’s template. For example, Client(environment=Environment.STAGING, region="ie1") now resolves to the Staging template
(https://api.stage.ie1.example.com) rather than the Production one.
An explicitly provided base_url is no longer overridden by URL variables.
5.20.1
(fix): Stop passing required literal query parameters as keyword arguments in generated
snippets and wire tests. Required literals (e.g. response_type="code") are
hardcoded inside the generated method and omitted from its signature, so passing
them raised TypeError: got an unexpected keyword argument. Optional literal
query parameters remain in the signature and are still included.
5.20.0
(feat): Add opt-in, platform-guarded TCP keepalive for the generated default HTTP
transport. Enable it via the new tcp_keepalive custom config
(enabled, idle_seconds, interval_seconds, count); it is disabled by
default so existing generated output is unchanged. When enabled, the default
httpx transport applies SO_KEEPALIVE plus the platform’s idle/interval/count
knobs (with a macOS TCP_KEEPIDLE -> TCP_KEEPALIVE fallback and guards for
older/minimal platforms) so long, non-streaming requests survive
idle-connection reaping by a firewall/load balancer/NAT. A user-supplied
httpx_client or a custom_transport http_client always takes precedence
over the keepalive default. Opting in requires httpx>=0.25.
5.19.3
(fix): Revert the smart-casing digit/word boundary behavior introduced in 5.18.4. snake_case
names keep a digit run fused to the following word (conversations_v2configuration),
restoring pre-5.18.4 output. The behavior will become opt-in via the new
smart-casing-digit-word-boundary option in generators.yml once the generator
consumes the IR version that carries the setting.
5.19.2
(fix): Fix the OAuth token provider crashing with “Access token not present in OAuth response”
when the token response does not include a refresh token. Client-credentials token
responses often omit refresh_token; the provider now treats it as optional instead
of raising.
5.19.1
(fix): OAuth client credentials token requests now send grant_type: "client_credentials"
when the token endpoint declares a non-literal grant_type request property. The
property is synthesized in the token request and is no longer surfaced as a
user-supplied option.
5.19.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 to requests whose HTTP method is listed in the IR. A
caller-supplied key still takes precedence.
5.18.4
(fix): Fix smart-casing snake_case names dropping the word boundary after a number.
Sub-client accessors and methods like ConversationsV2Configuration now generate
conversations_v2_configuration instead of conversations_v2configuration.
5.18.3
(fix): Expose basic auth credentials (e.g. account_sid / auth_token) on the top-level
client when the API also configures OAuth (auth: any). Previously the root client
constructor only accepted OAuth client credentials or a bearer token, even though the
underlying client wrapper supported basic auth. The credentials are now optional
constructor parameters that are forwarded to the client wrapper, and the client can be
instantiated with basic auth alone without raising an error.
5.18.2
(fix): Preserve leading and trailing underscores in generated namespace/module names.
Previously a subpackage named _agents (via x-fern-sdk-group-name: _agents)
was transformed to agents, stripping the underscore. Now it generates a
private _agents/ Python module with a matching client._agents accessor,
enabling the pattern of hiding autogenerated clients behind a hand-written
public layer.
5.18.1
(fix): Normalize the architecture label in the structured User-Agent (emitted when
include_platform_headers is enabled) so the 64-bit x86 aliases (x64,
amd64, x86_64) all report as the canonical x86_64, keeping the value
consistent across generators.
5.18.0
(feat): Add opt-in support for a structured User-Agent header of the form
{sdkName}/{version} ({os}; {arch}) Python/{pythonVersion}, matching the
Twilio helper-library shape. This is gated behind the include_platform_headers
config option and is disabled by default. When enabled, the platform + runtime
information is consolidated into the User-Agent header, superseding the
default {package}/{version} value, and the discrete X-Fern-Runtime /
X-Fern-Platform headers are no longer emitted. The platform group and runtime
segment are dropped gracefully when they cannot be determined, and the header
remains subject to omit_fern_headers.
5.17.1
(fix): Generated code snippets (README, OAuth token override examples) now use
the custom bearer token parameter name from the API spec (e.g. api_key)
instead of always using the default token.
5.17.0
(feat): Add a timeout config option as an alias for timeout_in_seconds. Both keys
are in seconds and timeout_in_seconds continues to work, with timeout
taking precedence when both are set.
(feat): Add a timeout key to the generated SDK’s RequestOptions as an alias for the
per-request timeout_in_seconds. Both are in seconds; timeout_in_seconds keeps
working, with timeout taking precedence when both are provided.
5.16.1
(fix): Emit attribute docstrings for aliased Pydantic model fields (e.g. fields renamed
from camelCase wire names to snake_case) so IDEs surface the field description
on hover, matching the behavior of non-aliased fields.
5.16.0
(feat): Implement transparent SSE stream auto-reconnection for resumable: true
endpoints, bringing the Python SDK to parity with TypeScript and Go. When a
resumable stream ends prematurely, EventSource now re-issues the original
request with a Last-Event-ID header and resumes from the last dispatched
event id (never a parsed-but-undispatched id, avoiding silent event loss).
Reconnection is gated on a configured stream terminator, honors
stream_reconnection_enabled and max_stream_reconnection_attempts (with
reset-on-progress), backs off 1s by default (or the server retry: value,
clamped to 30s), guards against empty reconnect bodies, and remains
cancellable during the backoff delay. Supported for both sync and async
clients.
5.15.2
(fix): Fix ImportError when a type uses extends to inherit from a base type that
is part of a circular reference cycle (e.g. Acai extends Berry where
Berry → Animal → Cat → Fruit → Acai). Python inheritance requires a
top-level import of the base class, which cannot coexist with the ghost
reference imports needed for circular forward-ref resolution. The generator
now automatically falls back to inlining the base type’s properties instead
of using Python class inheritance when it detects a circular extends chain.