Order id or payload hash? Choosing a Sume Idempotency-Key

An order-id key gives 409 idempotency_conflict when the prompt changes; adding a payload hash gives a new paid job. Choose on purpose, with Python.

4 min readSume
All posts

Pick the key to match the question you want Sume to answer. If the key is the order id, a retry returns the original job, but an edited prompt with the same key returns 409 idempotency_conflict and nothing runs. If the key is the order id plus a hash of the payload, an edited prompt becomes a new key and a second paid job. Neither is wrong; the second just spends money.

The docs say to use a key again only for the same operation and payload, and to derive it from the item the run makes.

The four outcomes

These come from the Format create page. Job submits share the replay and 409 idempotency_conflict behavior (see Generation admission), but the docs describe the idempotency_key_in_use row for Formats only. On Formats a key is scoped to one Format and may be up to 255 characters.

What a repeated Idempotency-Key does (read 2026-10-07)
SituationResult
Same key, same bodyOriginal receipt returned; no second run or charge (200 and idempotency_hit: true on Format runs)
Same key, different body409 idempotency_conflict; nothing runs
Same key, two simultaneous requestsOne wins; the other gets 409 idempotency_key_in_use, retryable after about a second
New key, same bodyA new run, and a new charge

Which key shape to use

Use the order id alone when a business object should produce exactly one video: an order, a listing, a lesson. The 409 on an edit is a feature, because it forces your code to decide whether the edit should replace the video or create a version.

Use order id plus version when edits are expected and each should be paid for. Make the version a number you increment on purpose, not a hash that changes with whitespace; an unstable key derivation is the cause the docs list for unexpected conflicts.

  • Never use a random UUID generated inside the retry loop; it defeats the point.
  • Never reuse a key across batches; a replayed bulk key returns the old queue.
  • Store the key beside the job id so a restart can resubmit safely.
  • A 429 or 503 on submit is retried with the same key.

Code

The helper below builds a key from an order id and an explicit version, and a separate one with a canonical payload hash, so you can see the trade-off.

import hashlib, json


def key_by_version(order_id, version):
    return f"order-{order_id}-v{version}"


def key_by_payload(order_id, body):
    canon = json.dumps(body, sort_keys=True, separators=(",", ":"))
    return f"order-{order_id}-" + hashlib.sha256(canon.encode()).hexdigest()[:16]


body = {"prompt": "Slow push-in on a mug", "model": "seedance-2"}
print(key_by_version(8823, 1))
print(key_by_payload(8823, body))
print(key_by_payload(8823, {**body, "prompt": "Slow push-in on a mug."}))

Decide before you build

Write down who pays for a changed prompt. If the answer is "the customer, once per approved version", use a version number. If it is "never twice for the same order", use the order id alone and surface the 409 as "this order already has a video".

Handling the 409 in your code

Treat the two 409 codes differently. idempotency_key_in_use means another request with the same key is still being admitted, so wait about a second and retry the same call. idempotency_conflict means your body changed; stop, show the user that this order already has a request, and offer to create a new version with a new key.

Never loop on a conflict: nothing will change until you change the key or the body.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume