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 can be authored in the HeyGen app under Brand Kit or created and edited over the API. Creating them over the API is what lets each of your own customers get their own vocabulary: mint a glossary per tenant, keep it in sync with their product catalog, and pass its ID on every render.
API reference: Create Brand Glossary · Update Brand Glossary · Get Brand Glossary · List Brand Glossaries
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, Templates, and single-scene
avatarandimagevideos — it sets pronunciation. The term keeps its spelling in the script and in captions; only the audio changes. - In translation — it pins terminology. A term that a general translator would render literally stays your term instead, so
Reformerarrives as the Pilates equipment rather than a political activist.
Create a glossary
POST /v3/brand-glossaries takes a name and an optional list of terms. Include the terms to populate the glossary in the same call, or omit them and fill the list in later.
Send an
Idempotency-Key header so a retry is safe: a repeat within 24 hours replays the original response rather than creating a second glossary.
201 returns the full glossary, the same shape you read back later:
brand_glossary_id on your next creation request and it takes effect on that render.
Choosing terms
A pronunciation is a respelling, not a phonetic alphabet: write the term the way you would coach a person to say it, in syllables the voice can read. Hyphens and spaces are how you break it up.- Brand and product names —
HeyGen→hey-jen,HyperFrames→hyper frames. - Acronyms your team says as a word — an acronym spelled out letter by letter when you say it as a word is a glossary entry, and so is the reverse.
- Numerals, years, and units — a written
2024can be read several defensible ways, and a glossary is how you pick one.
Update a glossary
PATCH /v3/brand-glossaries/{brand_glossary_id} edits an existing glossary. Each field is replaced independently:
- A field you omit is left untouched.
- A field you send replaces that value in full.
- An empty
termsarray removes every term.
data object the create call returns, with updated_at moved forward. Send at least one of name or terms; an empty body is a 400 with "Provide at least one field to update."
Adding one term
terms is replace-in-full, so adding a single term means reading the glossary, appending to the list, and sending the whole list back. Read first every time rather than from a cached copy — a teammate editing the same glossary in the app is otherwise overwritten.
A glossary can also carry translation rules, which control how terms are handled when a video is translated. Those are managed in the HeyGen app under Brand Kit and are never modified by a
PATCH here, so a glossary edited in the app keeps them through an update made over the API.Find and inspect glossaries
GET /v3/brand-glossaries returns the glossaries in the authenticated workspace.
updated_at is how you tell which of several similarly named glossaries your team still maintains.
GET /v3/brand-glossaries/{brand_glossary_id} 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.
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.Apply a glossary
Passbrand_glossary_id at the top level of the creation request. It is global to the request — one glossary per call.
POST /v3/videos it applies to "type" of studio, avatar, or image, and in a translation batch or a video batch it is set per item.
What a glossary leaves alone
- Captions and subtitles keep the original spelling. A term written
HeyGenstill readsHeyGenon screen and in the.srtsidecar while being spokenhey-jen. The respelling is for the voice, not the viewer. - Scenes with finished audio are untouched. A Studio scene that supplies
audio_urloraudio_asset_idalready has its audio, so there is no synthesis step for the glossary to influence.
Errors
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}, POST /v3/video-translations, and POST /v3/video-translations/proofreads — where it resolves to the same workspace record, so existing requests keep working.
It is not accepted on POST /v3/videos, 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.
