Choosing a Sume Idempotency-Key: business key plus a payload version
A good Idempotency-Key is stable across retries and changes with the request. Build it from your order id and a payload hash, or hit 409 idempotency_conflict.

Derive the Sume Idempotency-Key from something stable about the work, like an order id, plus a short hash of the exact payload. A retry then reuses the key and gets the original job back, while a deliberately edited request gets a fresh key instead of 409 idempotency_conflict.
The rules from the docs
Send the header on submits you may retry after a timeout or network failure, and reuse a key only for the same operation and payload. Reusing a key with a different body is 409 idempotency_conflict; do not retry that as-is, fix how you derive the key. idempotency_key_in_use is a different 409, where another request with the same key is still in flight and you can resend after about a second.
A derivation that works
Canonicalize the body so key order cannot change the hash. Do not put timestamps or random values in the hashed input, or every retry looks new and you pay twice.
import asyncio
import hashlib
import json
def idempotency_key(order_id: str, payload: dict) -> str:
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":"))
digest = hashlib.sha256(canonical.encode()).hexdigest()[:12]
return f"order-{order_id}-{digest}"
async def main() -> None:
a = idempotency_key("8823", {"prompt": "mug", "duration": 6})
b = idempotency_key("8823", {"duration": 6, "prompt": "mug"})
c = idempotency_key("8823", {"prompt": "mug", "duration": 8})
print(a == b, a == c) # True False
asyncio.run(main())When you want a new job on purpose
Changing the payload changes the key, so you get a new paid job; that is intended for an edit. For a failed Format run, the docs say to retry with a new key, so mint one deliberately rather than reusing the failed one.
| Situation | Result |
|---|---|
| Retry with same key and body | Original job returned |
| Same key, different body | 409 idempotency_conflict |
| Same key, first request in flight | 409 idempotency_key_in_use, resend soon |
Sources
Related posts
More in Developers
- Sume image API size vs resolution vs aspect_ratio: which to send
On POST /v1/images, size is only a shorthand for a resolution tier and exact pixels are not served. Send resolution and aspect_ratio from the model's list.
- Sume job status: stop on terminal, fetch on result_ready
A Sume status reply has two booleans. terminal says stop polling; result_ready says GET /result will work. Failed and canceled jobs stop but have no result.
- Music 1.0 is retiring: switch to /v1/music-router/generate in one line
Sume's Music 1.0 routes keep working but now resolve through the Music Router. Which URL to change, what stays the same, and how to see which engine ran.
- Sume ratelimit-limit differs on reads and writes: read the header
ratelimit-limit shows the budget the current call spent from, so a GET shows reads and a POST shows writes. Read the header; do not hard-code the plan table.
Written by Sume