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

# Create a video (async)

`POST /v1/videos`

## Request

- Base URL: `https://api.vivideo.ai`
- URL: `https://api.vivideo.ai/v1/videos`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/vivideo/apis/vivideo-api/docs/v1/videos/post.ts> (a function with typed inputs; its response is checked against the schema)

Starts a video generation. Premium accounts are charged credits
atomically and rendering starts immediately (`status: "processing"`).
Free accounts receive a one-time preview (`status: "preview"`) with an
upgrade link instead of a render.

Send an `Idempotency-Key` header so network retries can never create or
charge a duplicate video. Identical concurrent requests without one are
rejected with `409 duplicate_request`.

## Headers

- `Idempotency-Key` string

## Request body

- union
  - CreateVideoAuto
    - `mode` 'auto', required
    - `prompt` string, required
    - `duration_seconds` integer
    - `avatar_id` string: From GET /v1/avatars (optional).
    - `voice_id` string: From GET /v1/voices (optional).
    - `brand_kit_id` string: A brand_ref from GET /v1/brand-kits (optional).
    - `style_id` string: A HeyGen template/style id (optional).
    - `file_asset_ids` string[]: HeyGen asset_ids from POST /v1/assets — reference files the video agent can weave in.
    - `orientation` 'landscape' | 'portrait'
    - `folder_id` string
    - `name` string
  - CreateVideoManual: The operation is inferred from the inputs: text-to-video by default; image_to_video with image_url; first_last_frame with first_frame_url + last_frame_url; multiple_images with image_urls. resolution, duration_seconds, aspect_ratio and style are validated against the chosen model's allowed values (see GET /v1/models) — a 400 lists what's allowed.
    - `mode` 'manual', required
    - `model` string, required: A model id from GET /v1/models.
    - `prompt` string, required
    - `duration_seconds` integer: Must match one of the model's durations (e.g. 4 for '4s').
    - `resolution` string: Must be one of the model's resolutions.
    - `aspect_ratio` string: Must be one of the model's aspect_ratios.
    - `negative_prompt` string: Models with supports_negative_prompt.
    - `seed` integer: Models with supports_seed.
    - `generate_audio` boolean: Models with native_audio.
    - `style` string: One of the model's styles (e.g. PixVerse anime).
    - `movement_amplitude` string: Vidu motion control (auto/small/medium/large).
    - `cfg_scale` number: Kling prompt-adherence 0–1.
    - `camera_fixed` boolean
    - `auto_fix` boolean
    - `image_url` string: Switches the request to image_to_video.
    - `first_frame_url` string: With last_frame_url → first_last_frame.
    - `last_frame_url` string
    - `end_image_url` string
    - `image_urls` string[]: Reference images → multiple_images (models that support it, e.g. veo31_fast).
    - `folder_id` string
    - `name` string

## Response `201`

Video accepted (processing) or free preview created.

- Video
  - `id` string
  - `object` string
  - `mode` 'auto' | 'manual'
  - `model` string
  - `status` 'queued' | 'processing' | 'completed' | 'failed' | 'preview'
  - `name` string
  - `folder_id` string
  - `created_at` string
  - `credits_charged` number
  - `poll_interval_seconds` integer
  - `video_url` string: Present when status=completed.
  - `video_url_no_captions` string
  - `caption_url` string
  - `thumbnail_url` string
  - `duration_seconds` number
  - `progress` object
    - `status` string
    - `queue_position` integer, nullable
    - `percent` number, nullable
  - `error` object
    - `code` string
    - `message` string
    - `credits_refunded` boolean
  - `preview` object: Present when status=preview (free-account funnel).
    - `image_url` string, nullable: Low-res preview image — display blurred.
    - `image_note` string
    - `message` string
    - `upgrade_url` string

## Other responses

- `400`: Invalid parameters (`invalid_request`, `unknown_model`, `invalid_url`).
- `401`: Missing, malformed or revoked API key (`missing_api_key`, `invalid_api_key`, `api_key_revoked`).
- `402`: Not enough credits (`insufficient_credits`); `links.buy_credits` points to the top-up page.
- `403`: Premium plan required or the free allowance is used (`upgrade_required`, `free_limit_reached`); `links.upgrade` = https://app.vivideo.ai/upgrade.
- `409`: Duplicate request (`duplicate_request`) or an Idempotency-Key still in flight (`idempotency_in_flight`).
- `429`: Rate limit hit (`rate_limited`). Honor the `Retry-After` header / `retry_after_seconds` field.

---

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