Downloading the mp4 inside the webhook? Sume's 10 s limit

A callback handler that fetches the video before replying will time out. Sume allows each webhook delivery 10 seconds and 10 attempts: store the id, return 2xx.

5 min readSume
All posts

If your old video callback downloaded the finished mp4 before answering, it will misbehave on Sume. The webhooks guide gives every delivery attempt a 10 second timeout and up to 10 attempts total, spaced 30 seconds apart by default. A slow handler burns that budget and gets retried. Verify the signature, durably store the job_id, return 2xx, and do the download in a separate worker.

The budget you are working with

Sume sends terminal events only: job.completed, job.failed and job.canceled. There are no progress callbacks, so every delivery matters, and the payload for a completed job carries artifacts with Sume media URLs.

Sume job webhook delivery limits (read 2026-10-04)
PropertyValue
AttemptsUp to 10 in total
SpacingFixed 30 seconds by default, not exponential
Timeout per attempt10 seconds
Eventsjob.completed, job.failed, job.canceled
Idempotency key on your sidejob_id

Why a download in the handler goes wrong

A multi-megabyte download, a transcode, and a database write easily exceed 10 seconds on a busy host. Sume sees a timeout, schedules a retry, and your handler runs twice. If the first run finishes late and the second starts, you can store two copies or, worse, charge your own customer twice. The guide's advice is to treat job_id as the idempotency key on your side.

A handler that returns fast

Keep the handler to four steps: read the raw body, verify the HMAC over timestamp.raw_body, insert a row keyed by job_id with ON CONFLICT DO NOTHING, and return 200. A queue consumer then fetches the artifact URL, copies it into your storage, and marks the row done. The status endpoint remains the backup for events that never arrive, and the guide notes you can redeliver a real terminal event with POST /v1/jobs/{job_id}/webhook/redeliver after attempts run out.

# pseudo-flow, any framework
body = request.raw_body
if not verify(body, headers, secret):   # reject empty secret
    return 401
job_id = json.loads(body)["job_id"]
db.insert_if_absent(job_id, body)       # unique on job_id
queue.enqueue("fetch_artifact", job_id)
return 200

Check that you are safe

Send a test delivery from the dashboard to your staging URL and time it. Under about two seconds leaves headroom. Then kill the consumer, complete a job, and confirm the row exists without the file: that is the failure mode the split is designed to survive. See Jobs and results for the polling fallback.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume