Overview
A template is a video layout you build once in HeyGen Studio, with named slots for text, media, avatars, and voices. Use the API to find your templates, read what each one exposes, and generate videos from them:GET /v3/templates— list the API-ready templates in your workspace.GET /v3/templates/{template_id}— read a template’s variable schema (with current defaults) and its scenes.POST /v3/templates/{template_id}— fill the variables and render a video.
Templates are created and edited in the HeyGen web editor. Only templates that have variables defined appear in the list, and the detail endpoint supports templates built in the current editor format (draft version 4). Create a template in HeyGen Studio first, then drive it from the API.
List Templates
- Endpoint:
GET /v3/templates - Purpose: Return a paginated list of API-ready templates in the workspace.
Response
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
limit | integer | No | 100 | Templates per page, 1–100. |
token | string | No | — | Opaque pagination cursor from a previous response’s next_token. |
Get a Template
- Endpoint:
GET /v3/templates/{template_id} - Purpose: Return template details including its variable schema (with current default values) and scene list.
Response
variables object is keyed by variable name, and each value is returned in the same shape a generate request accepts — so you can take this response, replace the default values with your own, and submit it back to render a video. The content, asset, and other fields hold the template’s current defaults; a text variable may come back empty when the template leaves it unfilled.
Variable Types
Every variable has atype discriminator that determines the rest of its fields:
text
| Field | Type | Required | Description |
|---|---|---|---|
content | string | Yes | Replacement text, up to 10000 characters. May be empty in a GET response (an unfilled default); must be non-empty when generating. |
image
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
asset | object | Yes | — | Image to place — see Asset input. |
fit | string | No | contain | How the image fits the placeholder box: cover, contain, crop, or none. |
video
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
asset | object | Yes | — | Video to place — see Asset input. |
fit | string | No | contain | How the video fits the placeholder box: cover, contain, crop, or none. |
play_style | string | No | loop | Playback when the video is shorter than the scene: fit_to_scene, freeze, loop, once, or full_video. |
volume | number | No | 1.0 | Audio volume of the video track, 0.0 (muted) to 1.0. |
audio
| Field | Type | Required | Description |
|---|---|---|---|
asset | object | Yes | Audio to place — see Asset input. |
voice
| Field | Type | Required | Description |
|---|---|---|---|
voice_id | string | Yes | Voice used for text-to-speech. Browse with GET /v3/voices. |
locale | string | No | Optional voice locale, e.g. en-US. |
character
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
character_id | string | Yes | — | Avatar ID or talking photo ID to place. |
character_type | string | No | avatar | Kind of character character_id refers to: avatar or talking_photo. |
Asset input
image, video, and audio variables take an asset object, discriminated by type. Provide one of:
| Form | Shape |
|---|---|
| Public URL | { "type": "url", "url": "https://..." } |
| Uploaded asset | { "type": "asset_id", "asset_id": "..." } — from POST /v3/assets (see Upload Assets). |
| Inline base64 | { "type": "base64", "media_type": "image/png", "data": "<base64>" } |
Scenes
scenes lists the template’s scenes in order. Each has a scene_id (usable to restrict a render to a subset of scenes), the script text with variable placeholders left unreplaced, and the variables referenced in that scene.
Generate a Video
- Endpoint:
POST /v3/templates/{template_id} - Purpose: Render a video from the template, replacing its variables with the values you supply.
Quick Example
Response
GET /v3/videos/{video_id} until status is completed, then read the download URL.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
variables | object | Yes | — | Replacements keyed by variable name, each following the per-type shapes in Variable Types. Only include the variables you want to change. |
title | string | No | — | Title for the generated video. |
scene_ids | array of strings | No | — | Scene IDs to render, in order — repeats allowed to duplicate a scene. Scenes must already exist in the template; the API can’t create new ones. Omit to render every scene. |
dimension | object | No | — | Output resolution override as { "width": ..., "height": ... } (even, 128–4096). Must keep the template’s aspect ratio. |
fps | number | No | 25 | Output frame rate: 25, 30, or 60. |
caption | boolean | No | false | Burn captions into the video. |
subtitles | object | No | — | Subtitle style — see Subtitle settings. Supplying this implies captions. |
reorder_music | boolean | No | true | When true, background-audio tracks move with their scenes; when false, they stay pinned to the original layout positions. |
keep_text_vertically_centered | boolean | No | false | Re-center replaced text elements based on their rendered height. |
include_gif | boolean | No | false | Include a GIF preview URL in the webhook payload. |
enable_sharing | boolean | No | false | Make the generated video’s share page publicly accessible. |
callback_url | string | No | — | Webhook URL called with the result, in addition to any registered endpoints. |
callback_id | string | No | — | Opaque ID echoed back in webhook events for this video. |
folder_id | string | No | — | Folder to place the generated video in. |
brand_voice_id | string | No | — | Brand voice ID controlling pronunciation and term handling. |
Subtitle settings
When you passsubtitles, preset_name is required; the rest override the preset.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
preset_name | string | Yes | — | Subtitle preset, e.g. classic, bold, bright. |
alignment | integer | No | 2 | Subtitle alignment. |
disable_highlight | boolean | No | false | Override the preset’s word-highlight style. |
font_size | integer | No | — | Font-size override for the preset. |
position | object | No | — | Position override as { "x": ..., "y": ... }. |
From template to video
The typical flow is three steps:- Discover —
GET /v3/templatesto find the template and itsid. - Inspect —
GET /v3/templates/{template_id}to read the variable schema and defaults. - Fill and generate — replace the defaults in the
variablesobject with your own values andPOSTthem toPOST /v3/templates/{template_id}, then pollGET /v3/videos/{video_id}for the result.

