Sume webhook delivery statuses for jobs and runs, and a poll reconcile
Delivery status runs from pending to delivered, retrying, failed or exhausted; runs add not_armed. Failed or exhausted means poll the result, not a failed job.

The webhook_delivery.status on a Sume job is one of pending, delivering, delivered, retrying, failed or exhausted, and on a Format run it can also be not_armed. A failed or exhausted delivery says nothing bad about the work: the job or run still reached its real terminal state, and you fetch it by polling.
That is the point of reading the field. It tells you whether to wait for a callback, replay one, or stop waiting and read the result yourself.
The values and what to do
The job vocabulary comes from the errors page, and the run block is described on the Format runs page (read 2026-10-03).
| Status | Applies to | Next step |
|---|---|---|
| not_armed | Runs | A URL is stored and nothing is scheduled yet; the run is still going |
| pending | Jobs and runs | Armed; wait, next_attempt_at says when |
| delivering | Jobs | An attempt is in flight |
| retrying | Jobs and runs | An attempt failed; another is scheduled |
| delivered | Jobs and runs | Your endpoint answered 2xx; nothing to do |
| failed or exhausted | Jobs and runs | Sume gave up; read the result by polling or call redeliver |
Read it from the receipt
For a run, the block sits on the receipt and carries status, attempts, max_attempts, next_attempt_at, last_status_code and last_error, where last_error is Sume's transport error and never your response body. For a job the same information is visible on the job object and in job events when available. These commands print the status for each (the run path is data.webhook_delivery; the job query finds the block wherever the envelope nests it).
# Format run receipt
curl -sS "https://api.sume.com/v1/format-runs/$RUN_ID" \
-H "Authorization: Bearer $SUME_API_KEY" | jq '.data.webhook_delivery.status'
# Generation job
curl -sS "https://api.sume.com/v1/jobs/$JOB_ID" \
-H "Authorization: Bearer $SUME_API_KEY" \
| jq '[.. | objects | select(has("webhook_delivery")) | .webhook_delivery.status]'A small reconciler
Run a periodic task over jobs and runs you submitted but never heard back about. For each one, read the status endpoint; if it is terminal, process it exactly as the webhook handler would, keyed on the same job_id or run_id. If the delivery shows failed or exhausted after you fixed your endpoint, POST /v1/jobs/{job_id}/webhook/redeliver (needs jobs:write) or POST /v1/format-runs/{run_id}/webhook/redeliver (needs formats:write) replays the terminal event with a fresh signature and does not consume one of the automatic attempts.
Redeliver answers 409 webhook_not_configured when no URL was set and 409 run_not_terminal while a run is still going, so check the status first. For the attempt arithmetic on jobs, see attempts and manual redeliveries.
Sources
Related posts
More in Developers
- Sume webhooks plus a sweeper: recover jobs whose callback never came
Webhook delivery can fail after 10 attempts while the Sume job still finishes. Run a sweeper that polls jobs stuck non-terminal in your own table.
- Sume run webhook behind a redirect: a 3xx counts as a failed attempt
Sume does not follow redirects on run webhooks, so a 301 from an http or www hostname is a failed delivery. The URL is also re-checked at delivery time.
- Supabase Realtime for Sume render progress, with RLS per subscriber
Add the job table to the supabase_realtime publication and subscribe with a row filter. Realtime checks RLS for every subscriber, so keep the table lean.
- SvelteKit +server.js endpoint to verify a Sume webhook signature
A SvelteKit +server.js POST handler gets a Fetch Request, so request.text() gives the raw body Sume signs. Verify the HMAC, then handle job.completed.
Written by Sume