> ## Documentation Index
> Fetch the complete documentation index at: https://heygen-1fa696a7.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# HeyGen Voice Speech

> Generate completed or streaming audio from a professional voice clone with the HeyGen Voice speech APIs.

<img className="w-full h-44 object-cover rounded-xl" src="https://mintcdn.com/heygen-1fa696a7/hfMXXwJzjE7vBSYZ/images/theme/research-2.webp?fit=max&auto=format&n=hfMXXwJzjE7vBSYZ&q=85&s=d6ee10585b27ddaf8137d6ed67791708" alt="" noZoom width="1400" height="788" data-path="images/theme/research-2.webp" />

<Warning>
  These APIs are in private preview and require an `ACTIVE` [professional voice clone](/docs/voices/professional-voice-clone), a paid feature backed by purchased [voice clone slots](https://app.heygen.com/developers/usage).
</Warning>

The [HeyGen Voice](/docs/models/heygen-voice) model synthesizes speech two ways from the same request body:

* `POST /v3/models/audio/tts` waits for generation and returns one audio URL.
* `POST /v3/models/audio/tts/stream` returns ordered audio parts as Server-Sent Events (SSE).

For stock, designed, or instant-cloned voices, use [Third Party Speech](/docs/voices/speech).

Synthesis costs 0.6 API credits per generated minute. Each endpoint allows 30 requests per minute per workspace member.

## Request fields

| Field             | Type    | Required | Description                                                                |
| ----------------- | ------- | -------- | -------------------------------------------------------------------------- |
| `voice_id`        | string  | Yes      | An `ACTIVE` professional voice owned by the API key's workspace.           |
| `text`            | string  | Yes      | Plain prose to synthesize, 1–5,000 characters.                             |
| `language`        | string  | Yes      | Language code for synthesis, such as `en`.                                 |
| `seed`            | integer | No       | Best-effort deterministic seed, `0`–`4294967295`.                          |
| `with_timestamps` | boolean | No       | Streaming only. Adds word-timestamp events to the stream. Default `false`. |

Unknown fields return `400 invalid_parameter`. For `<break>` pauses, use [Third Party Speech](/docs/voices/speech#adding-pauses).

## Generate completed speech

```bash theme={null}
curl -X POST "https://api.heygen.com/v3/models/audio/tts" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "voice_id": "0f4e5d8c9a1b4d62a914938d06c31234",
    "text": "Hello from my professional voice.",
    "language": "en",
    "seed": 7
  }'
```

```json Response theme={null}
{
  "data": {
    "audio_url": "https://files.heygen.ai/generated/model-speech.wav",
    "duration": 3.42
  }
}
```

The request stays open until the file is assembled, so no polling is needed. `audio_url` is one mono PCM16 WAV at 44.1 kHz; `duration` is in seconds.

## Stream speech

The stream is `text/event-stream`. Disable response buffering and handle each event as it arrives.

```bash theme={null}
curl -N --no-buffer -X POST "https://api.heygen.com/v3/models/audio/tts/stream" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "voice_id": "0f4e5d8c9a1b4d62a914938d06c31234",
    "text": "Hello from my professional voice.",
    "language": "en",
    "with_timestamps": true
  }'
```

**Audio events** carry base64-encoded standalone WAV parts. Play them in ascending `part_index` order; each part is a complete WAV container, so decode them individually rather than concatenating the bytes.

```text theme={null}
data: {"type":"audio","part_index":0,"audio":"UklGR..."}

data: {"type":"audio","part_index":1,"audio":"UklGR..."}
```

**Alignment events** appear when `with_timestamps` is `true`. Each word carries `text`, `start_time` and `end_time` in seconds, and a `confidence` from `0` to `1`.

```text theme={null}
data: {"type":"alignment","word_alignments":[{"text":"Hello","start_time":0.0,"end_time":0.42,"confidence":0.99}]}
```

A clean stream ends with `data: [DONE]`. If synthesis fails mid-stream, the stream ends with an error event instead and no `[DONE]`:

```text theme={null}
data: {"type":"error","detail":"Voice inference failed mid-stream"}
```

Errors before the first event use the standard JSON [error envelope](/docs/error-codes).

## Errors

| HTTP status | Error code              | Meaning                                                                                                                                                    |
| ----------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`       | `invalid_parameter`     | Missing or unknown field, or invalid `text`, `language`, or `seed`.                                                                                        |
| `400`       | `voice_expired`         | The workspace is over its professional voice clone slot limit. [Add a slot](https://app.heygen.com/developers/usage) or delete another professional voice. |
| `402`       | `insufficient_credit`   | The API credit balance is empty.                                                                                                                           |
| `403`       | `forbidden`             | The account is not enabled for the preview.                                                                                                                |
| `404`       | `voice_not_found`       | The voice is not in the caller's workspace.                                                                                                                |
| `409`       | `voice_not_ready`       | Training is still `PENDING`.                                                                                                                               |
| `409`       | `voice_training_failed` | Training `FAILED`; inspect `failure_reason` on the voice.                                                                                                  |
| `429`       | `rate_limit_exceeded`   | Retry after the seconds in `Retry-After`.                                                                                                                  |
| `503`       | `service_unavailable`   | Inference is busy; the request is safe to retry.                                                                                                           |
