S
Seedance 2.0 API Guide

Seedance 2.0 Video Generation API

Access ByteDance Seedance 2.0 video generation models through the TokenHub unified API. Supports text-to-video, image-to-video, video editing, audio-driven generation and more. This guide walks you through the complete integration process.

See Models and Pricing for the current published catalog and rates. These pages update automatically.

Using Gemini to write prompts or scripts? See the text-generation API examples. For an unlisted model, use the model ID provided by your account administrator. Gemini API

Responses API streaming and billingThe request body limit is 50 MiB. Text-generation requests have a 30-minute budget including waiting and output; your client or the model service may stop sooner. HTTP 413 indicates body size, not the token limit. Requests rejected before a model call incur no model charges.

Query your balance and usage or manage API keys with an access token generated in Settings. View account API documentation

Search API keys by name or prefix and browse 20 keys per page. New keys appear on the first page. Refresh the list to see keys created in another window or through the API. API Keys

Text → VideoImage → VideoVideo → VideoAudio Reference480p / 720p / 1080p4–15 sec

1Get Your API Key

  1. Visit tokenhub.store to create an account (GitHub / Google sign-in supported)
  2. Go to Dashboard → API Keys, click "Create New Key"
  3. Go to Dashboard → Billing to add credits (1 Credit = $1 USD)
  4. Copy your API Key (format: th-xxxxxxxxxxxx...)
⚠️ The API Key is only shown once upon creation. Save it securely. If lost, you'll need to create a new one.

2API Overview

Base URL

https://tokenhub.store/api/v1

Authentication

All requests require an API Key in the header:

Header
Authorization: Bearer th-your-api-key

Two Endpoints

POST
/videos/generations

Create a video generation task, returns task ID

GET
/videos/generations/{task_id}

Query task status, returns video URL on success

3Models & Pricing

Model IDInputPriceDescription
doubao-seedance-2.0No video input$6.970/1M (1080p $7.727)Flagship model, highest quality. 1080p supported.
With video input$4.242/1M (1080p $4.697)Flagship with video input, cost-effective.
doubao-seedance-2.0-fastNo video input$5.606/1MFast model, quicker generation.
With video input$3.333/1MFast model with video input, most affordable.

Billing Details:

  • Output video: billed per 1M tokens (token count depends on resolution and duration)
  • Input image: free (no charge)
  • Input video: billed per 1M tokens at the with-video-input rate
  • Total cost = total tokens consumed × per-token rate (see table above)

Example: doubao-seedance-2.0 without video input (≤720p), generating a 5s video at ~1M tokens → cost ≈ $6.970

4Request Parameters

ParameterTypeRequiredDescription
modelstringRequiredModel ID, e.g. "doubao-seedance-2.0"
promptstringRequiredVideo description text. English prompts generally yield better results
durationnumberOptionalVideo duration (sec), range 4–15, default 5
resolutionstringOptional"480p", "720p", or "1080p" (default 720p; 1080p only for doubao-seedance-2.0)
aspect_ratiostringOptionalAspect ratio: "adaptive" (default), "16:9", "9:16", "1:1", etc.
image_urlstringOptionalReference image URL (image-to-video)
image_urlsstring[]OptionalArray of multiple reference image URLs
video_urlstringOptionalReference video URL (video editing / video-to-video)
video_urlsstring[]OptionalArray of multiple reference video URLs (max 3)
video_durationsnumber[]OptionalArray of per-video durations in seconds, e.g. [3, 5]
input_video_durationnumberOptionalTotal input video duration in seconds (alternative to video_durations)
audio_urlstringOptionalReference audio URL (background music / SFX)
audio_urlsstring[]OptionalArray of multiple reference audio URLs (max 3)
generate_audiobooleanOptionalWhether to generate audio, default true
watermarkbooleanOptionalWhether to add watermark, default false
contentarrayOptionalMedia assets array. Each item: { type: "image_url", image_url: { url }, role }. Supported roles: first_frame (max 1), last_frame (max 1), reference_image, reference_video, reference_audio

5Input Limits

You can freely combine text, images, videos, and audio as input. Note the following limits:

Images: 0–9 per request
Videos: 0–3 per request, each 2–15s, total duration ≤ 15s
Audios: 0–3 per request, each 2–15s, total duration ≤ 15s
❌ "Text + Audio only" and "Pure Audio" input are NOT supported

Supported Formats

  • Image formats: JPEG, PNG, WebP, BMP, TIFF, GIF (max 30MB each)
  • Video formats: MP4, MOV (H.264/H.265, max 50MB each)
  • Audio formats: WAV, MP3 (max 15MB each)
⚡ Tip: Only video duration affects billing. Total cost = (input video duration + output video duration) × rate. Input images are free.

6Complete API Examples

The most basic usage — describe a scene in text to generate a video.

bash
curl -X POST https://tokenhub.store/api/v1/videos/generations \
  -H "Authorization: Bearer th-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2.0",
    "prompt": "A golden retriever running on a sunny beach, waves crashing in the background, cinematic slow motion, 4K quality",
    "duration": 5,
    "resolution": "720p",
    "aspect_ratio": "16:9",
    "watermark": false
  }'

Response:

json
{
  "id": "xxxxxx-task-id",
  "object": "video.generation.task",
  "model": "doubao-seedance-2.0",
  "status": "queued",
  "created": 1719900000
}

Video generation is asynchronous — poll the status until complete.

bash
# Poll task status using the task_id from creation response
curl https://tokenhub.store/api/v1/videos/generations/YOUR_TASK_ID \
  -H "Authorization: Bearer th-your-api-key"

Task in progress:

json
{
  "id": "YOUR_TASK_ID",
  "object": "video.generation.task",
  "model": "doubao-seedance-2.0",
  "status": "running",
  "created": 1719900000
}

Task completed (video URL received):

json
{
  "id": "YOUR_TASK_ID",
  "object": "video.generation.task",
  "model": "doubao-seedance-2.0",
  "status": "succeeded",
  "created": 1719900000,
  "data": [
    {
      "video_url": "https://tokenhub-data.tos-cn-hongkong.volces.com/user_sd_file/YOUR_TASK_ID.mp4",
      "cover_image_url": "https://tokenhub-data.tos-cn-hongkong.volces.com/user_sd_file/YOUR_TASK_ID_cover.jpg"
    }
  ],
  "usage": {
    "video_duration": 5
  }
}
💡 Recommended polling interval: every 3-5 seconds. Status values: queued → waiting, running → generating, succeeded → done, failed → error

7Python Full Example

python
import requests
import time

API_BASE = "https://tokenhub.store/api/v1"
API_KEY = "th-your-api-key"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

# Step 1: Create video generation task
payload = {
    "model": "doubao-seedance-2.0",
    "prompt": "A majestic eagle soaring over snow-capped mountains, golden hour lighting, cinematic aerial shot",
    "duration": 5,
    "resolution": "720p",
    "aspect_ratio": "16:9",
    "watermark": False
}

resp = requests.post(f"{API_BASE}/videos/generations", json=payload, headers=headers)
task = resp.json()
task_id = task["id"]
print(f"Task created: {task_id}, status: {task['status']}")

# Step 2: Poll for result
while True:
    resp = requests.get(f"{API_BASE}/videos/generations/{task_id}", headers=headers)
    result = resp.json()
    status = result["status"]
    print(f"Status: {status}")

    if status == "succeeded":
        video_url = result["data"][0]["video_url"]
        duration = result["usage"]["video_duration"]
        print(f"Video ready! Duration: {duration}s")
        print(f"URL: {video_url}")
        break
    elif status == "failed":
        print(f"Failed: {result.get('error', {}).get('message', 'Unknown error')}")
        break

    time.sleep(5)

8JavaScript / Node.js Full Example

javascript
const API_BASE = "https://tokenhub.store/api/v1";
const API_KEY = "th-your-api-key";

const headers = {
  "Authorization": `Bearer ${API_KEY}`,
  "Content-Type": "application/json"
};

// Step 1: Create task
const createResp = await fetch(`${API_BASE}/videos/generations`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    model: "doubao-seedance-2.0",
    prompt: "A majestic eagle soaring over snow-capped mountains, cinematic aerial shot",
    duration: 5,
    resolution: "720p",
    aspect_ratio: "16:9",
    watermark: false,
  }),
});
const task = await createResp.json();
console.log("Task created:", task.id);

// Step 2: Poll for result
const poll = async () => {
  while (true) {
    const resp = await fetch(`${API_BASE}/videos/generations/${task.id}`, { headers });
    const result = await resp.json();
    console.log("Status:", result.status);

    if (result.status === "succeeded") {
      console.log("Video URL:", result.data[0].video_url);
      console.log("Duration:", result.usage.video_duration, "seconds");
      return result;
    }
    if (result.status === "failed") {
      console.error("Failed:", result.error?.message);
      return result;
    }
    await new Promise(r => setTimeout(r, 5000));
  }
};

await poll();

9Image-to-Video Python Example

python
import requests, time

API_BASE = "https://tokenhub.store/api/v1"
headers = {
    "Authorization": "Bearer th-your-api-key",
    "Content-Type": "application/json"
}

# Image-to-Video with a single reference image
payload = {
    "model": "doubao-seedance-2.0",
    "prompt": "The woman in the photo turns to face the camera and smiles warmly, her hair gently blowing in the wind",
    "duration": 5,
    "resolution": "720p",
    "image_url": "https://your-bucket.com/portrait.jpg",
    "watermark": False
}

resp = requests.post(f"{API_BASE}/videos/generations", json=payload, headers=headers)
task_id = resp.json()["id"]
print(f"Task: {task_id}")

# Poll for result
while True:
    r = requests.get(f"{API_BASE}/videos/generations/{task_id}", headers=headers).json()
    if r["status"] == "succeeded":
        print(f"Done: {r['data'][0]['video_url']}")
        break
    elif r["status"] == "failed":
        print(f"Error: {r.get('error', {}).get('message')}")
        break
    time.sleep(5)

10Real-Person Image to Video

When your input image contains a real person, TokenHub automatically routes the request to an upstream that supports real-person generation. No client changes required.

Triggers automatically when the upstream content filter detects a real person in the input image.

Request shape is identical to ordinary image-to-video — same POST /v1/videos/generations body.

Two possible response shapes

  • Normal: { "id": "cgt-...", "status": "queued" } (existing behaviour)
  • Real-person path: { "id": "pat-...", "status": "queued" } — additional asset processing, expect 10-90 seconds of extra latency

GET polling is identical — call /v1/videos/generations/{id} with whichever id POST returned, until status is succeeded or failed. The id rewrites are handled server-side; you always see the same id for the lifetime of the request.

Error: unsupported_real_person_input

Returned with status 400 when no real-person-capable provider is configured for your account. Contact your administrator to enable a supported provider.

Error: Asset processing timed out

Returned via GET with status: failed when the upstream asset preparation exceeds 5 minutes. Safe to retry the request.

Complete lifecycle example

The pat-id is opaque to your client — keep polling until status changes.

bash
# POST
curl -X POST https://tokenhub.store/api/v1/videos/generations \
  -H "Authorization: Bearer $TH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2.0",
    "prompt": "let her dance and spin",
    "duration": 8,
    "resolution": "480p",
    "content": [
      { "type": "image_url", "image_url": { "url": "https://example.com/portrait.png" }, "role": "first_frame" }
    ]
  }'
# → {"id":"pat-abc123","status":"queued"}

# GET (asset still uploading)
curl https://tokenhub.store/api/v1/videos/generations/pat-abc123 -H "Authorization: Bearer $TH_KEY"
# → {"id":"pat-abc123","status":"queued"}

# GET (upstream task running)
# → {"id":"pat-abc123","status":"running"}

# GET (complete — id stays pat-, video_url in data)
# → {"id":"pat-abc123","status":"succeeded","data":[{"video_url":"..."}]}

11Prompt Tips

Basic Structure

Recommended format: [Subject] + [Action] + [Environment/Background] + [Camera/Style]

Good Prompt Examples

  • "A young woman walking through a cherry blossom garden, petals falling in slow motion, soft natural lighting, cinematic 35mm film look"
  • "Close-up of hands pouring latte art into a ceramic cup, steam rising, warm cafe ambiance, shallow depth of field"
  • "Aerial drone shot of a winding river through autumn forest, golden and red leaves, morning mist, 4K cinematic"

Tips for Reference Images/Videos

  • Use "image 1", "image 2", "video 1", "audio 1" in the prompt to reference your assets
  • Specify scene content per time segment (e.g. "0-2s: xxx, 2-4s: xxx")
  • Specify start/end frames (e.g. "first frame is image 1", "end frame freezes on image 2")
  • Specify camera composition source (e.g. "use video 1 POV throughout")
  • Specify audio usage (e.g. "use audio 1 as background music throughout")

Tips

  • English prompts generally produce better results; Chinese is also supported
  • More specific, vivid descriptions lead to better results
  • Avoid overly abstract descriptions (e.g. "a nice video")
  • Camera language greatly improves quality (slow motion, close-up, aerial shot, tracking shot...)

12FAQ

Ready to Start?

Sign up for TokenHub and start using the Seedance 2.0 Video Generation API now

© 2026 TokenHub · Powered by ByteDance Seedance 2.0 · support@tokenhub.store