Seedance: video generation API
Generate video with Seedance 2.0 / 2.5: parameters, results, and caveats.
| Item | Value |
|---|---|
| Base URL | https://api.hop-base.com/v1 |
| Submit a task | POST /v1/video/generate |
| Poll a task | GET /v1/video/tasks/{task_id} |
| List tasks | GET /v1/video/tasks |
| Upload an asset (2.0 only) | POST /v1/sd/assets |
| Key group | China: "Seedance China (Doubao)"; overseas: "Seedance overseas + Seedream" |
Available models
| Variant | Model ID | Resolutions | Duration (s) | Official price |
|---|---|---|---|---|
| 2.0 Standard (China) | doubao-seedance-2-0-260128-a | 480p / 720p / 1080p | 4–15 | $4.12from/ 1M tokens |
| 2.0 Fast (China) | doubao-seedance-2-0-fast-260128-a | 480p / 720p | 4–15 | $2.43from/ 1M tokens |
| 2.0 Mini (China) | doubao-seedance-2-0-mini-260615-a | 480p / 720p | 4–15 | $0.824from/ 1M tokens |
| 2.5 (China) | doubao-seedance-2-5-260628-a | 480p / 720p / 1080p | 4–30 | $6.18from/ 1M tokens |
| 2.0 Standard (Overseas) | dreamina-seedance-2-0-hcdreamina-seedance-2-0-epdreamina-seedance-2-0-260128 | 480p / 720p / 1080p / 4K | 4–15 | $2.40from/ 1M tokens |
| 2.0 Fast (Overseas) | dreamina-seedance-2-0-fast-hcdreamina-seedance-2-0-fast-epdreamina-seedance-2-0-fast-260128 | 480p / 720p | 4–15 | $3.30from/ 1M tokens |
| 2.0 Mini (Overseas) | dreamina-seedance-2-0-mini-hcdreamina-seedance-2-0-mini-epdreamina-seedance-2-0-mini-260615 | 480p / 720p | 4–15 | $2.10from/ 1M tokens |
| 2.5 (Overseas) | dreamina-seedance-2-5-260628 | 480p / 720p / 1080p | 4–30 | $6.40from/ 1M tokens |
On overseas 2.5, 1080p works only where your group supports it, and 4K is not supported.
China models are served by the Seedance China (Doubao) group and overseas models by the Seedance overseas + Seedream group. The China group covers Standard, Fast, Mini, and Seedance 2.5; only 4K needs the overseas Standard model. Overseas keys cannot call doubao-* IDs.
Per-tier prices and full specs for each model are on its model card, for example dreamina-seedance-2-5-260628 and doubao-seedance-2-0-260128-a.
Request parameters
All fields are top-level JSON fields — do not nest them under parameters. Integers and booleans sent as strings ("5", "true") or integers sent as decimals are rejected. The whole request body is capped at 64 MB, inline Data URLs included.
| Parameter | Required | Type & limits | Default | Description |
|---|---|---|---|---|
model | Required | a model ID from the table above | — | Sets the duration, resolution and media limits |
content | Required | non-empty array, shapes below | — | The prompt goes in a text item |
duration | Optional | integer; 2.0: 4–15 or -1; 2.5: 4–30 or -1 | 2.0: 5; 2.5: -1 | Length in seconds; -1 lets the model choose |
resolution | Optional | per model in the model table | 720p | Must be one the model lists |
ratio | Optional | 16:9 / 4:3 / 1:1 / 3:4 / 9:16 / 21:9 / adaptive | adaptive | adaptive follows the reference image or lets the model choose |
generate_audio | Optional | boolean | 2.5: true; 2.0: none | On 2.0, send it explicitly |
watermark | Optional | boolean | 2.5: false; 2.0: none | On 2.0, send it explicitly |
return_last_frame | Optional | boolean | 2.5: true | Returns task.last_frame_url when available; not guaranteed on 2.0 |
priority | Optional | integer 0–9 | — | Scheduling hint for the task queue; completion time is not guaranteed |
execution_expires_after | Optional | integer 3600–259200 (seconds) | — | Does not change the 24-hour limit |
callback_url | Optional | HTTP(S) URL | — | Does not replace polling |
safety_identifier | Optional | 1–64 ASCII characters | — | Stable ID for your end user, used for abuse monitoring; do not put personal data in it |
frames, seed, camera_fixed, draft, draft_task, and service_tier are rejected (400) on both generations. Every field is also listed in API reference: Submit a video task.
size, seconds, n, and aspect_ratio are not Seedance parameters: they are ignored without an error, and the task runs at the default duration and 720p. Use duration, resolution, and ratio.
content items
content items are text / image_url / video_url / audio_url:
"content": [
{ "type": "text", "text": "An orange cat runs across the grass, camera follows" },
{ "type": "image_url", "image_url": { "url": "https://example.com/cat.png" }, "role": "reference_image" },
{ "type": "video_url", "video_url": { "url": "https://example.com/ref.mp4" } }, // role defaults to reference_video
{ "type": "audio_url", "audio_url": { "url": "https://example.com/ref.mp3" } } // role defaults to reference_audio
]An image's role is first_frame, last_frame, or reference_image:
- A single image without a role is treated as the first frame.
- Multiple images must set roles.
- When a video or audio reference is present, images must be
reference_image. - Frame mode takes at most 2 images: one must be
first_frame, two must be onefirst_frameand onelast_frame, and it cannot be mixed with references. - A Seedance 2.0 audio reference must be paired with an image or video; 2.5 accepts audio-only input.
Images and audio may be base64 Data URLs; video may not. Seedance 2.0 also accepts a ready asset://asset-id.
Reference media specs
These rules apply to Seedance 2.0 and 2.5, China and overseas, not to every video model.
Every reference is downloaded and checked at submit; a failing one returns an immediate 400 (no code; match on message) and incurs no task cost. Media that passes can still fail later on content review.
| Item | Image | Video | Audio |
|---|---|---|---|
| Count limit | 2.0: 9; 2.5: 30 | 2.0: 3; 2.5: 10 | 2.0: 3; 2.5: 10 |
| Formats | jpg / jpeg / png / webp / bmp / tif / tiff / gif / heic / heif | mp4 / mov (container must be MP4/ISO-BMFF) | wav / mp3 |
| Size | < 30 MiB | ≤ 200 MiB | ≤ 15 MiB |
| Dimensions | 300-6000 px per side | 300-6000 px per side; total pixels 409,600-8,295,044 | - |
| Aspect ratio | 0.4-2.5 | 0.4-2.5 | - |
| Duration | - | 2.0: 2-15s; 2.5: 2-30s | 2.0: 2-15s; 2.5: 2-30s |
| Frame rate | - | 24-60 FPS | - |
Frame mode takes at most 2 images. The combined video and audio totals fall under the same cap as a single clip and are counted separately, not added together: on 2.0 all reference videos together must be ≤ 15 seconds, all reference audio together also ≤ 15 seconds, and each clip ≥ 2 seconds.
The output duration and reference-media durations are independent limits. 1 MiB = 1,048,576 bytes.
Media URL must be a publicly reachable http(s) address:
- Private / loopback / link-local addresses and URLs with credentials are rejected.
- At most 3 redirects are followed.
- Each item must download and parse within 2 minutes.
- Data URLs must be
data:<MIME>;base64,….
Asset library (Seedance 2.0 only)
The asset library takes an existing public media URL and returns an asset ID, which you reference as asset://asset-id in Seedance 2.0 generation. Ordinary references can also use direct URLs without registration.
Upload. Save the returned data.Id; acceptance does not mean readiness.
curl https://api.hop-base.com/v1/sd/assets \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{
"URL": "https://example.com/your-image.jpg",
"Name": "character_front",
"AssetType": "Image"
}'{
"data": {
"Id": "assetEXAMPLE"
}
}Wait until ready. Query with the same group key roughly every 5 seconds, with a timeout. data.Status of Active means ready (completed / succeeded are also accepted, case-insensitively).
curl https://api.hop-base.com/v1/sd/assets/assetEXAMPLE \
-H "Authorization: Bearer sk-your-key"{
"data": {
"Id": "assetEXAMPLE",
"Status": "Active",
"AssetType": "Image"
}
}Wait while processing. Handle upload or moderation failures instead of submitting generation or polling forever.
Reference. Prefix the complete data.Id with asset:// and put it in generation content; do not substitute any URL from the query response.
curl https://api.hop-base.com/v1/video/generate \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{
"model": "dreamina-seedance-2-0-260128",
"content": [
{
"type": "text",
"text": "The subject waves gently at the camera"
},
{
"type": "image_url",
"image_url": {
"url": "asset://assetEXAMPLE"
},
"role": "reference_image"
}
],
"duration": 5,
"resolution": "720p",
"ratio": "16:9"
}'Upload request fields:
| Field | Required | Type & limits | Default | Description |
|---|---|---|---|---|
URL (or url) | Required | public HTTP(S) URL; no base64 or multipart | — | Host local files first |
AssetType (or asset_type) | Required | Image / Video / Audio, case-insensitive | — | Media type of the asset; checked against "Reference media specs" |
Name | Optional | string | — | Label for your own reference; not used in generation |
Duration (or duration / duration_seconds) | Optional | integer seconds | — | The real duration is still checked |
The upload downloads and checks the media against the 2.0 rules in "Reference media specs", so video and audio must run 2–15 seconds. Upload 400s carry error.code (for example invalid_asset_duration).
Adjust the content item to the media type:
- Video:
type: video_url,video_url.url: asset://…, androle: reference_video. - Audio:
audio_url/reference_audio. - For a first-frame image use
role: first_frame, and for a last framelast_frame; do not mix first/last frames with multimodal references.
Do not rewrite asset IDs or reuse them across groups or users. Generation still checks readiness, type, counts, and specifications; registration bypasses neither the 2.0 limits nor content moderation.
Response
Submit and single-task query responses are wrapped in task; do not read a top-level id / outputs.
Submit response
A successful submit returns 200 with a task.id such as vt… for later status queries. The submit response carries only id, model, status (pending or processing), outputs (always empty), error, created_at, and completed_at; get results by querying.
{
"task": {
"id": "vtEXAMPLE",
"model": "dreamina-seedance-2-5-260628",
"status": "pending",
"outputs": [],
"error": null,
"created_at": "2026-09-23T08:00:00Z",
"completed_at": null
}
}Task query fields
| Field | Description |
|---|---|
task.id | HopBase task ID, vt… |
task.status | One of pending / processing / completed / failed |
task.outputs | Output URLs, an array of strings, not {url} objects |
task.duration_seconds | Clip length; for auto-duration tasks, read after completion |
task.last_frame_url | Optional, only when a last frame exists; re-signed on every query |
task.usage.completion_tokens | Billable token count; tokens, not a dollar amount |
task.error.message | Failure reason in English, no code field |
task.completed_at | null until finished |
usage.cost / usage.cost_cny / usage.cost_usd | Actual charge once the task ends; see Video overview |
task.status is always one of these four values. Read task.outputs only on completed: a task reports completed only after its result links are ready, so outputs is never empty then. On pending / processing, keep polling; every 5 seconds is recommended.
480p and 720p generation usually takes 2-5 minutes; 1080p and 4K take longer. Output URLs support browser playback and Range requests and expire 30 days after completion.
In progress
{
"task": {
"id": "vtEXAMPLE",
"model": "dreamina-seedance-2-5-260628",
"status": "processing",
"outputs": [],
"error": null,
"created_at": "2026-09-23T08:00:00Z",
"completed_at": null
}
}Succeeded
Below is an excerpt of a completed task (HTTP 200); IDs, URLs, and usage are illustrative:
{
"task": {
"id": "vtEXAMPLE", // HopBase task ID
"model": "dreamina-seedance-2-5-260628",
"status": "completed",
"duration_seconds": 5, // for auto-duration tasks, read after completion
"outputs": ["https://api.hop-base.com/example-signed-video.mp4"], // array of strings, not {url} objects
"last_frame_url": "https://api.hop-base.com/example-signed-last-frame.jpg", // optional, only when a last frame exists
"usage": { "completion_tokens": 1000, "total_tokens": 1000 }, // optional; tokens, not a dollar amount
"error": null,
"created_at": "2026-09-23T08:00:00Z",
"completed_at": "2026-09-23T08:03:10Z" // null until finished
},
"usage": { "cost": 3.4, "currency": "CNY", "cost_cny": 3.4, "cost_usd": 0.5 }
}Failed
A failed generation still returns HTTP 200 on query, with status failed and the reason in task.error.message. Failed tasks are not billed.
{
"task": {
"id": "vtEXAMPLE",
"status": "failed",
"outputs": [],
"error": { "message": "<English failure reason>" }
}
}The message is English with no code field. Links are replaced by [URL_REDACTED], and request IDs and internal error codes are removed; when no reason is available it is a generic English fallback.
Task list
GET /v1/video/tasks accepts ?page=1&limit=20 and returns {"tasks": [...], "total": 1, "totalPages": 1}, where each element is a task object. limit defaults to 20 (maximum 100), and only API-submitted tasks are listed.
Minimal example
# 1. Submit
curl https://api.hop-base.com/v1/video/generate \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{
"model": "dreamina-seedance-2-5-260628",
"content": [
{ "type": "text", "text": "An orange cat runs across sunlit grass as the camera follows" }
],
"duration": 5,
"resolution": "720p",
"ratio": "16:9",
"generate_audio": false,
"watermark": false
}'
# 2. Poll with the returned task.id; every 5 seconds is recommended
curl https://api.hop-base.com/v1/video/tasks/vt-your-task-id \
-H "Authorization: Bearer sk-your-key"Notes
Seedance 2.5 task modes
Seedance 2.5 has no explicit task-mode parameter. When a request carries a reference_video, Seedance classifies it as ordinary generation, video extension, or video editing based on the prompt text. A continuation-style prompt ("continue this clip", "extend the shot") is treated as video extension.
| Mode | Must send |
|---|---|
| Video editing | duration: -1 and ratio: "adaptive" |
| Video extension, first/last-frame | ratio: "adaptive" |
The submit still returns 200 and the task only turns failed during polling, with no charge. When a reference video is present and the prompt could read as continuing the source clip, send ratio: "adaptive".
The failure message reads like identified your task as video extension based on your prompt. Seedance 2.0 has no extension or editing mode and is unaffected.
Real-person reference images
An image with a real person passed directly (URL or Data URL) may be rejected at submit: a synchronous 4xx with error.code input_sensitive and a message explaining the fix. On Seedance 2.0, use the asset library; 2.5 has no asset library and cannot use real-person references yet.
Seedance 2.0: upload the same image to the asset library (above) and reference it as asset://asset-id once ready. If you need a real-person reference, switch to 2.0 with the asset library. Registration does not bypass other content review.
Timeouts, cancellation, and result links
- A task still unfinished 24 hours after creation is failed automatically and not billed.
- Video tasks cannot be cancelled; do not resubmit after a successful submit, because every resubmission is another billed task.
- Output URLs are signed URLs on
api.hop-base.com, valid for 30 days after completion; querying again does not extend them, and an expired URL returns 410.
Moving from the overseas group to the China group
The China group also accepts the overseas dreamina-* IDs above as compatibility aliases (4K is still rejected). Existing clients moving from overseas to China only swap the key — base_url, API paths, request parameters, and polling logic stay the same.
After switching, call GET /v1/models with the new key to pick the complete model ID. Tasks submitted earlier remain queryable with their original task IDs.
Common errors and fixes
Three shapes copied from other APIs are rejected outright:
| What you sent | Fix |
|---|---|
A top-level prompt alone | Put the prompt in content[].text |
image_url as a string | Send an object {"url": …} |
type as image / input_image | Use image_url / video_url / audio_url |
Submit-time parameter errors
These errors return 400 synchronously; no task is created and nothing is billed. The body is {"error":{"message":"…","type":"invalid_request_error"}} with no code field, so match on message (numbers and indexes vary):
# Types and values
duration must be an integer # same for priority / execution_expires_after
watermark must be a boolean # same for generate_audio / return_last_frame
Seedance 2.0 duration must be an integer in 4-15 or -1, got 20
Seedance 2.5 duration must be an integer in 4-30 or -1, got 40
model dreamina-seedance-2-0-hc does not support parameter seed # rejected field; names the model you requested
model dreamina-seedance-2-0-hc does not support ratio 2:1
model dreamina-seedance-2-0-fast-hc does not support resolution 1080p
request body must not exceed 64MB
priority must be within 0-9, got 10
execution_expires_after must be within 3600-259200 seconds
callback_url must be a valid http(s) URL
safety_identifier must be an ASCII string of 1-64 characters
# content structure
missing content # only a top-level prompt was sent
content[0].image_url must be an object # image_url sent as a string
content[0].type does not support image # type sent as image / input_image
content[0].text must not be empty
multi-image scenarios must specify first_frame/last_frame or reference_image roles
images in a multimodal reference scenario must set role=reference_image
first/last frame image-to-video cannot be mixed with the multimodal reference scenario
Seedance 2.0 supports at most 9 reference images
# Model and group
domestic doubao-seedance-2-0-fast-260128-a only supports 480p, 720p, got 1080p
model seedream-5-0-pro is an image generation model, use POST /v1/images/generations insteadTwo cases are not these 400s:
| Error | Fix |
|---|---|
404 The current group does not support the requested model: <model ID> | The model ID is not in your key's group (e.g. a doubao-* ID with an overseas key); use a key from the group that serves the model |
Ends with only supports 480p or 720p, got 1080p | Overseas 2.5 asked for 1080p and your group does not support it; nothing is downgraded, so use 720p or a group that supports 1080p |
The 404 comes before the checks above; read valid IDs from GET /v1/models.
Reference media errors
content[1] is the item's index in content:
content[1] media URL returned HTTP 403 # the host refused the download (hotlink protection, expired signature…)
content[1] unable to fetch media file, make sure the URL is publicly accessible
content[1] media URL hostname could not be resolved
content[1] media URL must point to a public address, not a private or reserved one
content[1] too many redirects for media URL
content[1] unable to parse media metadata of the video asset # corrupt file or wrong format
content[1] media data URL must be base64-encoded
content[1] image data URL does not support MIME type image/svg+xml
# allowed: image/jpeg png webp bmp tiff gif heic heif; audio/wav audio/mpeg
content[1] reference image width and height must be within 300-6000 px, got 200x200
content[1] video asset duration must be within 2-15 seconds, got 16.000 seconds
total reference video duration must not exceed 15 seconds, got 18.000 secondsIf a reference cannot be downloaded and parsed within 2 minutes, the submit returns 503 with code upstream_timeout:
media validation timed out, please retry laterThis is a temporary service-side condition, not a problem with your media. Retry the same request later.
Asset-library reference errors are also synchronous 400s without a code:
content[1] reference asset is not ready yet, current status is Processing # keep querying; submit once Active
content[1] requires a image asset, got Video # AssetType does not match image_url / video_url / audio_url
content[1] references a retired Seedance 2.5 EP asset; ... # asset25-* is retired; pass the original public URL
... cannot be mixed in one task # reference assets from one upload batch, or pass public URLsTask failure reasons
OutputVideoSensitiveContentDetected / OutputAudioSensitiveContentDetected # output failed review; PolicyViolation = copyright
rejected by content moderation # the generated video, prompt, or reference media failed moderation
InputImageSensitiveContentDetected, other Input…Sensitive… # input media failed review, incl. real-person privacy
InvalidParameter / is not valid / missing required / identified your task as # invalid parameter or task mode
task no longer exists # the task no longer exists
task expired / timed out / did not finish within 24 hours # the task timed outReview and parameter failures (the first four) fail again if resubmitted unchanged: change the prompt, media, or parameter first. The last two can be resubmitted as is.
Billing
Seedance bills by video tokens; task.usage.completion_tokens is the billable token count. Failed tasks and submit-time 400s are not billed.
A submit reserves balance for the estimated cost, released when the task ends. With duration: -1, 2.5 reserves for 30 seconds and 2.0 for 15; when balance is tight, send an explicit duration to reserve less. Balance rules and the usage.cost fields are in Video overview; official prices per model are in the table above and on the model cards, and each request's actual charge is on the Usage page in the console.
Next steps
- Video overview: compare the video families and their shared task flow
- API reference: Submit a video task: request fields
- API reference: Query a video task: response fields
- Error codes and retries: what each error code means and whether to retry