Developers

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.

5 min readSume
All posts

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 uuidgen per 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_key also 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:

Format run replays, from Create a run, read 2026-09-25.
ReplayResult
Same key, same body200 with the original receipt and idempotency_hit: true. No second run, no second charge.
Same key, different body, including a different instruction or attachment list409 idempotency_conflict. Nothing runs.
Same key, two requests at the same momentOne 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.

From Create a run, Agent Completions, Jobs and results, Video Generation, and MCP tools and gates, read 2026-09-25.
SurfaceHow to send itOn replay
Format runsIdempotency-Key header on every create200, the original receipt, idempotency_hit: true
Agent CompletionsIdempotency-Key headerThe original receipt with idempotency_hit: true
Generation job submitsIdempotency-Key headerThe original job instead of a second bill
POST /v1/videosIdempotency-Key headerThe original job
Hosted MCP write and paid toolsidempotency_key argument, requiredUsed 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}/status with exponential backoff, honoring next_poll_after_seconds when present. A job created on /v1/videos is visible there too.
  • A sync submit that runs out of wait budget still returns 2xx with the job id. Continue with status_url.
  • On the hosted MCP server, jobs_wait holds at most 55s per call. On wait_slice_expired, or a 524 transport failure, call jobs_wait again on the same ids; never resubmit the paid create.
  • A client-side timeout cancels nothing. POST /v1/jobs/{id}/cancel does, 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

Written by Sume