Bulk queue key from a payload hash: same body 202, new body 409
Derive a Format bulk queue Idempotency-Key from a sha256 of its body. The same body replays 202 with the old queue; a changed body gives 409.

To make a bulk queue safe to retry, derive its Idempotency-Key from a sha256 of the exact { concurrency, items } body. Sending the same body again returns 202 and the queue that already exists, so a lost response costs nothing. Sending a changed body under the same key returns 409 idempotency_conflict, and details.queue_id names the original queue.
The replay rules
The docs give the key a scope of one Format. The header wins if you also send idempotency_key in the body.
| Replay | Result |
|---|---|
| same key, same concurrency and items | 202 and the queue that already exists |
| same key, different payload | 409 idempotency_conflict, details.queue_id names the original |
| new key, same payload | a second queue, so the work runs twice |
| key scope | one Format |
Why hash the body
A random key per attempt does not protect you, because a retry after a timeout has a new random key and starts a second queue. A key that is a function of the body is the same on every attempt. If the first call reached the server, the retry gets the old queue back. If it did not, the retry creates the queue.
The side effect is useful: editing one item changes the hash, so you get a new key and a new queue and not a 409. A 409 then only means that something reused a key by hand. Note the cost of the other direction. If you want to run an identical batch again on purpose, the same key returns the old queue, so add a run label to the hash input, such as the date.
The unspent key and the `completed` queue
A replay returns the queue as it is now, with current counts. It does not re-run failed items. After a queue is completed, check counts.failed and counts.canceled; completed means that every item is terminal, not that all succeeded. To retry only the failed rows, build a new body from those rows and let its hash make a new key.
import hashlib, json
def bulk_key(handle: str, slug: str, body: dict, label: str = "") -> str:
if not handle or not slug:
raise ValueError("handle and slug are required")
canon = json.dumps(body, sort_keys=True, separators=(",", ":"))
digest = hashlib.sha256((f"{handle}/{slug}|{label}|" + canon).encode()).hexdigest()
return "bulk-" + digest[:32]
body = {"concurrency": 4, "items": [{"instruction": "clip 1"}, {"instruction": "clip 2"}]}
same = {"concurrency": 4, "items": [{"instruction": "clip 1"}, {"instruction": "clip 2"}]}
edit = {"concurrency": 4, "items": [{"instruction": "clip 1"}, {"instruction": "clip 3"}]}
print(bulk_key("demo", "promo", body) == bulk_key("demo", "promo", same))
print(bulk_key("demo", "promo", body) == bulk_key("demo", "promo", edit))A worked retry
Say a script posts a 40-item queue and the connection drops before the reply arrives. With a random key, the script retries, and the server may now hold two queues of 40 items, 80 runs. With the hashed key, the retry sends the same key and the same body, and the server answers 202 with the queue it already made. The script reads id and status_url and carries on to polling.
Now say that the script is changed to drop item 17 and is run again against the same key by hand. The hash changes, so the key changes, and a new queue is made. If a person reuses the old key with the new body, the answer is 409 and details.queue_id points to the first queue. That is the signal to look, not to retry.
What the key does not cover
The docs say the queue has no webhook, no list-queues call and no cancel-queue call. Keep the returned id (frq_...) in your own store, since you cannot list queues to find it later. If you lose it, replay the same body with the same key to get the queue back as a 202.
Sources
Related posts
More in Formats
- Bulk queue spend ceiling: 100 items at $2 is $200; 16 live is $32
With generation_spend_cap_usd of $2 per bulk item, 100 items cap at $200 in total and 16 running items at $32 at once. Caps are ceilings, not prices.
- Bulk queue, empty wallet: failed items, fresh key, check balance
If the wallet runs out during a bulk run, later child runs fail admission and become failed items. Check the balance, then resubmit with a fresh key.
- Bulk queue worst case: 100 items x per-item cap, $300 not $40,000
Each child in a Sume bulk queue is a run with its own spend cap. 100 items at $3 cap at most $300; the default $400 cap would allow $40,000. Set caps per item.
- Cancel a Sume bulk queue: there is no queue cancel, so cancel children
Sume's API has no cancel-queue endpoint. Cancel each child with POST /v1/format-runs/{run_id}/cancel; the item frees its slot, and you pay for what already ran.
Written by Sume