curl --request POST \
--url https://api.example.com/v1/seedance/video/generations \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"callback_url": "<string>",
"return_last_frame": true,
"service_tier": "<string>",
"execution_expires_after": 123,
"camera_fixed": true,
"generate_audio": true,
"safety_identifier": "<string>",
"content": [
{
"type": "<string>",
"text": "<string>",
"role": "<string>"
}
],
"resolution": "<string>",
"ratio": "<string>",
"duration": 123,
"frames": 123,
"seed": 123,
"watermark": true,
"draft": true,
"priority": 123
}
'import requests
url = "https://api.example.com/v1/seedance/video/generations"
payload = {
"model": "<string>",
"callback_url": "<string>",
"return_last_frame": True,
"service_tier": "<string>",
"execution_expires_after": 123,
"camera_fixed": True,
"generate_audio": True,
"safety_identifier": "<string>",
"content": [
{
"type": "<string>",
"text": "<string>",
"role": "<string>"
}
],
"resolution": "<string>",
"ratio": "<string>",
"duration": 123,
"frames": 123,
"seed": 123,
"watermark": True,
"draft": True,
"priority": 123
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
callback_url: '<string>',
return_last_frame: true,
service_tier: '<string>',
execution_expires_after: 123,
camera_fixed: true,
generate_audio: true,
safety_identifier: '<string>',
content: [{type: '<string>', text: '<string>', role: '<string>'}],
resolution: '<string>',
ratio: '<string>',
duration: 123,
frames: 123,
seed: 123,
watermark: true,
draft: true,
priority: 123
})
};
fetch('https://api.example.com/v1/seedance/video/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/seedance/video/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'callback_url' => '<string>',
'return_last_frame' => true,
'service_tier' => '<string>',
'execution_expires_after' => 123,
'camera_fixed' => true,
'generate_audio' => true,
'safety_identifier' => '<string>',
'content' => [
[
'type' => '<string>',
'text' => '<string>',
'role' => '<string>'
]
],
'resolution' => '<string>',
'ratio' => '<string>',
'duration' => 123,
'frames' => 123,
'seed' => 123,
'watermark' => true,
'draft' => true,
'priority' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/seedance/video/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"callback_url\": \"<string>\",\n \"return_last_frame\": true,\n \"service_tier\": \"<string>\",\n \"execution_expires_after\": 123,\n \"camera_fixed\": true,\n \"generate_audio\": true,\n \"safety_identifier\": \"<string>\",\n \"content\": [\n {\n \"type\": \"<string>\",\n \"text\": \"<string>\",\n \"role\": \"<string>\"\n }\n ],\n \"resolution\": \"<string>\",\n \"ratio\": \"<string>\",\n \"duration\": 123,\n \"frames\": 123,\n \"seed\": 123,\n \"watermark\": true,\n \"draft\": true,\n \"priority\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/seedance/video/generations")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"callback_url\": \"<string>\",\n \"return_last_frame\": true,\n \"service_tier\": \"<string>\",\n \"execution_expires_after\": 123,\n \"camera_fixed\": true,\n \"generate_audio\": true,\n \"safety_identifier\": \"<string>\",\n \"content\": [\n {\n \"type\": \"<string>\",\n \"text\": \"<string>\",\n \"role\": \"<string>\"\n }\n ],\n \"resolution\": \"<string>\",\n \"ratio\": \"<string>\",\n \"duration\": 123,\n \"frames\": 123,\n \"seed\": 123,\n \"watermark\": true,\n \"draft\": true,\n \"priority\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/seedance/video/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"callback_url\": \"<string>\",\n \"return_last_frame\": true,\n \"service_tier\": \"<string>\",\n \"execution_expires_after\": 123,\n \"camera_fixed\": true,\n \"generate_audio\": true,\n \"safety_identifier\": \"<string>\",\n \"content\": [\n {\n \"type\": \"<string>\",\n \"text\": \"<string>\",\n \"role\": \"<string>\"\n }\n ],\n \"resolution\": \"<string>\",\n \"ratio\": \"<string>\",\n \"duration\": 123,\n \"frames\": 123,\n \"seed\": 123,\n \"watermark\": true,\n \"draft\": true,\n \"priority\": 123\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>"
}Seedance Video Generation
Video generation API compatible with the official Seedance protocol, supporting text-to-video, image-to-video, reference media, and synchronized audio
curl --request POST \
--url https://api.example.com/v1/seedance/video/generations \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"callback_url": "<string>",
"return_last_frame": true,
"service_tier": "<string>",
"execution_expires_after": 123,
"camera_fixed": true,
"generate_audio": true,
"safety_identifier": "<string>",
"content": [
{
"type": "<string>",
"text": "<string>",
"role": "<string>"
}
],
"resolution": "<string>",
"ratio": "<string>",
"duration": 123,
"frames": 123,
"seed": 123,
"watermark": true,
"draft": true,
"priority": 123
}
'import requests
url = "https://api.example.com/v1/seedance/video/generations"
payload = {
"model": "<string>",
"callback_url": "<string>",
"return_last_frame": True,
"service_tier": "<string>",
"execution_expires_after": 123,
"camera_fixed": True,
"generate_audio": True,
"safety_identifier": "<string>",
"content": [
{
"type": "<string>",
"text": "<string>",
"role": "<string>"
}
],
"resolution": "<string>",
"ratio": "<string>",
"duration": 123,
"frames": 123,
"seed": 123,
"watermark": True,
"draft": True,
"priority": 123
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
callback_url: '<string>',
return_last_frame: true,
service_tier: '<string>',
execution_expires_after: 123,
camera_fixed: true,
generate_audio: true,
safety_identifier: '<string>',
content: [{type: '<string>', text: '<string>', role: '<string>'}],
resolution: '<string>',
ratio: '<string>',
duration: 123,
frames: 123,
seed: 123,
watermark: true,
draft: true,
priority: 123
})
};
fetch('https://api.example.com/v1/seedance/video/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/seedance/video/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'callback_url' => '<string>',
'return_last_frame' => true,
'service_tier' => '<string>',
'execution_expires_after' => 123,
'camera_fixed' => true,
'generate_audio' => true,
'safety_identifier' => '<string>',
'content' => [
[
'type' => '<string>',
'text' => '<string>',
'role' => '<string>'
]
],
'resolution' => '<string>',
'ratio' => '<string>',
'duration' => 123,
'frames' => 123,
'seed' => 123,
'watermark' => true,
'draft' => true,
'priority' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/seedance/video/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"callback_url\": \"<string>\",\n \"return_last_frame\": true,\n \"service_tier\": \"<string>\",\n \"execution_expires_after\": 123,\n \"camera_fixed\": true,\n \"generate_audio\": true,\n \"safety_identifier\": \"<string>\",\n \"content\": [\n {\n \"type\": \"<string>\",\n \"text\": \"<string>\",\n \"role\": \"<string>\"\n }\n ],\n \"resolution\": \"<string>\",\n \"ratio\": \"<string>\",\n \"duration\": 123,\n \"frames\": 123,\n \"seed\": 123,\n \"watermark\": true,\n \"draft\": true,\n \"priority\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/seedance/video/generations")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"callback_url\": \"<string>\",\n \"return_last_frame\": true,\n \"service_tier\": \"<string>\",\n \"execution_expires_after\": 123,\n \"camera_fixed\": true,\n \"generate_audio\": true,\n \"safety_identifier\": \"<string>\",\n \"content\": [\n {\n \"type\": \"<string>\",\n \"text\": \"<string>\",\n \"role\": \"<string>\"\n }\n ],\n \"resolution\": \"<string>\",\n \"ratio\": \"<string>\",\n \"duration\": 123,\n \"frames\": 123,\n \"seed\": 123,\n \"watermark\": true,\n \"draft\": true,\n \"priority\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/seedance/video/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"callback_url\": \"<string>\",\n \"return_last_frame\": true,\n \"service_tier\": \"<string>\",\n \"execution_expires_after\": 123,\n \"camera_fixed\": true,\n \"generate_audio\": true,\n \"safety_identifier\": \"<string>\",\n \"content\": [\n {\n \"type\": \"<string>\",\n \"text\": \"<string>\",\n \"role\": \"<string>\"\n }\n ],\n \"resolution\": \"<string>\",\n \"ratio\": \"<string>\",\n \"duration\": 123,\n \"frames\": 123,\n \"seed\": 123,\n \"watermark\": true,\n \"draft\": true,\n \"priority\": 123\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>"
}model must be a platform model identifier, which the gateway rewrites to the channel model name after routing. callback_url is overridden and injected by the gateway with a signed default callback address.
Features
- The
contentelement list supports five types: text, image, video, audio, and draft task - Supports first frame / last frame / reference images (1-9 for the 2.0 series) / reference video / reference audio
- Supports synchronized audio via
generate_audio(Seedance 2.0 series and 1.5 Pro only) - Supports online/offline inference via
service_tierand task timeout viaexecution_expires_after - Supports draft mode
draft(1.5 Pro only), last frame returnreturn_last_frame, and task prioritypriority(2.0 only) - Supports video editing (2.5 only), edit the visuals or audio of the original video, adding, deleting, or modifying objects in the video, or redrawing or repairing part of the frame.
- Supports Video extension (2.5 only), Extend the original video forward or backward.
Authentication
Include theAuthorization header in the format Bearer YOUR_API_KEY.
Supported Video Models
| Model Identifier | Model Type | Model Description |
|---|---|---|
| seedance-2.5 | Reference Video | seedance 2.5 is a next-generation video creation model with major improvements in long-form storytelling, multimodal referencing, and editing |
| seedance-2.0 | Reference Video | seedance 2.0 core video generation model |
| seedance-2.0-mini | Reference Video | new generation high-cost-benefit video generation model |
| seedance-2.0-fast | Reference Video | inherited the core functions and advantages of seedance-2.0, faster speed |
Quick example
import requests
url = "https://api.haitoken.ai/v1/seedance/video/generations"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
data = {
"model": "seedance-2.0",
"content": [
{"type": "text", "text": "A golden retriever runs along the beach at sunset, camera slowly tracking"},
{
"type": "image_url",
"image_url": {"url": "https://example.com/images/dog.png"},
"role": "first_frame"
}
],
"duration": 5,
"resolution": "720p",
"ratio": "16:9",
"generate_audio": True,
"watermark": False
}
response = requests.post(url, json=data, headers=headers)
print(response.json())
const response = await fetch('https://api.haitoken.ai/v1/seedance/video/generations', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'seedance-2.0',
content: [
{ type: 'text', text: 'A golden retriever runs along the beach at sunset, camera slowly tracking' },
{
type: 'image_url',
image_url: { url: 'https://example.com/images/dog.png' },
role: 'first_frame'
}
],
duration: 5,
resolution: '720p',
ratio: '16:9',
generate_audio: true,
watermark: false
})
});
const data = await response.json();
console.log(data);
curl -X POST 'https://api.haitoken.ai/v1/seedance/video/generations' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"model": "seedance-2.0",
"content": [
{"type": "text", "text": "A golden retriever runs along the beach at sunset, camera slowly tracking"},
{
"type": "image_url",
"image_url": {"url": "https://example.com/images/dog.png"},
"role": "first_frame"
}
],
"duration": 5,
"resolution": "720p",
"ratio": "16:9",
"generate_audio": true,
"watermark": false
}'
{
"id": "cgt-20260730120000-a1b2c3"
}
Next steps
- See Query Seedance video task to retrieve generation results
- See Video generation for the unified protocol
- See the Wan protocol for native Alibaba Wan parameters
- See the model list for available video models
Body
Platform model identifier (e.g. seedance-2.0), rewritten to the channel model name by the gateway after routing
Result callback URL (the upstream POSTs notifications on task status changes; when the gateway has a callback configured, it overrides and injects a signed default address)
Whether to return the last frame image of the generated video (PNG, same resolution as the video, no watermark), default false; can be used as the first frame of the next task to quickly generate multiple consecutive video segments
Service tier: default online inference (default) / flex offline inference (50% of the online price); the Seedance 2.0 series only supports online inference and does not support this parameter
Task timeout threshold (seconds), counted from created_at, range [3600, 259200], default 172800 (48 hours); the task is automatically terminated and marked as expired after timeout
Whether to fix the camera, default false; not supported in reference image scenarios and the Seedance 2.0 series
Whether to generate audio synchronized with the visuals (voice/sound effects/background music), default true; only supported by the Seedance 2.0 series and 1.5 Pro
Unique end-user identifier (for platform security audit, English only, max 64 characters; it is recommended to pass a hash of the username/user ID/email to avoid leaking privacy)
Content element list (text prompt / image / video / audio / draft task ID)
Show child attributes
Show child attributes
Generated video resolution: 480p / 720p / 1080p / 4k; the Seedance 2.0 series and 1.5 Pro default to 720p, 1.0 Pro / Pro Fast default to 1080p; 1080p is not supported by 2.0 Fast / 2.0 Mini, 4k is only supported by Seedance 2.0
Generated video aspect ratio: 16:9 / 4:3 / 1:1 / 3:4 / 9:16 / 21:9 / adaptive (intelligently selected based on the input)
Generated video duration (integer seconds); choose either duration or frames, frames takes precedence, default 5; Seedance 1.0 Pro / Pro Fast: [2, 12]; 1.5 Pro: [4, 12] or -1 (model intelligently selects the duration); Seedance 2.0 series: [4, 15] or -1
Generated video frame count (choose either duration or frames, frames takes precedence), used to generate fractional-second durations; only supported by Seedance 1.0 Pro / Pro Fast (not supported by the 2.0 series and 1.5 Pro), range [29, 289] and must satisfy 25 + 4n (frame rate 24, frames = seconds x 24)
Random seed, range [-1, 2^32-1], default -1 (random); not supported by the Seedance 2.0 series
Whether the generated video carries an "AI Generated" watermark, default false
Whether to enable draft mode (480p preview video at a lower cost for quick validation), default false; only supported by Seedance 1.5 Pro; draft mode does not support last frame return or offline inference
Task execution priority 0-9, higher values queue earlier, default 0; only supported by Seedance 2.0, only affects the queue order of the same Endpoint, not supported for offline inference (flex)
Response
Task ID