doubao-seedance-2.0-fast-face
ByteDance Seedance 2.0 Fast on reAPI — async 4–15 second video at 480p or 720p with generated audio. Full parameter reference, request modes, content filter and billing dimensions.
The Fast tier of ByteDance's Seedance 2.0 on reAPI. It takes the same request
as Seedance 2.0 — text, photos, clips or audio in; 4–15 seconds of video with
generated speech, sound effects and music out — and caps at 720p for a lower
per-second rate. Mode is implicit: which media fields you set (prompt,
image_urls, image_with_roles, video_urls, audio_urls) decides whether
the request runs as text-to-video, image-to-video, first/last-frame
transition, or reference-driven generation. Two variants share one endpoint
and one parameter shape — pick the variant via model. See pricing on the
model page.
Quick example
curl https://reapi.ai/api/v1/videos/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-2.0-fast-face",
"prompt": "A street dancer spins under neon signs at night, handheld tracking shot",
"resolution": "720p",
"size": "9:16",
"duration": 5
}'import requests
resp = requests.post(
"https://reapi.ai/api/v1/videos/generations",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"model": "doubao-seedance-2.0-fast-face",
"prompt": "A street dancer spins under neon signs at night, handheld tracking shot",
"resolution": "720p",
"size": "9:16",
"duration": 5,
},
timeout=30,
)
print(resp.json())const r = await fetch("https://reapi.ai/api/v1/videos/generations", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "doubao-seedance-2.0-fast-face",
prompt: "A street dancer spins under neon signs at night, handheld tracking shot",
resolution: "720p",
size: "9:16",
duration: 5,
}),
});
console.log(await r.json());package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]any{
"model": "doubao-seedance-2.0-fast-face",
"prompt": "A street dancer spins under neon signs at night, handheld tracking shot",
"resolution": "720p",
"size": "9:16",
"duration": 5,
})
req, _ := http.NewRequest("POST",
"https://reapi.ai/api/v1/videos/generations", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}Authentication
Every call needs a Bearer token. Generate keys at reapi.ai/settings/apikeys.
Authorization: Bearer YOUR_API_KEYKeys carry the active workspace's billing scope — there is no separate project header.
Endpoint
POST /api/v1/videos/generations
GET /api/v1/tasks/{id}Submission is async. The POST returns immediately with the task id; poll
GET /api/v1/tasks/{id} with it until the task completes. Polling does not
consume credits.
Variants
Two variants, one parameter shape. Pick via model:
| Model id | Resolutions | Web search (tools) |
|---|---|---|
doubao-seedance-2.0-fast-face | 480p / 720p | ✅ |
seedance-2.0-fast-pr | 480p / 720p | ❌ |
Both accept real-person reference images and clips, and both carry the
content_filter switch. Neither accepts duration: -1 — set an explicit
length. For 1080p, 4k or automatic duration, use
Seedance 2.0.
seedance-2.0-fast-pr is the official Fast model at reseller pricing, on its
own per-second rates. Same request body, except tools (web search): a request
carrying it is accepted, then its task fails with code 80007 and the credits
are refunded in full.
reAPI never silently substitutes one variant for another: resolution: "1080p"
on a Fast variant returns 400, never an auto-downgraded clip.
Request body
Mode is implicit — which media fields you set decides text-to-video, image-to-video, first/last-frame, or reference-driven generation (see Task types).
| Field | Type | Default | Notes |
|---|---|---|---|
model | string | — | doubao-seedance-2.0-fast-face or seedance-2.0-fast-pr. Required. |
prompt | string | — | Describe the video: 3–20000 chars. Required on every request, in every mode. Wrap spoken lines in double quotes to steer the generated speech. |
duration | integer | 5 | Output length in seconds: 4–15. -1 (automatic length) is not available on Fast. |
size | string | 16:9 | 16:9 / 9:16 / 1:1 / 4:3 / 3:4 / 21:9 / adaptive (match the input image / video). |
resolution | string | 720p | 480p / 720p, lowercase only. |
bitrate_mode | enum | "default" | default: no processing; standard: smaller files; high: lighter compression. No extra generation charge — see bitrate_mode. |
generate_audio | boolean | true | Generate synced speech, sound effects and background music. Independent of audio_urls, which is a reference for the model, not a synthesis toggle. |
watermark | boolean | false | Stamp an "AI generated" mark in the bottom-right corner. |
return_last_frame | boolean | false | Return output.last_frame_url for continuous chaining. |
tools | object[] | — | [{ "type": "web_search" }] to let the model query the web. doubao-seedance-2.0-fast-face only. |
image_urls | string[] | — | Up to 9 reference images (jpeg / png / webp / bmp / tiff / gif / heic / heif). Public HTTP(S) URLs. Every entry is sent as a reference image; to pin the opening or closing frame, use image_with_roles. |
image_with_roles | object[] | — | Images with an explicit role: { url, role } where role is first_frame, last_frame, or reference_image. At most one first_frame and one last_frame, and a last_frame needs a first_frame; up to 9 entries. Frame roles cannot be mixed with reference_image in one array, and cannot be combined with video_urls / audio_urls. |
video_urls | string[] | — | Up to 3 reference clips (mp4 / mov, H.264 / H.265 with AAC / MP3 audio, 300–6000 px per side), combined ≤ 15 s. |
audio_urls | string[] | — | Up to 3 reference audio tracks (wav / mp3), each 2–15 s, combined ≤ 15 s. Needs an image (image_urls or a reference_image entry) or video_urls alongside. |
content_filter | boolean | true | Safety checking. Set false to run the task on the unmoderated route — see content_filter below. |
Checked before anything is submitted or charged:
promptis present on every request (3–20000 chars)resolutionis480por720p, anddurationis a whole number from 4 to 15image_urlsandimage_with_rolesare mutually exclusive (both carry reference images — pick one)- at most one
first_frameand onelast_frame, and alast_framealways needs afirst_frame(there is no last-frame-only task type) - frame roles and
reference_imagecannot share oneimage_with_rolesarray, and frame roles cannot be combined withvideo_urls/audio_urls audio_urlsneeds a visual reference (an image or a clip) alongside it- reference clips: 3 max, 15 s combined; reference audio: each 2–15 s, 3 max, 15 s combined
There is no seed on Seedance 2.0 Fast — the upstream model does not support
one, so the field is rejected rather than silently ignored.
bitrate_mode — enum, default "default"
This is reAPI output processing after generation.
"default"or omitted: return the original file without processing or re-encoding. This is the default setting."standard": compress for smaller files and faster downloads."high": apply lighter compression to retain more detail thanstandard, usually producing a larger file. It does not enhance the original video.
Processing preserves resolution, frame timing, audio, and the MP4/MOV container. If encoding would increase file size, the original file is kept. The generation charge is unchanged. Processing adds time and supports source files up to 1 GiB; savings vary by video.
Legacy booleans remain accepted: false maps to "default", and true maps
to "standard". Other values return 400 before charging.
{ "bitrate_mode": "default" }content_filter — boolean, default true
With the default (true) the request runs on the moderated route: prompts,
reference material and output are checked, and a rejection fails the task with
a refund.
Set content_filter: false to run the same request on the unmoderated route
instead. What changes:
- API keys only. A non-admin website session that sends
content_filter: falseis rejected with400before anything is charged; the playground runs moderated for normal users. - Same parameters, same price. Every field, tier gate and rate in this document applies unchanged — which channel served the request is internal. The route still caps at 720p.
- Output storage. On
doubao-seedance-2.0-fast-facethe output lands in an isolated bucket and its URLs stay valid for 30 days. Onseedance-2.0-fast-prthe result URLs are returned as delivered (unless you setbitrate_mode) and carry no retention guarantee. Either way, mirror the files you want to keep.
Platform terms apply to everything you generate on either route.
{
"model": "doubao-seedance-2.0-fast-face",
"prompt": "A street dancer spins under neon signs at night",
"resolution": "720p",
"duration": 5,
"content_filter": false
}Task types and constraints
Seedance 2.0 Fast picks its job from the media fields you send — there is no
mode parameter:
| Job | What it does | Needs | Hard rules |
|---|---|---|---|
| Text-to-video | new clip from a prompt | prompt only | none |
| Image reference | new clip guided by reference images | prompt + image_urls (1–9) | none |
| First / last frame | animates between given frames | prompt + image_with_roles (1–2 frames) | frames cannot be combined with video_urls / audio_urls |
| Reference | new clip guided by clips and / or audio, optionally images | prompt + video_urls and / or audio_urls (+ optional image_urls) | audio needs an image or a clip alongside; clips and audio ≤ 15 s combined each |
Mutex rules. Reference images (image_urls, or image_with_roles
entries with role reference_image) can be combined with video_urls and / or
audio_urls in one multimodal reference job. Rejected with 400 (code
20003) before anything is charged: image_urls together with
image_with_roles; first_frame / last_frame roles together with
video_urls or audio_urls; frame roles mixed with reference_image in one
array; and audio_urls without an image or a clip alongside.
Troubleshooting
| Failure | What it means | What to do |
|---|---|---|
| Synchronous 400 on submit | A field violates the schema (1080p on Fast, an illegal field combination, missing prompt, …) | The error names the field — fix and resubmit; nothing was charged |
Synchronous 400 naming a format (… format matroska is not supported) | A reference file is not in a format the model accepts. The check reads the file itself, so a renamed extension does not help | Re-encode: images to jpeg / png / webp, clips to H.264 mp4, audio to wav / mp3 |
Synchronous 400 content_filter cannot be disabled from the website | The request came from a browser session with content_filter: false | Call the endpoint with an API key |
400 with code 30002 on a reference video | reAPI could not read the clip's length to price it | Make sure the URL is public and the file is a readable mp4 / mov; nothing was charged |
Task fails with 80007 on seedance-2.0-fast-pr | The request carried tools (web search), which this variant does not support | Drop tools, or use doubao-seedance-2.0-fast-face; the credits were refunded |
| Task fails citing sensitive content | Reference material or the generated output was rejected by moderation | Fully refunded. Real-person references are supported and reviewed automatically |
402 on submit | Not enough credits for the reserve (a reference video is billed on top of the output) | Top up, or set a shorter duration |
Task stays processing | Normal for a few minutes — generation time grows with length and references | Keep polling; tasks that can never finish are failed and refunded automatically |
No data: URIs. reAPI rejects base64 inputs platform-wide — every URL
field must be a public HTTP(S) URL. Upload to your own object storage (S3, R2,
OSS, …) and pass the URL.
Response envelope
The submit call returns { "id", "model", "status": "processing", "created_at" }.
Polling GET /api/v1/tasks/{id} returns the full envelope below; output and
error fill in when the task finishes.
{
"id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
"model": "doubao-seedance-2.0-fast-face",
"status": "completed",
"created_at": 1735000000,
"output": {
"video_urls": ["https://cdn.reapi.ai/media/tasks/.../0.mp4"],
"last_frame_url": "https://cdn.reapi.ai/media/tasks/.../0.png"
},
"usage": { "credits": 430 },
"error": null
}| Field | Type | Notes |
|---|---|---|
id | string | Task identifier — keep it for polling and audit |
model | string | Echo of the submitted model |
status | string | processing / completed / failed |
created_at | integer | Submission unix timestamp |
output | object | null | null until completion |
output.video_urls | string[] | Generated MP4 URL(s) |
output.last_frame_url | string | null | Present only when the request set return_last_frame: true |
usage.credits | integer | Credits settled for the task |
error | object | null | Populated on failed — { code, message, request_id } |
Poll GET /api/v1/tasks/{id} (see the Tasks reference) until
status === "completed". Generated URLs expire — mirror them to your own
storage if you need long-term retention.
Validation errors
All cases below return HTTP 400 with the noted code. Pattern-match on
code, not message — message strings carry request-specific context
(field names, observed values) and are not a stable contract.
| Trigger | Code | Message |
|---|---|---|
Missing prompt | 20002 | prompt: Invalid input: expected string, received undefined |
prompt shorter than 3 chars | 20003 | prompt: Too small: expected string to have >=3 characters |
prompt longer than 20,000 chars | 20003 | prompt: Too big: expected string to have <=20000 characters |
1080p / 4k on a Fast variant | 20003 | resolution: resolution=<1080p|4k> is not supported by <variant> (use doubao-seedance-2.0 or doubao-seedance-2.0-face) |
duration below 4 (including -1) / above 15 | 20003 | duration: Too small: expected number to be >=4 / duration: Too big: expected number to be <=15 |
size not one of the seven values | 20005 | size: Invalid option: expected one of "16:9"|"9:16"|"1:1"|"4:3"|"3:4"|"21:9"|"adaptive" |
image_urls and image_with_roles together | 20003 | image_with_roles: image_urls and image_with_roles are mutually exclusive |
first_frame / last_frame + video_urls or audio_urls | 20003 | image_with_roles: first_frame / last_frame entries cannot be combined with video_urls or audio_urls (use role "reference_image" for a reference job) |
image_with_roles with a last_frame but no first_frame | 20003 | image_with_roles: image_with_roles with a last_frame also needs a first_frame (the vendor has no last-frame-only task type) |
image_with_roles mixing a frame role with reference_image | 20003 | image_with_roles: image_with_roles cannot mix first_frame/last_frame with reference_image — they are separate task types; send reference images in image_urls instead |
image_with_roles[i].role invalid | 20003 | image_with_roles.0.role: Invalid option: expected one of "first_frame"|"last_frame"|"reference_image" |
audio_urls without a visual reference | 20003 | audio_urls: audio_urls requires image_urls, a reference_image entry in image_with_roles, or video_urls |
image_urls / image_with_roles > 9 | 20003 | <field>: Too big: expected array to have <=9 items |
video_urls > 3 / audio_urls > 3 | 20003 | <field>: Too big: expected array to have <=3 items |
tools[i].type not web_search | 20003 | tools.0.type: Invalid input: expected "web_search" |
Unknown field (for example seed) | 20003 | Unrecognized key: "seed" |
| A URL entry that is not a valid URL | 20003 | <field>.<i>: Invalid URL (for image_with_roles: image_with_roles.<i>.url: Invalid URL) |
A valid URL that is not public HTTP(S) (a data: URI, ftp://, …) | 20003 | <field>.<i>: must be a public http(s) URL |
bitrate_mode not default / standard / high (or a boolean) | 20003 | bitrate_mode: Invalid input |
content_filter: false from a non-admin website session | 20003 | content_filter cannot be disabled from the website. Submit this request with an API key instead. |
reAPI then reads each reference file before charging. These checks also return
400 with code 20003:
| Trigger | Message |
|---|---|
| Image not jpeg / png / webp / bmp / tiff / gif / heic / heif | image_urls[i] format <codec> is not supported (images must be jpeg, png, webp, bmp, tiff, gif, heic or heif) |
| Clip not an mp4 / mov container | video_urls[i] format <container> is not supported (videos must be mp4 or mov) |
| Clip not H.264 / H.265, or its audio track not AAC / MP3 | video_urls[i] video codec <codec> is not supported (must be H.264 or H.265/HEVC) / video_urls[i] audio track codec <codec> is not supported (must be AAC or MP3) |
| Clip with no video stream | video_urls[i] has no video stream (audio-only files belong in audio_urls) |
| Clip shorter than 2 s, or 16 s or longer | video_urls[i] duration X.XXs is out of range (must be 2–15s, with <16s accepted for container metadata padding) |
| Clip side outside 300–6000 px | video_urls[i] resolution WxH is out of range (width and height must each be 300–6000px) |
| Clip pixel count outside 407,696–8,295,044 | video_urls[i] pixel count N is out of range (must be 407696–8295044) |
| Clip aspect ratio outside 0.4–2.5 | video_urls[i] aspect ratio WxH is out of range (width/height must be 0.4–2.5) |
| Clips 16 s or longer in total | video_urls total duration X.XXs exceeds the 15s limit, with <16s accepted for container metadata padding |
| Audio not wav / mp3 | audio_urls[i] format <container> is not supported (audio must be wav or mp3) |
| Audio track shorter than 2 s or longer than 15 s | audio_urls[i] duration X.XXs is out of range (must be 2–15s) |
| Audio longer than 15 s in total | audio_urls total duration X.XXs exceeds the 15s limit |
A reference video whose length cannot be read fails with code 30002; the
message contains Could not determine source video duration for billing:.
Nothing is charged.
The full envelope is { "error": { "code", "message", "request_id" } } —
see the Errors catalog for wire format and request_id
correlation.
Pricing
Seedance 2.0 Fast bills per second of video, at a rate that depends on three axes:
- Variant —
doubao-seedance-2.0-fast-faceorseedance-2.0-fast-pr, each on its own rates - Resolution —
480p/720p - Mode —
refwhen the request uploads a reference video (video_urls),textotherwise. Reference images, frames and audio do not change the mode.refrates are lower thantextrates at every cell
credits = ceil(per_second_rate × billable_seconds × 1000) 1 credit = $0.001Live per-second rates are on the model page — that table is generated from the current price, so it is always the authoritative number. Failed jobs are always refunded in full.
A reference video is billed too, on top of the output
Send video_urls and you pay for the source footage plus the generated
clip:
billable_seconds = min(30, ceil(total_length_of_video_urls) + duration)reAPI measures every reference clip server-side, so this is the real length of
the file, not a value you declare. Reference images and audio are free —
they add no seconds. A 5-second source clip with duration: 6 bills
11 seconds at the ref rate; the same request without video_urls bills
6 seconds at the (higher) text rate.
Recipes
Text-to-video, vertical:
{
"model": "doubao-seedance-2.0-fast-face",
"prompt": "A street dancer spins under neon signs at night, quick handheld tracking shot",
"resolution": "720p",
"size": "9:16",
"duration": 5
}First / last frame transition:
{
"model": "doubao-seedance-2.0-fast-face",
"prompt": "Smooth transition from day to night",
"image_with_roles": [
{ "url": "https://your-cdn.com/day.jpg", "role": "first_frame" },
{ "url": "https://your-cdn.com/night.jpg", "role": "last_frame" }
],
"duration": 5
}Reference clip plus reference audio (the clip's length is billed on top of
duration; the audio adds no seconds):
{
"model": "seedance-2.0-fast-pr",
"prompt": "A scene of a person speaking",
"video_urls": ["https://your-cdn.com/reference.mp4"],
"audio_urls": ["https://your-cdn.com/speech.wav"],
"size": "16:9",
"duration": 6
}Continuous chain — request the last frame, then pass output.last_frame_url
to the next call in image_with_roles with role first_frame:
{
"model": "doubao-seedance-2.0-fast-face",
"prompt": "The dancer turns toward the camera",
"image_with_roles": [
{ "url": "https://your-cdn.com/dancer-start.png", "role": "first_frame" }
],
"return_last_frame": true
}