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.

5 min readSume
All posts

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.

webhook_delivery.status values (Sume OpenAPI, read 2026-10-09)
StatusMeaning for you
pendingNot yet sent
deliveringAn attempt is in flight
retryingAnother attempt is scheduled; leave it
deliveredYour endpoint answered 2xx
failedThe attempt failed; read last_error
exhaustedAll 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

All Developers posts

Written by Sume