Seedance 2.0 API

Build video generation into your product with async task creation, status polling, webhooks, and credit-aware billing.

Base URL
https://api.seedance2.ai
On 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_xxxxxxxx
sk_live_

Use sk_live_ keys for production traffic.

sk_test_

Use sk_test_ keys for sandbox integration testing with the same API contract.

401

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.

Submit a task

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
    }
  }'
Result option: Polling

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"
Result option: Webhook

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.

POST
/v1/videos/generations
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
    }
  }'

Generation modes

generation_type controls which media inputs are accepted and how the model interprets them.

ModeRequired mediaOptional mediaNotes
text-to-videopromptduration, aspect_ratio, resolution, seedText prompt only. image_urls, video_urls, and audio_urls are not needed.
image-to-videoprompt + image_urls array (1-2 image URLs)duration, aspect_ratio, resolution, seedimage_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-videoprompt + at least one image or videoimages, videos, and audio within material limitsAudio cannot be used alone with text. Add at least one image or video when audio is provided.
text-to-video

Use 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-video

Use 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-video

Use 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

Text + Image
Text + Video
Text + Image + Video
Text + Image + Audio
Text + Video + Audio
Text + Image + Video + Audio
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

HeaderRequiredDescriptionExample
AuthorizationYesBearer API key used to authenticate the request.Bearer sk_live_xxx
Content-TypeYesAll write requests use JSON.application/json

Top-level fields

FieldTypeRequiredDefaultRange / EnumModesExample
model

Model variant used for generation.

stringYes-seedance-2-0 | seedance-2-0-fastallseedance-2-0
callback_url

HTTPS endpoint that receives task completion and failure callbacks.

stringNo-HTTPS URL, no private networksallhttps://your-domain.com/hook
input

Generation settings and media references.

objectYes--all-

input.* fields

FieldTypeRequiredDefaultRange / EnumModesExample
input.prompt

Text prompt describing the video to create.

stringYes-non-empty textalla cat surfing
input.generation_type

Generation mode. Defaults to text-to-video.

stringNotext-to-videotext-to-video | image-to-video | reference-to-video-image-to-video
input.image_urls

Publicly 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_urls

Publicly 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_urls

Publicly 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.duration

Output video length in seconds.

intNo54-15 secondsall5
input.aspect_ratio

Output aspect ratio. adaptive lets the service infer the best ratio.

stringNoadaptive16:9 | 4:3 | 1:1 | 3:4 | 9:16 | 21:9 | adaptiveall16:9
input.resolution

Output resolution tier.

stringNo720p480p | 720p | 1080pall720p
input.generate_audio

Whether the model should generate audio when supported.

booleanNotruetrue | falsealltrue
input.watermark

Whether to add a watermark.

booleanNofalsetrue | falseallfalse
input.web_search

Whether to allow web search augmentation when supported.

booleanNofalsetrue | falseallfalse
input.return_last_frame

Whether to return the last frame URL when available.

booleanNofalsetrue | falseallfalse
input.seed

Deterministic seed. Use -1 for a random seed.

intNo-1-1 or 0-4294967295all-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 pricing

Response

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"
}
ValueMeaning
status=queuedAccepted and waiting to be submitted or processed.
status=generatingProvider is processing the generation.
status=completedVideo completed and data.results contains the result URL.
status=failedGeneration failed or timed out.
billing_status=reservedCredits are reserved while the task is in progress.
billing_status=chargedTask succeeded and the reservation is settled.
billing_status=refundedTask failed or timed out and credits were returned.
billing_status=refund_failedRefund 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
  }
}
CodeHTTPMeaningRetry?
invalid_request400Missing or invalid parameters.No, fix the request.
invalid_api_key401API key is missing, invalid, or revoked.No, use a valid key.
insufficient_credits402Not enough credits. The task is not accepted or charged.After recharge.
forbidden403API key lacks the required scope.No.
not_found404Task does not exist or does not belong to the key owner.No.
rate_limited429Request rate exceeded.Yes, follow Retry-After.
internal_error500Server 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.

API logs