One idempotency key per model when a video fallback changes payload

Reusing an Idempotency-Key after switching video models returns 409 idempotency_conflict. Build the key from order, model, and prompt hash so retries stay safe.

5 min readSume
All posts

If your video pipeline falls back to a second model and keeps the first model's Idempotency-Key, Sume treats the request as the same operation with a different payload and answers 409 idempotency_conflict. Derive the key from the order id, the model id, and a hash of the prompt, so a retry of the same request reuses the key and a different model gets a new one.

The reverse mistake is worse. If you generate a fresh random key on every attempt, a client timeout that hides a successful submit creates a second paid job. The goal is a key that is stable under retries and different under real changes.

What Sume documents

These rules come from the generation admission, jobs, and video pages, read 2026-10-08.

  • Send Idempotency-Key on submit requests that you may retry after a client timeout or network failure.
  • Use the same key again only for the same operation and payload.
  • A reused key with a different operation or payload returns 409 idempotency_conflict.
  • On /v1/videos, a replay with the same key returns the original job, so you are not billed a second time.
  • For sume/auto, resolution is a pure function of the normalized request and the catalog version, so an idempotent replay gets the same price and route.

Three situations, three keys

The second row is the one that surprises people. A failed job is terminal, and the next attempt is a new operation. Treat it that way.

When to reuse the key (rules from Sume docs read 2026-10-08)
SituationPayload changed?Key
Client timed out, unsure the submit landedNoReuse the same key
The first job reached failed, you retry on model BYes, the model fieldNew key that includes model B
The same order is re-rendered with a new promptYesNew key that includes the new prompt hash

A key function you can test

The function needs no network. Its output is stable for the same inputs, so you can assert on it in a unit test.

Run python3 key.py and compare the two lines: the same inputs give the same key, and changing only the model changes the key.

import hashlib

def idem_key(order_id: str, model: str, prompt: str) -> str:
    digest = hashlib.sha256(prompt.encode()).hexdigest()[:12]
    return f"{order_id}:{model}:{digest}"

a = idem_key("order-8823", "seedance-2.5", "Slow push-in on a mug")
b = idem_key("order-8823", "seedance-2.5", "Slow push-in on a mug")
c = idem_key("order-8823", "wan-3.0", "Slow push-in on a mug")
print(a == b, a == c)
print(a)
print(c)

Edge cases

Keep the key under a sensible length and do not put personal data in it. It is an opaque string to Sume, but it ends up in your logs. If you also vary resolution or duration between attempts, add them to the hash input, because they are part of the payload.

When two requests with the same key arrive at the same moment, a Format run returns 409 idempotency_key_in_use, which is retryable after about a second. The generation endpoints document the conflict case; for the in-use case, check the page of the surface you call before you rely on it.

Test the policy before launch day

Write three unit tests around idem_key and one around your retry wrapper. The first asserts that the same inputs give the same key. The second asserts that a different model gives a different key. The third asserts that a different prompt gives a different key. The wrapper test uses a fake HTTP layer that fails the first submit with a timeout and succeeds on the second, then asserts that both calls carried the same Idempotency-Key header.

Do not spend real money on this. A fake that returns a canned 202 envelope is enough, and it keeps the test fast enough to run on every commit.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume