Developers

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.

6 min readSume
All posts

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:

Run delivery statuses from Runs and results and the Sume API reference, read 2026-09-26.
StatusMeaning
not_armedThe 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, retryingArmed. next_attempt_at is when the next attempt is due.
deliveredYour endpoint answered 2xx.
failed, exhaustedSume 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 2xx counts as delivered, so store the event durably, answer, then do the work.
  • A redirect. Run deliveries do not follow redirects, so a 3xx is a failed attempt; register the final URL.
  • A 500 on an event type your handler does not know. Answer unknown events with 204, 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_url or status_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 leaves webhook_delivery on the earlier 2xx and only counts the attempt in manual_redeliveries.
  • 409 webhook_not_configured means there was no webhook URL; 409 job_not_terminal or run_not_terminal means it is still running. A job or run you cannot see is 404.
  • 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-fingerprint header 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. verifyWebhook also enforces a replay window, toleranceSeconds, that defaults to 300. Signed webhooks for video runs covers rotation.

Sources

Related posts

Written by Sume