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

# Text to speech

> One endpoint, native and OpenAI-compatible

`POST /v1/audio/speech` has two modes, chosen by `model`. Every field works in both; only the defaults and the error shape differ. The model behind both is the same.

| | **Native** (`model` = `mihu-ses-v1`, or no `model`) | **OpenAI-compatible** (`model` = `tts-1`, `tts-1-hd`, `gpt-4o-mini-tts`, any `gpt-4o*-tts*`) |
| - | - | - |
| `response_format` default | `pcm` | `mp3` |
| Language without `language` | from the voice, else Turkish | from the voice, else detected from the text |
| Errors | `{"error": {"message", "code"}}` | `{"error": {"message", "type", "param", "code"}}` |

## OpenAI SDK

Any OpenAI TTS client works with only `base_url` and `api_key` changed:

```python theme={null}
from openai import OpenAI
client = OpenAI(base_url="https://tts.eu.mihu.ai/v1", api_key=KEY)

client.audio.speech.create(model="tts-1", voice="alloy", input="Merhaba, siparişiniz yolda.").write_to_file("out.mp3")

with client.audio.speech.with_streaming_response.create(
        model="gpt-4o-mini-tts", voice="onyx", input="Guten Tag! Ihre Bestellung ist unterwegs.",
        response_format="opus", speed=1.1) as r:
    for chunk in r.iter_bytes():
        ...   # play or forward while it streams
```

For one-word inputs (`No`, `Ok`) pass `language` (in the SDK: `extra_body={"language": "es"}`) or use a voice such as `lucia`.

## Streaming

* Audio is sent as soon as it is generated. With `pcm` the first bytes are audio; with `wav` a 44-byte header comes first.
* `mp3`, `opus`, `aac`, `flac` and `speed` other than 1 go through an encoder that adds about 0.07 s to the first audio.
* If the client closes the connection (for example on barge-in), synthesis stops.
* With `stream_format: "sse"` the answer is Server-Sent Events: `speech.audio.delta` events with base64 audio, then `speech.audio.done`.

## Answer headers

`X-Sample-Rate: 24000`, `X-Language`, `X-Voice` (always the voice id), `X-Model: mihu-ses-v1`.

## Text handling

* **Normalization** (`normalize`, on by default): numbers, amounts, dates, times and abbreviations are written out ("14.30" → "on dört otuz"). `false` reads the text as it is.
* **Generate and verify** (`verify`, Turkish, off by default): a speech recognizer listens to each sentence chunk; a chunk it does not hear as written is said once more and the better take is sent. Fewer misread or skipped words, but the first audio comes about 2 s later. For files and prepared announcements, not for live calls.
* **Russian:** stress marks are added automatically. Text that already carries them (U+0301 after the vowel, or `+` before it: `з+амок`) is kept as written. Latin words are said in Cyrillic; for a name that must sound a certain way, write it in Cyrillic.

## Errors

| Status | Meaning |
| - | - |
| `400` | Invalid body, empty or too long input, invalid `speed` or `stream_format`, unknown model, language not available |
| `401` | Missing or wrong API key |
| `404` | Custom voice not found |
| `409` | Voice made with another model: create it again |
| `500` | Synthesis failed before any audio |
| `503` | All workers busy or still loading; retry |


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