Changelog
2.20.4
(fix): Honor endpoint-level retries: { disabled: true } (x-fern-retries). Requests for those
endpoints pin maxRetries to 0, so they are never retried regardless of the client-level or
per-request retry options.
2.20.3
(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.
2.20.2
(fix): Global headers typed as a literal<"..."> with an env fallback no longer throw when
neither the constructor parameter nor the environment variable is set. The literal is
known at compile time, so it is now used as the header’s default value.
2.20.1
(fix): Render an empty body in snippets for an example that omits a request body the API does not
require. The generated request wrapper still requires the body, so the snippet left the
required key out and did not typecheck.
2.20.0
(feat): Add a respectOptionalRequestBody option. When enabled, an endpoint whose request body the API
does not require lets the caller leave that body out of the call, and such a call sends neither a
body nor a Content-Type header. refund(string $id, RefundRequest $request) becomes
refund(string $id, ?RefundRequest $request = null), and a body carried in a request wrapper
becomes an omittable property, so new RefundWithHeaderRequest([]) no longer throws. Snippets
that supply no body render as $client->bulkRefund();. The option defaults to false, so existing
signatures, output, and snippets are unchanged.
2.19.0
(feat): Add an opt-in preferExplicitAuth configuration option. When enabled (and the API composes
OAuth client-credentials with basic auth via auth: any), auth credentials passed
explicitly to the client constructor take precedence over environment-variable
defaults when selecting the auth scheme — e.g. explicitly provided basic auth
credentials win over OAuth client ID/secret environment variables. Disabled by
default, so existing generated output and runtime behavior are unchanged.
2.18.2
(fix): Fixed wire tests for APIs with basic auth schemes that use custom parameter names
(e.g. accountSid/authToken): the generated test client constructor now uses the
scheme’s actual parameter names instead of hardcoded username/password.
Also fixed WireMock stubs for auth: any APIs combining Basic and OAuth/Bearer:
stubs now expect the Bearer Authorization header the client actually sends instead
of the Basic header.
2.18.1
(fix): The generated composer.json version (and the fallback User-Agent header) now honors
the version passed via fern generate --version for local-file-system output,
instead of always defaulting to 0.0.0. The Composer package name also falls back to
the CLI-provided package name when packageName is not set in generators.yml.
2.18.0
(feat): Add an opt-in allowUserAgentAppInfo config (default false). When enabled, the
generated client accepts an optional appInfo client option
(array{name: string, version?: string, comment?: string}) whose product token is
appended to the User-Agent header for all three branches (the structured platform
value, the configured user-agent template value, and the default
{package}/{version}), producing e.g. acme/sdk/1.0.0 partner-app/3.1.0 (+https://partner.example)
per RFC 9110. Caller-supplied values are sanitized (name/version percent-encoded to
RFC 7230 tchars; comment delimiters and control characters escaped) and trimmed
before encoding, so untrusted values cannot inject additional header content. The
header is still overridable by an explicit User-Agent and suppressed by
omitFernHeaders. Default-off output is byte-identical.
2.17.0
(feat): Add an encode-path-params config option (default false). When enabled, generated clients
pass path parameter values through RawClient::encodePathParam() at the point they are
substituted into the path template, so a value containing / or .. can no longer change which
endpoint the request resolves to. The default false preserves the existing (unencoded)
behavior; TypeScript, Go, Java, and C# already encode path params.
2.16.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.
2.15.0
(feat): Support webhook body-hash binding in generated signature verification helpers.
When a webhook signature declares a body-hash binding, the helper now recomputes
the encoded hash of the raw request body, extracts the transmitted hash from the
configured query parameter of the notification URL, and timing-safe-compares them
(failing closed) before verifying the outer HMAC over the verbatim notification URL.
2.14.1
(fix): Render the selected environment’s URL template(s) when server URL variables
(e.g. region) are provided alongside a named environment. Previously the
first environment’s template was always used, so
new Client(environment: Environments::Staging(), region: 'ie1') resolved
to Production-shaped URLs. A custom environment or explicitly provided
base URL is left untouched.
2.14.0
(feat): Include a usage code example in each endpoint method’s PHPDoc block, so IDEs
(PhpStorm, Intelephense) surface an example on hover.
2.13.4
(fix): Global API headers configured with an env fallback (e.g. X-Twilio-Version with
env: TWILIO_VERSION) now fall back to the environment variable in the root client
constructor when the parameter is not passed explicitly. Optional headers never throw
when both the parameter and the environment variable are missing.
2.13.3
(fix): Emit a standalone LICENSE file at the repo root when a custom license is
configured (license: { custom: ./LICENSE } in the generator’s github block).
Previously the PHP generator only set the license field in composer.json and
never wrote the license file itself, so GitHub license detection and compliance
scanners reported no license. This brings the PHP generator to parity with the
TypeScript, Python, Java, and Go generators.
2.13.2
(fix): Send request bodies declared with the application/x-www-form-urlencoded content type
(e.g. OAuth token endpoints) as form-urlencoded instead of JSON. A new
UrlEncodedApiRequest core type encodes the body with http_build_query and sets the
Content-Type: application/x-www-form-urlencoded header.
2.13.1
(fix): Wire OAuth client-credentials authentication into the root client when the OAuth
scheme is not the first scheme in the API’s auth configuration (e.g.
auth: any with basic auth listed before OAuth). Previously the OAuth token
provider was only generated when OAuth was the first auth scheme, so the root
client silently fell back to the other schemes and never used the OAuth
credentials. When both an OAuth and an inferred auth scheme are present, the
provider-based scheme that appears first in the auth configuration is used.
2.13.0
(feat): Auto-generation of the idempotency key header is now driven by the IR
(sdkConfig.idempotencyKeyGeneration) instead of a generator config flag. When
enabled, retry-unsafe requests (the IR-configured eligible methods, POST/PUT by
default) attach the configured header (default Idempotency-Key) with a freshly
generated UUIDv4 unless the caller supplies one. The header name and eligible
methods come from the IR so behavior is consistent across generators.
2.12.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 parameters on
the client constructor and interpolated into the base URL(s) at construction time,
falling back to each variable’s default when not provided. Conflicting constructor
option names are de-collided with a serverUrl prefix and numeric suffix when needed
(e.g. a variable named environment is exposed as serverUrlEnvironment).