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

# Text to Speech

> Text-to-speech, speech-to-text, voice management, and real-time streaming audio APIs.

# Audio Generation

Mesh API provides a full suite of audio endpoints — convert text to speech, transcribe audio files, stream TTS/STT in real time, and browse available voices — all through a single API key.

All endpoints share the same base URL: `https://api.meshapi.ai/v1/audio`

**Auth:** `Authorization: Bearer rsk_<your-key>` on all REST requests. WebSocket endpoints accept the key via `Sec-WebSocket-Protocol: Bearer <rsk_...>` or `?api_key=<rsk_...>`.

***

## Text-to-Speech

`POST /v1/audio/speech`

Convert a text string into audio. The brand behind a model (ElevenLabs, Sarvam, etc.) is selected automatically based on the model you pass — models like `hexgrad/kokoro-82m` and `cartesia/sonic-2` are also available. Streaming is enabled by default.

### Request body

| Field                        | Type    | Default             | Description                                                                                                                                                                                                                |
| :--------------------------- | :------ | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`                      | string  | `eleven_flash_v2_5` | Model ID. Determines which provider handles the request.                                                                                                                                                                   |
| `input`                      | string  | —                   | Text to synthesize. **Required.**                                                                                                                                                                                          |
| `voice`                      | string  | —                   | Voice ID/name for the selected model's brand (an ElevenLabs voice ID, or a Kokoro/Cartesia voice). Browse valid IDs with `GET /v1/audio/voices` (filter by `brand`, `model`, or `search`). Required for ElevenLabs models. |
| `speaker`                    | string  | `anushka`           | Speaker name for Sarvam models. Ignored for ElevenLabs.                                                                                                                                                                    |
| `stream`                     | boolean | `true`              | Stream audio chunks as they are generated.                                                                                                                                                                                 |
| `response_format`            | string  | provider default    | Output audio format (e.g. `mp3_44100_128`, `pcm_22050`, `wav_44100`).                                                                                                                                                      |
| `language_code`              | string  | —                   | BCP-47 language code (e.g. `en-US`).                                                                                                                                                                                       |
| `voice_settings`             | object  | —                   | Fine-tune ElevenLabs voice: `stability`, `similarity_boost`, `style`, `use_speaker_boost`, `speed`.                                                                                                                        |
| `seed`                       | integer | —                   | Reproducible generation seed.                                                                                                                                                                                              |
| `previous_text`              | string  | —                   | Text that came before `input` — used for better prosody.                                                                                                                                                                   |
| `next_text`                  | string  | —                   | Text that comes after `input` — used for better prosody.                                                                                                                                                                   |
| `apply_text_normalization`   | string  | —                   | `auto`, `on`, or `off`. Controls ElevenLabs text normalizer.                                                                                                                                                               |
| `enable_logging`             | boolean | —                   | Pass `false` to opt out of ElevenLabs request logging.                                                                                                                                                                     |
| `optimize_streaming_latency` | integer | —                   | ElevenLabs latency-quality trade-off level (0–4).                                                                                                                                                                          |
| `pitch`                      | float   | —                   | Sarvam pitch adjustment.                                                                                                                                                                                                   |
| `pace`                       | float   | —                   | Sarvam speaking pace.                                                                                                                                                                                                      |
| `loudness`                   | float   | —                   | Sarvam output loudness.                                                                                                                                                                                                    |
| `target_language_code`       | string  | `hi-IN`             | Sarvam target language.                                                                                                                                                                                                    |

### Supported output formats

**Streaming (`stream: true`):** `mp3_22050_32`, `mp3_24000_48`, `mp3_44100_32/64/96/128/192`, `pcm_8000/16000/22050/24000/32000/44100/48000`, `ulaw_8000`, `alaw_8000`, `opus_48000_32/64/96/128/192`

**Non-streaming (`stream: false`):** All of the above, plus `wav_8000/16000/22050/24000/32000/44100/48000`

### Response

The response body is raw audio bytes with the `Content-Type` matching the requested format (e.g. `audio/mpeg`, `audio/wav`).

### Examples

<Tabs>
  <Tab title="curl (streaming)">
    ```bash theme={null}
    curl -X POST https://api.meshapi.ai/v1/audio/speech \
      -H "Authorization: Bearer rsk_..." \
      -H "Content-Type: application/json" \
      -d '{
        "model": "eleven_flash_v2_5",
        "input": "Hello! This is a test of the Mesh API text-to-speech endpoint.",
        "voice": "JBFqnCBsd6RMkjVDRZzb",
        "response_format": "mp3_44100_128"
      }' \
      --output speech.mp3
    ```
  </Tab>

  <Tab title="curl (non-streaming WAV)">
    ```bash theme={null}
    curl -X POST https://api.meshapi.ai/v1/audio/speech \
      -H "Authorization: Bearer rsk_..." \
      -H "Content-Type: application/json" \
      -d '{
        "model": "eleven_flash_v2_5",
        "input": "Hello! This is a test.",
        "voice": "JBFqnCBsd6RMkjVDRZzb",
        "stream": false,
        "response_format": "wav_44100"
      }' \
      --output speech.wav
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import httpx

    response = httpx.post(
        "https://api.meshapi.ai/v1/audio/speech",
        headers={"Authorization": "Bearer rsk_..."},
        json={
            "model": "eleven_flash_v2_5",
            "input": "Hello! This is a test.",
            "voice": "JBFqnCBsd6RMkjVDRZzb",
            "response_format": "mp3_44100_128",
        },
    )
    with open("speech.mp3", "wb") as f:
        f.write(response.content)
    ```
  </Tab>

  <Tab title="Node.js">
    ```ts theme={null}
    import fs from "fs";

    const res = await fetch("https://api.meshapi.ai/v1/audio/speech", {
      method: "POST",
      headers: {
        Authorization: "Bearer rsk_...",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        model: "eleven_flash_v2_5",
        input: "Hello! This is a test.",
        voice: "JBFqnCBsd6RMkjVDRZzb",
        response_format: "mp3_44100_128",
      }),
    });

    const buffer = await res.arrayBuffer();
    fs.writeFileSync("speech.mp3", Buffer.from(buffer));
    ```
  </Tab>
</Tabs>

***

## WebSocket TTS Streaming

`WS /v1/audio/speech/stream/{voice_id}`

Stream text-to-speech in real time. You send text chunks as they become available (e.g. as an LLM streams tokens), and receive audio back chunk by chunk — minimising latency compared to the REST endpoint. The streaming frame protocol depends on the model family. The `voice_id` is part of the URL path.

* **Standard streaming models** — e.g. `hexgrad/kokoro-82m`, `cartesia/sonic-2`, `cartesia/sonic-3`, `canopylabs/orpheus-3b-0.1-ft` — use the text-buffer protocol.
* **ElevenLabs models** (`elevenlabs/*`) use ElevenLabs' native stream-input frames.

### Authentication

Pass your Mesh API key in one of two ways:

* `Sec-WebSocket-Protocol: Bearer rsk_...` header
* `?api_key=rsk_...` query parameter

### Query parameters

| Parameter       | Default             | Description                                                   |
| :-------------- | :------------------ | :------------------------------------------------------------ |
| `model_id`      | `eleven_flash_v2_5` | Model to use. Determines the streaming frame protocol.        |
| `output_format` | `pcm_22050`         | Audio format for streamed audio. See supported formats below. |
| `language_code` | —                   | BCP-47 language code.                                         |

<Note>
  ElevenLabs models additionally accept `enable_logging` (`true`/`false` logging opt-out), `enable_ssml_parsing` (enable SSML in the input text), `inactivity_timeout` (seconds of inactivity before the session closes, 1–180), `sync_alignment` (return word-level alignment data with each audio chunk), `auto_mode` (optimise for low-latency, fully-automated generation), `apply_text_normalization` (`auto`, `on`, or `off`), and `seed` (reproducible seed, 0–4294967295).
</Note>

### Message protocol — standard streaming models

**Client → server (JSON frames)**

| Frame type                 | Fields         | Description                            |
| :------------------------- | :------------- | :------------------------------------- |
| `input_text_buffer.append` | `text: string` | Append a chunk of text to the buffer.  |
| `input_text_buffer.commit` | `{}`           | Flush the buffer and finish synthesis. |

**Server → client (JSON frames)**

| Frame type                             | Fields                   | Description                                             |
| :------------------------------------- | :----------------------- | :------------------------------------------------------ |
| `conversation.item.audio_output.delta` | `delta: string` (base64) | Audio chunk. Decode from base64 to get raw audio bytes. |
| `conversation.item.audio_output.done`  | `{}`                     | Signals all audio has been sent.                        |

#### Example

```js theme={null}
const ws = new WebSocket(
  "wss://api.meshapi.ai/v1/audio/speech/stream/af_bella" +
    "?model_id=hexgrad/kokoro-82m&output_format=pcm_24000&api_key=rsk_..."
);

ws.onopen = () => {
  // 1. Append text chunks
  ws.send(
    JSON.stringify({
      type: "input_text_buffer.append",
      text: "Hello, this is streamed text-to-speech.",
    })
  );

  // 2. Flush + finish
  ws.send(JSON.stringify({ type: "input_text_buffer.commit" }));
};

ws.onmessage = ({ data }) => {
  const frame = JSON.parse(data);
  if (frame.type === "conversation.item.audio_output.delta") {
    // Decode base64 audio and play / write to file
    const audioBytes = atob(frame.delta);
    console.log(`Received ${audioBytes.length} bytes of audio`);
  }
  if (frame.type === "conversation.item.audio_output.done") {
    console.log("Stream complete");
    ws.close();
  }
};
```

### Message protocol — ElevenLabs models

**Client → server (JSON frames)**

| Frame type             | Fields                                                                                           | Description                                        |
| :--------------------- | :----------------------------------------------------------------------------------------------- | :------------------------------------------------- |
| `initializeConnection` | `text: " "`, optional `voice_settings`, `generation_config`, `pronunciation_dictionary_locators` | Must be the first message sent.                    |
| `sendText`             | `text: string`, optional `try_trigger_generation`, `voice_settings`, `flush`                     | Send a chunk of text to synthesize.                |
| `closeConnection`      | `text: ""`                                                                                       | Signal end of input and close the session cleanly. |

**Server → client (JSON frames)**

| Frame type    | Fields                                         | Description                                              |
| :------------ | :--------------------------------------------- | :------------------------------------------------------- |
| `AudioOutput` | `audio: string` (base64), optional `alignment` | Audio chunk. Decode from base64 to get raw audio bytes.  |
| `FinalOutput` | `isFinal: true`                                | Signals all audio has been sent.                         |
| `error`       | `message: string`                              | Sent before closing on auth, format, or upstream errors. |

<Note>
  Any credential fields (`xi-api-key`, `authorization`, `api_key`) in client frames are stripped before forwarding upstream — your upstream credentials are never exposed to the client.
</Note>

#### Example

```js theme={null}
const ws = new WebSocket(
  "wss://api.meshapi.ai/v1/audio/speech/stream/JBFqnCBsd6RMkjVDRZzb" +
    "?model_id=eleven_flash_v2_5&output_format=mp3_44100_128&api_key=rsk_..."
);

ws.onopen = () => {
  // 1. Initialize the connection
  ws.send(JSON.stringify({ text: " " }));

  // 2. Stream text chunks
  ws.send(JSON.stringify({ text: "Hello, this is streamed text-to-speech." }));

  // 3. Close when done
  ws.send(JSON.stringify({ text: "" }));
};

ws.onmessage = ({ data }) => {
  const frame = JSON.parse(data);
  if (frame.audio) {
    // Decode base64 audio and play / write to file
    const audioBytes = atob(frame.audio);
    console.log(`Received ${audioBytes.length} bytes of audio`);
  }
  if (frame.isFinal) {
    console.log("Stream complete");
    ws.close();
  }
};
```

### Supported output formats

**ElevenLabs models:** `mp3_22050_32`, `mp3_44100_32/64/96/128/192`, `pcm_16000/22050/24000/44100`, `ulaw_8000`

**Standard streaming models:** `pcm`, `mp3`, `wav`, `opus`, `aac`, `flac`, each with an optional sample rate (e.g. `pcm_24000`).

***

***

## Together AI voices

Together-hosted TTS models (Kokoro, Orpheus, Cartesia Sonic) don't use the ElevenLabs voice catalogue — each model has its own set of voices passed in the same `voice` field. The `/v1/audio/voices` endpoint lists ElevenLabs voices only; use the references below for Together models.

### Kokoro — `hexgrad/kokoro-82m`

Pass a voice name such as `af_bella`. Kokoro also supports **voice mixing**: join two or more voices with `+` (e.g. `af_bella+af_heart`), with optional per-voice weights in parentheses (e.g. `af_bella(2)+af_heart(1)`).

A selection of the 50+ available voices (prefix key: `a`=American, `b`=British, `j`=Japanese, `z`=Chinese, `e`=Spanish, `f`=French, `h`=Hindi, `i`=Italian, `p`=Portuguese; `f`=female, `m`=male):

```
af_heart  af_bella  af_nova   af_sarah  af_sky   am_adam   am_echo  am_michael
am_onyx   am_puck   bf_emma   bf_alice  bf_lily  bm_george bm_lewis bm_daniel
jf_alpha  jm_kumo   zf_xiaoxiao zm_yunxi ef_dora  ff_siwis  hf_alpha hm_omega
```

### Orpheus — `canopylabs/orpheus-3b-0.1-ft`

One of: `tara`, `leah`, `jess`, `leo`, `dan`, `mia`, `zac`, `zoe`.

### Cartesia Sonic — `cartesia/sonic-2`, `cartesia/sonic-3`

Pass the voice **display name** (not a voice ID). 130+ voices are available; a selection of English voices:

```
friendly sidekick   nonfiction man   newsman          newslady       calm lady
helpful woman       reading lady     reading man      british reading lady
british narration lady   meditation lady   new york man   indian lady   indian man
```

```json theme={null}
{
  "model": "cartesia/sonic-3",
  "input": "Hello from Cartesia Sonic.",
  "voice": "friendly sidekick"
}
```

<Info>
  **Streaming with Together models.** When `stream: true`, Together TTS models only emit raw PCM — set `response_format` to a `pcm_*` value (e.g. `pcm_16000`, `pcm_24000`). For non-streaming requests (`stream: false`) you can also use `mp3_*` or `wav_*`.
</Info>

## Available voices

List available voices (ElevenLabs voices):

```bash theme={null}
curl https://api.meshapi.ai/v1/audio/voices \
  -H "Authorization: Bearer rsk_YOUR_KEY"
```

You can filter and search using query parameters:

| Parameter         | Description                                         |
| ----------------- | --------------------------------------------------- |
| `search`          | Full-text search string                             |
| `page_size`       | Number of results per page (1–100)                  |
| `next_page_token` | Pagination cursor from previous response            |
| `voice_type`      | Filter by voice type                                |
| `category`        | Filter by voice category                            |
| `voice_ids`       | Comma-separated list of specific voice IDs to fetch |
| `sort`            | Sort field                                          |
| `sort_direction`  | Sort direction                                      |

**Response:**

```json theme={null}
{
  "voices": [
    {"voice_id": "EXAVITQu4vr4xnSDxMaL", "name": "Sarah", ...},
    {"voice_id": "AZnzlk1XvdvUeBnXmlld", "name": "Brian", ...}
  ],
  "has_more": false,
  "next_page_token": null,
  "total_count": 2
}
```

## Available models

| Model                          | Provider | Notes                                          |
| ------------------------------ | -------- | ---------------------------------------------- |
| `openai/tts-1`                 | OpenAI   | Fast, standard quality                         |
| `openai/tts-1-hd`              | OpenAI   | Higher quality, slower                         |
| `sarvam/bulbul:v3`             | Sarvam   | Indian languages (Hindi, Tamil, Telugu, etc.)  |
| `hexgrad/kokoro-82m`           | Together | Open-weight, 50+ voices, supports voice mixing |
| `canopylabs/orpheus-3b-0.1-ft` | Together | Expressive English voices                      |
| `cartesia/sonic-2`             | Together | Cartesia Sonic 2 — 130+ voices                 |
| `cartesia/sonic-3`             | Together | Cartesia Sonic 3 (latest) — 130+ voices        |

<Info>
  Together TTS voices are passed in the `voice` field but follow each model's own naming — see [Together AI voices](#together-ai-voices) above.
</Info>
