Redeliver a missed speech-to-text webhook without rerunning the job
Your receiver was down when a Sume STT job finished. Redeliver the terminal webhook with one call instead of paying to transcribe again.

If your webhook receiver missed the callback for a finished Sume STT job, call POST /v1/jobs/{id}/webhook/redeliver. It re-sends the job's real terminal payload with a fresh timestamp and a sume-v1 signature, and it works even after the automatic attempts are exhausted. You do not resubmit the audio and you do not pay for a second transcription.
This is the fix for the usual 3 a.m. problem: a deploy took your endpoint down while a batch of transcripts finished.
What exactly does redeliver do?
Per the Sume OpenAPI spec, redeliver re-POSTs the terminal event, which is job.completed, job.failed or job.canceled. It requires the jobs:write permission and does not consume one of the automatic 10 retries. It returns 409 if the job is still running or was created without a webhook_url, and 404 for a job you cannot see.
| Situation | Result |
|---|---|
| Job finished, receiver missed it | Terminal payload sent again |
| Automatic retries exhausted | Still works |
| Job still running | 409 |
| Job created without webhook_url | 409 |
| Job in another workspace | 404 |
What must your receiver handle?
Delivery is terminal only. There are no progress or partial callbacks, so you will see one of three event types per job. A redelivery carries a fresh timestamp, so key your own processing on the job id, not on the timestamp, and make the handler safe to run twice.
- Verify the
sume-v1signature before you trust the body. - Deduplicate on job id so a redelivery does not write a transcript twice.
- Return a 2xx quickly and do heavy work after you respond.
How do you call it?
Pass the job id from the original submit response:
import os, requests
H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
job_id = os.environ["JOB_ID"]
r = requests.post(
f"https://api.sume.com/v1/jobs/{job_id}/webhook/redeliver",
headers=H, timeout=30,
)
print(r.status_code)
if r.status_code == 409:
print("job still running or no webhook_url was set")
When is polling better?
If you cannot expose a public HTTPS endpoint at all, skip webhooks and poll /v1/jobs/{id}/status. The webhook URL must be public HTTPS; localhost, private-network and non-HTTPS URLs are rejected. For the wider pattern of job ids and hosted artifacts, see keeping a TTS pipeline portable.
Sources
Related posts
More in Developers
- Reels safe-zone boxes in Python: a pure function for any frame size
Meta's Reels percentages are relative, so one pure Python function gives the safe box for any frame size. It runs offline and feeds a caption anchor.
- Reference image preflight checklist before a Seedance 2.5 job
Most reference-to-video failures are input problems. A checklist and a curl preflight for URLs, count and mix before you pay for a Seedance 2.5 job on Sume.
- Removed OpenAI video ids: the exact list and a script to find them
OpenAI removed the Videos API and five sora-2 model ids on 2026-09-24. The exact ids from its deprecations page, and a Python script that finds them in a repo.
- Replace your mocked Sora client with a Sume contract test
Tests that mocked a Sora client now guard nothing. Write a small pytest contract test around your own video interface, plus one live smoke test against Sume.
Written by Sume