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

# Speech (OpenAI-compatible)

> Use Bland voices through the OpenAI text-to-speech request and error shapes.

## Overview

This endpoint implements OpenAI's `/audio/speech` contract. If you already use an OpenAI SDK or a compatible router such as LiteLLM, change the base URL, API key, and model to route speech through Bland.

```python theme={null}
import os
from pathlib import Path

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["BLAND_API_KEY"],
    base_url="https://api.bland.ai/v2",
)

with client.audio.speech.with_streaming_response.create(
    model="btts-3",
    voice="coral",
    input="Hello from Bland.",
) as response:
    response.stream_to_file(Path("hello.mp3"))
```

For LLM tokens, interruptions, and the lowest conversational latency, use [Realtime Speech (WebSocket)](https://docs.bland.ai/api-v2/post/tts-ws.md). For a complete input string with Bland-specific audio controls, use [Synthesize Speech (HTTP)](https://docs.bland.ai/api-v2/post/tts.md).

## Headers

**authorization** `string` *required*

`Bearer <your API key>`. OpenAI SDKs send this from their `api_key` or `apiKey` configuration.

## Body parameters

**model** `string` *required*

`btts-3` or `btts-2`.

OpenAI model IDs such as `tts-1` and `gpt-4o-mini-tts` are not aliased. Unknown IDs return `400` with code `model_not_found`.

The model must match the selected Bland voice. A mismatch returns `400` with code `model_voice_mismatch`.

**input** `string` *required*

Non-empty text to speak. Maximum 4,096 characters.

**voice** `string` *required*

A recognized OpenAI voice name, mapped to a Bland core voice, or a Bland voice UUID for the full catalog.

| OpenAI name | Bland voice |
| - | - |
| `alloy`, `ash`, `coral`, `fable` | River |
| `amber`, `august`, `lily`, `nova`, `shimmer` | Karen |
| `ballad`, `blue`, `echo`, `onyx`, `sage`, `verse` | Matthew |

Names are case-insensitive. An unrecognized name returns `400`.

**response\_format** `string` (default: mp3)

`mp3`, `opus`, `aac`, `flac`, `wav`, or `pcm`.

`pcm` is raw 24 kHz signed 16-bit little-endian mono audio. The other formats use a 48 kHz render and include their normal file or stream framing.

**speed** `number` (default: 1.0)

Only `1.0` is accepted. Other values return `400` because Bland does not currently expose speed control on this endpoint.

**stream\_format** `string` (default: audio)

Only `audio` is supported. `sse` returns `400`.

**instructions** `string`

Accepted and ignored. This OpenAI field has no Bland equivalent.

## Response

The response body contains audio bytes. `Content-Type` matches the requested format:

| `response_format` | `Content-Type` |
| - | - |
| `mp3` | `audio/mpeg` |
| `opus` | `audio/ogg` |
| `aac` | `audio/aac` |
| `flac` | `audio/flac` |
| `wav` | `audio/wav` |
| `pcm` | `audio/pcm` |

MP3, Opus, AAC, FLAC, and raw PCM can begin streaming before synthesis completes. WAV is buffered until its final RIFF header length is known.

**x-request-id** `string`

Unique request ID. Include it in support requests.

## Errors

Errors use OpenAI's envelope so SDK error handling remains readable:

```json theme={null}
{
  "error": {
    "message": "The model 'tts-1' does not exist. Supported models: btts-3, btts-2.",
    "type": "invalid_request_error",
    "param": "model",
    "code": "model_not_found"
  }
}
```

| Condition | HTTP | Code |
| - | - | - |
| Missing or malformed field | 400 | `null` |
| Unknown model | 400 | `model_not_found` |
| Model does not match the selected voice | 400 | `model_voice_mismatch` |
| Unsupported voice type | 400 | `null` |
| Out of credits | 402 | `insufficient_quota` |
| Professional voice is still a draft | 403 | `voice_not_live` |
| Voice UUID is not found or accessible | 404 | `voice_not_found` |
| Synthesis fails before audio begins | 500 | `synthesis_failed` |

## Examples

```bash cURL theme={null}
curl -X POST "https://api.bland.ai/v2/audio/speech" \
  -H "Authorization: Bearer $BLAND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "btts-3",
    "input": "Hello from Bland.",
    "voice": "coral",
    "response_format": "mp3"
  }' \
  --output hello.mp3
```

```python OpenAI SDK theme={null}
import os
from pathlib import Path

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["BLAND_API_KEY"],
    base_url="https://api.bland.ai/v2",
)

with client.audio.speech.with_streaming_response.create(
    model="btts-3",
    voice="coral",
    input="Hello from Bland.",
) as response:
    response.stream_to_file(Path("hello.mp3"))
```

```python LiteLLM theme={null}
import os

import litellm

litellm.speech(
    model="openai/btts-3",
    voice="coral",
    input="Hello from Bland.",
    api_base="https://api.bland.ai/v2",
    api_key=os.environ["BLAND_API_KEY"],
)
```

```js Node.js theme={null}
import fs from "node:fs/promises";
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.BLAND_API_KEY,
  baseURL: "https://api.bland.ai/v2",
});

const response = await client.audio.speech.create({
  model: "btts-3",
  voice: "coral",
  input: "Hello from Bland.",
});

await fs.writeFile("hello.mp3", Buffer.from(await response.arrayBuffer()));
```

***

Docs for agents: [llms.txt](https://docs.bland.ai/llms.txt)


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