5.41.17
(fix): Fix reference.md source links when package_name contains dots or package_path is set.
Links previously used the dotted Python module path (e.g. src/acme.management/actions/client.py)
instead of the directory path (src/acme/management/actions/client.py).
(fix): reference.md method links now point at the method’s line range in client.py
(e.g. src/acme/management/actions/client.py#L54-L125) instead of the top of the file.
5.41.16
(fix): When whitelabel is enabled, the SDK’s logger is now named after the package, with dashes
turned into dots (for example acme-orders logs as acme.orders), instead of
{package name}_sdk_{version}. The name no longer changes on every release, and it sits under
parent loggers such as acme.
(fix): The PyPI package name is now always normalized per the Python packaging spec: runs of
., _, and - become a single -, and the name is lowercased (for example Acme_Orders.v2
becomes acme-orders-v2). This applies to pyproject.toml, the SDK name header, and the
User-Agent. PyPI already treats these spellings as the same package, so installs are unaffected.
5.41.15
(fix): When whitelabel is enabled, the SDK’s platform headers are now sent as X-Codegen-*
(for example X-Codegen-Language) instead of X-Fern-*, and the SDK’s logger is named
{package name}_sdk_{version} instead of fern.
5.41.14
(fix): README generation in self-hosted GitHub mode can clone a private repository with a personal
access token again. Upgrades @fern-api/generator-cli to 0.12.1, which also sends the token as an
Authorization header. Before this, git in the generator image (libcurl 8.23+) dropped the token
from the clone URL and failed with could not read Username.
5.41.13
(fix): When whitelabel is enabled, every generated file now uses the unbranded header
(“This file was auto-generated from our API Definition.”). Previously __init__.py files,
most core/ utilities, _default_clients.py, webhook signature helpers, XML model tests,
and test asset models still said “by Fern”. Files copied from disk no longer get the
header twice.
5.41.12
(fix): Generated SDKs now keep the original copyright and license notices for core files
adapted from open-source projects: core/jsonable_encoder.py (FastAPI, MIT), the four
core/http_sse/ modules (httpx-sse, MIT), the Retry-After parsing in
core/http_client.py (urllib3, MIT) and the file types in core/file.py (httpx, BSD-3-Clause).
5.41.11
(fix): Fix recursive aliases and undiscriminated unions under pydantic_config.version: v2 without
wrapped_aliases. A plain alias that refers back to itself (e.g. JsonLike = Union[List["JsonLike"], ...],
or a map whose values are a union containing that map) was expanded endlessly by Pydantic, so building
the model raised RecursionError or ... is not fully defined. Such an alias is now a
typing_extensions.TypeAliasType at runtime, which Pydantic v2 resolves lazily, and stays a plain alias
under TYPE_CHECKING for mypy and pyright. Values come back as plain dicts and lists, with no root
model to unwrap. Other aliases, and SDKs on Pydantic v1, both or wrapped_aliases, are unchanged.
5.41.10
(fix): Fix the README “Async Client” snippet dropping types imported from the package root.
Previously the whole from <package> import <Client>, <Type>, ... line of the sync
snippet was discarded, so the async example only imported the async client and
referenced request types that were never imported. The async snippet now imports
those names alongside the async client.
5.41.9
(fix): update_forward_refs now passes its namespace to model_rebuild under Pydantic v2. Models whose
forward references go through a union alias (e.g. a recursive Union["Branch", Leaf, "Items"] whose
members are imported under TYPE_CHECKING) were left incomplete, and parsing them raised
PydanticUserError: ... is not fully defined.
5.41.8
(fix): Fix SDKs generated with tcp_keepalive.enabled: true ignoring the HTTP_PROXY, HTTPS_PROXY,
ALL_PROXY and NO_PROXY environment variables. httpx skips environment proxies whenever a
custom transport is passed, so the default sync and async clients now also pass mounts
built from the environment proxies, each carrying the keepalive socket options.
5.41.7
(fix): Add the http_client_extra option. When set (e.g. http_client_extra: client), httpx is
declared as an optional dependency exposed under that extra (pip install <pkg>[client]), so a
plain install of a package used for its models only (e.g. TwiML) does not pull in the HTTP stack.
Off by default; existing SDKs are unchanged.
5.41.6
(fix): Respect the retry-after-ms response header when computing retry delays. The header value was
compared to 0 before being converted to a number, raising a TypeError that was silently
swallowed, so the client always fell back to Retry-After or exponential backoff.
5.41.5
(fix): XML (TwiML) serialization drops characters outside the XML 1.0 Char production (e.g. \x01) from text and attribute values instead of emitting XML that no parser accepts.
5.41.4
(fix): Path parameter values of exactly . or .. now raise a ValueError before the request is
sent. These are dot-segments that httpx resolves, so they could change which endpoint the
request was sent to. When encode_path_params is off (the default), values are not
percent-encoded, so any . or .. segment inside the value (including %2e forms) is also
rejected.
5.41.3
(fix): WebhooksHelper.verifyRequest now parses name=value settings headers when
webhook-signature.algorithm-header sets key-id-parameter/algorithm-parameter
(e.g. Twilio’s X-Twilio-Webhooks-Signature-Settings: key=<id>,algorithm=HMAC_SHA256),
so the key resolver receives the bare key ID instead of key=<id>. Requires IR 67.33.0.
5.41.2
(fix): The generated WebhooksHelper now consumes algorithm-header from api.settings.webhook-signature:
a request-level verifyRequest helper reads the configured signature header first (missing or empty
fails early with “could not run: missing signature header”), then the algorithm-selection header
(e.g. X-Twilio-Webhook-Signature-Settings: <key_id>;HMAC_SHA256) to pick the HMAC algorithm from
the configured wire values and hand the key ID to an application-supplied secret resolver. When the
header is absent the configured default algorithm and the plain secret are used, so legacy
auth-token flows keep working. The lower-level verifySignature is unchanged and still returns
false without throwing.
5.41.1
(fix): Models that keep unknown JSON keys no longer keep one that matches a declared field except for case
(e.g. VALUE next to value). Such a key used to be sent again after the declared field, so a
case-insensitive decoder on the receiving end (e.g. Go’s encoding/json) read it instead of the
field’s value. Other unknown keys (e.g. brand_new_field) are still kept and sent as before.
5.41.0
(feat): Wire tests now cover every example instead of only the first one per endpoint. Each user-specified
example gets its own test (or the first autogenerated success example when there are none), and when
none of an endpoint’s user examples is an error example, the autogenerated error examples are added
too. Error tests assert the typed error the client raises for the status code (or the base ApiError
when the client can’t dispatch to a typed error) along with its status_code and body. Each test is
served by its own X-Test-Id-scoped WireMock stub with the declared status code, and the test client
disables retries. Set wire_tests.fallback_to_autogenerated_error_examples: false to leave out
autogenerated error examples.
5.40.0
(feat): Support inferred bearer auth with type: refresh-token. The generated InferredAuthTokenProvider
always sends grant_type="refresh_token" to the get-token endpoint, and grant_type is no longer
a client constructor parameter. Users pass only the refresh token (and any other non-literal
token endpoint parameters).
(feat): Inferred auth now works next to other auth schemes (auth: any and endpoint-security) when it has
credentials of its own, e.g. a type: refresh-token scheme next to OAuth client credentials.
The client takes the inferred credentials as optional constructor parameters (shared ones such as
client_id are added once) and uses the inferred token provider when they are passed, so
Client(refresh_token=...) and Client(client_id=..., client_secret=...) both work.
5.39.5
(fix): Fix the root client docstring example for global headers and root path parameters
that have a client-default. The example now passes the default as a keyword
argument (e.g. version="2024-01-01") instead of a bare positional value, which
was a SyntaxError when it followed another keyword argument.