---
title: "Create a video"
method: POST
path: "/v1/videos"
tags: ["Videos"]
---

# Create a video

`POST /v1/videos`

## Request

- Base URL: `https://api.naga.ac`
- URL: `https://api.naga.ac/v1/videos`
- Auth: one of:
  - HTTP bearer
  - API key in header `x-api-key`
- TypeScript: <https://skmtc.dev/naga/apis/nagaai-api/docs/v1/videos/post.ts> (a function with typed inputs; its response is checked against the schema)

Starts a video job and answers `202` at once: a clip takes from half a minute to several minutes. Requires an API key. Poll `GET /v1/videos/{id}` until `status` is `completed` or `failed`, then fetch the file from `GET /v1/videos/{id}/content`. NagaAI holds the full price of the clip on the balance while the job runs and charges it once, when the clip is ready. A job that fails is not charged.

## Request body

- VideosGenerationsRequest: Start one video generation job.
  - `model` string, required: The video model, named by its id or alias.
  - `prompt` string, required: What to generate, in words. One to 8192 characters, and moderation screens it first.
  - `duration` integer, nullable: Clip length in seconds; one of the `duration` values the model's `video_generation` operation lists in `GET /v1/models`. Absent takes its default.
  - `resolution` string, nullable: One of the `resolution` values the operation lists, such as `720p`. Absent takes its default.
  - `aspect_ratio` string, nullable: One of the `aspect_ratio` values the operation lists, such as `16:9`. Absent takes its default.
  - `frame_images` VideoFrameImage[], nullable: Images that become the first or the last frame, one per frame type.
    - `type` string, required: Always `image_url`.
    - `image_url` VideoImageUrl, required: The `{ "url": … }` wrapper the chat dialect uses for an image too; a video reference wears the same one.
      - `url` string, required: A public `https` URL or a `data:` URI.
    - `frame_type` string, required: `first_frame` or `last_frame`.
  - `input_references` VideoInputReference[], nullable: Images or videos the clip should follow — a character, an object, a style or a motion — not frames it starts or ends on. Only a model whose operation lists `input_references` takes them: its `properties` give the most of each `type`.
    - `type` string, required: `image_url` or `video_url`.
    - `image_url` object, nullable: The image, when `type` is `image_url`: a public `https` URL or a `data:` URI.
      - `url` string, required: A public `https` URL or a `data:` URI.
    - `video_url` object, nullable: The video, when `type` is `video_url`: a public `https` URL.
      - `url` string, required: A public `https` URL or a `data:` URI.
  - `generate_audio` boolean, nullable: Ask for a soundtrack. Only a model whose operation lists `generate_audio` accepts `true`, and the audio price applies.
  - `seed` integer, nullable: A seed for repeatable output, where the model supports one.

## Response `202`

The job, accepted and queued. Poll `polling_url` until `status` is `completed` or `failed`.

- VideoJob: A video job as the gateway reports it.
  - `id` string, required: The job id; the polling and content URLs carry it.
  - `object` string, required: Always `video.generation`.
  - `model` string, required: The model the job was submitted for, as the caller named it.
  - `status` string, required: `pending`, `in_progress`, `completed` or `failed`.
  - `polling_url` string, required: Where to poll this job.
  - `created_at` integer, required: Unix seconds when the job was accepted.
  - `completed_at` integer, nullable: Unix seconds when the job reached `completed` or `failed`.
  - `duration` integer, required: The requested clip length in seconds.
  - `resolution` string, required: The requested resolution.
  - `aspect_ratio` string, required: The requested aspect ratio.
  - `urls` string[], nullable: Links to the finished file; present once the job is `completed`.
  - `usage` object, nullable: What the job was charged; present once the job is `completed`.
    - `cost` string, required: Credits charged, as a decimal string.
    - `seconds` integer, required: Seconds of video the charge counts.
  - `error` object, nullable: Why the job failed; present only when it is `failed`. A failed job is not charged.
    - `message` string, required: A short, provider-neutral reason.
    - `type` string, required: `upstream_error`, `moderation` or `timeout`.

## Other responses

- `400`: The request is malformed: a field failed its constraint, the body is not valid JSON, the model is unknown, or a value is not one the model supports.
- `401`: The API key is missing, malformed, disabled, or does not belong to an account that may call this route.
- `402`: The balance, less the holds of the account's running video jobs, does not cover the full price of this one.
- `403`: The prompt was blocked by the moderation policy, or what is left of the key's credit limit does not cover the price.
- `413`: The request body is larger than the 32 MiB this gateway accepts.
- `500`: The gateway failed for a reason of its own. Report it — this status marks NagaAI's own bugs, never an upstream verdict.
- `503`: No upstream could take the job, or a store the gateway needs did not respond. `Retry-After`, when present, carries the suggested wait.

## Changes

- **2026-11-07** `cc10e5c4f3b5`: 1 info
  - added the new optional request property `input_references`
- **2026-11-03** `b697d49fa1f9`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/naga/apis/nagaai-api/changes/v1/videos/post.md)

---

[API](https://skmtc.dev/naga/apis/nagaai-api.md) - [All operations](https://skmtc.dev/naga/apis/nagaai-api/llms.txt) - [OpenAPI document](https://skmtc.dev/naga/apis/nagaai-api/revisions/cc10e5c4f3b5?raw)
