> This page is for Build.

> 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.5` (48 languages under one id, English included; recommended), `simba-3.2` (English) 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

# Audio formats

Two request fields control the audio you receive. They are not alternatives —
one names a container, the other names a container *and* a sample rate *and* a
bitrate.

| Field           | Shape                      | Example         | Use when                                      |
| --------------- | -------------------------- | --------------- | --------------------------------------------- |
| `audio_format`  | container only             | `mp3`           | The default sample rate and bitrate are fine. |
| `output_format` | `codec_sampleRate_bitrate` | `mp3_24000_128` | You need a specific rate or bitrate.          |

`output_format` takes precedence over `audio_format` on
`POST /v1/audio/speech`, and over the `Accept` header on
`POST /v1/audio/stream`. Setting both is not an error; the more specific one
wins.

> **Note**
>
> `audio_format` accepts `wav`, `mp3`, `ogg`, `aac` and `pcm`, and defaults to
> `wav`. The default is not guaranteed to stay `wav` — pass the value you
> expect rather than relying on it.

## Every `output_format` value

All 23 values, as the API accepts them. Streaming takes the same set minus the
two `wav_*` entries. An invalid value returns `400` and lists what is accepted,
so this table is a convenience rather than the contract.

| Codec           | Values                                                                                            |
| --------------- | ------------------------------------------------------------------------------------------------- |
| PCM             | `pcm_8000`, `pcm_16000`, `pcm_22050`, `pcm_24000`, `pcm_44100`, `pcm_48000`                       |
| µ-law           | `ulaw_8000`                                                                                       |
| MP3 (22.05 kHz) | `mp3_22050_32`, `mp3_22050_64`, `mp3_22050_96`, `mp3_22050_128`, `mp3_22050_160`, `mp3_22050_192` |
| MP3 (24 kHz)    | `mp3_24000_32`, `mp3_24000_64`, `mp3_24000_96`, `mp3_24000_128`, `mp3_24000_160`, `mp3_24000_192` |
| Ogg             | `ogg_24000`                                                                                       |
| AAC             | `aac_24000`                                                                                       |
| WAV             | `wav_24000`, `wav_48000`                                                                          |

`pcm_*` and `ulaw_8000` are headerless: raw samples with nothing to tell a
player the rate. Whatever consumes them has to be told.

> **Note**
>
> 160 kbps is the ceiling an MP3 carries at 22.05 and 24 kHz, so `mp3_22050_160`
> and `mp3_24000_160` are the maximum-fidelity MP3 formats — there is no higher
> MP3 to ask for. `mp3_22050_192` and `mp3_24000_192` were always encoded at
> 160 kbps, and the response reports the `mp3_*_160` it actually delivered
> rather than echoing the 192 back. The two `mp3_*_160` formats are produced by
> the Simba 3 models; pairing one with a legacy Simba 1.6 model returns `400`.

> **Note**
>
> `wav_*` is not available on the streaming routes. Use
> [`POST /v1/audio/speech`](https://docs.speechify.ai/build/api-reference/v1/audio/speech) for WAV.

## Setting a format

#### Python

```python
import os

from speechify import Speechify

client = Speechify(token=os.environ["SPEECHIFY_API_KEY"])

# audio_format: the container, at its default rate and bitrate.
basic = client.audio.speech(
    input="Hello from the Speechify API.",
    voice_id="geffen_32",
    model="simba-3.2",
    audio_format="mp3",
)

# output_format: container, sample rate and bitrate together. It wins.
explicit = client.audio.speech(
    input="Hello from the Speechify API.",
    voice_id="geffen_32",
    model="simba-3.2",
    output_format="mp3_24000_128",
)

# The format actually encoded, which is not always the one requested.
print(explicit.output_format)
```

#### TypeScript

```typescript
import { SpeechifyClient } from "@speechify/api";

const client = new SpeechifyClient({ token: process.env.SPEECHIFY_API_KEY! });

// audio_format: the container, at its default rate and bitrate.
const basic = await client.audio.speech({
  input: "Hello from the Speechify API.",
  voice_id: "geffen_32",
  model: "simba-3.2",
  audio_format: "mp3",
});

// output_format: container, sample rate and bitrate together. It wins.
const explicit = await client.audio.speech({
  input: "Hello from the Speechify API.",
  voice_id: "geffen_32",
  model: "simba-3.2",
  output_format: "mp3_24000_128",
});

// The format actually encoded, which is not always the one requested.
console.log(explicit.output_format);
```

#### cURL

```bash
# audio_format: the container, at its default rate and bitrate.
curl -X POST "https://api.speechify.ai/v1/audio/speech" \
  -H "Authorization: Bearer $SPEECHIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":"Hello from the Speechify API.","voice_id":"geffen_32","model":"simba-3.2","audio_format":"mp3"}'

# output_format: container, sample rate and bitrate together. It wins.
curl -X POST "https://api.speechify.ai/v1/audio/speech" \
  -H "Authorization: Bearer $SPEECHIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":"Hello from the Speechify API.","voice_id":"geffen_32","model":"simba-3.2","output_format":"mp3_24000_128"}'

# Streaming: output_format overrides Accept, and the Content-Type
# on the response names the format that was served.
curl -sS -D - -o speech.pcm \
  -X POST "https://api.speechify.ai/v1/audio/stream" \
  -H "Authorization: Bearer $SPEECHIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: audio/mpeg" \
  -d '{"input":"Hello from the Speechify API.","voice_id":"geffen_32","model":"simba-3.2","output_format":"pcm_16000"}'
# -> Content-Type: audio/L16; rate=16000; channels=1
```

## Telephony

Twilio and LiveKit SIP expect 8 kHz µ-law or 16 kHz PCM, so `ulaw_8000` and
`pcm_16000` are the two formats worth reaching for. Match the rate your
transport expects — a mismatch is not an error, it is audio that plays at the
wrong speed and pitch.

> **Warning**
>
> **Check your pinned API version before using `pcm_16000`.** On a workspace
> pinned before `2026-09-30`, the Simba 3 models answer `pcm_16000` with 24 kHz
> samples labelled `rate=16000`, so a 16 kHz pipeline plays them 1.5x slow and
> pitched down.
>
> A workspace created on or after `2026-09-30` is already correct — new
> workspaces start at the newest version — and so is any workspace that has
> moved its pin. An older pin keeps the bytes it has always received, because an
> integration built against 24 kHz breaks the moment they change.
>
> On an older pin, either move the pin, or use `ulaw_8000`, or keep playing the
> audio at 24 kHz until you move. See the
> [changelog](https://docs.speechify.ai/build/changelog/2026/9/30) and the
> [API Versioning guide](https://docs.speechify.ai/build/guides/concepts/api-versioning) for reading and
> setting your version.

## Streaming and the `Accept` header

On `POST /v1/audio/stream` the `Accept` header selects a container when
`output_format` is absent:

| Container | `Accept`     | Response `Content-Type`         |
| --------- | ------------ | ------------------------------- |
| MP3       | `audio/mpeg` | `audio/mpeg`                    |
| Opus      | `audio/ogg`  | `audio/ogg`                     |
| AAC       | `audio/aac`  | `audio/aac`                     |
| PCM       | `audio/pcm`  | `audio/L16; rate=…; channels=1` |

Those default to 24 kHz mono, and MP3 without a named bitrate resolves to
128 kbps. Send `output_format` when you need anything else — it overrides the
header. The resolved default is not part of the contract, so name the
`output_format` you want if your pipeline depends on it.

Streaming has no JSON envelope to report the format back in: the response body
is the audio, and the `Content-Type` is what tells you the format that was
served. It follows the `Accept` header, except raw PCM, which returns
`audio/L16` with `rate` and `channels` parameters, and µ-law, which returns
`audio/basic`.

`POST /v1/audio/speech` does report it. Its JSON response echoes
`output_format` when — and only when — the request set one, and reports the
format actually encoded — which is the requested
value unless the request named a bitrate above the MP3 ceiling, where it names
the bitrate delivered. Read the delivered format from there, not from what you
sent.