# Video

> Generate a 5–20 second clip from a prompt, optionally opening and closing on images from your library, and poll until it is ready.

`POST /v1/videos` takes a prompt and answers at once with a `gen_…` id. A clip takes minutes to make: poll `GET /v1/videos/{id}` until `status` is terminal, then download the MP4 from `video.url`. Every finished clip is also saved in your [asset library](https://docs.lumavox.ai/library/assets.md).

```bash title="curl"
curl https://api.lumavox.ai/v1/videos \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Waves rolling onto a black sand beach at dusk, slow dolly forward",
    "duration": 5,
    "resolution": "hd"
  }'
```

```json title="Response — 202 Accepted (abridged)"
{
  "id": "gen_a1B2c3D4e5F6g7H8",
  "status": "queued",
  "capability": "video",
  "model": "flux-3-video",
  "prompt": "Waves rolling onto a black sand beach at dusk, slow dolly forward",
  "aspect_ratio": "16:9",
  "width": 1280,
  "height": 720,
  "duration": 5,
  "resolution": "hd",
  "generate_audio": true,
  "start_frame": null,
  "end_frame": null,
  "credits_micros": 25000000,
  "video": null,
  "error": null,
  "created_at": "2026-10-24T09:20:11.502Z",
  "finished_at": null
}
```

A generation has the same fields whatever made it; [Images](https://docs.lumavox.ai/media/images.md) shows them all. `credits_micros` is what was charged, in micro-credits ([Conventions](https://docs.lumavox.ai/conventions.md#credits)).

The key needs the `video` scope. See [Authentication](https://docs.lumavox.ai/authentication.md).

## Poll until it finishes

Video is slow — expect minutes, not seconds — so poll every several seconds rather than continuously. `queued`, `submitted` and `running` mean keep going; `succeeded`, `failed` and `moderated` are final. [Queued jobs](https://docs.lumavox.ai/jobs.md) covers the pattern.

```bash title="curl"
curl https://api.lumavox.ai/v1/videos/gen_a1B2c3D4e5F6g7H8 \
  -H "Authorization: Bearer $API_KEY"
```

```json title="Response — succeeded (abridged)"
{
  "id": "gen_a1B2c3D4e5F6g7H8",
  "status": "succeeded",
  "capability": "video",
  "video": {
    "asset_id": "ast_Q9r8S7t6U5v4W3x2",
    "url": "https://…",
    "width": 1280,
    "height": 720,
    "duration_seconds": 5,
    "content_type": "video/mp4",
    "size_bytes": 6241920,
    "has_thumbnail": true
  },
  "error": null,
  "created_at": "2026-10-24T09:20:11.502Z",
  "finished_at": "2026-10-24T09:23:40.118Z"
}
```

- **The clip is always an MP4.**
- **`video.url` is a short-lived link** — about fifteen minutes, made fresh on every response. Poll again, or read the asset with `GET /v1/assets/{asset_id}`, for a new one.
- **`video.asset_id`** is the library entry, which keeps the clip after the link expires.
- **`error`** says why, when the status is `failed` or `moderated`.

## What you can set

Only `prompt` is required.

| Field | Default | What it does |
|---|---|---|
| `prompt` | — | What should happen in the clip. 1–4,000 characters. |
| `aspect_ratio` | `16:9` | One of `21:9`, `2:1`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`. Video accepts `2:1`, which images do not. |
| `duration` | `5` | Whole seconds, `5` to `20`. **Charged per second.** The finished clip's measured length is `video.duration_seconds`. |
| `resolution` | `hd` | `hd` (720p) or `fhd` (1080p). **The two are priced differently per second.** |
| `generate_audio` | `true` | Generate audio along with the picture. Set `false` for a silent clip. |
| `safety_tolerance` | `2` | `0` (strictest) to `4` — the ceiling is 4 for video, not the 5 images allow. |
| `start_frame` | none | An `ast_…` image in your library to open the clip on. |
| `end_frame` | none | An `ast_…` image to close the clip on. Requires `start_frame`. |
| `folder_id` | root | The `fld_…` folder in your library the finished clip goes in. |

### Resolution and shape

`resolution` sets the long edge — 1280 pixels for `hd`, 1920 for `fhd` — and `aspect_ratio` the other. `16:9` at `hd` is 1280 × 720; `9:16` at `hd` is 720 × 1280. The 202 response carries the `width` and `height` the clip will have.

### Animating your own images

Leave both frames out for text-to-video. Give `start_frame` to animate a still from your library — a product shot, a generated image, an upload:

```json title="Request body"
{
  "prompt": "The camera slowly orbits the helmet as the light shifts",
  "start_frame": "ast_a1B2c3D4e5F6g7H8",
  "end_frame": "ast_Z9y8X7w6V5u4T3s2",
  "duration": 8
}
```

- `start_frame` is pinned at the start of the clip; `end_frame` at `duration`.
- `end_frame` on its own is refused (422) rather than treated as an opening frame.
- Each frame must be an image in your library whose `status` is `ready`. One that is missing, not yours, not an image, or still processing is a 422, and nothing is charged.

[Images](https://docs.lumavox.ai/media/images.md) and the [upload flow](https://docs.lumavox.ai/library/assets.md#upload-a-file) are the two ways to get a frame into the library.

## Charges and refunds

- **Charged when accepted**, at `duration` × the per-second rate for the `resolution`. `credits_micros` on the 202 is what was charged.
- **Refunded in full** if the generation ends `failed` or `moderated`.
- **There is a limit on how many of your videos may be unfinished at once.** Over it, the request is a 429 and nothing is charged; the message says how many are running.

[Credits and usage](https://docs.lumavox.ai/usage.md) explains balances and plans.

## Errors

| Status | When |
|---|---|
| 400 | The body is not valid JSON. |
| 422 | A frame or `folder_id` that is missing, is not yours, or is not a ready image. |
| 402 | Your organisation has run out of credits, or this job's estimate would take its balance past the grace buffer. Nothing is charged. |
| 403 | The key does not hold the `video` scope. |
| 404 | (Poll) No video generation with that id in your organisation. |
| 422 | The body failed validation: an `aspect_ratio` or `resolution` outside its set, `duration` out of range, `end_frame` without `start_frame`, an empty prompt, an unknown field. `issues` names each. |
| 429 | Too many requests, or too many of your videos are still generating. Nothing was charged. |
| 503 | Video generation is not available on this deployment. |

See [Errors and limits](https://docs.lumavox.ai/errors.md) for the error shape.

## See also

- [Images](https://docs.lumavox.ai/media/images.md) — make the frames to animate.
- [Templates](https://docs.lumavox.ai/media/templates.md) — video generations someone has already designed.
- [The videos reference](https://docs.lumavox.ai/reference/videos.md) — every field.
