Poll or webhook for a 30-second AI video job? Use both

A 30-second Seedance 2.5 or Wan 3.0 clip runs for minutes. Submit async, take the signed webhook, and keep one status poll as the backup. Code included.

5 min readSume
All posts

Use a webhook as the main signal and a status poll as the backup. A 30-second clip from Seedance 2.5 or Wan 3.0 is a job that runs for minutes, so the HTTP request that submits it must not wait; it returns a job id, and you learn the outcome later.

Both vendors now advertise clips of up to 30 seconds in one pass (Seedance 2.5, Wan3.0). On Sume both are catalog ids on the video generation API: seedance-2.5 accepts 4-30 seconds and wan-3.0 accepts 2-30 seconds.

What each option costs you

Polling needs a timer and a stored job id for every clip in flight. A webhook needs a public HTTPS endpoint that verifies a signature. Sume documents the webhook as terminal-only: job.completed, job.failed, and job.canceled. There are no progress or partial deliveries, so a webhook cannot drive a progress bar.

Neither option is complete alone. Sume retries a failed delivery up to 10 times, 30 seconds apart by default, and then stops. The job still reached its real terminal state, so the docs tell you to keep status_url polls available for events that never arrive.

Polling versus webhook for one long video job (read 2026-10-07)
QuestionPoll status_urlWebhook
Who starts the contactYour codeSume
Progress signalStatus and queue state on each readNone, terminal events only
Needs a public HTTPS URLNoYes
Survives a missed messageYes, the job id is the handleOnly with a poll or redeliver
Dedupe keyJob idJob id

The pattern that holds up

Submit with mode: "async" and an Idempotency-Key, or send webhook_url and omit mode, which gives you webhook mode. Save the job id before you do anything else. Then schedule one slow status check, for example at twice your usual clip time, that reads the job and handles it only if your webhook receiver has not marked it done.

Treat job_id as the idempotency key on your side. The same terminal event can arrive twice, and a manual redeliver sends the real event again with a fresh timestamp and signature.

import os, requests
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
     "Idempotency-Key": "promo-8823-take-1"}
body = {
    "model": "seedance-2.5",
    "prompt": "Slow orbit around a ceramic mug on a desk, soft window light",
    "duration": 30,
    "resolution": "720p",
    "aspect_ratio": "9:16",
    "webhook_url": "https://example.com/hooks/sume",
}
r = requests.post("https://api.sume.com/v1/video-router/generate",
                  headers=H, json=body, timeout=30)
r.raise_for_status()
job = r.json()["data"]
print(job["request_id"], job["status_url"])  # store both, then return

When polling alone is fine

A script on your laptop, a nightly batch with no public address, or a prototype can skip the receiver and poll. Use the next_poll_after_seconds value from the response when it is present, and back off otherwise. Move to a webhook when you run hundreds of clips and the open timers become the cost.

Never resubmit a paid request because a local timer ran out. A client timeout does not cancel the job; it keeps running and keeps billing.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume