Poll a 30-second Seedance 2.5 job in Python: backoff and a deadline
A 30-second Seedance 2.5 job is slow. Poll /v1/videos/{id} with growing delays and a deadline. A stdlib Python script submits, waits and prints the cost.

Submit with POST /v1/videos, then poll GET /v1/videos/{id} with a delay that grows from a few seconds to about 20, and stop at a deadline you choose. The script below does that with the Python standard library and prints the status, the result URL and usage.
Do not poll in a tight loop. A long Seedance 2.5 job takes a while, and a one-second poll mostly returns the same pending status while adding load.
Statuses to handle
The poll response is the OpenRouter-shaped object. Sume maps its internal statuses to pending, in_progress, completed, failed and cancelled. expired exists in the enum for wire compatibility, but Sume never emits it. Treat completed, failed and cancelled as terminal.
| Sume status | Poll status | Action |
|---|---|---|
| queued | pending | keep polling |
| processing | in_progress | keep polling |
| completed | completed | read unsigned_urls and usage |
| failed | failed | read error, do not retry blindly |
| canceled | cancelled | stop |
The script
Set SUME_API_KEY first. The Idempotency-Key header makes a retry of the submit safe: the same key with the same body returns the same job, and the same key with a different body returns 409.
import json, os, time, urllib.request
KEY = os.environ["SUME_API_KEY"]
def call(method, path, body=None, idem=None):
headers = {"Authorization": "Bearer " + KEY, "Content-Type": "application/json"}
if idem:
headers["Idempotency-Key"] = idem
data = json.dumps(body).encode() if body else None
req = urllib.request.Request("https://api.sume.com" + path, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=60) as r:
return json.load(r)
job = call("POST", "/v1/videos", {
"model": "seedance-2.5", "prompt": "A drone shot over a foggy pine forest at dawn",
"duration": 30, "resolution": "720p", "aspect_ratio": "16:9"}, "seedance-30s-001")
deadline, delay = time.time() + 1800, 3
while time.time() < deadline:
job = call("GET", "/v1/videos/" + job["id"])
if job["status"] in ("completed", "failed", "cancelled"):
break
time.sleep(delay)
delay = min(delay * 1.5, 20)
print(job["status"], job.get("unsigned_urls"), job.get("usage"), job.get("error"))Why a deadline
A loop with no end hides a stuck job. The script stops after 30 minutes and prints the last status, and you decide what to do next. Sume's job history keeps the record, so a later check by id is still possible.
Fetching the file
unsigned_urls point to /v1/videos/{id}/content?index=0, which redirects to the artifact. Fetching them needs your API key in the Authorization header, as covered in the unsigned URL post.
If you would rather not poll at all, pass callback_url and let Sume call you when the job ends. See what a failed job sends.
Variations
Change a few lines for other models, and keep the rest.
- For
kling-3, setdurationto 15 or less. - For
gemini-omni-flash-1.1, setdurationto 10 or less. - For a shorter wait, use a lower resolution while you test the prompt.
- For several jobs, run one loop per job id and share a single deadline.
Related posts
More in Developers
- Poll a Seedance 2.5 job in Go: submit, wait 30 s, check status
A Go program that submits a 30-second Seedance 2.5 job to Sume, polls the polling_url every 30 seconds for up to 20 minutes, and prints the result URL.
- Poll a Seedance 2.5 job in TypeScript: deadline and failed states
A TypeScript submit-poll-download loop for a 30-second Seedance 2.5 render on Sume: the 30 s interval, a 20-minute deadline, and the three end states.
- Poll an H3 Max video job in Python: backoff, terminal, result
Submit minimax-h3-max to the Video Router, poll GET /v1/jobs/:id/status with backoff until terminal, then fetch the result. A runnable 25-line Python script.
- Poll or webhook for Wan 3.0 30-second jobs: use both on Sume
A webhook tells you when a Wan 3.0 job ends; polling is the backup when delivery fails. Sume retries a webhook up to 10 times at 30 s spacing. How to wire both.
Written by Sume