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
th-xxxxxxxxxxxx...)https://tokenhub.store/api/v1All requests require an API Key in the header:
Authorization: Bearer th-your-api-keyPOST/videos/generationsCreate a video generation task, returns task ID
GET/videos/generations/{task_id}Query task status, returns video URL on success
| Model ID | Input | Price | Description |
|---|---|---|---|
| doubao-seedance-2.0 | No 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-fast | No video input | $5.606/1M | Fast model, quicker generation. |
| With video input | $3.333/1M | Fast model with video input, most affordable. |
Billing Details:
Example: doubao-seedance-2.0 without video input (≤720p), generating a 5s video at ~1M tokens → cost ≈ $6.970
| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | Required | Model ID, e.g. "doubao-seedance-2.0" |
| prompt | string | Required | Video description text. English prompts generally yield better results |
| duration | number | Optional | Video duration (sec), range 4–15, default 5 |
| resolution | string | Optional | "480p", "720p", or "1080p" (default 720p; 1080p only for doubao-seedance-2.0) |
| aspect_ratio | string | Optional | Aspect ratio: "adaptive" (default), "16:9", "9:16", "1:1", etc. |
| image_url | string | Optional | Reference image URL (image-to-video) |
| image_urls | string[] | Optional | Array of multiple reference image URLs |
| video_url | string | Optional | Reference video URL (video editing / video-to-video) |
| video_urls | string[] | Optional | Array of multiple reference video URLs (max 3) |
| video_durations | number[] | Optional | Array of per-video durations in seconds, e.g. [3, 5] |
| input_video_duration | number | Optional | Total input video duration in seconds (alternative to video_durations) |
| audio_url | string | Optional | Reference audio URL (background music / SFX) |
| audio_urls | string[] | Optional | Array of multiple reference audio URLs (max 3) |
| generate_audio | boolean | Optional | Whether to generate audio, default true |
| watermark | boolean | Optional | Whether to add watermark, default false |
| content | array | Optional | Media 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 |
You can freely combine text, images, videos, and audio as input. Note the following limits:
The most basic usage — describe a scene in text to generate a video.
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:
{
"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.
# 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:
{
"id": "YOUR_TASK_ID",
"object": "video.generation.task",
"model": "doubao-seedance-2.0",
"status": "running",
"created": 1719900000
}Task completed (video URL received):
{
"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
}
}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)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();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)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.
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.
Returned with status 400 when no real-person-capable provider is configured for your account. Contact your administrator to enable a supported provider.
Returned via GET with status: failed when the upstream asset preparation exceeds 5 minutes. Safe to retry the request.
The pat-id is opaque to your client — keep polling until status changes.
# 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":"..."}]}Recommended format: [Subject] + [Action] + [Environment/Background] + [Camera/Style]
"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"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