Bulk run 409 idempotency_conflict: find the first queue by queue_id
A Sume bulk create that reuses a key with a different payload returns 409 with details.queue_id. How to read the original queue and decide what to resend.

What does a 409 from a Sume bulk create mean, and where is the queue I already started? If you send POST /v1/formats/{handle}/{slug}/bulk-runs with an Idempotency-Key you used before and a different { concurrency, items }, the API answers 409 idempotency_conflict, and details.queue_id names the original queue. Per the Bulk runs docs, the same key with the same payload is not an error: it returns 202 and the existing queue.
That asymmetry is the whole feature. It lets a crashed uploader retry safely, and it stops a changed list from silently attaching to an old queue.
The three outcomes of a key
| What you send | What you get | What it means |
|---|---|---|
| New key | 202 and a new queue | Items start, up to concurrency at once |
| Same key, same concurrency and items | 202 and the existing queue | A true replay; nothing new starts |
| Same key, different payload | 409 idempotency_conflict with details.queue_id | Your key was already spent on other content |
What to do on the 409
First read the queue named in details.queue_id with GET /v1/format-run-queues/{id}. You are looking for one of two situations. If that queue holds the rows you meant to send and you only rebuilt the request differently, for example the items were re-serialized with different key order or an extra field, then accept the original queue and carry on polling. If the list really changed, the old queue is a different job: leave it alone and mint a new key for the new list.
Never reuse the same key after changing the list in the hope the server will merge them. The control plane stores the key against one payload, and the docs say a replay of a spent key returns the old queue, not a new one. Derive keys from the business intent plus a revision suffix, so a deliberate change gets a new key by construction.
Naming keys so a conflict means something
A key that can collide by accident produces the wrong 409. A key made from a date, bulk-2026-10-04, collides with the second batch you send that day and with a different list. A key built from the campaign name, the revision and a hash of the list collides only when you really are resending the same job.
Keys are scoped to one Format and can be up to 255 characters, so there is room to be descriptive. Put the Format slug, the campaign and a short hash of the serialized items in the key.
When the 409 does arrive for a genuinely changed list, log both the new key and details.queue_id, so a human can see which earlier queue the key was spent on.
A safe create wrapper
This function shows the decision logic with the HTTP call stubbed out, so it runs anywhere. Swap post_bulk for a real request to api.sume.com with your key.
def post_bulk(key, payload, _seen={}):
if key in _seen and _seen[key] != payload:
return 409, {"error": {"code": "idempotency_conflict"},
"details": {"queue_id": _seen[key + "_id"]}}
_seen[key] = payload
_seen[key + "_id"] = "frq_demo"
return 202, {"data": {"id": "frq_demo"}}
def create(campaign, revision, payload):
key = f"{campaign}-r{revision}"
status, body = post_bulk(key, payload)
if status == 409:
return "conflict", body["details"]["queue_id"]
return "queued", body["data"]["id"]
items = {"concurrency": 2, "items": [{"instruction": "a"}]}
print(create("holiday", 1, items))
print(create("holiday", 1, items))
print(create("holiday", 1, {"concurrency": 2, "items": []}))
print(create("holiday", 2, {"concurrency": 2, "items": [{"instruction": "b"}]}))Sources
Related posts
More in Developers
- C2PA 2.2: file types that can carry credentials vs Sume outputs
C2PA 2.2 manifests can be embedded in JPEG, PNG, WebP, SVG, MP4, MOV and more. How that list lines up with the formats Sume image and video jobs return.
- C2PA 2.2 in plain terms: manifests, hard and soft bindings
C2PA 2.2 describes signed manifests with hash-based hard bindings and fingerprint or watermark soft bindings. What that implies after a re-encode or trim.
- Watch the Sume video catalog for new ids and changed limits in Python
Fetch GET /v1/videos/models, save a snapshot and diff new ids, removed ids and changed durations or resolutions. A Python script, testable offline.
- Claude batch custom_id is 64 characters: keep SKU keys valid
Anthropic batch custom_id allows 1 to 64 letters, digits, underscore and hyphen. How to sanitize SKUs, avoid collisions and carry the key into Sume input.
Written by Sume