Sume video mode: async, sync, subscribe or webhook? Cost is the same
Mode only decides how you learn the outcome: all four create the same job at the same price. A decision table for web apps, workers and batch pipelines.

Pick async for almost everything, add a callback_url when you can receive HTTPS, and treat sync and subscribe as a short convenience wait. The Sume docs are explicit that mode never changes whether a job is created, what it costs, or how long it runs; it only decides how you learn the outcome.
If you omit mode you get async. If you send webhook_url, or its alias callback_url, without a mode, you get webhook.
The four modes
From the jobs and results page. "Server blocks" is the part that surprises people: it is at most 30 seconds and can be less.
| Mode | HTTP returns | Server blocks | Client does next |
|---|---|---|---|
async | 202 with job envelope | No | Poll status_url until terminal, then read result_url |
sync | Envelope after up to 30 s | Yes, at most 30 s | Terminal: read it. Not terminal: poll, do not resubmit |
subscribe | Same as sync | Same as sync | Same as sync |
webhook | 202 with job envelope | No | Wait for the signed callback; keep polling as backup |
Choosing by app shape
A web app with a job table and a worker should use async or webhook and never hold a browser request open on a video. A serverless function with a hard time limit should do the same, because a video usually runs longer than any wait Sume offers.
sync is useful for image calls and short tests, where the result often fits inside the budget. When it does not, the response has sync.timed_out: true, and the right move is to poll the job that already exists. sync.capacity_exhausted: true means Sume skipped the wait because the process's waiter budget was full.
- Always store the job id from the first response.
- Webhook mode delivers only terminal events:
job.completed,job.failed,job.canceled. There are no progress or partial webhooks. - Keep
status_urlpolling as the backup in every mode. - There is no SSE stream for generation jobs; for a fal-style long wait, use
asyncand the SDK'swaitForJob.
What a retry looks like
A client-side timeout never cancels the job. Retrying the submit with the same Idempotency-Key returns the original job, so the mode you chose does not add risk of duplicates. A new key, in any mode, is a new job and a new charge.
curl -s https://api.sume.com/v1/videos \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Idempotency-Key: clip-8823-v1" \
-H "Content-Type: application/json" \
-d '{"model":"sume/auto","prompt":"Slow push-in on a ceramic mug","callback_url":"https://example.com/hooks/sume"}'
A sensible default
Start with async plus a signed callback_url, and a sweeper that polls any job older than your expected render time. That gives you push when the network is healthy and a poll when it is not, which is what the docs recommend for production.
Switch to sync only for a demo or a test script where blocking up to 30 seconds is acceptable. Never rely on it for video: a job that outlives the wait returns a non-terminal envelope, and the right response is to poll the existing job.
- Store the job id before anything else.
- Verify the callback signature on the raw body.
- Use one
Idempotency-Keyper logical request in every mode.
Sources
Related posts
More in Developers
- Sume webhooks: 10 attempts 30 seconds apart for a video receiver
A Sume job webhook is tried up to 10 times, 30 seconds apart by default, with a 10 s timeout each. What that means for a video receiver, plus a Python verifier.
- Sume webhook.test has no job_id: keep it out of your job table
The dashboard's Send test posts a signed webhook.test with no job_id. Route on event first, dedupe on job_id second, and no phantom job row appears.
- Can a Sume webhook arrive twice? Build an idempotent receiver
Sume retries failed webhook deliveries up to 10 times and Redeliver replays a real event, so one terminal event can reach you twice. Dedupe on job_id or run_id.
- Sweep Format runs for failed webhook deliveries, then redeliver
Sweep in Python: read each run's webhook_delivery, redeliver only failed or exhausted ones, and leave the rest alone. Uses formats:read, formats:write.
Written by Sume