Prerequisites
A Digital Twin
avatar_id (type: digital_twin). Use GET /v3/avatars/looks?avatar_type=digital_twin to find yours.A
voice_id for the voice you want. Use GET /v3/models/audio/voices to browse voices.Step 1 — Find your Digital Twin
List your private Digital Twin looks to get theavatar_id:
id field of the look you want. This is your avatar_id.
Step 2 — Choose a rendering engine
HeyGen v3 supports four rendering engines for Digital Twins. You select the engine via theengine object in your video creation request. Start with Avatar 6.
Before requesting an engine, check the
supported_api_engines array on the avatar look via GET /v3/avatars/looks/{look_id} — it lists which of heygen-avatar-6, heygen-avatar-6-turbo, avatar_iii, avatar_iv, and avatar_v the look accepts, and requesting an engine that isn’t listed will be rejected. See Models for full details on each engine.Step 3 — Create the video
Send aPOST request to /v3/videos with type: "avatar", your Digital Twin ID, a script, and a voice.
A type: "avatar" request renders one scene, so its script or audio must stay within 30 minutes. For a longer piece, compose it as a studio video with several scenes — see Usage Limits.
Using Avatar 6 (recommended)
Pass{"type": "heygen-avatar-6"} in the engine field. Direct the delivery with motion_prompt, and set engine.motion_expressiveness to less for calmer gestures:
heygen-avatar-6-turbo for the same inputs on the faster variant, and "resolution": "2k" for 2K output. The Avatar 6 guide lists every field.
For Avatar IV, omit engine (it is the default) or pass {"type": "avatar_iv"}. For Avatar V and its cross-reference-driven animation, pass {"type": "avatar_v"}. The rest of the request stays the same.
For digital twins,
motion_prompt works with Avatar 6 and Avatar V. Avatar IV rejects it.On Avatar 6, set engine.motion_expressiveness to default or less. The top-level expressiveness field works only for photo avatars and images on Avatar IV.Step 4 — Poll for completion
Generation is asynchronous. PollGET /v3/videos/{video_id} until status is completed (or failed, with failure_code and failure_message), or skip polling with a webhook. A completed video carries video_url, thumbnail_url, gif_url, and duration, plus captioned_video_url and subtitle_url when you request captions. These are presigned URLs with a limited expiry window: download promptly, or fetch the video again for fresh URLs.
Other parameters
Every other field, such astitle, background, voice_settings, and callback_url, is in the Create Video reference. Worth knowing: resolution takes 2k on Avatar 6 and 4k on Avatar III; aspect_ratio: "auto" matches the source and falls back to 16:9; remove_background works by default on new digital twins; output_format: "webm" returns a transparent background.
Captions and subtitles
Captions are off by default — omitcaption and video_url is a clean render with no subtitles. To generate captions, pass a caption object:
subtitle_url in the status response, while video_url stays clean. To also burn captions into a second render at captioned_video_url, add "style": "default" to the caption object.
caption is an object on /v3/videos. Boolean-style fields like caption: true or enable_caption (used by the v2 API and by the template endpoint) fail /v3/videos validation with invalid_parameter (“Extra inputs are not permitted”). Use the object form above.captioned_video_url (or the url from a webhook payload that points at the captioned render). Fetch GET /v3/videos/{video_id} and download video_url for the caption-free file.
Using webhooks instead of polling
Pass acallback_url when creating the video and HeyGen sends a POST to that URL when the video completes or fails. For production, register an endpoint via POST /v3/webhooks/endpoints and subscribe to avatar_video.success and avatar_video.fail.
