Skip to main content

Overview

Creating a video returns a video_id. Two endpoints read everything back from that id: The first is the endpoint you already poll after creating a video — it now returns far more than the status-and-URL pair it started with. The scenes endpoint is new.

Video Details

Response
Lifecycle
  • statuspendingprocessingcompleted or failed
  • created_at, completed_at — Unix timestamps; the difference is your render time
  • failure_code, failure_message — on a failed video: branch on the code, log the message
Deliverables — up to five outputs on a completed video: Placement
  • title, folder_id — where the video lives in your workspace
  • video_page_url — deep link to the video in the HeyGen app
  • duration — final length in seconds
  • output_language — BCP-47 code; present only on translated videos, which is also how you tell them apart
Media URLs are presigned and expire (the Expires parameter says when). Download what you need rather than storing the URLs — re-fetch the details for a fresh link at any time.
Fields that don’t apply are simply absent: a processing video has no video_url yet, and only a failed video carries failure fields.

Video Scenes

GET /v3/videos/{video_id}/scenes opens the composition itself — for any video in your workspace, whichever surface created it: a studio request, a template render, an avatar video, or a video composed by hand in the editor. It describes the video as it stands now, including editor changes made after creation. When a brand glossary shapes the video’s speech, video.brand_glossary_id carries its id. A video whose composition can’t be read answers with an error rather than an empty document: 404 video_not_found when there is no editor document to read (some translated videos, for example), and 400 when the video predates the current editor format. Anatomy of the scenes response: video context plus a list of scenes, each with a background, elements, and script
Response

Roles, not kinds

A scene’s three content fields split by the role a thing plays: background fills the frame, elements are placed within it, script is the audio over it.
A whole-frame image or clip lands in background — code that only walks elements misses it.
A video background or video element reads back with the same playback controls a studio scene accepts: playback (freeze / loop / fit_to_scene), trim, volume, speed_multiplier.

Reading elements

  • Every element appears — the count is always truthful. avatar, image, and video are described in full; anything else is a placeholder with just an id and type (like motion_graphics above).
  • Skip unrecognized types rather than erroring — the set is open and grows with the editor.
  • Recurse into containers — a group or mask carries its children under children, each described like a top-level element.
  • Avatar elements report what a create request can setavatar_id, engine, expressiveness, motion_prompt — so what you read back is what you could send back. New fields are added additively.

Reading scripts

Walking scenes[].script[].text yields the full narration in playback order — for search indexing, compliance review, or driving a translation.

Scope

  • Asset URLs (url, audio_url) are returned when a live link exists at the time of the response; when the stored link has lapsed, the field is absent — the element itself is still reported. As with the deliverables above, download media you need rather than storing the URLs.
  • The response is scoped to composition content. Visual styling — element geometry, text-element contents, animations, per-scene caption styling, background music — lives outside it, so a rebuild from this response reproduces the content and narration, not the pixel-exact layout.

Putting the two together

1

Wait for the render

Poll GET /v3/videos/{video_id} until status is completed — or skip polling with a webhook.
2

Download the deliverables

Grab video_url, subtitle_url, and friends before their presigned links expire.
3

Index the composition

Call GET /v3/videos/{video_id}/scenes — scripts for search, avatar and voice ids for auditing, scene structure for your own UI.
Requesting an id that doesn’t exist in your workspace returns 404 with code video_not_found, from either endpoint.