Skip to content

Video Generation API (Doubao Seedance) ​

Last updated: October 23, 2026 (Asia/Shanghai)

Related: Help Center · LLM API · Image Generation · Full Reference

tokenexplore provides two integration protocols for Seedance:

  • Seedance official protocol: the most complete set of parameters, with multimodal references, 2.5 editing/extension, asset library references, and signed callbacks; prefer it for new projects.
  • Video-compatible protocol: compatible with existing OpenAI video clients; supports common fields such as prompt, images, seconds, and metadata.

Both protocols share the same API key, account quota, and billing system, but their request fields, response structures, and task states differ. You must use the same protocol for creation, querying, and status checks; do not mix them.

The API gateway for all requests is https://ai.afp.net. The examples use the following environment variables:

bash
export CIYUAN_BASE_URL="https://ai.afp.net"
export CIYUAN_API_KEY="sk-xxxxxxxx"    # Create under "Token Management" in the console

Authentication uses the Authorization: Bearer sk-xxx header for all requests. Queries, downloads, and asset operations must use a token from the same account.

Keep your API key safe

An API key is a paid credential. Store it only in server-side environment variables or a secrets manager; never put it in frontend code, screenshots, logs, or public repositories.


1. Models and Endpoints ​

1.1 Models ​

Model IDNotes
doubao-seedance-2-5-260628Seedance 2.5, quality-first; supports 4–30 seconds and omni-modal reference/editing
doubao-seedance-2-0-260128Seedance 2.0 standard edition; supports 4–15 seconds
doubao-seedance-2-0-fast-260128Seedance 2.0 Fast, speed-first; generally 480p/720p only
doubao-seedance-2-0-mini-260615Seedance 2.0 Mini, lightweight and low-cost; generally 480p/720p only

Whether a model is available to the current token depends on the token group and channel configuration. Check first:

bash
curl "$CIYUAN_BASE_URL/v1/models" \
  -H "Authorization: Bearer $CIYUAN_API_KEY"

Do not call model IDs that are not in the returned list. Pricing and available resolutions are subject to "Model Marketplace / Pricing" in the console.

1.2 Endpoint Overview ​

ProtocolCreate taskQuery taskDownload resultMain request fields
Seedance official (recommended)POST /api/v3/contents/generations/tasksGET /api/v3/contents/generations/tasks/{task_id}content.video_url, or GET /v1/videos/{task_id}/contentcontent, integer duration, ratio
Video-compatiblePOST /v1/video/generations (also supports OpenAI Videos style POST /v1/videos)GET /v1/video/generations/{task_id} (OpenAI Videos style uses GET /v1/videos/{id})GET /v1/videos/{task_id}/contentprompt, images, string seconds, metadata

The official protocol also provides task listing and deletion:

text
GET    /api/v3/contents/generations/tasks?page_num=1&page_size=10
DELETE /api/v3/contents/generations/tasks/{task_id}

The list supports filter.status, filter.model, filter.service_tier, and repeated filter.task_ids; page_num and page_size range from 1 to 500 (defaults: 1 / 10). Deleting a queued task cancels it; deleting a finished task only removes the record; deleting a running task returns 409 task_cannot_be_cancelled.

The two protocols' endpoints and fields cannot be mixed

The official endpoint accepts only official fields such as content; the video-compatible endpoint accepts only fields such as prompt / images / seconds / metadata. Sending content to the video-compatible endpoint, or prompt to the official endpoint, will not work with the semantics you expect. The response structures and status enums also differ between the two protocols, so do not force the same parsing code onto both.


2. Seedance Official Protocol ​

2.1 Create a Task ​

The following example generates a 4-second, 480p, 16:9 video without audio, suitable for validating the pipeline first:

bash
curl "$CIYUAN_BASE_URL/api/v3/contents/generations/tasks" \
  -H "Authorization: Bearer $CIYUAN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-20261023-001" \
  -d '{
    "model": "doubao-seedance-2-5-260628",
    "content": [
      {"type": "text", "text": "An orange cat watching the rain by the window, slow push-in, cinematic lighting"}
    ],
    "duration": 4,
    "resolution": "480p",
    "ratio": "16:9",
    "generate_audio": false
  }'

A successful creation only means the platform has accepted the task; it returns a public task ID:

json
{"id": "task_xxxxxxxxx"}
  • The task ID is generated by the platform, not the upstream task ID; do not concatenate it onto an upstream URL.
  • Idempotency-Key prevents duplicate tasks and duplicate charges caused by client timeout retries: reuse the same value for the same business submission and use a new value for a new generation intent. The same key with a different request returns 409 idempotency_conflict.
  • The official create request body is limited to 64 MiB (about 64 MB); for large assets, use the asset library or a public HTTPS URL.
  • The legacy prefix /doubao/api/v3/contents/generations/tasks remains available as a compatibility entry point. For new projects, use /api/v3/contents/generations/tasks, and do not mix the two prefixes for queries.

2.2 Query a Task ​

bash
curl "$CIYUAN_BASE_URL/api/v3/contents/generations/tasks/task_xxxxxxxxx" \
  -H "Authorization: Bearer $CIYUAN_API_KEY"
StatusMeaningAction
queuedAccepted, waiting for generationKeep polling
runningUpstream generation in progressKeep polling
succeededGeneration succeededRead content.video_url
failedFailedRead error, adjust, and retry
cancelledCancelledStop polling
expiredTask record has expiredSubmit again

Successful response example:

json
{
  "id": "task_xxxxxxxxx",
  "model": "doubao-seedance-2-5-260628",
  "status": "succeeded",
  "content": {
    "video_url": "https://example.com/result.mp4",
    "video_asset_id": "asset_xxxxxxxxx"
  },
  "usage": {"completion_tokens": 38830, "total_tokens": 38830},
  "created_at": 1787827200,
  "updated_at": 1787827300
}
  • The final cost is settled based on usage.total_tokens.
  • Once result archiving is enabled on the platform, content.video_asset_id means the result has been archived to the current account's asset library; archiving may finish slightly later than the terminal generation state—if it does not appear immediately, query again later.
  • Failed tasks are refunded asynchronously after backend confirmation, but a successful submission does not mean the video was generated successfully; always rely on the task status.

2.3 Content Types and Asset Roles ​

content is an ordered array that describes the prompt and reference assets in order:

typeAccepted sourcesAvailable role
textUTF-8 textNone
image_urlPublic https, image data URL, asset:// assetfirst_frame, last_frame, reference_image
video_urlPublic https, asset:// asset (Base64 not supported)reference_video
audio_urlPublic https, audio data URL, asset:// assetreference_audio
draft_taskA task_xxx accessible to the current accountNone
json
{"type":"image_url","image_url":{"url":"https://example.com/first-frame.png"},"role":"first_frame"}
  • role and type are at the same level; one element can express only one content type.
  • asset:// can reference only assets owned by the current user with a valid status; if asset referencing is not enabled, it returns asset input is not enabled.
  • The official endpoint rejects unknown top-level fields and unknown fields inside content with 400 invalid_request; field names must match the documentation exactly.

2.4 Generation Parameters ​

ParameterRequiredNotes
modelYesUse a model ID from Section 1
contentYesOrdered content array; must contain at least one content element
durationNo2.0: -1 or 4–15; 2.5: -1 or 4–30
resolutionNoe.g. 480p, 720p; higher resolutions depend on the model and channel
ratioNo16:9, 4:3, 1:1, 3:4, 9:16, 21:9, adaptive
generate_audioNoWhether to generate audio
omni_reference_task_typeNo2.5 only: auto, reference, edit, extend
callback_urlNoCallback URL for terminal task states; requires callback capability to be enabled on the platform, and must be a public http(s) address
return_last_frameNoReturn the last frame; once result archiving is enabled on the platform, last_frame_url / last_frame_asset_id may appear in successful responses
execution_expires_afterNoTask execution expiry in seconds, range 3600–259200
seed / watermark / camera_fixedNoRandom seed / watermark / fixed camera
draft / frames / tools / output_format / service_tier / priority / safety_identifierNoAdvanced parameters; whether they take effect depends on the model and channel
  • Before charging and submitting to upstream, the platform validates the combination of duration, ratio, and 2.5 task type; unsupported combinations return 400 unsupported_parameter_combination.
  • ratio accepts only standard values; after successful generation, the actual ratio returned by upstream may be a fraction such as 427:240. Store it as a string and do not force-stretch it to 16:9.
  • Resolution, model capabilities, and billing tiers are subject to the console model description and your bill.

2.5 Video Reference and Editing (Seedance 2.5) ​

Use omni_reference_task_type to declare an omni-modal reference subtask (for a Seedance 2.5 first-frame task, if ratio is passed explicitly it must be adaptive); there is no edit: true field:

Scenarioomni_reference_task_typeParameter requirements
Regenerate with reference motion/style/camerareferenceAt least one reference asset; regular ratio and duration
Modify the visuals or audio of a reference videoeditAt least one reference_video; ratio=adaptive; duration=-1
Extend a reference videoextendAt least one reference_video; ratio=adaptive
Let the model decide automaticallyauto or omittedWhen a reference video is included, the platform requires adaptive and -1
bash
curl "$CIYUAN_BASE_URL/api/v3/contents/generations/tasks" \
  -H "Authorization: Bearer $CIYUAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2-5-260628",
    "content": [
      {"type": "text", "text": "Change the jacket of the person in the reference video to red, keeping the original motion, camera movement, and audio"},
      {"type": "video_url", "video_url": {"url": "https://example.com/source.mp4"}, "role": "reference_video"}
    ],
    "duration": -1,
    "ratio": "adaptive",
    "omni_reference_task_type": "edit"
  }'

If you need a fixed output ratio or duration, pass reference explicitly; the prompt should clearly state what to modify and what must be preserved (motion, camera, and audio).

2.6 Query, List, and Delete ​

To query a single task, see §2.2. List and delete examples:

bash
curl "$CIYUAN_BASE_URL/api/v3/contents/generations/tasks?page_num=1&page_size=10&filter.status=succeeded" \
  -H "Authorization: Bearer $CIYUAN_API_KEY"

curl -X DELETE "$CIYUAN_BASE_URL/api/v3/contents/generations/tasks/task_xxxxxxxxx" \
  -H "Authorization: Bearer $CIYUAN_API_KEY"
  • The list returns {"items": [...], "total": N}, sorted by created_at in descending order.
  • Available filter.status values match the task states: queued, running, succeeded, failed, cancelled, expired.
  • A successful deletion returns 204 No Content: queued tasks are cancelled; finished tasks have their upstream task deleted first, then the platform record soft-deleted; running tasks return 409 task_cannot_be_cancelled, and already-cancelled tasks return 409 task_already_cancelled.
  • Task IDs are visible only to the account that created them; you cannot query or delete another user's tasks.

2.7 Download the Result ​

After a task succeeds, prefer reading content.video_url. Upstream URLs may expire, so download or transfer the file as soon as possible; you can also have the platform proxy the download using the same token:

bash
curl -L "$CIYUAN_BASE_URL/v1/videos/<task_id>/content" \
  -H "Authorization: Bearer $CIYUAN_API_KEY" \
  -o output.mp4

This endpoint supports Range for resumable downloads; call it only after the task succeeds (official succeeded / OpenAI Videos style completed).

2.8 Signed Callbacks ​

When creating an official task, pass callback_url (callback capability must be enabled on the platform). After the task reaches a terminal state (succeeded / failed / cancelled / expired), the platform sends an HTTP POST to that address:

HeaderPurpose
X-Seedance-Event-IdUnique event ID; receivers should deduplicate on this field
X-Seedance-TimestampSignature timestamp (Unix seconds)
X-Seedance-SignatureHMAC-SHA256 signature in v1=<hex> format

The signed payload is timestamp + "." + raw_body. The API key used when creating the task is currently used as the signing secret. You must verify the signature against the raw request body you received; do not re-serialize the JSON before computing it.

js
import crypto from 'node:crypto'

export function verifySeedanceWebhook(rawBody, headers, signingSecret) {
  const timestamp = headers['x-seedance-timestamp']
  const received = headers['x-seedance-signature']
  const expected = 'v1=' + crypto
    .createHmac('sha256', signingSecret)
    .update(timestamp + '.' + rawBody)
    .digest('hex')

  return typeof received === 'string' &&
    received.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected))
}
  • The callback body contains id, type, created_at, and data; type is content_generation.task.{status}, and data is the task snapshot, with fields similar to the official task query response; archiving-related fields may only be filled in on query.
  • The platform uses at-least-once delivery semantics; handle events idempotently by X-Seedance-Event-Id, and return 2xx as soon as possible after verifying the signature and persisting the event.
  • If you don't need event notifications, polling is sufficient; polling and callbacks can be enabled at the same time.

3. Video-Compatible Protocol ​

The video-compatible protocol is intended for existing OpenAI video clients or unified task wrappers. It is an additional compatibility layer provided by the platform, not the Seedance official protocol.

3.1 Endpoints and How to Choose ​

OperationLegacy compatibility entryOpenAI Videos style
Create taskPOST /v1/video/generationsPOST /v1/videos
Query taskGET /v1/video/generations/{task_id}GET /v1/videos/{id}
Download resultGET /v1/videos/{task_id}/contentSame as left

The two entries return different response structures (see §3.4); use one entry consistently for creation and querying, and do not mix them within a single flow. Only the OpenAI Videos style entry uses queued / in_progress / completed / failed, where completed corresponds to the official protocol's succeeded; the legacy compatibility entry returns internal platform states (such as IN_PROGRESS / SUCCESS / FAILURE), so do not use completed to determine terminal states.

3.2 Create a Task ​

bash
curl "$CIYUAN_BASE_URL/v1/video/generations" \
  -H "Authorization: Bearer $CIYUAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2-5-260628",
    "prompt": "Sunrise over the sea, slow push-in, waves gently lapping the rocks, cinematic",
    "seconds": "4",
    "metadata": {
      "resolution": "480p",
      "ratio": "16:9",
      "generate_audio": false
    }
  }'

Successful creation response example (legacy compatibility entry):

json
{
  "id": "task_xxxxxxxxx",
  "task_id": "task_xxxxxxxxx",
  "status": "queued",
  "model": "doubao-seedance-2-5-260628",
  "created_at": 1787827200
}

If you use the OpenAI Videos style entry, the creation response is a video object (with no task_id):

json
{
  "id": "task_xxxxxxxxx",
  "object": "video",
  "model": "doubao-seedance-2-5-260628",
  "status": "queued",
  "progress": 0,
  "created_at": 1787827200
}

A successful creation only means the task has been accepted; the response does not contain a video URL.

3.3 Request Parameters ​

FieldNotes
modelRequired; model ID
promptRequired; the prompt
imagesArray of reference image URLs. The OpenAI Videos style path accepts only images; do not pass a single image
imageSingle image URL supported by the legacy compatibility entry (converted to images internally); new code should use images consistently
secondsDuration as a string, e.g. "4", "-1"; takes precedence over duration when both are present
durationDuration as an integer. The OpenAI Videos style entry can use it instead of seconds; the legacy compatibility entry reads only seconds and ignores duration
metadataPasses through official parameters: content, resolution, ratio, generate_audio, omni_reference_task_type, etc.
  • Parameters such as resolution, ratio, and generate_audio must be placed inside metadata; they are ignored at the top level.
  • Put reference images, videos, or audio in metadata.content, not text; write the prompt in prompt. If you need a first-frame role, explicitly write image_url + role: "first_frame" in metadata.content.
  • The compatibility protocol does not support binary file uploads; assets must be public URLs. To reuse assets, use the official protocol + asset library.
  • A top-level content does not cause the compatibility endpoint to return a parameter error; it is simply ignored. For multimodal references, put them in metadata.content or switch to the official protocol.

3.4 Query Status and Download ​

The OpenAI Videos style entry returns a video object with status queued → in_progress → completed (or failed):

bash
curl "$CIYUAN_BASE_URL/v1/videos/task_xxxxxxxxx" \
  -H "Authorization: Bearer $CIYUAN_API_KEY"
json
{
  "id": "task_xxxxxxxxx",
  "object": "video",
  "model": "doubao-seedance-2-5-260628",
  "status": "completed",
  "progress": 100,
  "created_at": 1787827200,
  "completed_at": 1787827300
}

The legacy compatibility entry returns a generic task structure, with the result URL in data.result_url (the field may not exist; rely on the download endpoint):

bash
curl "$CIYUAN_BASE_URL/v1/video/generations/task_xxxxxxxxx" \
  -H "Authorization: Bearer $CIYUAN_API_KEY"
json
{
  "code": "success",
  "message": "",
  "data": {
    "task_id": "task_xxxxxxxxx",
    "status": "IN_PROGRESS",
    "progress": "60%"
  }
}

Don't look for the result URL in the query response

The /v1/videos/{task_id} response does not contain metadata.url, task_id, or a video URL; for the legacy compatibility entry, the result URL is in data.result_url, and that field may not exist. Always download via GET /v1/videos/{task_id}/content.

bash
curl -L "$CIYUAN_BASE_URL/v1/videos/task_xxxxxxxxx/content" \
  -H "Authorization: Bearer $CIYUAN_API_KEY" \
  -o output.mp4

This endpoint supports Range for resumable downloads; downloads must use a token from the same account that created the task (any valid token on that account works).

3.5 Recommendations ​

  • For new projects, or when you need first/last frames, reference audio/video, 2.5 editing/extension, or asset library reuse, use the Seedance official protocol.
  • If you already have OpenAI video tools and only need text-to-video/image-to-video, use the video-compatible protocol; if you find that a parameter is not taking effect, switch to the official protocol.
  • Whichever protocol you choose, production systems should store task_xxx, the model, key generation parameters, and error messages, to make it easier to verify status, billing, and retries.

4. Asset Library (Official Assets API) ​

The asset library is used to first import reference images, reference videos, and reference audio into the platform, then reference them repeatedly in official-protocol tasks via asset://<asset ID>. It suits scenarios where the same asset is used many times, or where upstream cannot fetch external links directly.

Assets and groups belong to the current user; other users cannot view, modify, delete, or reference your assets via asset://.

The asset library uses the Action style of the Volcengine Assets API: all operations POST to a fixed path, with Action and Version in the query parameters. Do not build Actions into ordinary REST paths (such as /api/v3/assets/CreateAsset), or you will get a 404.

text
POST https://ai.afp.net/api/v3/assets?Action=<Action>&Version=2024-01-01
Authorization: Bearer sk-xxx
Content-Type: application/json

Twelve Actions are currently supported:

CategoryAction
GroupsCreateAssetGroup, ListAssetGroups, GetAssetGroup, UpdateAssetGroup, DeleteAssetGroup
AssetsCreateAsset, ListAssets, GetAsset, UpdateAsset, DeleteAsset
Real-person verificationCreateVisualValidateSession, GetVisualValidateResult

Version must be 2024-01-01; an unsupported Action returns InvalidAction, and an incorrect version returns InvalidVersion. Responses are uniformly wrapped in ResponseMetadata, with business data in Result and errors in ResponseMetadata.Error. The real-person verification capability is not currently connected to upstream; when all parameters are present, it returns OperationDenied.CapabilityNotSupported.

4.1 Create a Group and Import Assets ​

bash
curl "$CIYUAN_BASE_URL/api/v3/assets?Action=CreateAssetGroup&Version=2024-01-01" \
  -H "Authorization: Bearer $CIYUAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"Name":"Project assets","GroupType":"AIGC","ProjectName":"default"}'

curl "$CIYUAN_BASE_URL/api/v3/assets?Action=CreateAsset&Version=2024-01-01" \
  -H "Authorization: Bearer $CIYUAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "GroupId":"<group ID returned by the previous step>",
    "Name":"First frame",
    "AssetType":"Image",
    "URL":"https://example.com/first-frame.png",
    "ProjectName":"default"
  }'

CreateAssetGroup response example:

json
{
  "ResponseMetadata": {"RequestId": "req-xxxxxxxx", "Action": "CreateAssetGroup", "Version": "2024-01-01", "Service": "ark", "Region": "cn-beijing"},
  "Result": {"Id": "group-xxxxxxxx"}
}
  • CreateAsset returns Result.Id (the asset ID).
  • AssetType can only be Image, Video, or Audio, and must match the actual media type of the URL.
  • GroupType currently supports only AIGC; when ProjectName is omitted it defaults to default, with a maximum length of 64 bytes (UTF-8).
  • URL must be a public http(s) address accessible to the platform; the platform performs SSRF validation, and localhost and private network addresses are rejected.

4.2 Reference Assets in Generation Tasks ​

After importing an asset, use asset://<asset ID> instead of a URL in the official protocol's content:

json
{"type":"image_url","image_url":{"url":"asset://asset_xxxxxxxx"},"role":"first_frame"}
  • asset:// requires the platform's asset referencing capability to be enabled; when it is not enabled, it returns asset input is not enabled, in which case use a public http(s) URL instead.
  • The asset type must match the content item (image for image_url, video for video_url, audio for audio_url).
  • Tasks that reference assets must use a token from the same account that imported the assets.

4.3 Manage Assets (REST / Console) ​

In addition to the Action API, the platform also provides internal REST endpoints used by the console and automation tools:

text
POST   /api/v3/assets                               Upload a file or import from a public URL
GET    /api/v3/assets                               Paginate, search, and filter assets
GET    /api/v3/assets/{asset_id}                    Asset details
PATCH  /api/v3/assets/{asset_id}                    Rename or change group
DELETE /api/v3/assets/{asset_id}                    Delete asset
GET    /api/v3/assets/{asset_id}/content            Download / probe file (supports Range)
HEAD   /api/v3/assets/{asset_id}/content            Probe file
POST   /api/v3/assets/{asset_id}/prepare            Prepare/register an upstream asset for a model (request body must include model)
POST   /api/v3/assets/from-task                     Archive a task result as an asset

POST   /api/v3/asset-groups                         Create group
GET    /api/v3/asset-groups                         List groups
GET    /api/v3/asset-groups/{group_id}              Group details
PATCH  /api/v3/asset-groups/{group_id}              Rename group
DELETE /api/v3/asset-groups/{group_id}              Delete group

Legacy paths /api/media/assets and /api/media/asset-groups are still retained.
  • REST endpoints accept both the console login session and an API key; for automated programs, use Authorization: Bearer sk-xxx.
  • The /api/media/assets list supports page_num, page_size, q, kind, and group_id parameters; the upload endpoint supports multipart files or public URL import via url.
  • The console's "Asset Library" supports upload, preview, download, copying asset:// references, editing names/groups, and deletion; the list can be filtered by name, type, and group.
  • The per-file limit is 512 MB; the platform validates the actual MIME type and stores a SHA-256.
  • Asset library permissions are divided into view, upload, manage, delete, and archive; without permission, buttons are hidden or requests return 403.

4.4 Retention, Isolation, and Upstream Binding ​

  • Group records are retained long-term until explicitly deleted; DeleteAssetGroup requires that the group contain no unexpired assets, otherwise it returns OperationDenied.AssetGroupNotEmpty.
  • Platform assets are retained for 7 days by default, and the deployer can configure long-term retention. expires_at in asset management APIs or the console is a Unix timestamp in seconds; after expiry, assets no longer appear in lists and cannot be used for generation tasks. Expiry cleanup deletes only platform metadata; the underlying objects are reclaimed by object storage (S3 / Tencent COS-compatible) lifecycle rules.
  • Assets and groups are isolated by user + ProjectName; other users cannot query or reuse them; the default project name is default.
  • Platform assets are stored only in tokenexplore and are not synced upstream. When routing a task, the platform first checks whether candidate channels support the required image/video/audio capability; after selecting a channel, it registers a temporary upstream asset on demand for that task.
  • Upstream bindings are single-use by default, and upstream may delete them after the task ends; even if reuse is configured, the TTL will not exceed the upstream retention period. Upstreams that only support fetching URLs use the platform's short-lived URL directly. As a result, assets are not pre-bound to any upstream, and you can switch freely between channels.
  • Capabilities such as virtual assets, private real-person assets, real-person authentication, and update/delete are configured by administrators per channel; the current upstream does not support private real-person assets, and the related Actions return OperationDenied.CapabilityNotSupported rather than 404.
  • The URL returned by GetAsset / ListAssets is a temporary address issued by the platform (1 hour by default) and must not be stored as a permanent external link.
  • Assets referenced by in-progress tasks cannot be deleted; attempting to do so returns OperationDenied.AssetInUse.

5. Async Flow, Polling, and Billing ​

Submitting a task only means it has been enqueued. Recommended flow:

  1. Submit and save the returned task ID and the full request parameters (for the official protocol, include Idempotency-Key).
  2. Query every 5 seconds, backing off gradually to 15–30 seconds; avoid high-frequency polling.
  3. Download once the task reaches a successful terminal state (official succeeded / OpenAI Videos style completed); for failed, read error and stop retrying.
  4. A status of expired means the record has expired (the upstream record may no longer be queryable), and you need to submit again; result URLs expire, so download promptly after success.

Python polling example (official protocol):

python
import os, time, requests

BASE = os.environ["CIYUAN_BASE_URL"]
HEADERS = {"Authorization": f"Bearer {os.environ['CIYUAN_API_KEY']}"}

created = requests.post(f"{BASE}/api/v3/contents/generations/tasks", headers=HEADERS, json={
    "model": "doubao-seedance-2-5-260628",
    "content": [{"type": "text", "text": "An orange cat watching the rain by the window, slow push-in"}],
    "duration": 4, "resolution": "480p", "ratio": "16:9", "generate_audio": False,
})
created.raise_for_status()
task_id = created.json()["id"]
print("task:", task_id)

delay = 5
while True:
    info = requests.get(
        f"{BASE}/api/v3/contents/generations/tasks/{task_id}", headers=HEADERS
    ).json()
    status = info.get("status")
    print("status:", status)
    if status == "succeeded":
        url = info["content"]["video_url"]
        break
    if status in ("failed", "cancelled", "expired"):
        raise RuntimeError(info.get("error") or status)
    time.sleep(delay)
    delay = min(delay * 1.5, 30)

video = requests.get(url, timeout=120)
video.raise_for_status()
open("output.mp4", "wb").write(video.content)
print("saved output.mp4")

Billing is calculated from the upstream-returned usage.total_tokens along with the model, input type, and resolution; a hold may be placed at submission time, and failed tasks are refunded asynchronously. The final amount is subject to the console bill.


6. Common Errors and Troubleshooting ​

ErrorCommon causeHandling
401 UnauthorizedInvalid or expired key, or missing request headerCheck the Bearer header and key status
No available channel for modelModel not enabled, channel not enabled, or group lacks permissionCheck /v1/models first
503 channel_not_availableThe official protocol cannot find a Seedance-compatible channelCheck channel configuration and group
400 invalid_requestMissing content, malformed JSON, unknown field, asset input is not enabledCheck field names and types
400 unsupported_parameter_combinationUnsupported combination of duration, ratio, and task typeAdjust per 2.4 / 2.5
403 OperationDenied.CapabilityNotSupportedAsset library not enabled at all (Action requests)Contact an administrator to enable asset library capability
400 OperationDenied.CapabilityNotSupportedThe current upstream does not support the asset/capability (e.g. private real-person)Use a supported asset type or channel
404 not_foundOfficial task API not enabled, or asset library REST routes not enabledConfirm the platform has enabled the corresponding capability
413 asset_too_largeUploaded file exceeds 512 MBCompress the asset or use a public URL
asset_not_found / asset_not_active (REST management API)Asset deleted, owned by someone else, or not yet availableGo back to the asset library to confirm and re-copy the reference
invalid_asset / asset_not_supported (task referencing an asset)asset:// type mismatch, asset unavailable, or the current channel does not support itCheck asset ownership/type, or switch to a channel that supports the capability
409 task_cannot_be_cancelledRunning tasks cannot be cancelledWait for the terminal state or stop polling
Stuck in queuedUpstream queueing or channel switchingKeep polling; retry after your business timeout
Task failedParameters, content moderation, or upstream errorSave error, adjust, and resubmit
Result URL unavailableTask not finished or URL expiredConfirm the success status; download promptly or proxy via the content endpoint
Callback signature mismatchRequest body re-serialized, wrong secret, or timestamp not the original valueCompute the HMAC from the raw body + timestamp, and check the v1= prefix

Official protocol or video-compatible: which should I choose?

Use the official protocol when you need first/last frames, reference audio/video, 2.5 editing/extension, the asset library, or signed callbacks; use the compatibility protocol when you already have OpenAI video tools and only need text-to-video/image-to-video. The endpoints and fields of the two protocols cannot be mixed.


Previous: Image Generation · Back to: Help Center