# Create Speech

`POST https://api.vultrinference.com/v1/audio/speech`

Generate speech from text. OpenAI's request shape plus OpenRouter's, so both SDKs work unchanged. The response body is the audio itself.

**Voices:** `voice` selects the mode as well as the voice. A built-in speaker (`GET /v1/audio/voices?model=` lists them) speaks the input, and `instructions` can direct its style. `design` creates a new voice from the description in `instructions`. `clone` (or leaving `voice` out) with `input_references` speaks in the voice of a reference clip: send it base64-encoded in `input_audio.data`, with its transcript in a `text` part for the closest match. Clip URLs are not accepted. A cloned voice cannot follow `instructions`.

**Formats:** `response_format` is `mp3` (the default), `opus`, `flac`, `wav` or `pcm` (24 kHz 16-bit mono, labelled `audio/pcm;rate=24000;channels=1`). `aac` returns 400.

**Streaming:** `stream_format` `audio` (the default) returns the audio; `pcm` at `speed` 1 streams as it is generated. `sse` returns `speech.audio.delta` events with base64 audio and a final `speech.audio.done` event with usage; `pcm` at `speed` 1 streams, other formats arrive as one delta. A failure mid-stream ends an SSE stream with a `speech.audio.error` event.

**Billing:** Per second of audio generated, before `speed`, rounded up. The seconds and cost are in the `X-Usage-Seconds` and `X-Usage-Cost` headers, or in the `speech.audio.done` usage; a raw `pcm` stream reports neither.

OpenRouter's `provider`, `user`, `session_id` and `trace` are accepted and ignored, except that `provider.options` under our OpenRouter slug can carry `instructions`, `language`, `speed`, `seed`, `temperature`, `top_p` and `top_k`.

## Body (application/json)

- `model` (string, required): The text-to-speech [model](#operation/list-models), e.g. `qwen3-tts-12hz-1.7b`.
- `input` (string, required): The text to speak, up to the model's `max_prompt_length` in characters.
- `voice` (string or object): A built-in speaker, `design` or `clone`, as a string or as OpenAI's `{"id": ...}`. Defaults to the model's default speaker, or `clone` when `input_references` is sent.
- `instructions` (string): Style for a built-in speaker, or the description of the voice for `design`. Not accepted with `clone`.
- `input_references` (array of objects): OpenRouter's reference parts for `clone`. One `input_audio` clip and, optionally, its transcript as a `text` part.
  - `type` (string, required) [input_audio, text]
  - `input_audio` (object)
    - `data` (string, required): The clip, base64-encoded or a base64 data URI. Up to 15 MB decoded. URLs are not accepted.
    - `format` (string) [wav, mp3, flac, ogg, m4a, webm]
  - `text` (string): What the clip says. [at most 10000 characters]
- `language` (string): The language of the input, as `auto` (the default), an ISO 639-1 code or a name.
- `response_format` (string) [default mp3, mp3, opus, flac, wav, pcm]
- `stream_format` (string) [default audio, audio, sse]
- `speed` (number) [default 1, range 0.25–4]
- `seed` (integer)
- `temperature` (number) [range 0–2]
- `top_p` (number): The engine takes values above 0, so 0 is sent as 0.000001, which keeps only the likeliest token. [range 0–1]
- `top_k` (integer) [at least -1]

## Responses

- `200`: The audio, or SSE events when stream_format is sse.
- `400`: Bad Request, such as an unknown voice or a voice that does not fit the request (error-payload)
- `401`: The API key is missing, unknown or not active. Send it as Authorization: Bearer <key>. (error-payload)
- `404`: Model not found (error-payload)
- `429`: Too many requests for this model from your subscription in the last minute, or too many running at once. Wait for Retry-After, then retry. (error-payload)

## Example

```bash
curl https://api.vultrinference.com/v1/audio/speech \
  -H "Authorization: Bearer $VULTR_INFERENCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3-tts-12hz-1.7b",
    "input": "Welcome to Vultr Serverless Inference.",
    "voice": "aiden",
    "instructions": "Warm and upbeat, like a radio host."
  }'
```

```python
import os
import requests

response = requests.post(
    "https://api.vultrinference.com/v1/audio/speech",
    headers={"Authorization": f"Bearer {os.environ['VULTR_INFERENCE_API_KEY']}"},
    json={
        "model": "qwen3-tts-12hz-1.7b",
        "input": "Welcome to Vultr Serverless Inference.",
        "voice": "aiden",
        "instructions": "Warm and upbeat, like a radio host.",
    },
)
print(response.status_code)
```

```javascript
const response = await fetch("https://api.vultrinference.com/v1/audio/speech", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.VULTR_INFERENCE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "qwen3-tts-12hz-1.7b",
    "input": "Welcome to Vultr Serverless Inference.",
    "voice": "aiden",
    "instructions": "Warm and upbeat, like a radio host."
  }),
});
console.log(response.status);
```
