Edited script, same Idempotency-Key: 409 conflict on Sume TTS
Reusing an Idempotency-Key with a changed transcript returns 409 idempotency_conflict on Sume. How to key each script version so edits never collide.

If you change the transcript and reuse the same Idempotency-Key, Sume answers 409 idempotency_conflict and creates nothing. That is the safety working: the key means "this exact request". Give each script version its own key and the conflict never shows up, while a true retry of one version still returns the original job.
What the key promises
Send Idempotency-Key on any generation call. Repeat the identical request with the same key and you get the existing job back instead of a second charge. Repeat the key with a different payload and the API refuses. This holds for TTS 1.0, STT 1.0 and the music endpoints alike.
| Same key | Same payload | Result |
|---|---|---|
| Yes | Yes | The original job comes back; no new charge |
| Yes | No | 409 idempotency_conflict; nothing is created |
| No | Yes | A new job, a new charge |
| No | No | A new job, a new charge |
A key that tracks the edit
A good key names the intent, not the time. Hash the fields that define the audio, so an unchanged script reuses its key and a changed one gets a fresh one.
import hashlib
import json
def tts_key(project, transcript, avatar, language):
body = json.dumps(
[transcript, avatar, language], ensure_ascii=False
)
digest = hashlib.sha256(body.encode()).hexdigest()[:16]
return f"{project}-{digest}"
print(tts_key("promo", "Hello there.", "narrator", "en"))
print(tts_key("promo", "Hello there!", "narrator", "en"))Mistakes to avoid
- A fixed key like
testin a script: the second run with new text fails. - A timestamp key: every retry after a network error buys another job.
- Resubmitting after a sync timeout. A timed-out wait means the job is still running; poll
status_urlinstead.
Handling the 409
Treat idempotency_conflict as a bug in key construction, not as a transient error. Do not retry with the same key. Log the key and the changed field, then rebuild the key from the new payload and submit once. Sume does not document an expiry window in the pages I read, so do not rely on a key aging out.
Sources
Related posts
More in Developers
- Fade in and out on a Timeline render: output fade seconds 0 to 5
Set output.fade_in_seconds and fade_out_seconds (0 to 5 s, sum within the render length). The music bed has its own fade_out_seconds, up to 10.
- Fast-cut Shorts in Timeline: eight chained fades, then a hard cut
Timeline refuses more than 8 adjacent fades with too_many_chained_transitions. Transitions must be 1 s or less and half the shorter neighbour. How to plan cuts.
- Fix an underexposed photo: curves first, AI edit only if needed
Underexposed photo? Try Pillow autocontrast and gamma for free, then an ideogram/ideogram-v4.5 edit at $0.075 only if noise or colour needs more.
- How do I fix one sentence in finished AI narration without redoing it?
Retake just the wrong sentence with a one-cent TTS job, then splice it into the original file with a $0.01 Timeline audio concat using source_in and duration.
Written by Sume