2.76.3
(fix): The README “Environments” usage example now passes the client options via the
clientOptions: named argument so the generated snippet compiles. The root
client constructor’s first positional parameter is the auth token string, so
the previous new Client(new ClientOptions { ... }) snippet passed
ClientOptions where a string? token was expected.
2.76.2
(fix): A generated nested type whose name matches the SDK’s root namespace segment now emits
global::-qualified references. Previously such a nested type shadowed the namespace
root within its enclosing type’s body, so references like Acme.Api.SomeType resolved to the
nested type and failed to compile. The global:: qualifier is applied
only to references written inside the enclosing type where the shadow is visible, so
unrelated references to the same root segment elsewhere in the SDK are left
unqualified.
2.76.1
(fix): Endpoints without a request wrapper (no request object, a request that is just
a body, or a bytes request) now send service- and endpoint-level headers whose
types are literals (e.g. Accept-Encoding: literal<"gzip">). Previously these
headers were silently dropped because there was no request object to carry them.
2.75.2
(fix): Fix a compile error in the generated OAuthTokenProvider when the token endpoint’s
expires-in response property is optional. The provider now null-checks the value
before computing the token expiry instead of passing a nullable number to
DateTime.AddSeconds.
2.75.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.76.0
(fix): Add an opt-in dedupe-union-base-properties configuration flag (default off) that stops
duplicating a discriminated union’s base properties on its samePropertiesAsObject variant
leaves. The decision is read from the IR fact
ObjectTypeDeclaration.deferredUnionBaseProperties (computed once in the IR with structural
type equality and an exclusive-variant guard), so the generator never re-derives it. When
enabled, the union envelope owns the shared base properties, the variant leaf class and its
example initializers omit them, and the union’s JSON reader strips union-owned properties
before deserializing a variant. Off by default, so existing generated output is unchanged; the
default is expected to flip in a future major version with a migration.
2.75.0
(feat): Add support for auto-generating an Idempotency-Key header on generated SDK
clients, driven by the IR. When sdkConfig.idempotencyKeyGeneration is present
(configured once via the auto-generate-idempotency-key generator config key
and resolved by the CLI), the SDK attaches an idempotency-key request header
whose value is a freshly generated UUIDv4 (System.Guid.NewGuid().ToString())
at request time. The wire header name and the eligible HTTP methods come from
the IR, so behavior is consistent across every generator. A caller-provided
value always wins: a declared idempotency header or a header supplied through
request-options takes precedence, and the generated UUID is only a fallback.
The header is only injected on the eligible methods. Disabled by default, so
existing generated output is unchanged.
2.74.0
(feat): Add support for server URL variables (region/edge routing). When an API’s servers
declare URL variables (e.g. https://api.{region}.example.com), each variable is
now exposed as an optional string property on ClientOptions (idiomatic PascalCase,
e.g. Region). Variable names that collide with an existing client option are
prefixed with ServerUrl (e.g. an environment variable becomes ServerUrlEnvironment).
When set at construction time, the values are interpolated into the environment base
URL(s), falling back to each variable’s default otherwise. Explicit BaseUrl or
Environment options take precedence, and interpolation fails clearly when a required
variable has neither a client option nor a default.
2.73.2
(fix): Enable automatic response decompression on the default HttpClient. The default client
is now created with an HttpClientHandler configured with AutomaticDecompression
(DecompressionMethods.All on .NET 5+, GZip | Deflate on older targets), so responses
with a Content-Encoding of gzip or deflate are decompressed transparently — including
when an Accept-Encoding request header is set explicitly by the API spec. User-supplied
HttpClients provided via ClientOptions are not modified.
2.73.1
(fix): Make the structured User-Agent (emitted when includePlatformHeaders is
enabled) comply with the RFC 7230 token grammar. The runtime token is now
dotnet instead of .NET, since a leading dot is not a valid token
character (e.g. dotnet/8.0.4). The architecture label is also normalized so
the 64-bit x86 aliases (x64, amd64, x86_64) all report as the canonical
x86_64.
2.73.0
(feat): Add opt-in support for a structured User-Agent header on generated SDK
clients of the form {sdkName}/{sdkVersion} ({os}; {arch}) {runtime}/{runtimeVersion}
(e.g. my-sdk/1.2.0 (linux; x64) .NET/8.0.4). The OS, architecture, and
runtime version are resolved at runtime via
System.Runtime.InteropServices.RuntimeInformation and System.Environment.
This is gated behind a new include-platform-headers config option and is
disabled by default, so existing generated output is unchanged. When enabled
it remains subject to the omit-fern-headers config option.
2.72.2
(fix): Make each scheme’s credentials optional under any-composed auth. Previously,
with a multi-scheme auth: any: [...] config the generated client treated OAuth
(and other) credentials as unconditionally required at construction, so a caller
who only wanted API-key auth could not instantiate the client. Credentials now
fall back to environment variables without throwing, and the OAuth/inferred token
provider and auth headers are only set up when that scheme’s credentials are present.
2.72.1
(chore): Bump the bundled @fern-api/generator-cli to 0.9.44 so every local-only commit
is signed when pushing to GitHub, not just HEAD. Replay branches contain multiple
commits (e.g. [fern-generated] + [fern-replay]); previously only the HEAD
commit was recreated via the GitHub API and signed, leaving earlier commits on
the PR unverified.
2.72.0
(feat): Add a default-timeout-in-milliseconds config option to the C# SDK generator
for expressing the default network timeout in milliseconds (mapping to .NET’s
TimeSpan). The generated ClientOptions.Timeout is now computed from
milliseconds (or Timeout.InfiniteTimeSpan when set to "infinity").
The default-timeout-in-seconds option is now deprecated but remains fully
backwards compatible: when only the seconds key is set, it is converted to
milliseconds. The new key takes precedence when both are set.
2.71.2
(fix): Fix mock-server tests and XML-doc <example> snippets calling client methods with
path parameters in the wrong order (CS1503) when a user-authored example lists its
path-parameters in a different order than the URL path template. The generated method
signature follows the IR’s canonical (URL-template) order, but the snippet writer was
consuming the example’s path-parameters positionally in the author’s declared order.
Example values are now bound to each parameter by name and emitted in the endpoint’s
canonical path-parameter order, matching the generated signature.
2.71.1
(fix): Fix SSE stream reconnection correctness to match the reference implementation:
(1) Do not reconnect when no terminator is configured (the client cannot
distinguish a completed stream from a dropped connection).
(2) Apply a default 1-second backoff between reconnect attempts when the
server sends no retry: directive (previously zero delay).
(3) Use the last dispatched event ID for reconnection rather than the
last parsed id, preventing silent event loss on mid-event drops.
(4) Treat reconnect function failures as consumed attempts; throw
IOException with the last failure as InnerException when the cap is
exhausted, instead of silently truncating the stream.
(5) Let OperationCanceledException propagate immediately from reconnectFn
instead of swallowing it as a retry attempt.
(6) Dispose the old HTTP response only after a new one is successfully
obtained, preventing ObjectDisposedException on retry.
2.71.0
(feat): Add opt-in SSE stream reconnection for resumable endpoints.
When an SSE endpoint is marked as resumable, the generated SDK
automatically reconnects using the Last-Event-ID header.
New RequestOptions fields: MaxStreamReconnectAttempts, DisableStreamReconnection.
2.70.0
(feat): Add support for undocumented/extra parameters: AdditionalQueryParameters from
RequestOptions are now applied to all endpoints (previously only endpoints with
defined query parameters would merge them). Also add ADDITIONAL_BODY_PROPERTIES
feature to README generation.
2.69.2
(fix): Fix shell injection code scanning alert in OIDC publish workflow by passing
API key through env block instead of direct interpolation.
2.69.1
(fix): Fix generated wire tests failing to compile when a header, query parameter, or
auth header example value contains characters that are special inside a C#
string literal (e.g. double quotes, backslashes, or control characters). These
values are now emitted through escapeForCSharpString in the mock-server
.WithHeader(...) / .WithParam(...) matchers instead of being interpolated
raw into a double-quoted string.