HeyGen API idempotency key vs Sume: two different 409s
HeyGen returns 409 request_in_progress for an in-flight retry. Sume returns 409 idempotency_conflict only when a key is reused for a different payload.

Both APIs take an Idempotency-Key header, but their 409s mean different things. HeyGen's changelog says that on its look endpoints a retry while the original run is in flight returns 409 request_in_progress; Sume's 409 idempotency_conflict means the key was reused for a different operation or payload.
HeyGen details are from its API changelog; Sume's are from Generation admission and Jobs and results, read 2026-09-30.
What does HeyGen say about its key?
For video creation, the changelog says to send an Idempotency-Key header so a retry does not start a second generation. For look endpoints it adds that a retry while the original is in flight returns 409 request_in_progress, and one after it finishes replays the original response.
What does Sume say about its key?
The admission docs recommend an Idempotency-Key for every paid submit that may be retried, and not resubmitting a paid request just because your local worker timed out. The retry rule is explicit: reuse the same key so the retry returns the original job instead of billing a second one.
| Situation | HeyGen (changelog) | Sume (docs) |
|---|---|---|
| Retry while original is running | 409 request_in_progress (look endpoints) | Reuse the same key; the retry returns the original job |
| Retry after original finished | Original response is replayed (look endpoints) | Same key returns the original job |
| Same key, different payload | Not stated in the entry | 409 idempotency_conflict |
| Client action on 409 | Not stated in the entry | Reuse keys only for exact retries |
How should my retry code treat a 409?
Branch on the code, not the status. A request_in_progress means the original is still running, so wait rather than resubmit; an idempotency_conflict is a bug in how you generate keys, because the payload changed under a stable key. Keep a stable key per intent and a new key per new intent.
async function submit(body, key) {
const res = await fetch("https://api.sume.com/v1/avatar-1.0/talking-video", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.SUME_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": key,
},
body: JSON.stringify(body),
});
if (res.status === 409) throw new Error("key reused for a different payload");
return res.json();
}Where else does this matter?
Wrappers that retry automatically are the usual source of duplicate submits; see axios-retry with idempotency keys for generating the key once per request intent.
Sources
Related posts
More in Developers
- HeyGen Video Agent edit_plan vs Sume preview regenerate
HeyGen's edit_plan revises named scenes in one turn, up to 50 items. Sume has no in-place scene edit: regenerate preview stills, then render.
- HeyGen video scenes API vs Sume job result previews
HeyGen's GET /v3/videos/{video_id}/scenes returns each scene's visuals and script. Sume job results return media.sume.com artifacts and scene previews.
- Hookdeck 15-minute timeout and Sume's 10-second webhook attempt
Hookdeck's longer destination timeout does not change Sume's fixed 10-second attempt. Ack fast at the relay URL and give your handler its own time budget.
- How long does Sume retry a webhook before giving up?
Sume job webhooks give up after about 4.5 minutes of gaps, run webhooks after about 3 hours. Cumulative timings per attempt, then redeliver or poll.
Written by Sume