> ## 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 Studio Template

> Find your HeyGen Studio templates and read each one's variable schema over the API, then fill the slots and render.

## 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`](/reference/list-templates) — list the API-ready templates in your workspace.
* [`GET /v3/templates/{template_id}`](/reference/get-template) — read a template's variable schema (with current defaults) and its scenes.
* [`POST /v3/templates/{template_id}`](/reference/generate-video-from-template) — fill the variables and render a video.

<Note>
  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](https://app.heygen.com/avatar/studio) first, then drive it from the API.
</Note>

## List Templates

* Endpoint: `GET /v3/templates`
* Purpose: Return a paginated list of API-ready templates in the workspace.

```bash theme={null}
curl -X GET "https://api.heygen.com/v3/templates?limit=100" \
  -H "x-api-key: YOUR_API_KEY"
```

```json Response theme={null}
{
  "data": {
    "templates": [
      {
        "id": "77e650952c024c6188a35e23e7088617",
        "name": "Quarterly Update",
        "thumbnail_url": "https://.../thumb.png",
        "aspect_ratio": "16:9",
        "created_at": 1711929600,
        "updated_at": 1711929600
      }
    ],
    "has_more": false,
    "next_token": null
  }
}
```

### 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.

```bash theme={null}
curl -X GET "https://api.heygen.com/v3/templates/77e650952c024c6188a35e23e7088617" \
  -H "x-api-key: YOUR_API_KEY"
```

```json Response theme={null}
{
  "data": {
    "id": "77e650952c024c6188a35e23e7088617",
    "name": "Quarterly Update",
    "aspect_ratio": "16:9",
    "variables": {
      "headline": {
        "type": "text",
        "content": "Q3 in review"
      },
      "cover_image": {
        "type": "image",
        "asset": { "type": "url", "url": "https://.../cover.png" },
        "fit": "cover"
      }
    },
    "scenes": [
      {
        "scene_id": "scene_1",
        "script": "Welcome to the {{headline}} update.",
        "variables": [
          { "name": "headline", "variable_type": "text" }
        ]
      }
    ]
  }
}
```

The `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 a `type` 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](#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](#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](#asset-input). |

#### `voice`

| Field      | Type   | Required | Description                                                                            |
| ---------- | ------ | -------- | -------------------------------------------------------------------------------------- |
| `voice_id` | string | Yes      | Voice used for text-to-speech. Browse with [`GET /v3/voices`](/reference/list-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`](/reference/upload-asset) (see [Upload Assets](/docs/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

```bash theme={null}
curl -X POST "https://api.heygen.com/v3/templates/YOUR_TEMPLATE_ID" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "variables": {
      "headline": { "type": "text", "content": "Q3 in review" },
      "cover_image": {
        "type": "image",
        "asset": { "type": "url", "url": "https://example.com/cover.png" },
        "fit": "cover"
      }
    },
    "title": "Quarterly Update — Q3",
    "caption": false
  }'
```

```json Response theme={null}
{
  "data": {
    "video_id": "vid_9f2c..."
  }
}
```

Generation is asynchronous. Poll [`GET /v3/videos/{video_id}`](/reference/get-video) 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](#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](#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](/docs/webhooks) 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 pass `subtitles`, `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:

1. **Discover** — [`GET /v3/templates`](/reference/list-templates) to find the template and its `id`.
2. **Inspect** — [`GET /v3/templates/{template_id}`](/reference/get-template) to read the variable schema and defaults.
3. **Fill and generate** — replace the defaults in the `variables` object with your own values and `POST` them to [`POST /v3/templates/{template_id}`](/reference/generate-video-from-template), then poll [`GET /v3/videos/{video_id}`](/reference/get-video) for the result.
