> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thinnest.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# The API

> Stream Aero TTS from https://tts.thinnest.ai: OpenAI-compatible, a native endpoint, and a WebSocket.

* **Host:** every request goes to `https://tts.thinnest.ai`.
* **Key:** use a **full-access** API key from **Settings → API keys**, sent as `Authorization: Bearer <key>`. A build
  or read-only key cannot speak, because speech spends money.
* **A developer acting for a customer:** add `X-Workspace: <customer id>`, as on the rest of the API.

## OpenAI-compatible: `POST /v1/audio/speech`

This takes the same request as OpenAI's speech API, so OpenAI SDKs and the tools built on them work with two changes:
the base URL `https://tts.thinnest.ai/v1` and your key.

```bash theme={null}
curl https://tts.thinnest.ai/v1/audio/speech \
  -H "Authorization: Bearer $THINNEST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "aero-tts", "voice": "anvi", "input": "नमस्ते! आपका ऑर्डर कल पहुँच जाएगा।", "response_format": "mp3"}' \
  --output speech.mp3
```

| Field | Values |
| - | - |
| `model` | `aero-tts` (`tts-1` and `gpt-4o-mini-tts` are accepted as the same) |
| `voice` | A voice id, such as `anvi` or `arjun`, or one of your cloned voices. OpenAI's names (`alloy`, `nova`, `echo`, `onyx` and the rest) are accepted and speak as Anvi or Arjun |
| `input` | Up to 4,000 characters |
| `response_format` | `mp3` (default), `opus`, `wav`, `pcm` (24 kHz, 16-bit, mono) |
| `speed` | `1.0` only, for now |
| `language` | Optional, not in OpenAI's schema: a code such as `hi`. Leave it out and the script decides |

## Native: `POST /v1/speech`

This adds what OpenAI's shape cannot carry: 8 and 16 kHz output, and mu-law for phone lines.

```json theme={null}
{ "text": "...", "voice": "anvi", "language": "auto", "format": "mulaw", "sample_rate": 8000 }
```

* **`format`:** `pcm`, `wav`, `mulaw`, `mp3` or `opus`.
* **`sample_rate`:** `8000`, `16000` or `24000`. mp3 and opus are 24000 only.
* **Streaming:** audio streams back as it is made.
* **Headers:** the response carries `X-Request-Id`, `X-Characters` (what the request counted, free or charged), and
  `X-Concurrency-Limit` and `X-Concurrency-In-Use`.

## WebSocket: `wss://tts.thinnest.ai/v1/stream`

One connection carries many utterances, each with an `id`, and each can be cancelled mid-sentence. Use it for live
conversations.

| You send | We send |
| - | - |
| `{"type":"speak","id":"u1","text":"...","voice":"anvi","format":"pcm","sample_rate":24000}` | `{"type":"audio","id":"u1","audio":"<base64>"}` for each chunk |
| `{"type":"cancel","id":"u1"}` | then exactly one `{"type":"end","id":"u1","chars":42}` or `{"type":"error",...}` |
| `{"type":"ping"}` | `{"type":"pong"}` |

To get raw bytes instead of base64, add `"binary": true`. Each frame is then: 1 byte for the id's length, the id, then
the audio.

Browsers cannot send an `Authorization` header on a WebSocket, so connect from your server.

## Voices

`GET https://app.thinnest.ai/api/v1/tts/voices` lists the catalogue.

## Errors

| Status | Code | What to do |
| - | - | - |
| 400 | `validation_failed` | Fix the field the message names |
| 401 | `unauthorized` | Check the key |
| 402 | `insufficient_balance` | Your free characters and wallet are used up. Add money to your wallet |
| 403 | `not_available` | Aero TTS is not on for this workspace, for example one billed in another currency |
| 429 | `concurrency_limit` | Your plan's requests-at-once limit: retry after one finishes |
| 429 | `rate_limited` | Over 600 requests a minute: slow down |
| 503 | `overloaded` | Briefly busy: retry after `Retry-After` |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.