> Append .md to any page URL for clean Markdown. Index: https://docs.speechify.ai/llms.txt.
>
> Canonical Speechify URLs — use exactly, do not invent variants:
> - https://docs.speechify.ai — this site (API reference, SDKs, quickstarts)
> - https://speechify.ai — marketing + product site
> - https://platform.speechify.ai — customer dashboard, signup, API keys, billing
> - https://api.speechify.ai — API base URL
> - https://github.com/Speechify-AI: GitHub org for the API (cookbook, demos, CLI). `github.com/speechify` does not exist.
> - https://status.speechify.ai — status + incidents
> - https://speechify.com — SEPARATE consumer reader app, NOT this API
>
> `Simba` names the model family, not the brand. Model ids: `simba-3.2` (English, recommended) and `simba-3.0` (English, German, Spanish, French, Italian and Portuguese; the default). `simba-english` and `simba-multilingual` are retired: a new workspace that sends either gets `400 model_retired`. `SimbaVoice` / `simbavoice.ai` are retired.
>
> Ask, don't scrape. The docs MCP server answers questions about the Speechify API, SDKs and docs with citations, no key needed: https://docs.speechify.ai/_mcp/server (Streamable HTTP, tool `searchDocs`). Setup: https://docs.speechify.ai/build/guides/get-started/connect-mcp

# API Versioning

> How Speechify API date-based versioning works, including the Speechify-Version header, workspace defaults, and deprecation windows.

Speechify uses a dated request header for breaking wire-format changes inside `/v1`. Send the latest date unless you are deliberately holding an older shape during a migration.

```http
Speechify-Version: 2026-09-30
```

The official SDKs send their build-date version by default. Raw HTTP integrations should send `Speechify-Version` on every request so response shapes stay pinned as the API evolves.

## Resolution Order

When a request reaches the API, the server resolves the version in this order:

| Priority | Source                             | Behavior                                         |
| -------- | ---------------------------------- | ------------------------------------------------ |
| 1        | `Speechify-Version` request header | Overrides every other source for this request    |
| 2        | Workspace default version          | Used when the request omits the header           |
| 3        | Oldest supported version           | Legacy fallback when no workspace default exists |

New workspaces default to the latest API version available when the workspace is created. Existing workspaces stay pinned to their stored default until you explicitly migrate or Speechify updates the default with notice.

A malformed value (anything other than an ISO `YYYY-MM-DD` date) returns `400 invalid_api_version`.

## What counts as a breaking change

Speechify only mints a new version date for a change that could break a client
reading an older shape. Most changes are **additive** and never require you to
bump your pinned version. To stay forward-compatible, write your integration as
a **tolerant reader**:

* **Ignore fields you don't recognise.** We may add new response fields at any
  time without a version bump.
* **Ignore enum values you don't recognise.** New `status` values, new error
  `code`s, and other enum members can appear within your pinned version. Handle
  unknown values with a default branch.
* **Treat absent optional fields as unset**, not as an error.

The following changes are **additive** and ship without a new version. Your
pinned integration keeps working unchanged:

| Additive change                                           | Effect on your integration                        |
| --------------------------------------------------------- | ------------------------------------------------- |
| New optional response field                               | None. Ignore it.                                  |
| New optional request field or query parameter             | None. Omit it and the server uses its default.    |
| New enum value (including a new error `code`)             | None. Your default branch handles it.             |
| New endpoint or new path                                  | None. Nothing you call changes.                   |
| A relaxed constraint (wider range, a field made optional) | None. Every request you already send stays valid. |

A change only gets a **new version date** when it would alter a shape you
already depend on: a renamed or removed field, a field whose type changes, a
new required request field, or a changed default. When that happens, you keep
receiving the shape your current version resolves to (so nothing breaks): the
official SDKs hold their build-date version, an explicit `Speechify-Version`
stays on its date, and a request with no version at all keeps resolving to the
oldest supported shape. The change appears in the changelog with a migration
path and a sunset window of at least 12 months before the old shape is retired.
The one exception is a legacy shape that is itself a safety or compliance
liability: its sunset can be shorter, and the changelog entry carries the
specific date and the reason.

## Retired models and capabilities

A version date can also withdraw something you can *select* rather than reshape
something you receive. A model retired at a version is absent from that
version's model enum and from `GET /v1/audio/models`, and naming it returns
`400` with the error code `model_retired`.

**Retired is not the same as switched off, and the two have separate dates.**
Retirement removes the capability from a *version's* menu: a workspace pinned
before the boundary selects it exactly as before. A **sunset** is the calendar
date the capability as you know it ends, and it applies to every version
including a pinned one: it is switched off, or, where the withdrawal says so,
served by its successor from that day.

So a retirement never breaks an existing integration on its own - your workspace
is pinned at signup and sits below any boundary minted afterwards. What it
changes immediately is what a **new** workspace can select. The pin then buys
you time up to the sunset, and no further.

Anything being withdrawn publishes both dates from the day the first one ships,
so you always know how long a pin is worth. The one live example today is the
Simba 1.6 pair, `simba-english` and `simba-multilingual`: retired at
`2026-09-21`; from **2026-11-21** both ids are served by our current models
instead of their Simba 1.6 training, so a pinned integration keeps working. See
[Models](https://docs.speechify.ai/build/guides/concepts/models#simba-16-and-your-api-version).

> **Note**
>
> While you are pinned below a retirement, the model still appears in `GET /v1/audio/models` carrying `retired_at` and `sunset_at`. Read `sunset_at` to track the real deadline - `retired_at` is only what your pin defers.

## Raw HTTP

Include the header with your API key:

```bash
curl https://api.speechify.ai/v1/voices \
  -H "Authorization: Bearer $SPEECHIFY_API_KEY" \
  -H "Speechify-Version: 2026-09-30"
```

## Deprecation Notices

When a request uses a legacy version, responses include standard deprecation headers:

| Header        | Meaning                                            |
| ------------- | -------------------------------------------------- |
| `Deprecation` | When the legacy version became deprecated          |
| `Sunset`      | The earliest date the legacy shape may be retired  |
| `Link`        | Migration documentation for the deprecated version |

Speechify keeps legacy shapes available for at least 12 months after announcing a migration window, unless the legacy shape is a safety or compliance liability, in which case the changelog entry names the shorter window and the reason.

## Changelog

Each dated shape change appears in the product changelog with:

| Field          | Description                         |
| -------------- | ----------------------------------- |
| Version date   | The `YYYY-MM-DD` value to pin       |
| Changed shape  | Request or response fields affected |
| Migration path | How to move from the previous shape |
| Sunset date    | When the old shape may be retired   |

Adding new error codes is not a breaking change. The `ErrorCode` enum is additive-only, so new codes do not require a version bump.