TL;DR
Seedance 2.0 API launched on April 2, 2026 through Volcengine Ark. You create a video generation task with POST /v1/contents/generations/tasks, store the returned task ID, then poll the task endpoint until status becomes succeeded. The API supports text-to-video, image-to-video, first-and-last-frame control, multimodal references, and native audio generation. A 5-second 1080p video costs roughly $0.93. Download the generated video within 24 hours because the URL expires.
Want to use Seedance 2.0 API? Want to use Nanobanana API at 40% off? Try the ultimate AI API platform for all AI media APIs: Hypereal AI
Introduction
On April 2, 2026, ByteDance's Volcengine Ark platform released the official Seedance 2.0 API. Before that, developers could only generate Seedance 2.0 videos through the Volcengine web console. This guide focuses on the programmable API flow: submit a task, poll for completion, download the result, and handle production errors.
The API uses an async task pattern:
-
POSTa generation request. - Read the returned task ID.
-
GETthe task result until it succeeds or fails. - Download the video URL before it expires.
That flow is worth testing end-to-end before shipping. Apidog Test Scenarios can chain the submit request, extract the task ID, poll the result endpoint, and assert that the final response contains a valid video_url.
What is Seedance 2.0?
Seedance 2.0 is a ByteDance video generation model available through Volcengine Ark.
Model IDs:
doubao-seedance-2-0-260128
doubao-seedance-2-0-fast-260128
Use the standard model for production output. Use the fast model when iterating on prompts and settings.
Seedance 2.0 supports:
- Text-to-video
- Image-to-video
- First-and-last-frame control
- Multimodal references with images, video clips, and audio files
- Native audio generation
- Dialogue, sound effects, ambient sound, and music
- Lip sync in over 8 languages
- Natural-language camera control, such as dolly, tracking, and crane shots
- Up to 15-second outputs
- Up to 2K resolution
- 24 fps video
- Aspect ratios from
1:1to21:9
What changed from the web-console guides?
Earlier Seedance 2.0 tutorials described the Volcengine web UI because no public API was available at the time. Those guides usually showed how to enter a prompt in a browser and click a generate button.
The April 2, 2026 API release changes the workflow. You can now:
- Call Seedance from backend services
- Automate video generation pipelines
- Generate videos from user input
- Store results in your own object storage
- Add retries, cost tracking, and validation
- Test the entire async lifecycle
For developer use cases, use the API flow instead of the old UI workflow.
Prerequisites
Create a Volcengine account at:
https://www.volcengine.com
Then open the Ark API key page:
https://console.volcengine.com/ark/region:ark+cn-beijing/apikey
Generate an API key and export it locally:
export ARK_API_KEY="your-api-key-here"
Every request uses the key as a Bearer token:
Authorization: Bearer YOUR_ARK_API_KEY
New accounts receive free trial credits. The trial balance covers roughly 8 full 15-second generations at 1080p.
Base URL
All examples in this guide use the Beijing Ark endpoint:
https://ark.cn-beijing.volces.com/api/v3
The task creation endpoint is:
POST /v1/contents/generations/tasks
The task polling endpoint is:
GET /v1/contents/generations/tasks/{task_id}
Text-to-video: submit your first task
cURL
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-0-260128",
"content": [
{
"type": "text",
"text": "A golden retriever running through a sunlit wheat field, wide tracking shot, cinematic"
}
],
"resolution": "1080p",
"ratio": "16:9",
"duration": 5,
"watermark": false
}'
The API returns immediately with a task ID:
{
"id": "cgt-2025xxxxxxxx-xxxx"
}
Store this ID. You need it for polling.
Python SDK
Install the Ark runtime SDK:
pip install volcenginesdkarkruntime
Submit a text-to-video task:
import os
from volcenginesdkarkruntime import Ark
client = Ark(api_key=os.environ.get("ARK_API_KEY"))
resp = client.content_generation.tasks.create(
model="doubao-seedance-2-0-260128",
content=[
{
"type": "text",
"text": "A golden retriever running through a sunlit wheat field, wide tracking shot, cinematic",
}
],
resolution="1080p",
ratio="16:9",
duration=5,
watermark=False,
)
print(resp.id)
Async workflow: submit, poll, download
Seedance generation is not synchronous. A 5-second 1080p video usually takes 60 to 120 seconds.
The task lifecycle is:
queued -> running -> succeeded
-> failed
-> expired
-> cancelled
Poll while the task is queued or running. Stop when it reaches a terminal state.
Full Python polling loop
This example submits a task, polls with exponential backoff, and downloads the result immediately after success.
import os
import time
import requests
from volcenginesdkarkruntime import Ark
client = Ark(api_key=os.environ.get("ARK_API_KEY"))
# Step 1: submit
resp = client.content_generation.tasks.create(
model="doubao-seedance-2-0-260128",
content=[
{
"type": "text",
"text": "Aerial shot of a mountain lake at sunrise, slow dolly forward",
}
],
resolution="1080p",
ratio="16:9",
duration=5,
watermark=False,
)
task_id = resp.id
print(f"Task submitted: {task_id}")
# Step 2: poll with exponential backoff
wait = 10
status = None
video_url = None
while True:
result = client.content_generation.tasks.get(task_id=task_id)
status = result.status
print(f"Status: {status}")
if status == "succeeded":
video_url = result.content.video_url
print(f"Video URL: {video_url}")
break
if status in ("failed", "expired", "cancelled"):
print(f"Task ended with status: {status}")
break
time.sleep(wait)
wait = min(wait * 2, 60)
# Step 3: download immediately
if status == "succeeded" and video_url:
response = requests.get(video_url, stream=True)
response.raise_for_status()
with open("output.mp4", "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
print("Downloaded: output.mp4")
Use backoff to avoid hammering the API. The example starts at 10 seconds and caps polling delay at 60 seconds.
Image-to-video: animate a still image
For image-to-video, add an image_url item to the content array. The image becomes the first frame of the video.
resp = client.content_generation.tasks.create(
model="doubao-seedance-2-0-260128",
content=[
{
"type": "text",
"text": "The woman slowly turns her head and smiles at the camera",
},
{
"type": "image_url",
"image_url": {
"url": "https://example.com/portrait.jpg"
},
},
],
ratio="adaptive",
duration=5,
watermark=False,
)
Use ratio="adaptive" when you want the output to follow the source image's aspect ratio. This helps avoid unwanted cropping or letterboxing.
Limits:
- Each image must be under 30 MB.
- You can provide up to 9 images in one request.
First-and-last-frame control
Seedance 2.0 can generate motion between two bookend images.
Use this when you know the start and end states, such as:
- Product transformations
- Blooming or morphing effects
- Before/after scenes
- Multi-shot continuity workflows
Example:
resp = client.content_generation.tasks.create(
model="doubao-seedance-2-0-260128",
content=[
{
"type": "text",
"text": "The flower blooms from bud to full open, macro lens, soft light",
},
{
"type": "image_url",
"image_url": {
"url": "https://example.com/flower-bud.jpg"
},
},
{
"type": "image_url",
"image_url": {
"url": "https://example.com/flower-open.jpg"
},
},
],
ratio="adaptive",
duration=8,
watermark=False,
)
When a prompt and two images are present, the model treats the images as first and last frames. Put them in this order:
- First frame image
- Last frame image
You can also set return_last_frame: true when generating a clip. The response includes an image of the final frame. Use that image as the first frame of your next request to chain multiple clips.
Multimodal references: combine images, video, and audio
Seedance 2.0 can accept images, video clips, and audio files in the same content array.
Supported content types:
{
"type": "text",
"text": "Prompt text"
}
{
"type": "image_url",
"image_url": {
"url": "https://example.com/image.jpg"
}
}
{
"type": "video_url",
"video_url": {
"url": "https://example.com/reference.mp4"
}
}
{
"type": "audio_url",
"audio_url": {
"url": "https://example.com/audio.mp3"
}
}
Request limits:
- Up to 9 images, max 30 MB each
- Up to 3 video clips, 2 to 15 seconds each, max 50 MB each
- Up to 3 audio files, MP3, max 15 MB each
Example:
resp = client.content_generation.tasks.create(
model="doubao-seedance-2-0-260128",
content=[
{
"type": "text",
"text": "Match the visual style of the reference clip and add the provided background audio",
},
{
"type": "image_url",
"image_url": {
"url": "https://example.com/style-reference.jpg"
},
},
{
"type": "video_url",
"video_url": {
"url": "https://example.com/motion-reference.mp4"
},
},
{
"type": "audio_url",
"audio_url": {
"url": "https://example.com/background-music.mp3"
},
},
],
duration=10,
ratio="16:9",
watermark=False,
)
When you include a video reference, billing uses the V2V tier: approximately $3.90 per million tokens instead of $6.40.
Native audio generation
Set generate_audio=True to generate an audio track with the video.
resp = client.content_generation.tasks.create(
model="doubao-seedance-2-0-260128",
content=[
{
"type": "text",
"text": "A street musician plays guitar outside a cafe in Paris, crowds passing by, city sounds",
}
],
resolution="1080p",
ratio="16:9",
duration=10,
generate_audio=True,
watermark=False,
)
Native audio generation supports:
- Dialogue
- Sound effects
- Ambient noise
- Background music
- Lip sync in over 8 languages
Because the model performs joint audio-video generation, token usage is slightly higher than the same request without audio. Track completion_tokens to measure the exact cost.
Control resolution, aspect ratio, and duration
Use these parameters to control output size, shape, and length.
resolution
Accepted values:
480p
720p
1080p
2K
Default:
1080p
Higher resolution consumes more tokens.
ratio
Accepted values:
16:9
9:16
4:3
3:4
21:9
1:1
adaptive
Use adaptive for image-to-video requests when you want the output to follow the input image dimensions.
duration
Accepted values:
4 to 15
Unit: seconds.
Default:
5
Longer videos cost proportionally more.
Model choice
Use the fast model while prototyping:
doubao-seedance-2-0-fast-260128
Use the standard model for final output:
doubao-seedance-2-0-260128
Choose Seedance 2.0 when you need native audio-video generation, bookend frame control, or multimodal references. If you only need simple text-to-video and want to minimize cost, test the fast model at lower resolution first.
Read cost from the response
After a task succeeds, inspect the usage field:
{
"usage": {
"completion_tokens": 246840,
"total_tokens": 246840
}
}
Token usage depends on duration and resolution.
Reference points from the official docs:
- 15-second 1080p video: approximately 308,880 tokens
- 5-second 1080p video: approximately 102,960 tokens
Pricing for T2V and I2V at 1080p is 46 yuan per million tokens, about $6.40 per million tokens.
Quick estimates:
| Duration | Approx tokens | Approx cost |
|---|---|---|
| 5 seconds | 102,960 | roughly $0.93 |
| 10 seconds | 205,920 | roughly $1.97 |
For V2V tasks, meaning requests with a video reference input, the rate is 28 yuan per million tokens, about $3.90 per million tokens.
For production cost tracking:
def estimate_cost_usd(completion_tokens: int, usd_per_million_tokens: float) -> float:
return completion_tokens / 1_000_000 * usd_per_million_tokens
cost = estimate_cost_usd(
completion_tokens=246_840,
usd_per_million_tokens=6.40,
)
print(f"${cost:.2f}")
Log completion_tokens, task type, model, resolution, duration, and estimated cost for every task.
Important: download videos within 24 hours
The video_url returned by a successful task points to Volcengine object storage. The URL expires 24 hours after the task succeeds.
After expiration:
- The URL returns
403 - The generated file is no longer available
- The task record may still be queryable, but the video cannot be downloaded
Always copy the video to your own storage as soon as status becomes succeeded.
The execution_expires_after field confirms the task expiry window in seconds. For example, 172800 means 48 hours for the task record. The video URL still expires after 24 hours.
Task history is limited to the last 7 days. You cannot query tasks older than that.
Test the Seedance API with Apidog
The Seedance API needs a chained test because task submission and task polling are separate calls.
Build the test flow like this.
Step 1: Create a Test Scenario
In Apidog, open the Tests module and create a scenario named:
Seedance 2.0 video generation
Add an environment variable:
ARK_API_KEY=your-api-key
Use it in requests as:
{{ARK_API_KEY}}
Step 2: Add the submit request
Create a custom POST request:
POST https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks
Headers:
Content-Type: application/json
Authorization: Bearer {{ARK_API_KEY}}
Body:
{
"model": "doubao-seedance-2-0-260128",
"content": [
{
"type": "text",
"text": "Aerial shot of a mountain lake at sunrise, slow dolly forward"
}
],
"resolution": "1080p",
"ratio": "16:9",
"duration": 5,
"watermark": false
}
Add an Extract Variable processor after this step.
Extract from the response body with JSONPath:
$.id
Save it as:
TASK_ID
Step 3: Add a wait step
Insert a Wait processor after extracting TASK_ID.
Use:
30 seconds
This gives the model time to leave the initial queue state before polling.
Step 4: Poll inside a loop
Add a For loop with a maximum of 20 iterations.
Inside the loop, add a GET request:
GET https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/{{TASK_ID}}
Headers:
Authorization: Bearer {{ARK_API_KEY}}
After the GET, add a Wait processor:
10 seconds
Set the loop break condition:
$.status == "succeeded" or $.status == "failed"
Step 5: Assert the final response
After the loop exits, add assertions:
$.status equals "succeeded"
$.content.video_url is not empty
Run the scenario. The report should show:
- The submit request
- The extracted task ID
- Each poll response
- The final status
- Assertion results
You can also import the Seedance endpoints from cURL commands into Apidog to avoid manually entering every header and parameter.
Pricing breakdown: common 1080p examples
The Seedance API uses pay-as-you-go token pricing. There are no monthly seats beyond your account balance and trial credits.
| Task type | Rate per 1M tokens |
|---|---|
| T2V / I2V at 1080p | 46 yuan / roughly $6.40 |
| V2V with video reference input | 28 yuan / roughly $3.90 |
Approximate 1080p costs:
| Duration | Approx tokens | Cost, T2V/I2V |
|---|---|---|
| 5 seconds | ~103,000 | ~$0.66 yuan / ~$0.93 |
| 10 seconds | ~206,000 | ~$9.48 yuan / ~$1.32 |
| 15 seconds | ~309,000 | ~$14.21 yuan / ~$1.97 |
New accounts start with free trial credits covering around 8 full 15-second generations.
For development:
- Start at
720p. - Use the fast model while tuning prompts.
- Switch to the standard model for final renders.
- Log token usage from every successful task.
- Download results to your own storage immediately.
Common errors and fixes
429 Too Many Requests
This usually means you hit the concurrency limit. Too many tasks are running at the same time.
Fix:
- Retry with exponential backoff.
- Start with a 10-second wait.
- Double the wait after each retry.
- Cap the wait at 60 seconds.
- Limit concurrent task submissions in your application.
status: "failed"
The model could not generate the video.
Common causes:
- Prompt triggered safety filters
- Input image was corrupted
- Input file was too large
- Parameter combination was invalid
Fix:
- Validate file size before submission.
- Check that URLs are reachable.
- Simplify the prompt.
- Retry with a smaller resolution or shorter duration.
status: "expired"
The task stayed in the queue too long and expired.
Fix:
- Submit a new task.
- Add retry logic for expired tasks.
- Track peak-load failures separately from validation failures.
You cannot restart an expired task.
403 on video_url
The video URL expired before you downloaded it.
Fix:
- Download immediately after
succeeded. - Store the file in your own object storage.
- If needed, regenerate using the same parameters and saved seed value.
Seed reproducibility
If you saved the seed value from a previous response, pass it in a later request with the same parameters. The model will attempt to reproduce the same output.
Exact reproduction is not guaranteed if parameters change or server-side model versions change.
Production checklist
Before you ship a Seedance integration:
- Store
ARK_API_KEYin a secret manager. - Use async job processing in your backend.
- Persist every task ID.
- Poll with exponential backoff.
- Handle
failed,expired, andcancelled. - Download videos immediately after success.
- Copy videos to your own storage.
- Log
completion_tokensfor cost tracking. - Track model, duration, resolution, ratio, and task type.
- Add automated scenario tests for the full submit-poll-download flow.
Conclusion
Seedance 2.0 API gives developers programmatic access to ByteDance video generation through Volcengine Ark. The core implementation pattern is simple:
- Submit a generation task.
- Poll until the task succeeds.
- Download the result within 24 hours.
- Track token usage for cost control.
The API is most useful when you need multimodal references, native audio generation, or first-and-last-frame control. Test the async flow before production so broken polling, missing task IDs, and expired video URLs do not reach users.
FAQ
What's the difference between doubao-seedance-2-0-260128 and doubao-seedance-2-0-fast-260128?
The standard model produces higher-quality output and is the better default for production. The fast model completes jobs more quickly at lower visual quality. Use the fast model for prompt iteration, then switch to standard for final renders.
Can I use Seedance 2.0 outside China?
The API endpoint is hosted in the Beijing region. Developers outside China can call it, but latency will be higher. Check Volcengine's terms of service for geographic restrictions that may apply to your account.
How do I chain multiple clips into a longer video?
Set return_last_frame: true on each generation. The response includes an image of the final frame. Pass that image as the first frame of the next request, then stitch the generated clips with a video editing library.
Does native audio generation cost more?
Yes, it increases token consumption slightly because the model performs joint audio-video generation. Compare completion_tokens between requests with and without generate_audio: true.
Can I use a webhook instead of polling?
Yes. Pass callback_url in the submit request. The API will POST the completed task result to that URL when the status changes. This is better for high-volume pipelines.
What happens if I exceed the 9-image limit?
The API returns a 400 validation error before creating the task. Reduce the content array to 9 images or fewer.
Is the seed parameter guaranteed to reproduce the exact same video?
No. The seed parameter improves reproducibility, but exact reproduction is not guaranteed if parameters differ or server-side model versions change.
How do I track spending across multiple tasks?
Read completion_tokens from each completed task and multiply it by the rate for that task type. Store the result in your database along with task ID, model, resolution, duration, ratio, and whether the request used video references.

Top comments (0)