Heygen Voice API Documentation

Heygen Voice API Documentation

Playground

Try it on WaveSpeedAI!

HeyGen Voice Text-to-Speech converts text into expressive speech using public voices or reference recordings for instant voice cloning, supporting narration, voiceovers, multilingual content, digital humans, and voice production workflows. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.

Features

HeyGen Voice turns text into natural, expressive speech. Choose a public voice or provide a single-speaker recording for instant voice cloning, with language selection and adjustable expressiveness.


Why Choose This?

  • 24 public voices — Choose a voice that fits your content.
  • Instant voice cloning — Use a reference recording instead of a public voice.
  • 39 supported languages — Select a language or let it be detected from the text.
  • Expression control — Adjust the delivery with an expressiveness setting.
  • WAV audio output — Generate speech as a 44.1 kHz WAV file.

Parameters

ParameterRequiredDescription
textYesText to speak, from 1 to 5,000 characters.
voiceNoSelect a public voice. Default: Jonah. Ignored when reference_audio is provided.
reference_audioNoSingle-speaker audio URL or upload for voice cloning. Only the first 3 minutes are used.
languageNoChoose a supported language code. Leave empty to detect the language from the text.
expressiveness_boostNoExpressiveness from 0 to 1. Default: 1.

How to Use

  1. Enter your text — Add the script you want spoken.
  2. Choose a voice — Select a public voice or upload a single-speaker reference recording.
  3. Adjust delivery — Optionally select the language and expressiveness.
  4. Generate — Submit the request and download the speech audio.

Pricing

$0.04 per 1,000 input characters, calculated using the actual text length.

Input CharactersPrice
100$0.004
1,000$0.04
5,000$0.20

The same rate applies when using a public voice or a reference recording.


Best Use Cases

  • Narration — Create spoken explanations and stories.
  • Video voiceovers — Add speech to presentations and social content.
  • Multilingual content — Generate speech in supported languages.
  • Custom voices — Use a reference recording for voice consistency.

Pro Tips

  • Use punctuation to guide phrasing and pauses.
  • Provide a clear recording with one speaker for voice cloning.
  • Set the language explicitly when the text is short or ambiguous.

Notes

  • text is required and supports up to 5,000 characters.
  • A reference recording takes priority over the selected public voice.
  • Only the first 3 minutes of reference audio are used.
  • Omit language to detect it from the text.
  • Use only recordings you own or have permission to clone.
  • The output is a WAV audio file, not a reusable voice ID.

  • HeyGen Avatar IV — Create talking-avatar videos from a portrait and speech audio.
  • HeyGen Avatar V — Create talking-avatar videos from a supported avatar and speech audio.

Authentication

For authentication details, please refer to the Authentication Guide.

API Endpoints

Submit Task & Query Result

set -euo pipefail

export WAVESPEED_API_KEY="your-api-key"

REQUEST_BODY=$(cat <<'JSON'
{
  "text": "A clear example input",
  "voice": "Jonah",
  "language": "ar",
  "expressiveness_boost": 1
}
JSON
)

# 1. Submit the prediction once. Never retry this request automatically:
# a retry after an unclear failure can create a second, billed task.
CHECK='The task may already exist. Check History or the predictions list before submitting again.'
if ! SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
  --connect-timeout 10 --max-time 60 \
  -X POST "https://api.wavespeed.ai/api/v3/heygen/voice" \
  -H "Authorization: Bearer ${WAVESPEED_API_KEY}" \
  -H "Content-Type: application/json" \
  -d "${REQUEST_BODY}"); then
  printf 'Submit failed. %s\n' "${CHECK}" >&2
  exit 1
fi

TASK=$(printf '%s' "${SUBMIT_RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
PREDICTION_ID=$(printf '%s' "${TASK}" | jq -r '.id // empty')
if [ -z "${PREDICTION_ID}" ]; then
  printf 'Submission response did not contain a prediction id. %s\n' "${CHECK}" >&2
  exit 1
fi
RESULT_URL="https://api.wavespeed.ai/api/v3/predictions/${PREDICTION_ID}/result"

# 2. Poll until the prediction reaches a final status.
BODY_FILE=$(mktemp)
trap 'rm -f "${BODY_FILE}"' EXIT
while true; do
  # Transient errors (429, 5xx) are retried, honoring Retry-After.
  HTTP_CODE=$(curl --silent --show-error --fail-with-body \
    --connect-timeout 10 --max-time 60 --retry 5 --retry-delay 2 \
    --output "${BODY_FILE}" --write-out '%{http_code}' \
    "${RESULT_URL}" \
    -H "Authorization: Bearer ${WAVESPEED_API_KEY}" || true)
  case "${HTTP_CODE}" in
    2??) ;;
    000|429|5??)  # dropped connection or temporary error: keep polling
      printf 'Task %s: HTTP %s, polling again in 10s\n' "${PREDICTION_ID}" "${HTTP_CODE}" >&2
      sleep 10; continue ;;
    *) printf 'Task %s: HTTP %s\n' "${PREDICTION_ID}" "${HTTP_CODE}" >&2
      cat "${BODY_FILE}" >&2; exit 1 ;;
  esac
  RESULT=$(jq 'if type == "object" and has("data") then .data else . end' "${BODY_FILE}")
  STATUS=$(printf '%s' "${RESULT}" | jq -r '.status // empty')

  case "${STATUS}" in
    completed) printf '%s\n' "${RESULT}" | jq '.outputs'; break ;;
    failed|cancelled|timeout|deleted)
      printf 'Task %s ended with status %s\n' "${PREDICTION_ID}" "${STATUS}" >&2
      printf '%s\n' "${RESULT}" | jq . >&2; exit 1 ;;
    *) sleep 2 ;;
  esac
done

Retry temporary errors only while polling, never the submit request. Errors, retries and timeouts

Parameters

Task Submission Parameters

Request Parameters

ParameterTypeRequiredDefaultRangeDescription
textstringYes-1 ~ 5000 charactersThe text to speak.
voicestringNoJonahJonah, Nadine, Tabitha, Soren, Elowen, Vincent, Jocelyn, Marielle, Corinne, Lucian, Kieran, Hugh, Noelle, Bram, Ewan, Iona, Cecily, Simon, Weston, Felicity, Gareth, Rory, Meredith, SabrinaPublic voice to use. Ignored when reference_audio is provided.
reference_audiostringNo-1 ~ unlimited characters · pattern: ^https?://Recording of a single speaker to clone instead of using a public voice. Only the first 3 minutes are used.
languagestringNo-ar, be, bg, ca, cs, da, de, el, en, es, fa, fi, fr, he, hi, hr, hu, id, it, ja, ko, mk, ms, nl, pl, pt, ro, ru, sk, sl, sr, sv, ta, th, tl, tr, uk, vi, zhLanguage of the text. Detected from the text when omitted.
expressiveness_boostnumberNo10 ~ 1How expressive the delivery is.

Response Parameters

ParameterTypeDescription
codeintegerHTTP status code (e.g., 200 for success)
messagestringStatus message (e.g., “success”)
data.idstringUnique identifier for the prediction, Task Id
data.modelstringModel ID used for the prediction
data.outputsarrayOutput values, usually URL strings; some models return text strings or structured result objects (empty when status is not completed)
data.urlsobjectObject containing related API endpoints
data.statusstringTask status. completed is successful; failed, cancelled, timeout, and deleted are failure terminal statuses.
data.created_atstringISO timestamp of when the request was created (e.g., “2023-04-01T12:34:56.789Z”)
data.errorstringError message (empty if no error occurred)
data.timingsobjectObject containing timing details
data.timings.inferenceintegerInference time in milliseconds

Result Request Parameters

ParameterTypeRequiredDefaultDescription
idstringYes-Task ID

Result Response Parameters

ParameterTypeDescription
codeintegerHTTP status code (e.g., 200 for success)
messagestringStatus message (e.g., “success”)
dataobjectThe prediction data object containing all details
data.idstringUnique identifier for the prediction
data.modelstringModel ID used for the prediction
data.outputsarray<string | object>Array of generated outputs (empty when status is not completed). Items are usually URL strings, but may be text strings or structured result objects, depending on the model.
data.urlsobjectObject containing related API endpoints
data.statusstringStatus: completed is successful; failed, cancelled, timeout, and deleted are failure terminal statuses
data.created_atstringISO timestamp of when the request was created
data.errorstringError message (empty if no error occurred)
data.timingsobjectObject containing timing details
data.timings.inferenceintegerInference time in milliseconds
© 2026 WaveSpeedAI. All rights reserved.