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
- First and last frame video API call: Wan 3.0, 6 s at 720p, $0.75
A working first-frame and last-frame request for Sume's /v1/videos: Wan 3.0, 6 seconds, 720p, $0.75. Which rows accept last_frame and which do not.
- 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 Image rewrites your instruction: result.prompt vs Sume's rows
BFL's FLUX 3 Image expands an edit instruction into a detailed prompt and returns it in result.prompt. What to log, and what Sume's rows return instead.
- FLUX 3 Image has no negative prompt: what to write, and Sume's rows
BFL's FLUX 3 Image has no negative_prompt field; it wants the positive version. The replacement table, a runnable rewriter, and Sume's image rows' fields.
Written by Sume