Sume job webhook_delivery: attempts, exhausted, redeliveries
Read the webhook_delivery object on a Sume job: status, attempts of 10, last_status_code, manual_redeliveries, and what to do when delivery is exhausted.

A job created with a webhook_url carries a webhook_delivery object that tells you whether the callback arrived: status, attempts against max_attempts, last_status_code, last_error, and manual_redeliveries. The documented ceiling is 10 automatic attempts, 10 seconds per attempt, with a fixed delay (30 seconds by default) between them. When delivery is exhausted, the job still reached its real terminal state; read it from the job and redeliver.
Field names come from the WebhookDelivery schema in the API reference; the retry numbers come from Webhooks. Both read 2026-10-02.
What fields does webhook_delivery have?
The object is on GET /v1/jobs/{id} (data.job.webhook_delivery) and is null on jobs without a webhook.
| Field | What it holds |
|---|---|
status | pending, delivering, delivered, retrying, failed, or exhausted |
event_type | job.completed, job.failed, or job.canceled |
attempts / max_attempts | Automatic attempts used, and the cap |
next_attempt_at, last_attempt_at, delivered_at | Timestamps; null until they apply |
last_status_code, last_error | What your endpoint answered, or the transport error |
signing_secret_fingerprint | Fingerprint of the secret the last attempt used |
manual_redeliveries | Count of partner-triggered redeliveries, separate from attempts |
What do the retry numbers mean?
The webhooks page says non-2xx responses and network errors are retried up to 10 attempts total, with a fixed delay between attempts (30 seconds by default), not exponential backoff, and a 10 second timeout per attempt. A slow endpoint burns the budget and gets retried, so return a 2xx fast after durably storing the event, and do the work afterwards.
Use job_id as your idempotency key on the receiving side: retries and redeliveries can send the same event more than once.
What do I do when status is exhausted?
Ten refused attempts leave a failed delivery and a job that is still in its real terminal state. Fix your endpoint, then call POST /v1/jobs/{job_id}/webhook/redeliver (scope jobs:write). Sume re-sends the job's real terminal event with a fresh timestamp and signature. The docs say this still works after automatic attempts are exhausted and does not consume one of the automatic 10; it increments manual_redeliveries.
If you would rather not wait for a delivery at all, polling stays available: webhooks are an optimization, not your only recovery path.
How do I find out why an attempt failed?
Work down this list; each step is a read, not a resubmit.
- Read
last_status_codeandlast_errorfirst; they are the last attempt's result. - Compare
signing_secret_fingerprintwith the fingerprint shown beside your secret in the dashboard. If they differ, your verifier holds a different secret; neither side has to quote the secret itself. - Read
GET /v1/jobs/{id}/events;webhook.deliveryis one of the public event types. - Redeliver is not Send test: Send test posts a dummy
webhook.testpayload to a URL you type and never replays a real job.
Sources
Related posts
More in Developers
- Submit a Sume video job with curl, save it with sume jobs download
The CLI has no video generate command, but jobs watch and jobs download work on jobs created through the API. A shell script that submits, waits and saves.
- List Sume jobs: next_cursor, starting_after, and idempotency_key
Page through GET /v1/jobs with limit, next_cursor and starting_after, then recover a lost wave by joining your own key to each job's idempotency_key.
- Sume SumeMediaFile duration_ms: the 10 percent check and null
In a Sume structured output, a duration_ms must agree with the artifact's recorded length within 10 percent, or the projection fails. A null means not measured.
- Sume media tools: which answer 200 and which answer 202 by default
video-inspect defaults to sync, trim, filter, compose and detach to async, and video-frames always returns 202. Defaults, the 30 s wait, and how to poll each.
Written by Sume