Sume 409 idempotency_conflict: same key, different body

Reusing an Idempotency-Key on a different body returns 409 on Sume. An exact retry returns the original job instead. How to build keys that behave.

5 min readSume
All posts

Sume returns 409 idempotency_conflict when you reuse an Idempotency-Key with a different operation or payload. An exact retry with the same key returns the original job and does not create or bill a second one. Treat a key as the identity of one intended generation, not as a session token.

Where it applies

Send the header on every paid submit that a client could retry: /v1/videos, /v1/images, TTS Router and the product routes. Without it, Sume's docs say not to retry a timed-out submit, since a second request could create a second job.

A safe retry

This submit can be repeated any number of times after a timeout. The second call returns the job the first one created.

curl -X POST https://api.sume.com/v1/videos \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: promo-clip-2026-10-05-001" \
  -d '{"model":"seedance-2","prompt":"A paper boat on a rain puddle"}'

Why you see the 409

The usual causes are a key built from something too coarse, such as the date, and a prompt edit followed by a retry with the old key. Both reuse a key for a new intent.

  • Derive the key from your own item id plus an attempt counter that only changes when the intent changes.
  • Persist the key next to the job id before you send the request.
  • On 409, do not retry. Change the key if the intent changed, or read the stored job if it did not.

What not to do

Do not generate a random key per HTTP attempt. That defeats the guarantee, because every retry becomes a new paid job. Generate the key once per intended generation and reuse it for all retries of that one.

Pair it with polling

Idempotency covers the submit. After it, treat the job id as your handle. If your process restarts, read status_url for the stored id instead of submitting again. A client-side timeout never cancels the job, so the original keeps running and billing until it ends.

Together the two rules give you at-most-once billing per intent: one key per intent on submit, one stored job id for everything after.

Related posts

More in Developers

All Developers posts

Written by Sume