Wan 3.0 draft and final need different Idempotency-Keys (409)
Reusing one Idempotency-Key for a 480p draft and a 1080p final of the same prompt returns 409 idempotency_conflict. A Python key builder that avoids it.

When you re-render a Wan 3.0 draft at final quality, change the Idempotency-Key. Sume's Generation admission page lists 409 idempotency_conflict for a key reused with a different operation or payload, and the 480p draft and the 1080p final differ in resolution. The key belongs to one exact request; reuse it only to retry that request. A retry of the draft costs nothing extra, and a 30-second 1080p final costs $7.50 against $1.875 for the draft.
A key that encodes what the request is
Build the key from the fields that change the result. Two requests with the same fields give the same key, so retries are safe; a changed field gives a new key.
import hashlib, json
def idem_key(shot: str, body: dict, version: int = 1) -> str:
fields = {k: body[k] for k in ("model", "prompt", "duration", "resolution", "aspect_ratio")}
digest = hashlib.sha256(json.dumps(fields, sort_keys=True).encode()).hexdigest()[:12]
return f"{shot}-{body['resolution']}-v{version}-{digest}"
draft = {"model": "wan-3.0", "prompt": "Slow push-in on a sneaker", "duration": 30,
"resolution": "480p", "aspect_ratio": "9:16"}
final = {**draft, "resolution": "1080p"}
print(idem_key("sneaker-ad", draft))
print(idem_key("sneaker-ad", final))
assert idem_key("sneaker-ad", draft) != idem_key("sneaker-ad", final)What each outcome means
| You send | Result |
|---|---|
| Same key, exact same payload | The original job comes back; no second reserve |
| Same key, different resolution | 409 idempotency_conflict |
| New key, same payload | A new job and a new reserve |
| No key on a retried POST | A second job is possible; keep the key |
The cost of getting it wrong
A conflict is a rejected call, not a charge, so the failure is annoying rather than expensive. The expensive error is the opposite one: minting a fresh key on every retry of a timed-out submit, which can start two jobs for the same shot. At 1080p, two 30-second jobs cost $15.00.
Persist the key with the shot before you send the request, so a crash and restart reuses it.
Storing the key
Write the generated key into your database row for the shot before you send the request, and read it back on retry. If you generate it from a hash of the request fields, as above, the key is reproducible even if the row is lost.
Version bump for a deliberate re-run
Submitting the same fields under a new version starts a new job on purpose, which is how you ask for another take. Use that when you want another attempt, and keep the version unchanged when you are only retrying a failed call.
Sources
Related posts
More in Developers
- wan-3.0 duration 1 gives 400: the 2 to 30 s range, 25 cents at 2 s
Sume lists wan-3.0 at 2 to 30 seconds. A 1-second request is a 400 unsupported_capability; a 2-second 720p clip bills 25 cents (list $0.10 per second x 1.25).
- Wan 3.0 reference limits on Sume: 10 images, 5 videos, 5 audio clips
Wan 3.0 on Sume takes up to 10 reference images, 5 reference videos (15 s total, 16 fps or more) and 5 audio clips (15 s total). Here is the full envelope.
- wave_size_hint 450 is not concurrency: sizing Sume submit waves
With concurrency 100 and a 500-job queue, Sume shows wave_size_hint 450 but your in-flight budget is 100. How to compute both from generation_limits.
- Webhook signature mismatch: Sume fingerprint vs OpenRouter t=,v1=
A video webhook that fails verification has three usual causes: parsed body, wrong secret, wrong header format. Sume adds a secret fingerprint header.
Written by Sume