Find exhausted Sume webhook deliveries and redeliver them in Python
Page GET /v1/jobs for completed and failed jobs, keep webhook_delivery.status exhausted, and call POST /v1/jobs/{id}/webhook/redeliver for each.

List your terminal jobs with GET /v1/jobs, keep the ones whose webhook_delivery.status is exhausted, and call POST /v1/jobs/{job_id}/webhook/redeliver on each. Sume re-sends the real terminal event with a fresh timestamp and signature, and that call does not use up one of the ten automatic attempts.
Do this after an outage on your side, such as a deploy that returned 500s for ten minutes while a batch of clips finished.
What are the delivery statuses?
The webhook_delivery object on a job carries the state. Only one value asks for a sweep.
| Status | Meaning for you |
|---|---|
| pending | Not yet sent |
| delivering | An attempt is in flight |
| retrying | Another attempt is scheduled; leave it |
| delivered | Your endpoint answered 2xx |
| failed | The attempt failed; read last_error |
| exhausted | All automatic attempts used; redeliver |
What does the sweep do?
The list takes one status at a time, so it runs once per terminal status. The key needs jobs:write for the redeliver call, and it only sees jobs its own member created.
import os, requests
BASE = "https://api.sume.com/v1"
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
def jobs(status):
cursor = None
while True:
q = {"status": status, "limit": 100}
if cursor:
q["starting_after"] = cursor
r = requests.get(f"{BASE}/jobs", headers=H, params=q, timeout=30)
r.raise_for_status()
data = r.json()["data"]
yield from data["jobs"]
cursor = data.get("next_cursor")
if not cursor:
return
for status in ("completed", "failed", "canceled"):
for job in jobs(status):
wd = job.get("webhook_delivery")
if wd and wd["status"] == "exhausted":
r = requests.post(f"{BASE}/jobs/{job['id']}/webhook/redeliver",
headers=H, timeout=30)
print(job["id"], r.status_code)What must my receiver do on a redeliver?
Treat job_id as the idempotency key. A redelivered event is the same event with a new signature, so a receiver that already stored it should answer 2xx and do nothing else. Only terminal jobs have an event to re-send, so run the sweep on completed, failed and canceled jobs.
How often should I run it?
Once after any incident is enough, and a daily run is a reasonable floor for a pipeline you cannot watch. Keep it away from the hot path. The list calls spend the read budget, and a sweep over a large history is a slow job by nature, so page at the full limit of 100 and stop paging once you pass the date of the outage.
Log each job id and the status code you got back, so the next person can tell which redelivers worked and which did not.
Is the sweep the only recovery path?
No. The docs say delivery is an optimization, and the status endpoint always has the final state. If you do not own a jobs:write key, read the job and take the result from there.
Sources
Related posts
More in Developers
- Five status vocabularies on the Sume and OpenRouter video APIs
Sume job status, the queue-shaped field, /v1/videos status, webhook delivery status and OpenRouter status differ in spelling. One TypeScript map fixes it.
- FLUX.3 not on Sume yet: detect it via /v1/images/models, fall back
Sume does not list FLUX.3. A Python script reads /v1/images/models, uses FLUX.3 if it appears, else Nano Banana 2.1 at 2K for $0.15. BFL 2k is $0.100.
- Format run expires_at: a 90 minute ceiling for your Python poll loop
A Sume Format run receipt has an expires_at deadline: 90 minutes from creation, sooner if the run goes quiet. Use it as your loop ceiling, with Python backoff.
- Four status vocabularies in the Sume API: job, resource, run, delivery
Jobs say queued and processing, resources say ready, deliveries say exhausted, queue-shaped fields say IN_QUEUE. A table so a client branches on the right one.
Written by Sume