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

# Edit Scenes

> Revise two scenes of a Video Agent video without touching the rest. Read the scene list, send an edit_plan with one instruction per scene, and poll the new draft.

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

<Info>
  **API reference:** [Get Video Scenes](/reference/get-video-scenes) · [Send Message or Request Revision](/reference/send-message-or-request-revision) · [Get Video](/reference/get-video) · [List Session Videos](/reference/list-session-videos)
</Info>

A scene edit changes only the scenes you name. Everything else in the video keeps its script, visuals, and pacing, so a small fix stays small: one call, a few minutes of rendering, and no re-prompting of the whole video. It works on any Video Agent session, whether you created it with `"mode": "generate"` or `"mode": "chat"` (see [Interactive Sessions](/docs/interactive-sessions)).

<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))", gap: "16px" }}>
  <Frame caption="Before · the first cut, four scenes from one prompt.">
    <video controls playsInline preload="metadata" className="w-full rounded-xl" poster="https://dynamic.heygen.ai/image/4143aae96d404a87ac558371d41fa1fb/original.jpg">
      <source src="https://resource2.heygen.ai/video/65f3e9ba12d04c5cb66abbda8635eb25/original.mp4" type="video/mp4" />
    </video>
  </Frame>

  <Frame caption="After · one edit_plan call. Scene 2 became a night-time room, scene 4 dropped the pre-order line. Scenes 1 and 3 are unchanged.">
    <video controls playsInline preload="metadata" className="w-full rounded-xl" poster="https://dynamic.heygen.ai/image/26893b44e5084112bc95dc1c9df635d4/original.jpg">
      <source src="https://resource2.heygen.ai/video/eb0bec1e37e544efb48acf39b87d0d0e/original.mp4" type="video/mp4" />
    </video>
  </Frame>
</div>

## Three calls

<Steps>
  <Step title="Read the scenes">
    [`GET /v3/videos/{video_id}/scenes`](/reference/get-video-scenes) on a completed video from the session. The response lists every scene in order with its `id`, `script`, `background`, and `elements`, plus one `edit_version` for the whole document. Wait for the video to reach `completed` first: while it is still rendering this call returns `409 resource_not_ready`.
  </Step>

  <Step title="Send the edit plan">
    [`POST /v3/video-agents/{session_id}`](/reference/send-message-or-request-revision) with an `edit_plan` array. Each item names one `scene_id`, the change in plain language, the `scene_snapshot_video_id` you read the scene from, and that snapshot's `edit_version`. No `message` is needed. The response carries the `video_id` of the new working draft.
  </Step>

  <Step title="Poll the draft">
    [`GET /v3/videos/{video_id}`](/reference/get-video) with the returned `video_id` until `status` is `completed`. The session's own `video_id` stays `null` while the edit runs, so poll the draft directly. [`GET /v3/video-agents/{session_id}/videos`](/reference/list-session-videos) lists every cut the session has produced.
  </Step>
</Steps>

## Example

The plan below produced the "after" video above. Two items, two scenes, one request.

```bash theme={null}
curl -X POST "https://api.heygen.com/v3/video-agents/$SESSION_ID" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "edit_plan": [
      {
        "scene_id": "ff943f68-159d-463b-84ac-b784a61c8bca",
        "text": "Change the on-screen headline to Evening mode and make the background a much darker, warmer night-time room with a single lit lamp. Keep the narration the same.",
        "scene_snapshot_video_id": "7c852479652e4e09b2cc6b12382b31f6",
        "edit_version": "e6eb1e63074cbfc694e4e6b64d3dc1b9cc004da54074d073631baaa825ce0e53"
      },
      {
        "scene_id": "e89c22a1-7619-4f26-bdb5-c5ec5555da4e",
        "text": "Replace the closing line with: Lumen. Light that knows you. Available now. Drop the pre-order URL from narration and on-screen text.",
        "scene_snapshot_video_id": "7c852479652e4e09b2cc6b12382b31f6",
        "edit_version": "e6eb1e63074cbfc694e4e6b64d3dc1b9cc004da54074d073631baaa825ce0e53"
      }
    ]
  }'
```

```json Response theme={null}
{
  "data": {
    "session_id": "6cbd1fbc886b434a920acfed05fa931b",
    "run_id": "c3817fcd60b543da8480b6bc7d03026f",
    "title": "Lumen Explainer Video",
    "video_id": "1af65ebabfdc48ed84fc2f4ec2abd20f"
  }
}
```

With the [CLI](/cli), the same turn is `heygen video scenes get <video_id>` followed by `heygen video-agent send <session_id> -d edit_plan.json`.

## What to expect

| Situation                         | What happens                                                                                                                                      |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Narration                         | Say "keep the narration" and the scene keeps its script while the visuals change. Give new copy and both change.                                  |
| Untouched scenes                  | Same script and visuals as before. The new draft is a new document, so scene and element ids are reissued; compare by content, not by id.         |
| Several edits in a row            | Each accepted turn returns the current working draft in `video_id`. Read that draft's scenes for the next `edit_version`.                         |
| `edit_version` no longer current  | `409 stale_edit_version`. Read the scenes again and resend with the new version.                                                                  |
| A `scene_id` outside the snapshot | `400 invalid_parameter`. The whole plan is rejected before anything is submitted, so a typo never produces a half-applied edit.                   |
| Reading scenes                    | A heavy read with a lower rate limit than `GET /v3/videos/{video_id}`. Poll the video for status and read scenes once it completes.               |
| Plan size                         | Up to 50 items per request, each up to 10,000 characters. Items may point at different snapshots from the same session, including earlier videos. |

## Edit with an agent

Ask a coding agent to make the change for you: it reads the scenes, picks the ones that match your description, and sends the plan.

```text Prompt for your agent wrap theme={null}
Read https://developers.heygen.com/docs/edit-scenes.md and https://developers.heygen.com/docs/for-ai-agents.md first. My HeyGen API key is in the HEYGEN_API_KEY environment variable; never ask me to paste it. Video Agent session <SESSION_ID> has a completed video <VIDEO_ID>. Call GET /v3/videos/<VIDEO_ID>/scenes, show me each scene's script in one line, and ask me which scenes to change and how. Then send one POST /v3/video-agents/<SESSION_ID> with an edit_plan covering only those scenes, using the scene ids and edit_version you read. Poll the returned video_id until completed and give me the video URL.
```
