---
title: "Stream Speech"
method: POST
path: "/v3/models/audio/tts/stream"
tags: ["Models"]
---

# Stream Speech

`POST /v3/models/audio/tts/stream`

## Request

- Base URL: `https://api.heygen.com`
- URL: `https://api.heygen.com/v3/models/audio/tts/stream`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

Stream speech from the voice identified by `voice_id`.

Set `output_format` to request raw PCM16, MP3, mu-law, or A-law audio bytes without SSE framing. Raw streams require `with_timestamps=false`; a failure after audio begins terminates the connection. `X-Audio-Sample-Rate` and `X-Audio-Channels` identify the audio parameters.
Otherwise, the response sends base64 WAV parts as Server-Sent Events (SSE). Set `with_timestamps` to `true` to include one alignment event after the audio. This event contains character and word timings for original and normalized text. Words use Unicode boundaries, without dictionary segmentation. A successful stream ends with `data: [DONE]`.

### Voice and settings

Use an `ACTIVE` HeyGen Voice clone in your workspace. `heygen-voice-1-turbo` speaks instant clones at lower latency and refuses professional clones. For paid models, API-key billing accumulates fractional usage. OAuth requests, including MCP calls, are rounded up per request to whole billing units, so their effective cost can be higher.

`seed`, `speed`, `pitch_shift`, and `pitch_variance` apply only to professional clones. Instant clones, including Turbo, accept and ignore these controls.

### Turbo Free

Use `heygen-voice-1-turbo-free` for instant voices without charge, including API-key and OAuth requests. This model is available to direct users and resellers for experimentation and prototyping. It has no latency, time-to-first-audio, or availability guarantee.

Per-user request limits and shared free capacity both apply. Either limit can return HTTP 429 with `code=rate_limit_exceeded`. Shared capacity can be exhausted even when you are below your own request limit. A timeout or service failure can return HTTP 500. Follow `Retry-After` when present; otherwise use exponential backoff. A free request never switches to a paid model. For streaming, HTTP 429 is returned before audio starts.

### Language

Set `language` to the language of `text`. If you omit it, the language is detected from `text`. Successful responses include `Content-Language`, the language the speech was generated in.

### Limits and request ID

The rate limit is 30 requests per minute per workspace member.
High demand can exceed the available capacity for speech generation. The service then returns HTTP 429 with `code=rate_limit_exceeded`. This response has no `Retry-After` header. Retry the request with exponential backoff. For streaming, the service returns HTTP 429 only before the response starts.

Successful responses include `X-Request-Id`. Use this ID when you contact support about the request. For instant clones, completed requests automatically retain audio for request stitching when speech retention is allowed. Pass completed IDs in `previous_request_ids` or `next_request_ids` to keep continuity. Use up to three IDs per field in playback order, from the same workspace, voice, and model, within two hours. Finish reading a stream before reusing its ID. If context is unavailable, synthesis continues with its normal defaults. Stitching is unavailable when speech retention is disabled.

## Request body

- StreamSpeechRequest
  - `end_user_id` string, nullable: Stable, opaque end-user identifier in your application, scoped to the authenticated workspace. Use 1–128 non-whitespace characters without personal information. Used for usage attribution and abuse investigation; does not change billing, authorization, or rate limits.
  - `output_format` SpeechOutputFormat
    - `encoding` 'pcm' | 'mp3' | 'ulaw' | 'alaw', required
    - `sample_rate_hertz` integer, nullable
    - `bit_depth` integer, nullable
    - `num_channels` integer
    - `bitrate_bps` integer, nullable
  - `model` 'heygen-voice-1' | 'heygen-voice-1-turbo' | 'heygen-voice-1-turbo-free': heygen-voice-1: instant and professional voices. heygen-voice-1-turbo: instant voices at lower latency. heygen-voice-1-turbo-free: instant voices without charge, subject to per-user limits and shared capacity. No latency or availability guarantee. Requests rejected by a limit or capacity check return HTTP 429. Timeouts and service failures can return HTTP 500.
  - `voice_id` string, required: Identifier of the voice used for speech synthesis.
  - `text` string, required: Text to synthesize. Instant voices accept caller-supplied IPA, such as <pron ipa="/ˈækmi/">Acme</pron>. Respelling cues are not supported. Unsupported IPA returns HTTP 400. Pronunciation requires an available pronunciation-capable model. Professional voices accept <break time="Xs"/> pauses (seconds, up to 5 per pause, e.g. <break time="0.5s"/>); other SSML, and break tags for an instant voice clone, are not supported.
  - `pronunciation_dictionary` object, nullable: Optional term-to-IPA dictionary, such as {"Acme": "/ˈækmi/"}. Use enclosing slashes for each IPA value. Matches whole terms without case sensitivity. Inline pronunciation takes precedence. Supports instant voices on heygen-voice-1 and heygen-voice-1-turbo when pronunciation is available. Omit expressiveness_boost to use 0.5, or supply a value from 0.0 to 1.0.
  - `language` string, nullable: Language code of `text`. Regional tags normalize to their supported base language, such as `en-US` to `en`. Omit it to detect the language from `text`. A confident reading that matches the letters of `text` is used, and the request fails with `invalid_parameter` if HeyGen Voice does not speak that language. Otherwise the first of these that HeyGen Voice speaks is used: the language the voice was created in, if `text` is written in that language's script; a less certain reading that a second reading of `text` without its numbers and brand names agrees with; the usual language of the script `text` is mostly written in, such as English for Latin letters; and, only when that script has no usual language, the reading itself. If none of them applies, the request fails with `invalid_parameter`. The `Content-Language` response header names the language used.
  - `previous_request_ids` string[], nullable: Completed speech request IDs before this text, in playback order, up to three. Use X-Request-Id from completed batch or fully consumed streaming responses within two hours. Requests must use the same workspace, voice, and model. Instant clones only, including Turbo. Unavailable when speech retention is disabled. Only the last three seconds of context are used. Unavailable context falls back to normal synthesis.
  - `next_request_ids` string[], nullable: Completed speech request IDs after this text, in playback order, up to three. Use X-Request-Id from completed batch or fully consumed streaming responses within two hours. Requests must use the same workspace, voice, and model. Instant clones only, including Turbo. Unavailable when speech retention is disabled. Only the first three seconds of context are used. Unavailable context falls back to normal synthesis.
  - `expressiveness_boost` number, nullable: Expressiveness boost for instant voices, from 0.0 to 1.0. Omit for professional voices. Omitted values use 0.5 with pronunciation and 1.0 otherwise.
  - `seed` integer, nullable: Optional best-effort deterministic generation seed for professional clones. Ignored for instant clones.
  - `speed` number, nullable: Speech speed multiplier for professional clones. Ignored for instant clones, including Turbo.
  - `pitch_shift` number, nullable: Pitch shift in semitones for professional clones. Ignored for instant clones.
  - `pitch_variance` number, nullable: Pitch variation multiplier for professional clones; 1.0 preserves the voice default. Ignored for instant clones.
  - `with_timestamps` boolean: Include character and word timings after the audio.

## Response `200`

Raw audio bytes when `output_format` is supplied; otherwise a Server-Sent Events stream. Each `data:` frame contains an audio, alignment, or terminal error event; a clean stream terminates with `data: [DONE]`.

## Other responses

- `400`: Invalid request parameters
- `401`: Authentication failed
- `402`: Payment required — `error.code` is one of: `usage_limit_reached`, `insufficient_credit`, `plan_upgrade_required`.
- `409`: Conflict — `error.code` is one of: `voice_not_ready`, `voice_training_failed`.
- `429`: Rate limit exceeded
- `502`: Upstream dependency failed — the request did not complete and is safe to retry.
- `503`: Temporarily unavailable — the request did not complete and is safe to retry.
- `504`: Upstream dependency timed out — the request did not complete and is safe to retry.

## Changes

- **2026-11-03** `7dfa5e59b4f5`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/heygen/apis/heygen-external-api/changes/v3/models/audio/tts/stream/post.md)

---

[API](https://skmtc.dev/heygen/apis/heygen-external-api.md) - [All operations](https://skmtc.dev/heygen/apis/heygen-external-api/llms.txt) - [OpenAPI document](https://skmtc.dev/heygen/apis/heygen-external-api/revisions/7dfa5e59b4f5?raw)
