---
title: "Create a video generation task"
method: POST
path: "/api/v1/videos"
tags: ["Generation"]
---

# Create a video generation task

`POST /api/v1/videos`

## Request

- Base URL: `https://viewmax.studio`
- URL: `https://viewmax.studio/api/v1/videos`
- Auth: HTTP bearer

Validates the request, charges credits, and submits the job before responding; the video renders asynchronously. Poll GET /api/v1/tasks/{taskId}. Omitted duration, resolution and aspect_ratio take `modes.<mode>.defaults` from GET /api/v1/models before pricing.

## Headers

- `Idempotency-Key` string

## Request body

- CreateVideoRequest
  - `model` string, required: Model id from GET /api/v1/models. Offline models return 400 `video model temporarily unavailable: <id>. ...`.
  - `prompt` string, required: Trimmed. At most the model's `max_prompt_length` characters when the catalog lists one (`minimax-h3`: 7000).
  - `mode` 'text-to-video' | 'image-to-video' | 'video-to-video' | 'frames-to-video' | 'reference-to-video': Must be a key of the model's `modes`. Default: `image-to-video` when `image_urls` is non-empty, else `video-to-video` when `video_urls` is non-empty, else `text-to-video`.
  - `image_urls` string[]: http(s) URLs the provider can fetch without authentication. image-to-video: 1 (some models 2); frames-to-video: 2 (start, end); reference-to-video: 1 or more. Per-model maximums are in the docs.
  - `video_urls` string[]: One source video. Required for `video-to-video`; optional for `reference-to-video` on Seedance 2.0, 2.0 Fast, 2 Mini and MiniMax H3.
  - `options` VideoOptions: Values must come from the model's `modes.<mode>` in GET /api/v1/models. Omitted `duration`, `resolution` and `aspect_ratio` take `modes.<mode>.defaults` before pricing. Other keys are forwarded unvalidated.
    - `duration` union: `"8s"`, `"8"` and `8` are equivalent.
      - string
      - integer
    - `resolution` string: Case-insensitive; send the catalog spelling, e.g. `720p`, `4k`, `768P`, `2K`.
    - `aspect_ratio` string: Exact case, e.g. `16:9`, `Auto`.
    - `audio` boolean: `true` only when `audio_toggle` is true; `false` is always accepted.
    - `source_video_duration_seconds` number: Source video length. Required with `video_urls` when the mode lists `credits_per_second` (Seedance 2.x, Seedance 2.5, MiniMax H3).

## Response `200`

Task created, or the existing task for a repeated `Idempotency-Key`.

- object
  - `code` 0, required
  - `message` 'ok', required
  - `data` Task, required: Generation task. Returned by every create endpoint and by GET /api/v1/tasks/{taskId}.
    - `id` string, required: Task id. Poll GET /api/v1/tasks/{taskId} with it.
    - `status` 'pending' | 'processing' | 'success' | 'failed' | 'canceled', required: `pending`/`processing`: keep polling. `success`: read `taskUrls`. `failed`/`canceled`: terminal, credits refunded.
    - `mediaType` 'video' | 'image' | 'music' | 'audio', required
    - `scene` string: Mode or scene, e.g. `text-to-video`, `text-to-image`, `text-to-music`, `text-to-speech`, `text-to-sound-effects`.
    - `model` string: Model identifier used for the job. May differ from the catalog id sent in the request.
    - `prompt` string
    - `options` string, nullable: JSON-encoded options as priced and submitted, including filled-in defaults and `mode` for video.
    - `taskUrls` string[], required: Result URLs. Empty until the task succeeds.
    - `costCredits` integer, required: Credits charged. `0` when a plan allowance covered it.
    - `waivedCredits` integer: Normal price waived by a plan allowance; otherwise `0`.
    - `fairUseKey` string, nullable: Plan allowance slot used by this task, or `null`.
    - `taskInfo` string, nullable: JSON string. While pending/processing/success it holds job diagnostics whose shape is not stable. On `failed`/`canceled` it is `{"errorCode","error","errorMessage"}`; `errorCode` is one of `insufficient_credits`, `auth_required`, `rate_limited`, `request_cancelled`, `provider_unavailable`, `invalid_input`, `content_rejected`, `busy`, `duplicate_request`, `generic`. `errorMessage` carries the provider's reason only for `invalid_input`.
    - `taskResult` string, nullable: JSON string. Same failure payload as `taskInfo` on `failed`/`canceled`; otherwise job diagnostics with no stable shape.
    - `taskId` string, nullable: Upstream job id (diagnostic only).
    - `createdAt` string, date-time
    - `updatedAt` string, date-time
    - `userId` string
    - `creditId` string, nullable
    - `visibility` string
    - `deletedAt` string, date-time, nullable

## Other responses

- `400`: `invalid_request`: fix the request using `message` before retrying (includes disabled or offline models). `content_rejected`: change the prompt or media. When the provider rejected an accepted task, `error.task_id` is set and the task is failed and refunded.
- `401`: Missing or invalid API key (`code: -1001`).
- `402`: Balance below the task cost (`code: -1002`). No task was created; do not retry until credits are added.
- `500`: Provider or server failure. With `error.task_id` the task failed and was refunded: retry once. When the hint says the outcome is unknown, the task stays `pending` with the charge kept: poll it instead of retrying.
- `503`: External content-safety check temporarily unavailable. Retry after a short delay.

---

[API](https://skmtc.dev/viewmax/apis/viewmax-studio-api.md) · [All operations](https://skmtc.dev/viewmax/apis/viewmax-studio-api/llms.txt) · [OpenAPI document](https://skmtc.dev/viewmax/apis/viewmax-studio-api/revisions/c4f378e09f44?raw)
