Sume webhook not received? How to debug delivery and signatures
When a Sume webhook does not arrive, read webhook_delivery on the job or run, prove your endpoint with a test delivery, then redeliver the real event.

When a Sume webhook is not received, start with the job or run itself: one created with a webhook URL carries a webhook_delivery object whose status, attempts, last_status_code, and last_error show whether Sume tried, what your endpoint answered, and whether Sume gave up. Then prove your receiver with a test delivery (POST /v1/webhooks/test-deliveries) and replay the real event with Redeliver.
This guide follows Sume's Webhooks, Run webhooks, and Verifying webhooks docs, with field definitions from the Sume API reference, read on 2026-09-26. How signing and retries work in general is covered in Signed webhooks for video runs.
Did Sume try to deliver at all?
First check that the URL was accepted and that the outcome sends anything. Webhook URLs must be public HTTPS: localhost, private-network, and non-HTTPS URLs are rejected at submit, and a run's URL is checked again at delivery time. Runs deliver only on completed or failed, never on canceled or skipped; jobs also send job.canceled.
Then read webhook_delivery.status. Jobs use pending, delivering, delivered, retrying, failed, and exhausted, and a job's events at GET /v1/jobs/{id}/events include webhook.delivery. Runs use not_armed, pending, retrying, delivered, failed, and exhausted:
| Status | Meaning |
|---|---|
not_armed | The URL is stored and nothing is scheduled yet: the run is still going, or it was canceled or skipped, which never arms a delivery. |
pending, retrying | Armed. next_attempt_at is when the next attempt is due. |
delivered | Your endpoint answered 2xx. |
failed, exhausted | Sume gave up. last_status_code and last_error say why. The run is unchanged. |
What do last_status_code and last_error tell me?
On a run, last_status_code is the HTTP status your endpoint returned on the last attempt, and last_error is Sume's own transport error, such as a timeout, a connection failure, or a non-2xx status, never your response body. A job's webhook_delivery carries the same two fields. Causes to check:
- A slow handler. Each attempt gets 10 seconds, and any
2xxcounts as delivered, so store the event durably, answer, then do the work. - A redirect. Run deliveries do not follow redirects, so a
3xxis a failed attempt; register the final URL. - A
500on an event type your handler does not know. Answer unknown events with204, so a new event type does not become a retry storm. - Every attempt refused. After 10 attempts the delivery stops, and the job or run still reached its real terminal state. Read it from
result_urlorstatus_url.
How do I test my endpoint without a real job?
Use Send test: the control on /dashboard/webhooks, or POST /v1/webhooks/test-deliveries with a key carrying account:write. It POSTs a dummy, signed webhook.test event to the public HTTPS URL you give it and returns the outcome as status_code and error, plus a signing_secret_fingerprint. It never replays a real job or run, and its body has no job_id or run id.
curl -X POST https://api.sume.com/v1/webhooks/test-deliveries \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "webhook_url": "https://example.com/hooks/sume" }'How do I replay an event I missed?
Fix the receiver, then Redeliver the real terminal event: POST /v1/jobs/{job_id}/webhook/redeliver with jobs:write, or POST /v1/format-runs/{run_id}/webhook/redeliver with formats:write and an empty body. Sume re-POSTs it with a fresh timestamp and signature, even after the automatic 10 attempts are exhausted.
- Read
redelivery(delivered,status_code,error) for the POST you just triggered. A failed redeliver of a call that was already delivered leaveswebhook_deliveryon the earlier2xxand only counts the attempt inmanual_redeliveries. 409 webhook_not_configuredmeans there was no webhook URL;409 job_not_terminalorrun_not_terminalmeans it is still running. A job or run you cannot see is404.- Redeliver never sends to a different URL. For jobs, a new URL is a new job.
Why does my endpoint reject every signature?
Sume signs every delivery with HMAC-SHA256 over <timestamp>.<raw_body>. When every delivery fails your check, look at the verifier in this order:
- The raw body. A parsed and re-serialized object does not verify. In Express, mount
express.raw({ type: "application/json" })on the webhook route only; in the Next.js App Router,await request.text()before anything else. - The secret. Compare the
x-sume-webhook-secret-fingerprintheader with the fingerprint shown beside the secret on the dashboard. The fingerprint is safe to paste into a ticket; the secret is not. - A rotation or the clock. For 24 hours after a rotation the signature header carries two
sume-v1=entries, so a verifier that compares the whole header for equality fails every delivery; accept a match on any entry.verifyWebhookalso enforces a replay window,toleranceSeconds, that defaults to 300. Signed webhooks for video runs covers rotation.
Sources
Related posts
Written by Sume