Seedance 2.0 API
Build video generation into your product with async task creation, status polling, webhooks, and credit-aware billing.
https://api.seedance2.aiOn this page
Introduction
The API lets you submit Seedance 2.0 video generation tasks programmatically. Generation is asynchronous: create a task, receive a task ID immediately, then get the finished video by polling the task endpoint or by receiving a webhook.
Async tasks
Polling works well for development and simple integrations.
Webhook ready
Webhooks are recommended for production because they avoid aggressive polling and notify your service when a task reaches a terminal state.
Credit aware
Credits are reserved on submit. Successful tasks are charged from that reservation; failed or timed-out tasks are refunded automatically.
Authentication
Create an API key in the dashboard and send it as a Bearer token on every request. The full key is shown only once at creation time.
Authorization: Bearer sk_live_xxxxxxxxUse sk_live_ keys for production traffic.
Use sk_test_ keys for sandbox integration testing with the same API contract.
Missing, invalid, or revoked keys return invalid_api_key with HTTP 401.
Quickstart
Submit a task first. After the task is accepted, choose one result delivery method: poll the task endpoint, or receive the terminal result through a webhook.
Create an asynchronous video task and receive a task ID immediately.
curl https://api.seedance2.ai/v1/videos/generations \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0",
"callback_url": "https://your-domain.com/api/seedance/webhook",
"input": {
"prompt": "a cat surfing on a neon wave, cinematic lighting",
"generation_type": "text-to-video",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
"generate_audio": true,
"watermark": false,
"web_search": false,
"return_last_frame": false,
"seed": -1
}
}'Fetch the task status endpoint when your integration prefers explicit polling.
curl https://api.seedance2.ai/v1/tasks/3f2aK9mR7xQp4TnZ8bLc6YwH \
-H "Authorization: Bearer sk_live_xxx"Pass callback_url when submitting the task, then receive completion or failure callbacks and update your own task record.
export async function POST(request: Request) {
const callbackData = await request.json();
if (callbackData.status === "completed") {
const videoUrl = callbackData.data.results[0];
// Save the video URL or update your own task record here.
}
if (callbackData.status === "failed") {
const errorMessage = callbackData.data.failed_reason;
// Mark your own task record as failed here.
}
return new Response(null, { status: 200 });
}Create a video task
Create a video task with POST /v1/videos/generations. The request body has a top-level model, an optional callback_url, and an input object containing prompt and generation settings.
/v1/videos/generationscurl https://api.seedance2.ai/v1/videos/generations \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0",
"callback_url": "https://your-domain.com/api/seedance/webhook",
"input": {
"prompt": "a cat surfing on a neon wave, cinematic lighting",
"generation_type": "text-to-video",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
"generate_audio": true,
"watermark": false,
"web_search": false,
"return_last_frame": false,
"seed": -1
}
}'Generation modes
generation_type controls which media inputs are accepted and how the model interprets them.
| Mode | Required media | Optional media | Notes |
|---|---|---|---|
text-to-video | prompt | duration, aspect_ratio, resolution, seed | Text prompt only. image_urls, video_urls, and audio_urls are not needed. |
image-to-video | prompt + image_urls array (1-2 image URLs) | duration, aspect_ratio, resolution, seed | image_urls must be an array. Provide 1 image URL for the first frame, or 2 image URLs for the first and last frames. Video and audio are ignored. |
reference-to-video | prompt + at least one image or video | images, videos, and audio within material limits | Audio cannot be used alone with text. Add at least one image or video when audio is provided. |
text-to-videoUse text-to-video when the prompt is the only creative input.
curl https://api.seedance2.ai/v1/videos/generations \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0",
"callback_url": "https://your-domain.com/api/seedance/webhook",
"input": {
"prompt": "a cinematic drone shot over a futuristic coastal city at sunrise",
"generation_type": "text-to-video",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p",
"generate_audio": true,
"watermark": false,
"web_search": false,
"return_last_frame": false,
"seed": -1
}
}'image-to-videoUse image-to-video when input.image_urls is an array with 1-2 image URLs: one URL sets the first frame, and two URLs set the first and last frames. Video and audio references are ignored in this mode.
curl https://api.seedance2.ai/v1/videos/generations \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0",
"input": {
"prompt": "the subject turns toward camera, soft studio motion",
"generation_type": "image-to-video",
"image_urls": ["https://your.cdn.com/first-frame.jpg"],
"duration": 5,
"resolution": "720p"
}
}'reference-to-videoUse reference-to-video for richer direction with reference images, videos, and audio. Audio cannot be used alone with text; include at least one image or video when audio is provided.
Material limits
- Up to 9 reference images
- Up to 3 reference videos, total duration <= 15 seconds
- Up to 3 reference audios, total duration <= 15 seconds
- Maximum 12 materials in total across all types
Supported input combinations
curl https://api.seedance2.ai/v1/videos/generations \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2-0",
"input": {
"prompt": "use the product from image 1 and the camera motion from the reference video",
"generation_type": "reference-to-video",
"image_urls": ["https://your.cdn.com/product.jpg"],
"video_urls": ["https://your.cdn.com/camera-motion.mp4"],
"audio_urls": [],
"duration": 8,
"resolution": "1080p"
}
}'Request parameters
Parameter names, enum values, endpoint paths, and examples are part of the API contract. Descriptions below explain how each field behaves.
Headers
| Header | Required | Description | Example |
|---|---|---|---|
Authorization | Yes | Bearer API key used to authenticate the request. | Bearer sk_live_xxx |
Content-Type | Yes | All write requests use JSON. | application/json |
Top-level fields
| Field | Type | Required | Default | Range / Enum | Modes | Example |
|---|---|---|---|---|---|---|
modelModel variant used for generation. | string | Yes | - | seedance-2-0 | seedance-2-0-fast | all | seedance-2-0 |
callback_urlHTTPS endpoint that receives task completion and failure callbacks. | string | No | - | HTTPS URL, no private networks | all | https://your-domain.com/hook |
inputGeneration settings and media references. | object | Yes | - | - | all | - |
input.* fields
| Field | Type | Required | Default | Range / Enum | Modes | Example |
|---|---|---|---|---|---|---|
input.promptText prompt describing the video to create. | string | Yes | - | non-empty text | all | a cat surfing |
input.generation_typeGeneration mode. Defaults to text-to-video. | string | No | text-to-video | text-to-video | image-to-video | reference-to-video | - | image-to-video |
input.image_urlsPublicly reachable image URLs. For image-to-video, send 1 image for the first frame or 2 images for the first and last frames. For reference-to-video, send up to 9 images as visual references. | string[] | Conditional | [] | Image-to-video: 1 or 2 images. Reference-to-video: up to 9 images. | image-to-video / reference-to-video | ["https://.../a.jpg"] |
input.video_urlsPublicly reachable reference videos for reference-to-video only. You can send up to 3 video files, and their combined playback time must be 15 seconds or less. | string[] | No | [] | Up to 3 videos. Combined video length must be 15 seconds or less. | reference-to-video | [] |
input.audio_urlsPublicly reachable reference audio files for reference-to-video only. You can send up to 3 audio files, and their combined playback time must be 15 seconds or less. | string[] | No | [] | Up to 3 audio files. Combined audio length must be 15 seconds or less. | reference-to-video | [] |
input.durationOutput video length in seconds. | int | No | 5 | 4-15 seconds | all | 5 |
input.aspect_ratioOutput aspect ratio. adaptive lets the service infer the best ratio. | string | No | adaptive | 16:9 | 4:3 | 1:1 | 3:4 | 9:16 | 21:9 | adaptive | all | 16:9 |
input.resolutionOutput resolution tier. | string | No | 720p | 480p | 720p | 1080p | all | 720p |
input.generate_audioWhether the model should generate audio when supported. | boolean | No | true | true | false | all | true |
input.watermarkWhether to add a watermark. | boolean | No | false | true | false | all | false |
input.web_searchWhether to allow web search augmentation when supported. | boolean | No | false | true | false | all | false |
input.return_last_frameWhether to return the last frame URL when available. | boolean | No | false | true | false | all | false |
input.seedDeterministic seed. Use -1 for a random seed. | int | No | -1 | -1 or 0-4294967295 | all | -1 |
Credits vary by resolution, duration, model, and whether reference-to-video includes video references. The credits value returned by the create response is the actual reserved amount for that task.
View credit pricingResponse
This is the success response from POST /v1/videos/generations. It means the task has been accepted and credits have been reserved. Use the returned taskId to poll GET /v1/tasks/:id or to match a completion or failure callback.
POST /v1/videos/generations success response
{
"taskId": "3f2aK9mR...",
"credits": 60
}Get task status
Use GET /v1/tasks/:id to retrieve the current task state. Poll no more than once every 10 seconds. For production systems, prefer webhooks.
curl https://api.seedance2.ai/v1/tasks/3f2aK9mR7xQp4TnZ8bLc6YwH \
-H "Authorization: Bearer sk_live_xxx"Completed task response
{
"id": "3f2aK9mR...",
"status": "completed",
"created_at": 1781234567,
"model": "seedance-2-0",
"billing_status": "charged",
"credits": 60,
"failed_reason": null,
"data": {
"results": ["https://cdn.seedance2.ai/.../x.mp4"],
"video_expires_at": "2026-06-13T10:00:00Z",
"last_frame_url": null,
"processing_time": 48
}
}Failed task response
{
"id": "3f2aK9mR...",
"status": "failed",
"created_at": 1781234567,
"model": "seedance-2-0",
"billing_status": "refunded",
"credits": 60,
"failed_reason": "provider_failed"
}| Value | Meaning |
|---|---|
status=queued | Accepted and waiting to be submitted or processed. |
status=generating | Provider is processing the generation. |
status=completed | Video completed and data.results contains the result URL. |
status=failed | Generation failed or timed out. |
billing_status=reserved | Credits are reserved while the task is in progress. |
billing_status=charged | Task succeeded and the reservation is settled. |
billing_status=refunded | Task failed or timed out and credits were returned. |
billing_status=refund_failed | Refund transaction failed and needs manual handling. |
After video_expires_at, data.results is empty. Download and store the file before the validity window ends.
Webhooks
When callback_url is present, Seedance calls your endpoint when the task is completed or failed, and sends JSON data describing the final result. If your endpoint returns a non-2xx response or does not respond within 15 seconds, delivery is retried up to 5 times. Retries reuse the same task id, so de-dupe by id. Return a 200 response as soon as you have safely recorded the callback data.
Task completion callback
{
"id": "3f2aK9mR...",
"status": "completed",
"created_at": 1781234567,
"model": "seedance-2-0",
"data": {
"results": ["https://cdn.seedance2.ai/.../x.mp4"],
"video_expires_at": "2026-06-13T10:00:00Z",
"last_frame_url": null,
"processing_time": 48
}
}Task failure callback
{
"id": "3f2aK9mR...",
"status": "failed",
"created_at": 1781234567,
"model": "seedance-2-0",
"data": {
"failed_reason": "provider_failed",
"credits_refunded": 60
}
}export async function POST(request: Request) {
const callbackData = await request.json();
if (callbackData.status === "completed") {
const videoUrl = callbackData.data.results[0];
// Save the video URL or update your own task record here.
}
if (callbackData.status === "failed") {
const errorMessage = callbackData.data.failed_reason;
// Mark your own task record as failed here.
}
return new Response(null, { status: 200 });
}Validate the callback data shape, de-dupe by id, update your own task record, and respond quickly.
callback_url must be HTTPS and must not point to private, loopback, or link-local network ranges.
Errors
POST /v1/videos/generations and GET /v1/tasks/:id return this error shape when the API request itself fails, such as invalid parameters, invalid API key, insufficient credits, rate limiting, or task not found. Some errors include extra fields such as required, available, or retry_after depending on the situation.
{
"error": {
"code": "insufficient_credits",
"message": "Not enough credits for this task.",
"required": 60,
"available": 12
}
}| Code | HTTP | Meaning | Retry? |
|---|---|---|---|
invalid_request | 400 | Missing or invalid parameters. | No, fix the request. |
invalid_api_key | 401 | API key is missing, invalid, or revoked. | No, use a valid key. |
insufficient_credits | 402 | Not enough credits. The task is not accepted or charged. | After recharge. |
forbidden | 403 | API key lacks the required scope. | No. |
not_found | 404 | Task does not exist or does not belong to the key owner. | No. |
rate_limited | 429 | Request rate exceeded. | Yes, follow Retry-After. |
internal_error | 500 | Server error. | Yes, retry later. |
Rate limits
Rate limits are applied per API key with a sliding window. Generation defaults to 60 requests per minute; status queries are more lenient. HTTP 429 responses include Retry-After.
Generation
60/min
Status queries
More lenient
429 header
Retry-After
Billing & credits
The API uses reserve on submit, charge on success, and refund on failure. Dashboard usage pages show API credit history, task logs, and time-based usage statistics.
Reserved
Credits are checked and reserved when the task is accepted.
Charged
Completed tasks settle the existing reservation.
Refunded
Failed or timed-out tasks return the reserved credits automatically.
Inspect usage in the dashboard
View API logs, task timelines, credit history, and time-based usage metrics.