GPT Image 2.5 is live — OpenAI's newest image model, targeted edits that leave the rest of the frame alone
rreAPI Docs

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_KEY

Keys 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 idResolutionsWeb search (tools)
doubao-seedance-2.0-fast-face480p / 720p✅
seedance-2.0-fast-pr480p / 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).

FieldTypeDefaultNotes
modelstring—doubao-seedance-2.0-fast-face or seedance-2.0-fast-pr. Required.
promptstring—Describe the video: 3–20000 chars. Required on every request, in every mode. Wrap spoken lines in double quotes to steer the generated speech.
durationinteger5Output length in seconds: 4–15. -1 (automatic length) is not available on Fast.
sizestring16:916:9 / 9:16 / 1:1 / 4:3 / 3:4 / 21:9 / adaptive (match the input image / video).
resolutionstring720p480p / 720p, lowercase only.
bitrate_modeenum"default"default: no processing; standard: smaller files; high: lighter compression. No extra generation charge — see bitrate_mode.
generate_audiobooleantrueGenerate synced speech, sound effects and background music. Independent of audio_urls, which is a reference for the model, not a synthesis toggle.
watermarkbooleanfalseStamp an "AI generated" mark in the bottom-right corner.
return_last_framebooleanfalseReturn output.last_frame_url for continuous chaining.
toolsobject[]—[{ "type": "web_search" }] to let the model query the web. doubao-seedance-2.0-fast-face only.
image_urlsstring[]—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_rolesobject[]—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_urlsstring[]—Up to 3 reference clips (mp4 / mov, H.264 / H.265 with AAC / MP3 audio, 300–6000 px per side), combined ≤ 15 s.
audio_urlsstring[]—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_filterbooleantrueSafety checking. Set false to run the task on the unmoderated route — see content_filter below.

Checked before anything is submitted or charged:

  • prompt is present on every request (3–20000 chars)
  • resolution is 480p or 720p, and duration is a whole number from 4 to 15
  • image_urls and image_with_roles are mutually exclusive (both carry reference images — pick one)
  • at most one first_frame and one last_frame, and a last_frame always needs a first_frame (there is no last-frame-only task type)
  • frame roles and reference_image cannot share one image_with_roles array, and frame roles cannot be combined with video_urls / audio_urls
  • audio_urls needs 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 than standard, 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: false is rejected with 400 before 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-face the output lands in an isolated bucket and its URLs stay valid for 30 days. On seedance-2.0-fast-pr the result URLs are returned as delivered (unless you set bitrate_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:

JobWhat it doesNeedsHard rules
Text-to-videonew clip from a promptprompt onlynone
Image referencenew clip guided by reference imagesprompt + image_urls (1–9)none
First / last frameanimates between given framesprompt + image_with_roles (1–2 frames)frames cannot be combined with video_urls / audio_urls
Referencenew clip guided by clips and / or audio, optionally imagesprompt + 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

FailureWhat it meansWhat to do
Synchronous 400 on submitA 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 helpRe-encode: images to jpeg / png / webp, clips to H.264 mp4, audio to wav / mp3
Synchronous 400 content_filter cannot be disabled from the websiteThe request came from a browser session with content_filter: falseCall the endpoint with an API key
400 with code 30002 on a reference videoreAPI could not read the clip's length to price itMake 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-prThe request carried tools (web search), which this variant does not supportDrop tools, or use doubao-seedance-2.0-fast-face; the credits were refunded
Task fails citing sensitive contentReference material or the generated output was rejected by moderationFully refunded. Real-person references are supported and reviewed automatically
402 on submitNot enough credits for the reserve (a reference video is billed on top of the output)Top up, or set a shorter duration
Task stays processingNormal for a few minutes — generation time grows with length and referencesKeep 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
}
FieldTypeNotes
idstringTask identifier — keep it for polling and audit
modelstringEcho of the submitted model
statusstringprocessing / completed / failed
created_atintegerSubmission unix timestamp
outputobject | nullnull until completion
output.video_urlsstring[]Generated MP4 URL(s)
output.last_frame_urlstring | nullPresent only when the request set return_last_frame: true
usage.creditsintegerCredits settled for the task
errorobject | nullPopulated 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.

TriggerCodeMessage
Missing prompt20002prompt: Invalid input: expected string, received undefined
prompt shorter than 3 chars20003prompt: Too small: expected string to have >=3 characters
prompt longer than 20,000 chars20003prompt: Too big: expected string to have <=20000 characters
1080p / 4k on a Fast variant20003resolution: 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 1520003duration: Too small: expected number to be >=4 / duration: Too big: expected number to be <=15
size not one of the seven values20005size: Invalid option: expected one of "16:9"|"9:16"|"1:1"|"4:3"|"3:4"|"21:9"|"adaptive"
image_urls and image_with_roles together20003image_with_roles: image_urls and image_with_roles are mutually exclusive
first_frame / last_frame + video_urls or audio_urls20003image_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_frame20003image_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_image20003image_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 invalid20003image_with_roles.0.role: Invalid option: expected one of "first_frame"|"last_frame"|"reference_image"
audio_urls without a visual reference20003audio_urls: audio_urls requires image_urls, a reference_image entry in image_with_roles, or video_urls
image_urls / image_with_roles > 920003<field>: Too big: expected array to have <=9 items
video_urls > 3 / audio_urls > 320003<field>: Too big: expected array to have <=3 items
tools[i].type not web_search20003tools.0.type: Invalid input: expected "web_search"
Unknown field (for example seed)20003Unrecognized key: "seed"
A URL entry that is not a valid URL20003<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)20003bitrate_mode: Invalid input
content_filter: false from a non-admin website session20003content_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:

TriggerMessage
Image not jpeg / png / webp / bmp / tiff / gif / heic / heifimage_urls[i] format <codec> is not supported (images must be jpeg, png, webp, bmp, tiff, gif, heic or heif)
Clip not an mp4 / mov containervideo_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 / MP3video_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 streamvideo_urls[i] has no video stream (audio-only files belong in audio_urls)
Clip shorter than 2 s, or 16 s or longervideo_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 pxvideo_urls[i] resolution WxH is out of range (width and height must each be 300–6000px)
Clip pixel count outside 407,696–8,295,044video_urls[i] pixel count N is out of range (must be 407696–8295044)
Clip aspect ratio outside 0.4–2.5video_urls[i] aspect ratio WxH is out of range (width/height must be 0.4–2.5)
Clips 16 s or longer in totalvideo_urls total duration X.XXs exceeds the 15s limit, with <16s accepted for container metadata padding
Audio not wav / mp3audio_urls[i] format <container> is not supported (audio must be wav or mp3)
Audio track shorter than 2 s or longer than 15 saudio_urls[i] duration X.XXs is out of range (must be 2–15s)
Audio longer than 15 s in totalaudio_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-face or seedance-2.0-fast-pr, each on its own rates
  • Resolution — 480p / 720p
  • Mode — ref when the request uploads a reference video (video_urls), text otherwise. Reference images, frames and audio do not change the mode. ref rates are lower than text rates at every cell
credits = ceil(per_second_rate × billable_seconds × 1000)     1 credit = $0.001

Live 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
}

Table of Contents