The Seedance API is the Volcengine Ark content-generation API, and five facts cover most of it. The task endpoint is POST https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks. The model id is doubao-seedance-2-5-260628. Authentication is Authorization: Bearer $ARK_API_KEY. The call is asynchronous, so you create a task and poll it. And the result URL is valid for 24 hours.
What the Seedance API actually is
ByteDance Seedance 2.5 has no developer site of its own; the only developer entry point is Volcengine Ark. Generation is a task you create and watch: the create call returns an id, the query call a status and, on success, a hosted video URL. Nothing is synchronous, so your worker holds the state. The Seedance topic hub maps the model generations.
The endpoints that are not real
Search for this API and you meet endpoints the vendor’s documentation does not contain: /v1/generate, /v1/status, /v2/generate and /v2/status, under a v1/v2 scheme. Ark has no such versioning: /api/v3/ is the API version, not a model version. A GitHub repository calling itself the official document for Seedance 2.5 belongs to an individual account, not to ByteDance or Volcengine. Proxy sites are no more official.
Authentication and the two base URLs
Every call carries -H "Authorization: Bearer $ARK_API_KEY". The key is created on the Ark API-key page in the console and is long-lived. The host serves two base URLs the vendor calls non-interchangeable.
| Base URL | Use |
|---|---|
https://ark.cn-beijing.volces.com/api/v3 | Standard inference |
https://ark.cn-beijing.volces.com/api/plan/v3 | Agent Plan enterprise only |
Use the Agent Plan enterprise key and its base URL on the second, or the call may fail or bill extra.
Creating a task: the request body
The minimal request
curl -X POST https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedance-2-5-260628",
"content": [
{ "type": "text", "text": "A 30-second sequence in three shots: [0-10s] a workshop at dawn, [10-20s] hands assembling a clock movement, [20-30s] the finished clock on a windowsill." },
{ "type": "image_url",
"image_url": { "url": "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/seedance2.5_30s_input.png" },
"role": "reference_image" }
],
"generate_audio": true,
"ratio": "16:9",
"duration": 30
}'
Three field groups carry the request: model, content and the generation parameters. Each content entry declares a type, and media entries also a role. Output runs 4 to 30 seconds, or -1 to let the model choose, at 480p, 720p or 1080p, 24 fps, in mp4 or mov.
Reference material and the ratio rules

One call accepts up to 50 reference items: 30 images, 10 videos and 10 audio clips. Roles are first_frame, last_frame, reference_image, reference_video and reference_audio, and only this generation takes audio on its own, without an image or video beside it. Four task types constrain the parameters.
| Task | Trigger | Extra rule |
|---|---|---|
| Text to video | Text only | none |
| First or last frame | first_frame or last_frame role | ratio must be adaptive |
| Video edit | reference_video with an edit intent | ratio adaptive, duration -1 |
| Video extend | reference_video with an extend intent | ratio must be adaptive |
A video edit also requires the reference video to run 4 to 30 seconds. omni_reference_task_type declares the intended task type, so a mismatch surfaces early.
Polling a task and reading the status values
curl -X GET "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/cgt-2026****-****" \
-H "Authorization: Bearer $ARK_API_KEY"
{
"id": "cgt-2026****-****",
"model": "doubao-seedance-2-0-260128",
"status": "succeeded",
"content": {
"video_url": "https://ark-content-generation-cn-beijing.tos-cn-beijing.volces.com/xxx"
},
"usage": { "completion_tokens": 108900, "total_tokens": 108900 },
"created_at": 1779348818,
"updated_at": 1779348874,
"seed": 78674,
"resolution": "720p",
"ratio": "16:9",
"duration": 5,
"framespersecond": 24,
"service_tier": "default",
"execution_expires_after": 172800,
"generate_audio": true,
"draft": false,
"priority": 0
}
The status values
Task ids start with cgt-, and status takes six values: queued, running, cancelled, succeeded, failed and expired. Only a queued task can be cancelled, and a cancelled record is deleted after 24 hours. Duration varies with model, load and output specification, and a callback URL can replace the polling loop.
Handling the result URL before it expires
# Poll until the task leaves the queue, then take the URL immediately.
while :; do
payload=$(curl -s -X GET \
"https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/${TASK_ID}" \
-H "Authorization: Bearer $ARK_API_KEY")
status=$(printf '%s' "$payload" | jq -r .status)
[ "$status" = "running" ] || [ "$status" = "queued" ] || break
sleep 10
done
# The vendor states the video URL is valid for 24 hours: archive it now.
if [ "$status" = "succeeded" ]; then
curl -sL -o "seedance-${TASK_ID}.mp4" "$(printf '%s' "$payload" | jq -r .content.video_url)"
fi
Three limits govern this loop: only tasks from the last 7 days can be queried, so an older id is gone; the video URL is valid for 24 hours, so download it in time; and a Seedance 2.5 result URL accepts at most 100 downloads, so copy it to your own storage. Other hosts share the shape — see the Pika topic hub.
Token pricing and the two official formulas
Billing is by token, and the rate depends on output resolution and on whether the input contains video.
| Output resolution | Input without video | Input with video |
|---|---|---|
| 480p, 720p | 70.00 CNY per 1M | 42.00 CNY per 1M |
| 1080p | 77.00 CNY per 1M | 46.00 CNY per 1M |
The 1080p row sits at 72 percent of list price. Two formulas turn a rate into a bill: video price is token rate times usage, and usage is input plus output seconds multiplied by output width, height and frame rate, over 1024. Only successful generations are billed. For a 5-second 720p output at 16:9 that is 5 x 1280 x 720 x 24 / 1024, about 108,000 tokens, roughly 7.6 CNY at the 70.00 rate — our arithmetic, not the vendor’s, since no per-second price is published. The reply above is a 2.0 example, so its token count is not a 2.5 estimate.
What the vendor does not publish
Not published, as of this review:
- Free quota for this model: third-party figures are not official.
- Any per-second price, or a worked conversion from tokens to seconds.
- Type and default for several request fields, because one reference page could not be read in full.
- Latency, queue depth and success-rate guarantees.
Rate limits are published: 600 requests per minute for enterprise accounts and 180 for individuals, concurrency of 10 and 3, and per-account QPS caps of 20 for querying a task, 1 for listing tasks and 20 for cancelling or deleting one.
Frequently asked questions
Is the Seedance API official? Yes: documented on the Volcengine domain, authenticated with an Ark API key, billed on the Ark pricing page.
Why does my request fail on ratio? First-frame, video-edit and video-extend tasks require ratio to be adaptive; video edit also needs duration at -1.
How long do I have to fetch the video? 24 hours. A 2.5 result URL accepts at most 100 downloads, and tasks stay queryable for 7 days.
Can I skip polling? Yes, with the documented callback URL, which pushes a POST when the status changes.
What does one clip cost? Ark publishes token rates, not per-clip prices; apply the formulas and label the result as your estimate.
Check every number against the official pages. For one-off videos, the Seedance guide covers the browser route.