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

# Brand Glossary

> Control how HeyGen says your custom terms. A brand glossary maps a term to its pronunciation so product names, acronyms, and numbers are spoken correctly in generated speech and carried intact through translation.

<img className="w-full h-44 object-cover rounded-xl" src="https://mintcdn.com/heygen-1fa696a7/hfMXXwJzjE7vBSYZ/images/theme/research.webp?fit=max&auto=format&n=hfMXXwJzjE7vBSYZ&q=85&s=3e4c2594813dcfd56985f3d63e3ba321" alt="" noZoom width="1400" height="788" data-path="images/theme/research.webp" />

A brand glossary is a list of your terms and the pronunciation each one should get. Pass its `brand_glossary_id` when you create a video and every term in the list is respelled for the voice — so `HeyGen` is spoken `hey-jen` rather than *hey-gen*, and an acronym your team says as a word isn't spelled out letter by letter.

Glossaries are authored in the HeyGen web app under **Brand Kit**. Over the API they are **read-only**: list them, read their terms, and reference them by ID.

<Info>
  **API reference:** [List Brand Glossaries](/reference/list-brand-glossaries) · [Get Brand Glossary](/reference/get-brand-glossary)
</Info>

## One glossary, two jobs

The same glossary record behaves differently depending on where you pass it, because the two pipelines need different things from it:

* **In generation** — [Studio](/studio-videos), [Templates](/templates), and single-scene `avatar` and `image` videos — it sets **pronunciation**. The term keeps its spelling in the script and in captions; only the audio changes.
* **In [translation](/docs/video-translate)** — it pins **terminology**. A term that a general translator would render literally stays your term instead, so `Reformer` arrives as the Pilates equipment rather than a political activist.

One list serves both, so a term you add for a Studio voiceover is also honored the next time you translate that video.

## List your glossaries

Full schema: [`GET /v3/brand-glossaries`](/reference/list-brand-glossaries). Returns the glossaries in the authenticated workspace.

### Query parameters

| Parameter | Type    | Default | Description                                            |
| --------- | ------- | ------- | ------------------------------------------------------ |
| `limit`   | integer | 10      | Results per page.                                      |
| `token`   | string  | —       | Opaque cursor from a previous response's `next_token`. |

```bash theme={null}
curl "https://api.heygen.com/v3/brand-glossaries" \
  -H "X-Api-Key: $HEYGEN_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "brand_glossary_id": "8c2d5e91a47b4f3c8d1e6a9b2f5c7d40",
      "name": "Acme Product Names",
      "created_at": "2026-03-10T18:22:22",
      "updated_at": "2026-06-19T17:34:52"
    }
  ],
  "has_more": false,
  "next_token": null
}
```

| Field               | Type   | Description                                                                                                     |
| ------------------- | ------ | --------------------------------------------------------------------------------------------------------------- |
| `brand_glossary_id` | string | Unique identifier. This is the value you pass when creating a video or translation.                             |
| `name`              | string | Display name. Glossaries created without a name come back as an empty string.                                   |
| `created_at`        | string | Creation timestamp (UTC).                                                                                       |
| `updated_at`        | string | Last update timestamp (UTC). Use this to tell which of several glossaries is the one your team still maintains. |

The list gives you names and IDs but not contents — to see what a glossary actually changes, read it by ID.

## Read a glossary's terms

[`GET /v3/brand-glossaries/{brand_glossary_id}`](/reference/get-brand-glossary) returns one glossary with its full term list. This is the endpoint to reach for when a generated video pronounces something unexpectedly — it tells you whether the term is in the list at all, and exactly what respelling it was given.

```bash theme={null}
curl "https://api.heygen.com/v3/brand-glossaries/8c2d5e91a47b4f3c8d1e6a9b2f5c7d40" \
  -H "X-Api-Key: $HEYGEN_API_KEY"
```

```json theme={null}
{
  "data": {
    "brand_glossary_id": "8c2d5e91a47b4f3c8d1e6a9b2f5c7d40",
    "name": "Acme Product Names",
    "created_at": "2026-03-10T18:22:22",
    "updated_at": "2026-06-19T17:34:52",
    "terms": [
      { "term": "HeyGen", "pronunciation": "hey-jen" },
      { "term": "2024", "pronunciation": "twenty twenty-four" }
    ]
  }
}
```

| Field                   | Type   | Description                                                  |
| ----------------------- | ------ | ------------------------------------------------------------ |
| `terms`                 | array  | Every mapping in the glossary.                               |
| `terms[].term`          | string | The term as written in a script. Matched case-insensitively. |
| `terms[].pronunciation` | string | The respelling handed to the voice in place of `term`.       |

Terms are not limited to brand names. Numerals, years, and units are common entries, since a written `2024` can be read several defensible ways and a glossary is how you pick one.

<Note>
  A glossary with `"terms": []` is valid and applying it is accepted, but it changes nothing. An empty term list is the usual explanation for a glossary that appears to have no effect.
</Note>

## Apply a glossary

Pass `brand_glossary_id` at the top level of the creation request. It is global to the request — one glossary per call.

<CodeGroup>
  ```bash Studio theme={null}
  curl -X POST "https://api.heygen.com/v3/videos" \
    -H "X-Api-Key: $HEYGEN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "studio",
      "brand_glossary_id": "8c2d5e91a47b4f3c8d1e6a9b2f5c7d40",
      "scenes": [
        {
          "type": "avatar_video",
          "input": {
            "type": "avatar",
            "avatar_id": "YOUR_AVATAR_ID",
            "script": "HeyGen shipped this in 2024.",
            "voice_id": "YOUR_VOICE_ID"
          }
        }
      ]
    }'
  ```

  ```bash Avatar theme={null}
  curl -X POST "https://api.heygen.com/v3/videos" \
    -H "X-Api-Key: $HEYGEN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "avatar",
      "brand_glossary_id": "8c2d5e91a47b4f3c8d1e6a9b2f5c7d40",
      "avatar_id": "YOUR_AVATAR_ID",
      "script": "HeyGen shipped this in 2024.",
      "voice_id": "YOUR_VOICE_ID"
    }'
  ```

  ```bash Translation theme={null}
  curl -X POST "https://api.heygen.com/v3/video-translations" \
    -H "X-Api-Key: $HEYGEN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "video": { "type": "url", "url": "https://example.com/source.mp4" },
      "output_languages": ["Spanish (Spain)"],
      "brand_glossary_id": "8c2d5e91a47b4f3c8d1e6a9b2f5c7d40"
    }'
  ```

  ```bash Template theme={null}
  curl -X POST "https://api.heygen.com/v3/templates/$TEMPLATE_ID" \
    -H "X-Api-Key: $HEYGEN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "brand_glossary_id": "8c2d5e91a47b4f3c8d1e6a9b2f5c7d40",
      "variables": {}
    }'
  ```
</CodeGroup>

See [On Brand](/docs/on-brand) for the full list of endpoints that accept the field. On [`POST /v3/videos`](/reference/create-video) it applies to `"type"` of `studio`, `avatar`, or `image`, and in a [translation batch](/batch-video-translations) or a [video batch](/batch-videos) it is set per item.

## What a glossary leaves alone

* **Captions and subtitles keep the original spelling.** A term written `HeyGen` still reads `HeyGen` on screen and in the `.srt` sidecar while being spoken `hey-jen`. The respelling is for the voice, not the viewer.
* **Scenes with finished audio are untouched.** A Studio scene that supplies `audio_url` or `audio_asset_id` already has its audio, so there is no synthesis step for the glossary to influence.

## Errors

Reading a glossary that does not exist in the workspace returns `404` with the [`resource_not_found`](/docs/error-codes#resource-not-found) code:

```json theme={null}
{
  "error": {
    "code": "resource_not_found",
    "message": "Brand glossary not found.",
    "param": null,
    "doc_url": null
  }
}
```

On a creation request, an unknown or inaccessible `brand_glossary_id` is rejected with `400` when the request is made, rather than failing partway through a render — so a bad ID produces no video and consumes no credits. Glossaries are workspace-scoped, so if an ID you can see in the app is rejected, check that the API key belongs to that same workspace.

## `brand_voice_id` is the former name

`brand_voice_id` was the original name for this field and is **deprecated**. It is accepted on three endpoints — [`POST /v3/templates/{template_id}`](/reference/generate-video-from-template), [`POST /v3/video-translations`](/reference/create-video-translation), and [`POST /v3/video-translations/proofreads`](/reference/create-proofread-session) — where it resolves to the same workspace record, so existing requests keep working.

It is **not** accepted on [`POST /v3/videos`](/reference/create-video), on any composition type. That request rejects unknown fields outright, so `brand_voice_id` there is a `400` rather than a silently ignored field — use `brand_glossary_id`. This is the trap for anyone porting a working translation payload over to Studio.

Prefer `brand_glossary_id` everywhere in new code. The old name is also misleading: a glossary never changes which voice speaks.
