Idempotency keys for AI video APIs: retry without paying twice
An idempotency key makes a retried create return the original run or job instead of a second paid one. How Sume's Idempotency-Key works on each API.

An idempotency key is a string you send with a paid create request so that a retry returns the original run or job instead of starting, and billing, a second one. On Sume, send an Idempotency-Key header on every create and derive it from the thing being made, such as an order id plus a version, not from the moment of asking.
The rules below come from Sume's Create a run, Jobs and results, Video Generation, Agent Completions, and MCP tools and gates docs pages, read on 2026-09-25.
Why do AI video APIs need idempotency keys?
Video work outlasts the request that asked for it. Even a sync submit waits at most 30 seconds, and video jobs routinely take longer. A 2xx means the job exists and paid work is in flight, not that it finished, and a client-side timeout does not cancel the job: it keeps running and still bills.
So do not resubmit a paid request just because a local process timed out. If you must retry the submit, reuse the same Idempotency-Key, and the retry returns the original job instead of billing a second one.
How should I build an idempotency key?
- Derive it from stable identifiers: your order id and a version you bump when you deliberately want a re-run.
- Never generate one per request. A
uuidgenper request makes the header decorative. - Reuse a key only for the same operation and payload.
- On Format runs, a key is up to 255 characters, and the body field
idempotency_keyalso works; the header wins when both are sent.
curl -sS -X POST "https://api.sume.com/v1/formats/acme/product-promo/runs" \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-8823-promo-v1" \
-d '{ "input": { "product_url": "https://shop.example.com/p/8823" } }'What happens when I replay a key?
On a Format run, a fresh create answers 202 and a replay answers 200 with the original receipt, so your code can treat both as success and store data.id. The full set of outcomes, from Idempotency:
| Replay | Result |
|---|---|
| Same key, same body | 200 with the original receipt and idempotency_hit: true. No second run, no second charge. |
Same key, different body, including a different instruction or attachment list | 409 idempotency_conflict. Nothing runs. |
| Same key, two requests at the same moment | One wins; the other gets 409 idempotency_key_in_use, which is retryable. Wait about a second and resend. |
Same key after a create that failed (402, 503, …) | The key was released. Fix the cause and retry with the same key. |
Which Sume endpoints accept idempotency keys?
Every create surface below takes one. On POST /v1/videos, the key is one of the documented differences from the OpenRouter Video Generation API, which has none on that route; with model: "sume/auto", a replay also prices and routes identically. More in OpenRouter-compatible video generation.
| Surface | How to send it | On replay |
|---|---|---|
| Format runs | Idempotency-Key header on every create | 200, the original receipt, idempotency_hit: true |
| Agent Completions | Idempotency-Key header | The original receipt with idempotency_hit: true |
| Generation job submits | Idempotency-Key header | The original job instead of a second bill |
POST /v1/videos | Idempotency-Key header | The original job |
| Hosted MCP write and paid tools | idempotency_key argument, required | Used for transport and dedup; it is not human approval |
curl -sS -X POST "https://api.sume.com/v1/videos" \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: desk-clip-8823-v1" \
-d '{
"model": "sume/auto",
"prompt": "A vertical UGC-style product clip on a desk, natural light",
"aspect_ratio": "9:16",
"duration": 5
}'What should I do after a timeout instead of resubmitting?
Pick the existing job back up. The steps below are from Jobs and results.
- Poll the job you already have at
GET /v1/jobs/{id}/statuswith exponential backoff, honoringnext_poll_after_secondswhen present. A job created on/v1/videosis visible there too. - A
syncsubmit that runs out of wait budget still returns2xxwith the job id. Continue withstatus_url. - On the hosted MCP server,
jobs_waitholds at most 55s per call. Onwait_slice_expired, or a524transport failure, calljobs_waitagain on the same ids; never resubmit the paid create. - A client-side timeout cancels nothing.
POST /v1/jobs/{id}/canceldoes, but only before generation work starts.
What does an idempotency key not do?
- It does not approve spend. For a preview, hosted MCP tools take
dry_run=true; for a cap,max_spend_usd, which is enforced only when you send it. See spend caps for unattended AI agents. - It does not cover a changed request. The same key with a different body is a
409, not a new run. - It does not span Formats. The same key sent to two Formats starts two runs.
Sources
Related posts
More in Developers
- Signed webhooks for Sume video runs: events, retries, verification
Sume sends one HMAC-SHA256 signed POST when a Format, Action, or Agent Completion run completes or fails. Verify the raw body and dedupe on request_id.
- Sume API errors and rate limits: codes, 429s, and when to retry
Sume API errors share one envelope with a stable code and a request id. Reads and writes have separate per-minute budgets; queue_full is not a rate limit.
- How Sume API keys work: scopes, auth headers, hosts, and rotation
A Sume API key is a workspace-scoped secret sent as Bearer or x-api-key, never both. Scopes are fixed at creation, and a key works only on its own host.
- How to generate avatar video from the terminal with the Sume CLI
Install the Sume CLI, sign in through the browser, and submit talking avatar videos. Image, Video, and Music 1.0 have no CLI submit command yet.
Written by Sume