---
title: "Synthesize speech (streaming, in any of 15 audio formats)"
method: POST
path: "/v1/audio/speech"
tags: ["audio"]
---

# Synthesize speech (streaming, in any of 15 audio formats)

`POST /v1/audio/speech`

## Request

- Base URL: `https://api.ditto.audio` (the document declares no server; this is the origin it was published from)
- URL: `https://api.ditto.audio/v1/audio/speech`
- Auth: HTTP bearer

Returns audio bytes. With `stream: true` (the default) the body uses chunked transfer-encoding and bytes are written as the model produces them, so you can start playing before synthesis finishes. The whole response is ONE continuous file from ONE encoder — concatenate the chunks, do not decode them individually.

Audio defaults to MPEG-2 Layer III (MP3), 24 kHz, mono, 128 kbps, with no Xing/LAME header and no ID3 tag — the body starts at the first audio frame. Set `response_format` for anything else: mp3, mp3_64, mp3_160, wav, wav24, wav32f, flac, flac24, pcm, pcm_f32, aiff, caf, au, mulaw, alaw. The exact numbers for a given response are echoed in the `X-Ditto-Audio-*` headers; decode and resample from those rather than assuming a rate. GET /v1/audio/format describes every encoding in full, without authentication.

**Streaming and container headers.** Formats that carry a length field (`wav`, `aiff`, `caf`, `au`, `flac`) write the format’s own UNKNOWN-length value while streaming, because a chunked body cannot be seeked back to and patched. Send `stream: false` for exact sizes, a `Content-Length`, and — for `flac` — a real MD5 in STREAMINFO. The samples are identical either way.

**Cost.** Hi-fidelity formats bill at 1.2× the normal rate, multiplied by the model’s own weighting — the audio is identical, but the bytes are several times larger. `mp3` (the default), `mp3_64`, `mulaw` and `alaw` are unchanged at 1×. Each format’s exact multiplier is in GET /v1/audio/format and in the `X-Ditto-Audio-Cost-Multiplier` response header.

Aborting the request closes the connection and STOPS server-side generation — cancelling actually saves inference, it does not just stop you reading.

The language actually used is echoed in `X-Ditto-Language`, with `X-Ditto-Language-Inferred: true` when it was detected from `input` rather than supplied.

Every response carries `X-Ditto-Quota-Limit`, `-Used`, `-Remaining`, `-Percent` and `-Reset` — billed SECONDS of audio, weighted per model (Kokoro 1.5×, XTTS 3×) and per format — so you can watch the allowance drain without a separate call. Omitted entirely for unmetered accounts.

## Request body

- SpeechDto
  - `model` 'kokoro' | 'xtts' | 'pocket', required: Model family. `kokoro` is fast and English-leaning; `xtts` is multilingual and voice-cloned; `pocket` is English voice cloning from a short reference clip.
  - `voice` string, required: Voice id from GET /v1/audio/voices. Must belong to `model`.
  - `input` string, required: The text to speak.
  - `language` string: BCP-47-ish language tag; see GET /v1/audio/languages. AUTHORITATIVE for this request — it overrides the voice’s native language, which is how one XTTS voice speaks many languages. Omit it and we infer the language from `input` (the answer comes back in the X-Ditto-Language header).
  - `response_format` 'mp3' | 'mp3_64' | 'mp3_160' | 'wav' | 'wav24' | 'wav32f' | 'flac' | 'flac24' | 'pcm' | 'pcm_f32' | 'aiff' | 'caf' | 'au' | 'mulaw' | 'alaw': Audio encoding. Defaults to `mp3` (MPEG-2 Layer III, 24 kHz mono, 128 kbps). **Lossy, standard rate:** `mp3`, `mp3_64`, `mulaw`, `alaw`. **Lossless or uncompressed, 1.2× rate:** `flac`, `flac24`, `wav`, `wav24`, `wav32f`, `pcm`, `pcm_f32`, `aiff`, `caf`, `au`, `mp3_160`. `flac` is the one to pick for quality: lossless, and roughly half the size of `wav`. `wav32f` and `pcm_f32` are bit-exact with what the model produced; everything else quantizes those floats first. `pcm`/`pcm_f32` are HEADERLESS raw samples, not files. Common spellings are accepted (`pcm_s16le`, `L16`, `.wav`, `u-law`, `aif`). `opus`, `aac` and `ogg` are NOT produced — the response says what to use instead. Hi-fidelity formats bill at 1.2× the normal rate, multiplied by the model’s own weighting — the audio is identical, but the bytes are several times larger. `mp3` (the default), `mp3_64`, `mulaw` and `alaw` are unchanged at 1×. Each format’s exact multiplier is in GET /v1/audio/format and in the `X-Ditto-Audio-Cost-Multiplier` response header. See GET /v1/audio/format.
  - `stream` boolean: true (default): chunked transfer-encoding, bytes written as the model produces them. false: one buffered body with Content-Length.
  - `speed` number: Speaking rate; >1 is faster.
  - `pauses` PausesDto
    - `sentence` number: Milliseconds after a sentence (. ! ? …). Setting it sends every sentence as its own engine call, so EVERY sentence boundary gets exactly this pause instead of the model’s own.
    - `clause` number: Milliseconds where a sentence too long for one engine call is cut at a comma, semicolon, colon or dash. Commas inside a call are paced by the model and are not affected.
    - `paragraph` number: Milliseconds at a blank line in `input`.

## Response `200`

Raw audio bytes (no envelope, no SSE framing) in the requested `response_format`. Chunked unless `stream:false`. Defaults to MPEG-2 Layer III, 24000 Hz, mono — the actual encoding is echoed in the `X-Ditto-Audio-*` headers below.

## Other responses

- `400`: UNKNOWN_VOICE / VOICE_MODEL_MISMATCH / UNKNOWN_LANGUAGE / UNSUPPORTED_LANGUAGE / UNSUPPORTED_FORMAT / INPUT_TOO_LONG.
- `401`: Missing, malformed, revoked or expired credential.
- `402`: QUOTA_EXCEEDED — monthly allowance exhausted. Billed in seconds of audio weighted per model (Kokoro 1.5×, XTTS 3×) and per format (hi-fidelity 1.2×). NOT retryable until `resetsAt`; see GET /v1/usage/quota.
- `403`: Key lacks the `audio:speech` scope.
- `429`: Rate limited (60/min per account). Retry after the number of seconds in the `Retry-After` header.
- `503`: NODE_UNAVAILABLE — no inference capacity right now.

---

[API](https://skmtc.dev/ditto/apis/ditto-audio-api.md) · [All operations](https://skmtc.dev/ditto/apis/ditto-audio-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ditto/apis/ditto-audio-api/revisions/30c8d7c218da?raw)
