3.108.7
(fix): With esmOnly: true, the SDK no longer runs or ships scripts/rename-to-esm-files.cjs.
The package is already "type": "module", so build:esm is now just tsc and the
main, types and exports entries point at dist/esm/**/*.js and *.d.ts
instead of .mjs and .d.mts.
3.108.6
(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.
3.108.5
(fix): XML (TwiML) serialization writes empty elements as <Hangup/> instead of <Hangup />, matching the legacy
twilio-node output byte for byte.
3.108.4
(fix): In Node, a rejected WebSocket handshake (a non-101 response) now includes the server’s response
body in the error. Callers see Unexpected server response: 400 (<body>) instead of only
Unexpected server response: 400, so a bad query parameter or an auth failure can be told
apart from other errors. The ErrorEvent also exposes the rejection as optional statusCode,
headers and body fields (the body is capped at 1000 characters); they stay undefined for
other errors. The error reaches error listeners and waitForOpen(). Retry behavior does not
change, and browser WebSockets are unaffected.
3.108.3
(fix): The generated serialization layer no longer throws “Maximum call stack size exceeded” when a
value fails validation with a very large number of nested errors. list, object and record
schemas now append child errors in a loop instead of spreading them into Array.prototype.push.
3.108.2
(fix): XML (TwiML) builders match the legacy call shapes: a child builder keeps the child’s name even when it
collides with the element’s text field (dial().number("+1…") adds a <Number> child; the text is set
with text(...) / setNumber(...)), every element builder has a uniform text(...) setter, and the
child-builder verbs are also available on the value itself (new VoiceResponse().say("hi")). Children added
through the value’s verbs live in its ordered content (which toXml() renders); the typed child property
(children) is not updated by them.
3.108.1
(fix): Fix TS1484 compilation error in the generated XML (TwiML) runtime: src/core/xml/builder.ts imported the
XmlSerializable interface as a value, which the ESM build (tsconfig.esm.json, verbatimModuleSyntax)
rejects. The import is now type-only, so pnpm build succeeds for SDKs with xml-encoded types.
3.108.0
(fix): With noSerdeLayer: false, JSON-style parts of a multipart request are now serialized before they are
encoded, as JSON request bodies are. A part whose type is or contains a named type was sent as toJson(value)
with the SDK’s camelCase property names instead of the wire names.
(feat): Add the opt-in includeMultipartPartContentType config option. When enabled, non-file parts of a
multipart request carry their declared content type (e.g. OpenAPI
encoding.<part>.contentType: application/json) as the part’s Content-Type header. It is off by
default because in browsers such parts are sent as a Blob, which also adds filename="".
3.107.8
(fix): With noSerdeLayer: false, the serialization Raw type of an undiscriminated union with a
self-recursive map member (e.g. map<string, JsonLike>) now uses an index signature instead of
Record<string, JsonLike.Raw>, which TypeScript rejected as a circular type alias (TS2456).
(fix): A named alias of a string-keyed map (e.g. Branch = map<string, Node>) is now emitted as
{ [key: string]: Node } instead of Record<string, Node>, in both the public type and the
serialization Raw type. The two are the same type, but TypeScript rejects a cycle that runs through
Record as a circular type alias (TS2456), so a map schema that is part of a recursive type now compiles.
3.107.7
(fix): Fix generated WebhooksHelper.verifyRequest failing to compile (TS2550: Property 'hasOwn' does not exist on type 'ObjectConstructor') under the SDK’s default target: ES6 tsconfig: the supported-algorithm
check used Object.prototype.hasOwnProperty.call, which the generator’s Biome --fix --unsafe pass rewrote
to the ES2022-only Object.hasOwn. The check is now an isSupportedAlgorithm type guard over
Object.keys(HMAC_ALGORITHMS), which Biome leaves alone and which compiles on ES6.
3.107.6
(fix): TypeScript dynamic snippets now follow the SDK generator’s noSerdeLayer default (on unless noSerdeLayer: false or serdeLayer: true is set), so they use wire property names (e.g. per_page) that match the generated request types. Without a serde layer, query parameters, headers, file fields and object properties use the wire value, as the SDK does, even when a name override gives them a different original name. Property names that aren’t valid identifiers (e.g. org.iso.18013.5.1) are now quoted, file values are always sent as a Blob, and a required file field (or file list) missing from the example gets a fs.createReadStream("/path/to/your/file") placeholder instead of being dropped. Optional file fields missing from the example are still left out; dynamic IR from CLIs that predate the isOptional flag treats every file as required. A config that never sets noSerdeLayer but pins a TypeScript generator older than 1.0 (where the serde layer was on by default) now gets wire-name snippets; fern generator upgrade sets the flag explicitly, so upgraded configs are unaffected.
3.107.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.
3.107.4
(fix): XML (TwiML) child builder methods accept the element’s text content as a string, so legacy-style calls
such as response.dial("+15551234567") and response.say("hi") produce <Dial>+15551234567</Dial>
instead of an empty element. Element text no longer escapes double quotes as " (attributes still do),
matching the legacy TwiML output.
3.107.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.
3.107.2
(fix): With flattenAnyAuthOptions enabled, dynamic snippets now keep nested auth options for APIs that use
endpoint-level security, which matches the generated SDK. Only auth: any snippets are flattened.
3.107.1
(fix): Reject . and .. as path parameter values. encodeURIComponent leaves dots unencoded, so URL resolution
removed these dot segments and sent the request, with its auth headers, to a different endpoint (for example,
/users/{userId}/roles with userId: ".." was sent to /roles). The SDK now throws its generic API error
(e.g. MyClientError) before the request is sent. SDKs generated with neverThrowErrors throw a plain Error.
3.107.0
(feat): Add the flattenAnyAuthOptions config option. When it is enabled and the API uses auth: any, each scheme’s
client options are flat (e.g. { apiKey }, { clientId, clientSecret }, { token }) instead of nested under the
scheme key (e.g. { apiKey: { apiKey } }). This matches the Python SDK. Options with the same name, such as the
bearer token and the OAuth token override, are shared, and an OAuth token skips the client-credentials flow.
The default is false, so existing SDKs keep the nested shape.
3.106.1
(fix): The generated API error’s requestId getter now works without configuration for
APIs that return the request ID under a vendor-specific header: it reads
X-Request-Id and otherwise falls back to the first response header whose name
ends in request-id / requestid (e.g. Twilio-Request-Id, x-amzn-RequestId).
Removed the requestIdHeader config option introduced in 3.106.0.
3.106.0
(feat): The generated API error class’s requestId getter now reads the canonical
X-Request-Id header (previously the lowercase x-request-id), matching the
casing of every other header the SDK emits. Added the requestIdHeader
config option so SDKs can point requestId at a different response header,
e.g. requestIdHeader: Twilio-Request-Id.
3.105.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.