Video generation

POST /v1/videos

Asynchronous video generation. Rendering takes a while (typically tens of seconds to a few minutes), so it uses a submit + poll model: submit returns a task ID immediately, then you poll for the result.

Supports text-to-video, image-to-video (single-image first frame / first-and-last frame / multi-image reference), plus reference video and reference audio for advanced use.

1. Submit: POST /v1/videos

1.1 Request parameters

Parameter Type Required Description
model string Yes Video model ID. See 1.2 Models.
prompt string Yes Text prompt. With reference assets you must refer to them explicitly as @Image1 / @Video1 / @Audio1 — see 1.4 @ reference syntax.
seconds string Yes Duration in seconds, as a string, range "5""15".
aspect_ratio string No Aspect ratio, default 16:9. Allowed values in 1.3 Value ranges.
resolution string No Resolution. Determined by the chosen model (see 1.2 Models); usually no need to send it.
size string No Standard parameter — a pixel string, one of 1280x720 / 1920x1080 / 720x1280 / 1080x1920, expressing orientation + resolution in a single field (the gateway translates it into whatever shape the target model's upstream expects). aspect_ratio + resolution are an optional, more granular equivalent; if both are sent, the explicit aspect_ratio / resolution wins.
image_url string No Single reference image, https:// URL or base64 data: URL, used as the first frame for image-to-video. Also accepts an asset:// asset reference (then treated as a character reference, not a first frame — see 1.5 Virtual-character asset library). Use this when you have only 1 image. Image inputs do not add billed tokens.
reference_image_urls string[] No Multiple reference images (up to 9) for style / character consistency, each a URL, data URL, or asset:// asset reference (see 1.5 Virtual-character asset library). @ImageN maps to the Nth item.
reference_video string No Reference video (send alongside reference_videos; value = first array item).
reference_videos string[] No Reference video array (up to 3, total length ≤ 15s). Note: the reference video's content adds to billed tokens (e.g. a 5s reference video adds roughly 108,900 tokens), but requests with video input are billed at a lower "with video input" per-token price tier — both tier prices are listed in the console model catalog.
audio_url string No Reference audio, e.g. for voice style (send alongside reference_audios; value = first array item). Requires ≥1 reference image.
reference_audios string[] No Reference audio array (up to 3, total length ≤ 15s). mp3 / wav / m4a / aac / ogg / flac, etc.
video_config object No Advanced config; currently supports reference_mode. See 1.3 Value ranges.
generate_audio boolean No Whether to include the model-generated soundtrack (music / sound effects). Defaults to true; set false for a silent video.
seed integer No Random seed. With the same seed and otherwise identical parameters, generations are reproducible.

Video generation requires an active subscription (token-based billing, see 3. Billing). Without one the API returns 402.

1.2 Models

There are two product lines: a domestic line and an overseas line (-hw suffix), with independent capabilities and pricing. The overseas line supports the virtual-character asset library (asset://); the domestic line does not. Per-model prices are in the console model catalog.

Model Output Line Asset library Notes
doubao-seedance-2-0 720p Domestic Standard definition. Omni reference (image + video + audio) and extreme aspect ratios.
doubao-seedance-2-0-1080p 1080p Domestic High definition; same capabilities, higher resolution (slower, more tokens per video).
doubao-seedance-2-0-hw 720p Overseas Standard definition; same as domestic 720p plus the virtual-character asset library.
doubao-seedance-2-0-1080p-hw 1080p Overseas High-definition overseas line.
doubao-seedance-2-0-fast-hw 720p Overseas Fast variant — faster generation, lower per-token price.

1.3 Value ranges

Parameter Allowed values / limits
seconds Integer string, "5""15" (inclusive).
aspect_ratio 16:9 / 9:16 / 1:1 / 4:3 / 3:4 / 21:9 (default 16:9).
resolution Determined by the model: 720p tier (doubao-seedance-2-0 / -hw / -fast-hw) → 720p, 1080p tier (doubao-seedance-2-0-1080p / -1080p-hw) → 1080p.
size Standard values: 1280x720 / 720x1280 (720p models), 1920x1080 / 1080x1920 (1080p models). Non-standard aspect ratios (e.g. 21:9's 1680x720) still need aspect_ratio + resolution.
video_config.reference_mode auto (default, multi-image reference) / start_frame (first frame, exactly 1 image) / start_end (first + last frame, exactly 2 images, no reference video).
Reference images up to 9.
Reference videos up to 3, total length ≤ 15s.
Reference audios up to 3, total length ≤ 15s, and require ≥1 reference image.

Portrait: send size:"720x1280" (recommended), or the equivalent aspect_ratio:"9:16" + resolution:"720p". If both are sent, the explicit aspect_ratio / resolution wins. Image-to-video: send image_url (single) or reference_image_urls (multiple), and refer to the image as @Image1 in prompt — otherwise the model won't condition on the reference image.

1.4 @ reference syntax

With reference assets, the model relies on @ImageN / @VideoN / @AudioN in prompt to know each asset's role. Assets are cited by type + index (e.g. Image 1 / Video 1 / Audio 1), numbered by their order of appearance in the request:

  • @Image1 = reference_image_urls[0] (or image_url for a single image), @Image2 = reference_image_urls[1], and so on
  • @Video1 = reference_videos[0], and so on
  • @Audio1 = reference_audios[0], and so on

With multiple assets you must reference them explicitly via @, otherwise the model guesses which image is which.

1.5 Virtual-character asset library

Besides https:// URLs and base64 data: URLs, the reference-image fields also accept asset://<asset ID> references — virtual-character material that is private to your org and that you upload beforehand to your own asset library. Upload it first via the asset library API to obtain an asset:// ID, then reference it in the video request:

{ "image_url": "asset://asset-20260713-xyz" }

Rules:

  • Assets are private to your org: only the creating org can reference its own asset:// IDs; referencing another org's (or a nonexistent) ID returns 400. See the asset library API to upload / list / delete.
  • An asset:// reference may go in image_url or as any item of reference_image_urls, and can be mixed with plain URLs / data URLs (e.g. "library character + your own scene image").
  • An asset:// item is always treated as a character reference — even in the image_url field it is not used as a first frame. For first-frame semantics, use a plain URL / data URL.
  • In prompt, refer to it as @ImageN per 1.4 @ reference syntax — numbering works exactly like regular reference images (by order of appearance in the request).
  • Like regular reference images, asset references do not add billed tokens, and they count toward the "up to 9 reference images" limit.
  • Overseas line (-hw series) only: doubao-seedance-2-0-hw / -1080p-hw / -fast-hw. The domestic line (doubao-seedance-2-0 / -1080p) does not support asset://.

1.6 Response

A successful submit returns immediately (task queued, video not produced yet):

{ "id": "task_xxxxxxxx", "status": "queued", "seconds": 5 }

Use the id field as the task ID for polling.

A successful submit is not a produced video. A queued task can still fail (e.g. content-safety rejection); wait for a terminal state via polling.

1.7 Examples

Text-to-video (size only, standard usage)

Sending size alone is enough to fix both orientation and resolution — no need to also send aspect_ratio / resolution:

curl https://api.portal.aiin1.ai/v1/videos \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "doubao-seedance-2-0",
    "prompt": "a red fox running in snow, cinematic",
    "seconds": "10",
    "size": "720x1280"
  }'

Text-to-video (landscape)

curl https://api.portal.aiin1.ai/v1/videos \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "doubao-seedance-2-0-1080p",
    "prompt": "A cinematic tracking shot through a neon-lit rainy street at night, slow dolly-in, 35mm grain",
    "aspect_ratio": "16:9",
    "size": "1920x1080",
    "seconds": "10"
  }'

Text-to-video (portrait)

curl https://api.portal.aiin1.ai/v1/videos \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "doubao-seedance-2-0",
    "prompt": "a red fox running in snow, cinematic",
    "seconds": "10",
    "aspect_ratio": "9:16",
    "resolution": "720p",
    "size": "720x1280"
  }'

Image-to-video (single-image first frame)

The reference image may be an https:// URL or a base64 data: URL. The prompt must refer to it as @Image1.

curl https://api.portal.aiin1.ai/v1/videos \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "doubao-seedance-2-0",
    "prompt": "@Image1 as the first frame, slow camera push-in, the character turns to look into the distance",
    "seconds": "10",
    "size": "720x1280",
    "image_url": "https://example.com/start-frame.jpg",
    "video_config": { "reference_mode": "start_frame" }
  }'

Image-to-video (multi-image: character + setting)

curl https://api.portal.aiin1.ai/v1/videos \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "doubao-seedance-2-0",
    "prompt": "@Image1 character wearing a white dress, dancing in the setting from @Image2, anamorphic lens",
    "aspect_ratio": "21:9",
    "resolution": "720p",
    "size": "1680x720",
    "seconds": "15",
    "reference_image_urls": [
      "https://example.com/character.jpg",
      "https://example.com/setting.jpg"
    ]
  }'

Image-to-video (first + last frame: exactly 2 images)

curl https://api.portal.aiin1.ai/v1/videos \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "doubao-seedance-2-0",
    "prompt": "Smoothly transition from the first frame to the second, with natural camera movement and lighting changes",
    "seconds": "10",
    "size": "1280x720",
    "reference_image_urls": [
      "https://example.com/start-frame.jpg",
      "https://example.com/end-frame.jpg"
    ],
    "video_config": { "reference_mode": "start_end" }
  }'

Virtual-character asset library (asset:// reference)

Mixing a library character with your own scene image — @Image1 refers to the asset, @Image2 to the scene. The model must be an overseas -hw name (the domestic line does not support asset://):

curl https://api.portal.aiin1.ai/v1/videos \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "doubao-seedance-2-0-hw",
    "prompt": "@Image1 character standing in the setting from @Image2, waving at the camera and smiling, natural light",
    "seconds": "5",
    "size": "1280x720",
    "reference_image_urls": [
      "asset://asset-20260713-xyz",
      "https://example.com/scene.jpg"
    ]
  }'

Omni reference (image + video + audio)

When using audio_url / reference_audios you must also send ≥1 reference image, otherwise it errors.

curl https://api.portal.aiin1.ai/v1/videos \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "doubao-seedance-2-0",
    "prompt": "@Image1 character dancing to the rhythm of @Audio1, camera motion referencing @Video1, cut on strong beats",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "size": "1280x720",
    "seconds": "10",
    "reference_image_urls": [
      "https://example.com/character.jpg",
      "https://example.com/scene.jpg"
    ],
    "reference_video": "https://example.com/camera-motion.mp4",
    "reference_videos": ["https://example.com/camera-motion.mp4"],
    "audio_url": "https://example.com/track.mp3",
    "reference_audios": ["https://example.com/track.mp3"]
  }'

2. Poll: GET /v1/videos/{id}

curl https://api.portal.aiin1.ai/v1/videos/task_xxxxxxxx \
  -H "Authorization: Bearer YOUR_API_KEY"

status goes queuedprocessingcompleted (or failed). Rendering is slow; poll every few seconds.

In progress:

{ "id": "task_xxxxxxxx", "status": "processing" }

Completed:

{
  "id": "task_xxxxxxxx",
  "status": "completed",
  "video_url": "https://<bucket>.r2.cloudflarestorage.com/...&X-Amz-Signature=...",
  "usage": { "total_tokens": 108900 }
}

Failed:

{ "id": "task_xxxxxxxx", "status": "failed" }

About video_url: on completion you get a download link with limited validity — download or re-host it promptly. For a reliable way to fetch the file, prefer the /content endpoint below.

Field reference

Field Description
id Task ID for polling. Bound to your API key's organization; others cannot access it.
status queued / processing / completed / failed.
video_url Convenience download link on completion, with limited validity.
usage.total_tokens Returned on completion — the exact token count billed for this task; use it to reconcile invoices.

Download the video: GET /v1/videos/{id}/content

Besides the video_url convenience field in the poll response, you can also fetch the raw video bytes directly from a standard endpoint (compatible with the OpenAI SDK's .download_content()). Only available once the task is completed:

curl https://api.portal.aiin1.ai/v1/videos/task_xxxxxxxx/content \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o output.mp4

Returns binary content as Content-Type: video/mp4. Use whichever fits — video_url is convenient for direct distribution/preview but has limited validity; /content has no expiry concerns and is the recommended way to reliably fetch the video file in production.

3. Billing

  • Billed by generated tokens: cost = generated tokens × the per-1M-token price. Per-model unit prices are listed in the console model catalog.
  • The token count is deterministic for a given resolution and duration: 720p ≈ 21,780 tokens per second of video (5s ≈ 108,900); 1080p ≈ 49,005 tokens/s (5s ≈ 245,025). doubao-seedance-2-0-fast-hw uses the same token count as 720p, at a lower unit price.
  • Reference images do not add billed tokens. Requests containing a reference video do have the video's content added to the token count (e.g. a 5s reference video adds roughly 108,900 tokens), but the whole request is billed at the cheaper "with video input" per-1M-token unit price — both prices are visible in the console model catalog.
  • The poll response includes usage.total_tokens, which is exactly what gets billed — use it to reconcile invoices.
  • Settled when the video completes; failed / abandoned tasks are not billed.

4. Common errors

HTTP Scenario Notes
400 Missing model Incomplete request.
400 seconds wrong type seconds must be a string, e.g. "10" (not a number).
400 seconds out of range Range is "5""15".
400 Wrong field type e.g. size sent as a number, reference_image_urls not an array of strings.
400 Unsupported size value Only 1280x720 / 1920x1080 / 720x1280 / 1080x1920 are supported; use aspect_ratio + resolution for other aspect ratios.
400 Resolution does not match the model tier Resolution is determined by the model you pick: the 720p tier (doubao-seedance-2-0 / -hw / -fast-hw) renders 720p only, the 1080p tier (-1080p / -1080p-hw) renders 1080p only. A cross-tier size / resolution is rejected — switch to the matching model variant.
400 Too many reference assets images ≤ 9 / videos ≤ 3 / audios ≤ 3.
400 Audio without a reference image Audio reference requires ≥1 reference image.
401 Invalid API key Check the Authorization header.
402 No active subscription Video is billed per token; you need an active subscription first.
403 Model not allowed for this key Check the key's allowed models.
404 Task not found / not your org The polled id is wrong or not owned by the current key's org.
413 Request body too large Prefer https:// URLs for reference images; switch from a large data URL to a URL.
503 Temporarily unavailable Upstream timeout or no available channel; retry later.