> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dreamlayer.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Video jobs and recovery

> Follow video state, resume events, download owned MP4s, cancel queued work, and handle failures without duplicate charges.

## What this lets you do

Finish a Video integration after accepting a quote: track the execution, recover interrupted connections, download the result, and handle cancellation or failure.

## What you need

* The `execution_id` returned by quote acceptance, saved as `VIDEO_EXECUTION_ID`
* The API key for the owning account
* The saved acceptance body and original idempotency key for uncertain submissions

## Steps

### 1. Read canonical state

```bash theme={null}
curl --fail-with-body "https://api.dreamlayer.io/v1/executions/$VIDEO_EXECUTION_ID" \
  -H "Authorization: Bearer $DREAMLAYER_API_KEY" \
  -H "DreamLayer-Version: 1" --output video-state.json

jq '{execution_id, status, video_job: (.video_job | {
  stage, requested_settings, metadata, download_url, error_code,
  credits, reserved_credits, settled_credits, credits_restored,
  billing_note, retention_expires_at
})}' video-state.json
```

`image_job` is `null` for Video. Use `video_job` and the top-level `status`.

| State | Meaning and next action |
| - | - |
| `queued` | Accepted and waiting to start. Cancellation is available only while still queued. |
| `submitting` | Starting the generation. Do not submit another copy. |
| `uncertain` | The service is reconciling an ambiguous result. Keep the execution ID and check billing fields; do not assume failure or start a replacement automatically. |
| `generating` | Generation is in progress. Continue following this execution. |
| `delivering` | The output is being prepared for owned delivery. Wait for completion. |
| `completed` | The output is available until its retention expiry. |
| `failed` | Inspect `video_job.error_code` and billing fields. A deliberate replacement is a new request. |
| `cancelled` | Queued work was cancelled and its credit hold restored. |
| `expired` | Output retention ended. The old asset is no longer downloadable. |

States can be skipped between reads. A response with HTTP `200` means the read succeeded, not that generation succeeded. Recovery may later deliver unresolved work; a restored hold alone is not proof that all processing has stopped.

### 2. Follow or resume events

```bash theme={null}
curl --no-buffer "https://api.dreamlayer.io/v1/executions/$VIDEO_EXECUTION_ID/events" \
  -H "Authorization: Bearer $DREAMLAYER_API_KEY" \
  -H "DreamLayer-Version: 1"
```

Video uses `progress`, `asset`, and `done` events. `progress` carries `{"text":"generating"}`-style display updates and a persisted event ID. `asset` contains the execution's asset ID and owned `download_url`. `done` ends that stream. Do not expect an initial `started` event; obtain the execution ID from the acceptance response.

Save the last fully processed event ID and reconnect with `Last-Event-ID`. Only send it when you have a cursor. Terminal events can be repeated on reconnect and need not carry an ID; deduplicate handling using the execution ID and read canonical status. Streams can close before completion, so a disconnect is not a cancellation or failure. Use status reads for `expired` and billing details rather than inferring them from `done`.

Limit polling and reconnects, and close unused streams. Video permits three open streams per API key. A five-second polling interval is a reasonable starting point, not a completion guarantee. See [shared request limits](/agent-api/limits).

### 3. Download the MP4

Once state is `completed`, the owned path is `/v1/video/executions/{execution_id}/asset`:

```bash theme={null}
curl --fail --location --proto '=https' --proto-redir '=https' \
  "https://api.dreamlayer.io/v1/video/executions/$VIDEO_EXECUTION_ID/asset" \
  -H "Authorization: Bearer $DREAMLAYER_API_KEY" \
  -H "DreamLayer-Version: 1" \
  --output dreamlayer-video.mp4
```

Use a current curl that strips Authorization on cross-origin redirects. **Do not use `--location-trusted`.** Other HTTP clients should request the API URL without following redirects, then fetch its HTTPS `Location` without API credentials. Never forward a bearer key to the storage destination or log signed URLs.

The API issues a signed link valid for 15 minutes. Output is retained for 30 days after completion; `retention_expires_at` is authoritative. If the signed link expires, request a new one from the same owned endpoint. Save your MP4 before retention ends. An expired link is not a reason to regenerate.

### 4. Cancel only eligible work

Cancellation is an optional action and succeeds only while the Video execution is `queued`:

```bash theme={null}
curl --fail-with-body --request POST \
  "https://api.dreamlayer.io/v1/executions/$VIDEO_EXECUTION_ID/cancel" \
  -H "Authorization: Bearer $DREAMLAYER_API_KEY" \
  -H "DreamLayer-Version: 1"
```

Success returns `202` with `status: cancelled` and restores the hold. A job may start between your status read and cancellation; then the API returns `409 conflict`. Read state instead of repeatedly cancelling. Closing a browser, terminal, or stream never cancels a video. Sprite-sheet cancellation rules are different.

## Confirm it worked

For delivery, check `completed`, download and play the MP4, and inspect `settled_credits`. For cancellation, check `cancelled` and `credits_restored`. Record the execution ID for support without putting credentials, prompts, full response bodies, or signed URLs into public logs.

## Common errors

Video business errors carry `error.code`, `error.reason`, `message`, and `retryable`. Framework validation and authentication errors can use the [shared error envelope](/agent-api/errors); do not require every Video error to contain `category` or `request_id`. Save `X-Request-ID` when present.

| Signal | Action |
| - | - |
| `401` or missing-header `422` | Correct authentication and required headers. |
| `403 route_unavailable` or `access_denied` | Check Video availability and use a supported API key, not an image-only installation connection. |
| `422 unsupported_duration`, `unsupported_settings`, or `clarification_required` | Revise the request and obtain a new quote. No generation started at quoting. |
| `409 quote_expired` | No new execution was admitted. Obtain and approve a fresh quote. Check a known execution first after uncertainty. |
| `409 pricing_unavailable` or `price_exceeds_limit` | Do not accept pending pricing or silently increase the user's approved ceiling. |
| `409 idempotency_conflict` | Restore the original body and key. Do not assign a new key automatically. |
| `402 insufficient_credits` on acceptance | Add API credits. This is a synchronous rejection, unlike image admission. |
| `429 too_many_active_jobs` on acceptance | Wait for capacity, back off, and retry the same approved request while its quote is valid. |
| Other `429` | Back off for request or stream limits; follow existing work. |
| `404 resource_not_found` | Check ownership, ID, and output completion. |
| `410 asset_expired` on download | Retention ended; the old MP4 cannot be retrieved. |
| `503` or lost acceptance response | Recover the original execution or replay its saved acceptance and key. Do not start a replacement automatically. |

## Troubleshooting

Persist the quote, acceptance body, idempotency key, execution ID, and event cursor securely. If acceptance returns no response, resend **the same `quote_id` and `max_credits` with the same API key and idempotency key**. An accepted quote is single-use and returns its existing execution, including after quote expiry. An unaccepted expired quote cannot start work.

For a long-running `uncertain` execution, inspect `credits_restored` and `billing_note` and contact support with its ID. Restored credits and later delivery do not trigger a second charge. Creating a new quote and accepting it can create a second video and charge; do that only deliberately.

## Next steps

* [Quote another text video](/agent-api/text-to-video)
* [Quote an image animation](/agent-api/image-to-video)
* [Pricing and sound](/agent-api/video-settings)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.