Which episode finished? Map a Sume run id to your episode record

A Sume Format run does not echo your episode number. Keep a ledger keyed by queue index and run id, and match webhooks on request_id.

5 min readSume
All posts

Sume will not hand your episode number back to you, so store it yourself: after a bulk create, save the queue id and, for each item, its index and run_id against your episode row. A webhook then carries the same run id as run_id and request_id, and that is the key to look up.

The docs say it plainly in two places. On the structured-output page, an order_id you sent in input can be invisible to the projection pass, so keep identifiers on your side keyed by run.id or by the Idempotency-Key you sent. On the call page, the same advice is that an identifier cannot be echoed back unless the run repeats it.

The two places an id shows up

The queue order is the order you submitted, so item 0 is your first episode. A failed item that never started keeps its index with run_id: null and an error set.

Where the run id appears (as of 2026-10-03)
WhereFieldUse it for
Queue receiptitems[i].index and items[i].run_idJoining your episode list to child runs; run_id is null while an item is queued
Webhook enveloperun_id and request_id (equal)Dedupe key, stable across retries

Build the ledger at create time

Write the queue id and your index-to-episode map before you start polling, then fill in run ids as they appear.

def link_queue(queue: dict, episodes: list[str]) -> dict[str, str | None]:
    items = queue["data"]["items"]
    if len(items) != len(episodes):
        raise ValueError("queue and episode list differ in length")
    return {episodes[i["index"]]: i["run_id"] for i in items}

queue = {"data": {"items": [
    {"index": 0, "status": "running", "run_id": "arun_a", "error": None},
    {"index": 1, "status": "queued", "run_id": None, "error": None},
]}}
print(link_queue(queue, ["s01e01", "s01e02"]))

Matching a webhook

  • Look up the episode by run_id from the envelope, not from the nested receipt id.
  • Dedupe on request_id; it is the same on every retry of the same run. Order deliveries by created_at.
  • Switch on outcome: ok, degraded (real artifacts but no structured output) or error.
  • A canceled or skipped run never delivers a webhook, so close those episodes from the response you got when you canceled or created.
  • A receipt over 1 MiB arrives with payload: null and error.result_url; fetch it from there.

What the queue will not do for you

There is no public list-queues or cancel-queue endpoint, so the queue id you saved is the only handle on that batch. Per-item webhooks are set with communication.webhook_url on each item, and the queue itself has none. Keep the mapping in your database; the receipts are the evidence, your table is the index.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume