Video Generation API · Tenant Integration Guide

Version v5 · 2026-10-09 · Somobai Video Generation Platform (changelog in §12)

The public API is compatible with the official Volcano Engine Ark API. If you have already integrated Ark video generation, migrating to this platform takes two changes: the domain and the credential. Request and response fields are unchanged. The asset library also offers a signed entry point compatible with the official Volcano Engine SDK (§9).


1. Quick Start

Three steps to your first video:

# 1. Check that your key works (lists the models you can use)
curl https://api.somobai.com/v1/models \
  -H "Authorization: Bearer sk-your-key-here"

# 2. Create a video task
curl -X POST https://api.somobai.com/api/v3/contents/generations/tasks \
  -H "Authorization: Bearer sk-your-key-here" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "doubao-seedance-2-0-260128",
        "content": [{"type": "text", "text": "A cat running across a meadow"}],
        "resolution": "720p",
        "duration": 5
      }'
# → {"id":"cgt-20260827103000-a1b2c"}

# 3. Poll until the task reaches a terminal state
curl https://api.somobai.com/api/v3/contents/generations/tasks/cgt-20260827103000-a1b2c \
  -H "Authorization: Bearer sk-your-key-here"

2. Authentication

All data-plane endpoints use a Bearer token:

Authorization: Bearer sk-xxxxxxxxxxxx

IP allowlist (required)

Authentication errors

HTTP code Meaning
401 unauthorized Missing or malformed Authorization header (does not start with Bearer sk-)
401 unauthorized Invalid, disabled or expired key
403 forbidden Client IP is not on the account's API allowlist, or no allowlist is configured
403 forbidden Client IP is not on the key's allowlist
403 forbidden Tenant is unavailable (suspended)

3. Video Generation

3.1 Create a task

POST /api/v3/contents/generations/tasks

Request headers

Header Required Description
Authorization Yes Bearer sk-xxx
Content-Type Yes application/json
Idempotency-Key No Idempotency key, see §3.2

Request body (same shape as the native Ark fields)

Field Type Required Description
model string Yes Model ID. Valid values come from GET /v1/models; supported specs are in §3.8
content array Yes Content array of text / image_url / video_url / audio_url items, optionally with a role (first_frame / last_frame / reference_image / reference_video / reference_audio)
resolution string No 480p / 720p / 1080p / 4k, default 720p. Per-model support in §3.8
duration int No Seconds, default 5. The Seedance 2.0 family requires a positive integer from 4–15. Seedance 2.5 accepts 4–30, or -1 to let the model decide
ratio string No 16:9 / 4:3 / 1:1 / 3:4 / 9:16 / 21:9 / adaptive
seed int No Random seed. Fix it for reproducible output; default -1
generate_audio bool No Whether to generate audio
watermark bool No Whether to add an AI watermark
return_last_frame bool No Whether to return the last frame as content.last_frame_url on success (handy for using it as the first frame of a follow-up shot)
execution_expires_after int No Task timeout in seconds, default 172800, range 3600–259200
tools array No Model tools, e.g. [{"type":"web_search"}]
callback_url string No Callback URL for this task only; takes precedence over the tenant-level webhook

Seedance 2.5 extended fields (passed through unchanged; effective as far as the model supports them)

Field Type Description
omni_reference_task_type string Omni-reference task type: auto / reference / edit / extend
output_format string Output container: mp4 / mov
bitrate_mode string Bitrate mode (note the snake_case spelling); accepted values depend on the model

Response 200

{"id": "cgt-20260827103000-a1b2c"}

Task IDs use the same format as Ark: cgt-yyyymmddHHmmss-xxxxx (legacy tasks created before 2026-08-27 use task_ + 24 hex characters and can still be queried by their original ID).

Note: the create endpoint returns only the ID, not the status. Query it with §3.3, or configure a webhook (§5).

Errors

HTTP code Trigger
400 InvalidParameter Body is not valid JSON; duration out of range; resolution not supported by the model; asset not ready
400 Original Ark error code When the upstream explicitly rejects a request, the real error code is passed through, e.g. InputImageSensitiveContentDetected.PrivacyInformation (input contains a real human face). You can branch on it using the official error-code documentation
403 AccessDenied No access to the model (not on the tenant or key allowlist)
403 QuotaExceeded Insufficient balance, or insufficient token quota for the model (depending on billing mode, see §7)
404 NotFound The referenced asset:// asset does not exist or does not belong to you
429 Throttling Concurrency limit reached / queue full, see §4
502 UpstreamError Service line failure (not a problem with the request); retry with backoff
503 ServiceUnavailable Service line temporarily unavailable; contact the platform

3.2 Idempotency

With an Idempotency-Key header, repeated requests with the same key under the same tenant do not create a new task; the ID of the first task is returned:

curl -X POST .../tasks -H 'Idempotency-Key: order-8837' ...
# → {"id":"cgt-20260827103000-a1b2c"}    first call: created
# → {"id":"cgt-20260827103000-a1b2c"}    retry: same ID, no double charge

Use your own business order number as the key. Keys never expire.

Idempotency matches on the key only and does not compare request bodies. The same key with different parameters still returns the first task.

3.3 Query a task

GET /api/v3/contents/generations/tasks/{id}

In progress

{
  "id": "cgt-20260827103000-a1b2c",
  "model": "doubao-seedance-2-0-260128",
  "status": "running",
  "resolution": "720p",
  "duration": 5,
  "error": null,
  "created_at": 1786886334,
  "updated_at": 1786886391
}

Succeeded

{
  "id": "cgt-20260827103000-a1b2c",
  "model": "doubao-seedance-2-0-260128",
  "status": "succeeded",
  "resolution": "720p",
  "duration": 5,
  "error": null,
  "content": {
    "video_url": "https://….mp4?… (valid for about 24 hours; copy it right away, see §6)",
    "last_frame_url": "https://….png?…"
  },
  "usage": {"completion_tokens": 103819, "total_tokens": 103819},
  "created_at": 1786886334,
  "updated_at": 1786886512
}

Failed

{
  "id": "cgt-20260827103000-a1b2c",
  "status": "failed",
  "error": {"code": "InvalidParameter", "message": "..."},
  "created_at": 1786886334,
  "updated_at": 1786886334
}

3.4 State machine

status Terminal Meaning
queued Accepted: waiting in the local queue or submitted and awaiting scheduling
running Generating
succeeded ✓ Succeeded; content.video_url is downloadable (24-hour validity, see §6)
failed ✓ Failed; see error
cancelled ✓ Cancelled
expired ✓ Queue or execution timeout (queue timeout has error.code = QueueTimeout)

Polling advice: make the first query 5 seconds after creation, then every 3–5 seconds. Webhooks (§5) are the better choice over polling.

3.5 Cancel a task

POST /api/v3/contents/generations/tasks/{id}/cancel
{"id": "cgt-20260827103000-a1b2c", "status": "cancelled"}

Limitation: only tasks that are queued and not yet submitted for execution can be cancelled. Otherwise you get:

{"error": {"code": "InvalidState", "message": "仅本地排队中的任务可取消"}}

(The message reads "only tasks in the local queue can be cancelled".) On cancellation the pre-authorized amount is released in full.

3.6 List tasks

GET /api/v3/contents/generations/tasks?status=succeeded
{"items": [ { /* same structure as a single task in §3.3 */ } ]}

3.7 List models

GET /v1/models
{
  "object": "list",
  "data": [
    {"id": "doubao-seedance-2-5-260628", "object": "model"},
    {"id": "doubao-seedance-2-0-260128", "object": "model"},
    {"id": "doubao-seedance-2-0-fast-260128", "object": "model"},
    {"id": "doubao-seedance-2-0-mini-260615", "object": "model"}
  ]
}

Only models you have access to and that the platform has enabled are returned. This endpoint is the authoritative list of available models; §3.8 is for reference.

3.8 Models and supported specs

Model Resolution Duration Notes
doubao-seedance-2-5-260628 480p / 720p 4–30s or -1 Next-generation flagship; up to 30 seconds, multimodal reference assets and the §3.1 extended fields
doubao-seedance-2-0-260128 480p / 720p / 1080p / 4k 4–15s Standard; the only tier supporting 1080p / 4K
doubao-seedance-2-0-fast-260128 480p / 720p 4–15s Fast; quicker turnaround
doubao-seedance-2-0-mini-260615 480p / 720p 4–15s Lightweight; lowest cost

A resolution the model does not support returns 400. duration: -1 is supported by Seedance 2.5 only. The authoritative model list is GET /v1/models (§3.7).

Seedance 2.5 reference asset limits: videos ≤30, images ≤10, audio ≤10, and ≤50 in total per task.

About 4K: the billable amount is about 4× that of 1080p (4 seconds ≈ 777,600 tokens), but the 4K per-token price is lower, so the actual cost is about 2× that of 1080p. See Billing in the console for unit prices.


4. Concurrency and Rate Limiting

429 response

{"error": {"code": "Throttling", "message": "并发已达上限,请稍后重试"}}

(The message reads "concurrency limit reached, please retry later".) In reject mode the response includes a Retry-After: 5 header.

Client advice: on 429, retry with exponential backoff (5s / 10s / 20s / 40s) and use an Idempotency-Key so retries are never charged twice.


5. Webhook Callbacks

Configure one of the following:

A push is sent when the task reaches a terminal state.

Request

POST <your URL>
Content-Type: application/json
X-Relay-Timestamp: 1786886512
X-Relay-Signature: 3f2a9c...

The request body is identical to the §3.3 query response.

Signature verification

X-Relay-Signature = hex(HMAC-SHA256(secret, timestamp + "." + rawBody))

Python example:

import hmac, hashlib, time

def verify(secret: str, ts: str, raw_body: bytes, sig: str) -> bool:
    if abs(time.time() - int(ts)) > 300:      # reject replays older than 5 minutes
        return False
    mac = hmac.new(secret.encode(),
                   (ts + ".").encode() + raw_body,
                   hashlib.sha256).hexdigest()
    return hmac.compare_digest(mac, sig)

Compute it over the raw bytes. Do not deserialize and re-serialize the JSON first.

Retries: non-2xx responses are redelivered, up to 5 deliveries in total (first attempt + 4 retries) with backoff of 20s / 40s / 80s / 160s. If all 5 fail, the delivery is marked failed and can be resent manually from the console Webhook page.

Requirements for your endpoint: return 2xx quickly (15-second timeout) and process asynchronously; be idempotent on id (the same task may be delivered more than once).

Strongly recommended: trigger your video copy job from the success callback. The 24-hour window in §6 starts the moment the task succeeds.


6. Video Files (⚠️ 24-hour validity — copy them promptly)

content.video_url / last_frame_url on a succeeded task are temporary signed URLs from the model provider and expire after about 24 hours.

As soon as you receive succeeded, download the files to your own storage (object storage / CDN). The platform does not keep generated outputs; after 24 hours the task's video can no longer be retrieved (the task record and billing details remain available).

If your business needs the platform to keep generated outputs (platform-side copy with 30-day persistent URLs), contact the platform to enable archive mode for your tenant.


7. Billing

7.1 Billing modes

One of two modes, as agreed commercially. You can see your mode and remaining balance under Billing in the console:

Balance (default): the platform allocates a balance (CNY), and each task is charged unit price × billable amount. - Price dimensions: model × scenario × resolution. Requests whose content contains a video_url are priced under the video reference scenario (a lower unit price than pure generation, but more tokens in total). - Your price list is under Billing in the console (unit: CNY per million tokens, the same basis as the official Volcano Engine price list). - The unit price is snapshotted into the task at creation; later price changes do not affect tasks already created. - The billing currency is Chinese yuan (CNY).

Per-model token pool: token quotas are allocated per model (e.g. "1 million tokens for 2.0"). Each task deducts its billable amount in tokens directly from that model's pool. Pools are metered separately and cannot be shared across models, with no currency conversion involved. The console Billing page shows each pool's balance and token ledger, and lets you request more quota per model.

Rules common to both modes: - An estimated amount is frozen at creation; after the terminal state the task is settled at the actual billable amount and the difference is released (tasks with duration: -1 are frozen based on the model's maximum duration). - failed / cancelled / expired tasks are released in full and not charged. - If balance or quota is insufficient, task creation returns 403 QuotaExceeded; you can request an adjustment in the console.

7.2 Billable amount

usage.total_tokens is the billable amount and matches your bill exactly:

The billable amount is the usage actually returned by the model (usage.total_tokens is what you are billed). The table below gives reference estimates per tier (production values deviate slightly) for cost planning and sanity checks:

billable tokens = encoded width × encoded height × (24 × output seconds + 1) ÷ 1024
Resolution Encoded size (2.0 family) Encoded size (2.5) 5-second task approx. (2.0 / 2.5)
480p 864×496 854×480 50.6K / 48.4K
720p 1248×704 1280×720 103.8K / 108.9K
1080p (2.0 standard only) 1920×1088 — 246.8K
4k (2.0 standard only) 3840×2160 — 972K

Estimate formula: width × height × (24 × seconds + 1) ÷ 1024 (the 4K tier has no +1 constant). Seedance 2.5 uses standard pixel dimensions as its encoded size.

Video reference tasks (content contains video_url) are billed by the amount the model actually processes: the input video duration also consumes tokens and a minimum usage applies. The usage.total_tokens returned after success is authoritative.

Asset and real-person verification endpoints do not consume video quota.


8. Asset Library and Real-Person Verification (optional)

Two ways to bring your own content into generation; use whichever fits:

What you have What to use How to reference it
Ordinary reference material: product shots, scenes, audio/video §8.1 Asset library asset://{asset_id}
The likeness of a specific real person (with that person's consent) §8.2 Real-person verification → portrait assets asset://{asset_id}

All resources are isolated per tenant (cross-tenant access always returns 404).

8.1 Asset library (platform-hosted)

Assets are hosted by the platform: an upload returns an asset ID that is usable immediately, and at generation time the platform distributes the asset to the executing service line automatically. You never need to know which line holds an asset, and line failures or changes don't affect your assets or references.

POST   /api/seedance/proxy/assets/groups        Create asset group (instant)
GET    /api/seedance/proxy/assets/groups        List asset groups
GET    /api/seedance/proxy/assets/groups/{id}   Asset group detail
PUT    /api/seedance/proxy/assets/groups/{id}   Update
DELETE /api/seedance/proxy/assets/groups/{id}   Delete (group must be empty)

POST   /api/seedance/proxy/assets               Create asset (requires an asset group)
GET    /api/seedance/proxy/assets               List assets (?GroupId=)
GET    /api/seedance/proxy/assets/{id}          Asset detail (includes downloadable URL)
PUT    /api/seedance/proxy/assets/{id}          Update
DELETE /api/seedance/proxy/assets/{id}          Delete

Authentication is the same as §2 (Bearer). Request and response bodies mirror the official Volcano Engine asset API (PascalCase fields wrapped in Result). Resource IDs look like asset-yyyymmddHHmmss-xxxxx / group-yyyymmddHHmmss-xxxxx, and CreateTime is an RFC 3339 timestamp in UTC+8 (e.g. 2026-08-26T18:00:00+08:00).

Key fields

Endpoint Field Description
Create asset group Name / Description Groups created directly are ordinary asset groups (AIGC); real-person portrait groups are produced by the verification flow (§8.2)
Create asset GroupId / URL / AssetType / Name The URL must be a publicly downloadable HTTPS address; the platform fetches and hosts it right away. AssetType: Image / Video / Audio
Asset detail Status / URL Active means it can be referenced. URL is a download address issued by the platform (same name as the standard Volcano Engine field); when it expires, query again for a fresh one. The legacy field AssetUrl carries the same value for compatibility — please switch to URL soon; it will be removed in a later version

Referencing an asset: put asset://{asset_id} in the url field of the corresponding media object in the video task's content.

8.2 Real-person verification (using a specific person's likeness)

Official compliance rules: images or videos containing real human faces cannot be used directly as input (they are blocked with InputImageSensitiveContentDetected.PrivacyInformation). The person must first authorize use through liveness verification:

POST   /api/seedance/face-verifications         Start real-person verification
GET    /api/seedance/face-verifications/{id}    Verification result

Flow:

  1. POST /api/seedance/face-verifications (the body may be empty; some lines support return_url) → returns verification_id, h5_url, and expires_in/expires_at (the H5 session lifetime — usually short, so direct the user to open it immediately)
  2. Have the consenting person themselves open h5_url in a mobile browser and complete liveness verification as prompted (lighting or angle may cause a failure; retrying is fine)
  3. Poll GET /api/seedance/face-verifications/{id}: waiting_user = not finished yet (if the response carries a note saying the session expired, start again from step 1); verified = success, and you get a group_id (the real-person portrait group); failed/expired = start over
  4. Upload images/videos/audio of that same person to the group_id (same asset endpoints as §8.1; the upstream checks face consistency — clear frontal photos are recommended, and videos are admitted only if every sampled frame passes). Once the asset is Active, reference it as asset://{asset_id}
  5. One portrait group can hold multiple looks of the same person, so one verification is enough; verify and group different people separately

Note: real-person assets are bound to the line on which verification was done (authorization is tied to that line's account), so tasks referencing them always run on that line. This is the only exception to the "assets are not pinned to a line" rule in §8.1.


9. Native Volcano Engine Ark-Compatible Entry Point (optional)

If you already have asset-library code built on the official Volcano Engine SDK, just change the endpoint — your signing logic stays the same:

POST https://api.somobai.com/?Action={Action}&Version=2024-01-01
Parameter Value
Service ark
Region cn-beijing
Version 2024-01-01
Signing algorithm Volcano Engine Signature V4 (HMAC-SHA256)

Create the AK/SK under console Settings. Supported Actions:

CreateAssetGroup ListAssetGroups GetAssetGroup UpdateAssetGroup DeleteAssetGroup CreateAsset ListAssets GetAsset UpdateAsset DeleteAsset

Responses are wrapped in ResponseMetadata / Result, matching the official Volcano Engine format. This entry point operates on the same platform asset library as the §8.1 REST endpoints, and the two can be mixed. Project and credential fields such as ProjectName are handled by the platform automatically — you don't need to, and shouldn't, send them.

Use the Bearer endpoints (§3 / §8.2) for video generation tasks and real-person verification; the signed entry point currently covers the asset library only.


10. Error Reference

All data-plane errors share one format:

{"error": {"code": "ErrorCode", "message": "Error description"}}
code HTTP What to do
unauthorized 401 Check your key; do not retry
forbidden 403 Check the IP allowlist / tenant status; do not retry
AccessDenied 403 No access to the model; contact the platform
QuotaExceeded 403 Insufficient balance / token quota; retry after an adjustment
InvalidParameter 400 Fix the parameters; do not retry unchanged
InputImageSensitiveContentDetected.PrivacyInformation 400 Input blocked for containing a real human face: use different material, or go through §8.2 real-person verification
Other original Ark error codes 400 Passed through when the upstream explicitly rejects; handle per the official error-code docs
InvalidState 400 The task's state does not allow this operation
NotFound 404 Check that the ID belongs to you
Throttling 429 Retry with exponential backoff
UpstreamError 502 Service line error; retry with backoff
ServiceUnavailable 503 Service line temporarily unavailable; contact the platform
InternalError 500 Platform error; retry with backoff, and contact the platform if it persists
QueueTimeout — Appears in the error field of expired tasks
Lowercase codes such as invalid_parameter / not_found / group_not_empty 4xx Error-code style of the asset endpoints (§8.1); meaning as the name says

Error message texts are currently returned in Chinese; branch on code, not on message.


11. Integration Checklist


12. Changelog

Version Date Changes
v5 2026-10-09 International (Chinese/English) edition: the guide is now also available in English; model specs updated for the current service line — Seedance 2.5 offers 480p/720p, and duration: -1 is supported by 2.5 only (§3.1/§3.8); added the Seedance 2.5 extended fields and pass-through rules (omni_reference_task_type / output_format / bitrate_mode, §3.1); this edition does not offer the extended model library or the character workshop, so those sections were removed (§8 now covers the asset library + real-person verification); corrected the reference billable-amount figures (§7.2); billing currency stated explicitly as CNY
v4 2026-08-27 Added Seedance 2.5: durations of 4–30 seconds, reference asset limits (videos ≤30 / images ≤10 / audio ≤10 / total ≤50, §3.8), separate encoded sizes for metering (§7.2); task IDs aligned with Ark as cgt-yyyymmddHHmmss-xxxxx (legacy task_ IDs can still be queried, §3.1); asset endpoints aligned with Volcano Engine: address field AssetUrl → URL (old field kept with the same value, to be retired), CreateTime changed to RFC 3339 in UTC+8, resource IDs changed to the asset-/group-yyyymmddHHmmss-xxxxx format (§8.1); Ark text-command compatibility (--resolution etc.; text commands win over top-level fields, §3.1); lenient Authorization header parsing (scheme case / extra spaces)
v3 2026-08-22 Generated outputs are now passed through: video_url is a 24-hour temporary URL that the platform does not copy, so move it promptly (§6); asset library upgraded to platform hosting: usable immediately after upload, distributed to lines automatically, assets no longer pinned to a line (§8.1); real-person verification detailed (H5 lifetime / status semantics, §8.2); original Ark error codes passed through on explicit upstream rejection (e.g. real-face blocking); error reference and checklist updated
v2 2026-08-21 Billable-amount basis documented (one platform formula, consistent across lines); per-model token pool billing mode added; model spec table; corrected the price direction for the video reference scenario; asset endpoint field table and real-person verification flow; added 503/501 error codes; stated that safety_identifier is injected by the platform
v1 2026-08-16 Initial release