Seedance 2.5 sync mode: a 30-second wait, then poll
mode sync on the Video Router blocks at most 30 seconds. A Seedance 2.5 job can outlast it, so read sync.timed_out and poll status_url without resubmitting.

With mode: "sync" on the Video Router, a Seedance 2.5 submit waits at most 30 seconds (wait_timeout_seconds is clamped to 0 to 30); if the job is not finished, you still get a normal response with sync.timed_out: true, and you must poll status_url rather than send the request again. Sume's docs say video jobs "routinely" outlast the wait, and a 4 to 30 second Seedance clip is a video job.
Everything here is from Sume's Jobs and results page and the Video Router entry in the API reference. The model's range, 4 to 30 seconds per generation, is in Video Router and ByteDance Seed's launch post (read 2026-10-02).
What does a timed-out sync response contain?
A 2xx with the job id and URLs. The wait running out is not an error and does not cancel or refund anything.
| Field | Meaning | What you do |
|---|---|---|
sync.timed_out: true | Wait ended before a terminal state | Poll status_url |
sync.capacity_exhausted: true | Sume skipped the wait; the waiter budget was full | Poll status_url |
status_url, result_url, events_url, cancel_url | Where to follow the job | Store the job id |
next_poll_after_seconds | Suggested delay before the next poll | Honour it when present |
Should I use sync for Seedance at all?
The docs steer new integrations to async or webhook: sync and subscribe "are just the wrong tool for anything that can outlast 30 seconds, which is most video work." subscribe is an alias of sync, with the same 30-second bound. If you do use sync for a short 4-second draft, still write the polling branch.
What is the safe polling loop?
Submit with an Idempotency-Key, read the envelope, and poll until terminal is true. A retry of the submit with the same key returns the original job; a new key buys a second render.
import asyncio, os, httpx
BODY = {"model": "seedance-2.5", "prompt": "A paper boat crossing a puddle",
"duration": 8, "mode": "sync", "wait_timeout_seconds": 30}
async def main():
key = os.environ["SUME_API_KEY"]
h = {"Authorization": f"Bearer {key}", "Idempotency-Key": "boat-001"}
async with httpx.AsyncClient(timeout=60) as c:
r = await c.post("https://api.sume.com/v1/video-router/generate", headers=h, json=BODY)
r.raise_for_status()
d = r.json()["data"]
while not d["terminal"]:
await asyncio.sleep(d.get("next_poll_after_seconds") or 5)
s = await c.get(d["status_url"], headers=h)
s.raise_for_status()
body = s.json()
d = body.get("data", body)
print(d.get("status"), d.get("result_ready"))
asyncio.run(main())What if my client gives up first?
A client-side timeout does not cancel the job; it keeps running and still bills. Keep the job id and resume from status_url, or cancel through cancel_url while cancelable is true. For long renders a webhook is terminal-only (job.completed, job.failed, job.canceled), so keep polling as a backup.
Sources
Related posts
More in Developers
- Seedance aspect ratios on Sume: 3:2 and 9:21 are not on every model
Sume accepts nine aspect ratios in total, but each video model lists its own subset. Check supported_aspect_ratios before you request 3:2 or 9:21.
- Seedance 2.5 input_references: image, video and audio shapes
The exact JSON for an image_url, video_url and audio_url entry in input_references on POST /v1/videos, one mixed Seedance 2.5 request, and the errors you get.
- Seedance 2.5 reference images in Python with asyncio and httpx
A runnable Python script: send reference images to seedance-2.5 on Sume's /v1/videos, poll every 30 s with asyncio, save the MP4, and handle the errors.
- Seedance 2.5 reference images in TypeScript with Node fetch
A Node 18+ ESM script: submit reference images to seedance-2.5 on Sume's /v1/videos, poll every 30 s with fetch, print the video URL. Rules and mistakes.
Written by Sume