SDK and config editions
Editions allow us to safely make updates and improvements to SDKs and the Stainless config that aren’t backwards-compatible, like changing default behavior or renaming a property. Every time we make a breaking change, we release a new version in the form of an “edition” which you can explicitly opt-in to when you’re ready.
There are two types of editions:
- Top-level editions are for general and cross-language changes and have a date-based identifier (e.g.,
2025-10-08) - Language-specific editions only impact a specific programming language and have an identifier that includes the language and date (e.g.,
typescript.2025-10-10) Each edition includes all of the improvements made up to and including the date in its identifier.
The editions we use for your projects are defined in your Stainless config. The top-level edition is specified in the top-level edition property, and language-specific editions are specified inside specific language targets:
# Top-level editionedition: 2025-10-08
# ...
targets: typescript: # Language-specific edition edition: typescript.2025-10-10 # ...When no edition property is present, the oldest available edition will be used. This applies to both the top-level edition property and the edition properties inside language targets. Also note that the top-level edition doesn’t cascade down into language targets. If you have a top-level edition set but a language target doesn’t have an edition property, for example, that language will use the oldest edition, not the one set at the top-level.
The top-level and language-specific editions in your config don’t need to match, and language-specific editions also don’t have to match each other. This gives you the flexibility to incrementally adopt new editions one language at a time without introducing breaking changes across multiple targets at once. Note that we may release language-specific editions without a corresponding top-level edition, making it impossible to have the same top-level and language-specific versions.
Below are all available editions and what was changed.
Config
Section titled “Config”2026-02-23
Section titled “2026-02-23”When choosing a name for a union variant, prefer the corresponding schema’s title property over its name in #/components/schemas.
We try the following options for union variant names, in order:
- If the variant is defined as a model, use the model name.
- Use the variant’s
x-stainless-variantNameproperty if it exists. - Use the variant’s
titleproperty if it exists. - If the variant is defined as a top-level schema in
#/components/schemas, use the name of the schema. - Use a generic name like
UnionVariant0.
For example, suppose your OpenAPI spec includes the following schemas:
components: schemas: Address: oneOf: - $ref: '#/components/schemas/Coordinates' # for drone delivery - $ref: '#/components/schemas/POBox' - $ref: '#/components/schemas/StreetAddress' Coordinates: type: object x-stainless-variantName: DroneDeliveryCoordinates properties: # ... properties omitted POBox: type: object title: CustomerPOBox properties: # ... properties omitted StreetAddress: type: object properties: # ... properties omittedLet’s assume that none of these schemas is defined as a model.
- We’ll derive the variant name for
Coordinatesfrom itsx-stainless-variantNameproperty,DroneDeliveryCoordinates. POBoxdoesn’t specifyx-stainless-variantName, so we’ll derive its variant name from itstitleproperty,CustomerPOBox.StreetAddressdoesn’t specifyx-stainless-variantNameortitle, so we’ll fall back to its name in#/components/schemas,StreetAddress.
For instance, in TypeScript we’ll generate the following code:
export type Address = | Address.DroneDeliveryCoordinates | Address.CustomerPoBox | Address.StreetAddress;Before this edition, we tried the name in #/components/schemas before the title property, so we generated the following code for this schema:
export type Address = | Address.DroneDeliveryCoordinates | Address.PoBox // instead of Address.CustomerPoBox | Address.StreetAddress;Note that updating to this edition does not affect variants that are configured as models or specify x-stainless-variantName, since the model name and x-stainless-variantName take precedence over the title and #/components/schemas name for union variant naming in all editions.
To revert to the previous behavior for union variant naming, set prefer_title_over_refnames to false at the top level in your Stainless config:
prefer_title_over_refnames: false2026-01-30
Section titled “2026-01-30”Enables per-endpoint security by default. For example, if your OpenAPI spec looks like this:
security: - BearerAuth: [] - ApiKeyAuth: []
securitySchemes: BearerAuth: type: http scheme: bearer ApiKeyAuth: type: apiKey name: api-key in: header
paths: /cards: post: security: - BearerAuth: [] # ... responses omittedAnd your stainless config:
settings: client_opts: bearer_token: type: string nullable: true auth: security_scheme: BearerAuth api_key: type: string nullable: true auth: security_scheme: ApiKeyAuth
resources: cards: methods: create: post /cardsWhen instantiating the SDK with both options:
from acme import Acme
client = Acme( api_key="my-api-key", bearer_token="my-bearer-token",)
client.cards.create()Previously, the SDK sent both the api-key and Authorization headers, which could cause authentication errors depending on how your API handles multiple authentication schemes.
Now the SDK will only send the Authorization header, as that is the only scheme configured for that endpoint in security.
To revert to the previous behavior of sending all configured options, set per_endpoint_security to false:
settings: per_endpoint_security: false2025-10-10
Section titled “2025-10-10”Placeholder edition with no functional changes. This will be the default edition for new projects.
2025-10-08
Section titled “2025-10-08”The first top-level edition for our original base functionality. This will be the default edition used if the top-level edition property is not present.