bytedance/seedance-2.5
Seedance 2.5 — the large-input, long-output member of the family.
Up to 30 reference images, 10 reference clips and 10 audio tracks, audio-only input, and output up to 30 seconds.
Not a cheaper successor to 2.0 — the most expensive model in the family.
| Slug | bytedance/seedance-2.5 |
| Kind | video |
| Vendor | bytedance |
| Endpoint | POST /v1/byteplus/contents/generations/tasks |
Charged per job from what the generator reports it rendered — your Logs show the exact figure for each one; see balance and billing.
Calling it
curl https://api.sociaro.com/v1/byteplus/contents/generations/tasks \
-H "Authorization: Bearer $SOCIARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bytedance/seedance-2.5",
"prompt": "a paper boat on a rain-soaked street",
"resolution": "720p",
"duration": 5
}'
# then poll the job id it returns:
curl https://api.sociaro.com/v1/byteplus/contents/generations/tasks/JOB_ID \
-H "Authorization: Bearer $SOCIARO_API_KEY"Parameters
Seedance 2.5 — the large-input, long-output tier
| Field | Type | Required | Default | Values | What it does |
|---|---|---|---|---|---|
content | array | yes | — | parts, each with its own type and an optional role | This is the whole input. `{"type":"text","text":…}`, `{"type":"image_url","image_url":{"url":…},"role":"first_frame"|"last_frame"|"reference_image"}`, `{"type":"video_url",…,"role":"reference_video"}`, `{"type":"audio_url",…,"role":"reference_audio"}`. Every other model on this endpoint takes flat fields — these three do not. One more part type exists on this model alone: `{"type":"draft_task","draft_task":{"id":…}}`, which renders the final of an earlier draft — see `draft` below. |
resolution | string | no | 720p | 480p · 720p · 1080p | A tier this model does not have is refused with a 400 naming the ones it does. The generator would ACCEPT it and silently render 720p, so the check is ours and it costs you nothing. |
duration | integer | no | 5 | 4–30, or -1 | Seconds. `-1` lets the model pick the length that suits the inputs. |
ratio | string | no | adaptive | 21:9 · 16:9 · 4:3 · 1:1 · 3:4 · 9:16 · adaptive | |
output_format | string | no | mp4 | mp4 · mov | `mov` carries 10-bit colour and PCM audio for editing work, and 2.5 is the only model here that offers it. |
generate_audio | boolean | no | — | true · false | |
bitrate_mode | string | no | the model's own | standard · high | Not in the vendor's public reference, but the generator honours it: `high` encodes at a higher bitrate than `standard` (in one 480p measurement about 4.6–6.9 Mbps against 1.2–1.9 Mbps), and the price is the same, because these models are metered per token. The default differs by model, so leave it out to take the model's own. On 2.5, leaving it out already gives a high bitrate (6.96 Mbps in the same measurement). |
return_last_frame | boolean | no | false | true · false | Asks for the closing still beside the clip. It arrives as `last_frame_url`, on the same expiring /v1/media terms, at NO extra cost — useful as the `first_frame` of the next clip. |
watermark | boolean | no | false here | true · false | The vendor defaults this on; we default it off. |
seed | integer | no | random | — | Every Seedance model we serve accepts it. The same seed gives similar, not identical, results: the vendor says complete consistency is not guaranteed. |
omni_reference_task_type | string | no | auto | auto · reference · edit · extend | What the references in `content` are FOR — generate from them, edit the source, or extend it; `auto` lets the model infer it from the prompt. Needs REFERENCE media in `content`: the generator refuses it on text-to-video and on first-frame jobs. Under `extend`, `duration` is the length of the ADDITION, not of the finished clip. THIS MODEL ONLY — the 2.0 rows accept the field and silently ignore it. |
draft | boolean | no | false | true · false | Renders a cheap 480p DRAFT instead of the finished clip, so you can judge the shot before paying for it. Send `resolution` as `480p` or leave it out — any other tier is a 400, because the generator renders 480p regardless and you would be charged for the tier you asked for. Keep the `job_id`: for the next SEVEN DAYS you can render the 1080p final from it by sending `{"type":"draft_task","draft_task":{"id":" |
Anything not listed here is refused rather than ignored, so a typo fails loudly instead of quietly producing something else.
Worked example
# extend an existing clip — duration is the length of the ADDITION
curl https://api.sociaro.com/v1/spicy/generations \
-H "Authorization: Bearer $SOCIARO_API_KEY" -H "Content-Type: application/json" \
-d '{ "model": "spicy/seedance-2-5",
"content": [
{ "type": "text", "text": "the camera drifts on past the lantern" },
{ "type": "video_url", "video_url": {"url": "https://your-cdn.example.com/clip.mp4"},
"role": "reference_video" }
],
"omni_reference_task_type": "extend",
"resolution": "1080p", "duration": 6 }'Not a cheaper successor to 2.0 — the most expensive model in the family. What it buys is scale of input and length of output:
| 2.0 | 2.5 | |
|---|---|---|
| reference images | up to 9 | up to 30 |
| reference videos | up to 3, each 2–15 s | up to 10, each 2–30 s |
| reference audio | up to 3 | up to 10 |
| audio-only input | not allowed | allowed |
| output length | 4–15 s | up to 30 s |
| resolution | up to 4K | up to 1080p — no 4K |
Metered per token, with the same minimum cost on video-input jobs as the rest of the family.
1080p arrived on 2026-08-14 and 4K is still unpriced by the vendor, so 4K is a 400. The tier
list on this page is read from what BytePlus prices, so it changes when they publish one.
omni_reference_task_type exists on this model alone. The 2.0 rows accept it and ignore it, which
buys you a clip that never used the setting and no error saying so.
How a job runs
These routes are a pass-through: you send BytePlus's own body and get their own response back, with our additions beside it. Generation takes longer than a request should wait, so it goes in three moves — submit, poll, collect.
# 1. submit — the id comes back as `id`. There is NO `job_id` on THIS response
curl -sS https://api.sociaro.com/v1/byteplus/contents/generations/tasks \
-H "Authorization: Bearer $SOCIARO_API_KEY" -H "Content-Type: application/json" \
-d '{ "model": "…", "content": [ … ] }'
# -> { "id": "cgt-…" }
# 2. poll every 5-10 s
curl -sS https://api.sociaro.com/v1/byteplus/contents/generations/tasks/cgt-… \
-H "Authorization: Bearer $SOCIARO_API_KEY"
# -> { "status": "running", … }
# -> { "status": "succeeded", "content": { "video_url": "<the vendor's own link>" },
# "media_url": "https://api.sociaro.com/v1/media/<media_id>" }
# 3. collect — the opaque id IS the credential, no header needed
curl -sSL "https://api.sociaro.com/v1/media/<media_id>" -o out.mp4
Images use POST /v1/byteplus/images/async and its poll in the same shape, and the faster models
also answer synchronously at POST /v1/byteplus/images/generations — one request, the picture in
the response. A model whose render outlasts the gateway's ~2-minute ceiling is refused there by
name, telling you to use the async route.
Reading the poll
Two differences will bite a client written against the poll-style routes. The SUBMIT returns
id, not job_id — code reading job_id there gets nothing and cannot poll at all. And status
is the VENDOR'S vocabulary: running, succeeded, failed — not processing, completed,
failed. A check for completed on this route never becomes true, which reads as a job that never
finishes rather than as an error.
The POLL response does carry job_id beside the vendor's id, as a convenience, and it returns
the vendor's whole body — around twenty fields — rather than the five-field shape the other routes
use. Gate on status rather than on the poll's HTTP code.
Prefer media_url over the vendor's raw link. Both are returned: content.video_url (or
data[].url for images) is theirs, kept for compatibility and due to be removed once nobody reads
it; media_url is ours. Ours points at our host, hides the vendor's storage, and expires. A second
asset arrives on the same terms — return_last_frame gives content.last_frame_url with
last_frame_media_url beside it.
Collecting the result
media_url is a capability: the opaque id is the credential, so no Authorization header is
needed and anyone holding the link can fetch it. It expires within the hour — download rather
than store the link.
Rules the gateway adds
Your key must be granted this model — 403 otherwise — and either spelling satisfies the grant:
our catalogue id or the vendor's own native one.
Because this is a pass-through, unknown fields go to the generator rather than being refused here,
and it is the generator that decides. The exception is resolution, which we check ourselves: an
unsupported tier is silently ignored upstream, so you would ask for the higher one, be handed a
lower one, and be charged. A tier we cannot price is refused at submit, before any money is spent,
with a message naming the ones this model has.
Ranges and enums are the generator's own, so an out-of-range value comes back as its rejection, in its wording and with its numbers.