Format run retry: same key and body gives 200, changed body 409
Retrying POST /v1/formats/{handle}/{slug}/runs with the same idempotency_key and body returns the first run; a changed body or a parallel duplicate returns 409.

If your client retries a Format run after a timeout, send the same idempotency_key with the byte-for-byte same body. Sume returns 200 with an idempotency_hit marker and the original receipt instead of starting a second run. Change the body under the same key and you get 409 idempotency_conflict; send a duplicate while the first request is still being created and you get 409 idempotency_key_in_use. Keys are scoped per Format, so one key can safely be reused across two different Formats.
A fresh run is accepted with 202 and a receipt that carries an arun_ id plus status_url, result_url, events_url and cancel_url. Store the receipt id the moment you have it; it is what you poll later. See Call a Format for the request fields.
What each retry outcome means
| Second request | Status | What to do |
|---|---|---|
| Same key, same body | 200 with idempotency_hit | Use the returned receipt; no new run started |
| Same key, different body | 409 idempotency_conflict | Pick a new key for the new request |
| Same key while first is still being created | 409 idempotency_key_in_use | Wait a moment and repeat the identical request |
| Different key, same body | 202 | A second, separately billed run |
A safe retry wrapper
Derive the key from your own job id, not from a timestamp, so a restart of your worker repeats the same key.
curl -X POST https://api.sume.com/v1/formats/sume/sume-product-commercial/runs \
-H "x-api-key: $SUME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"instruction": "15-second product commercial, clean studio light.",
"idempotency_key": "order-4812-commercial-v1",
"generation_spend_cap_usd": 20
}'Why not just retry blindly?
A Format run is unattended and can spend money. Without a key, a client that times out and retries starts two runs. With the key the retry is a read. If you do want a deliberate second take, change the key.
Sources
Related posts
More in Formats
- Webhook or polling for Sume Format runs, and the 1 MiB payload rule
Pick between the signed terminal webhook and polling status_url for Sume Format runs: delivery limits, dedupe keys, and what a payload over 1 MiB looks like.
- Format structured output: anyOf passes, oneOf and allOf are rejected
Which JSON Schema keywords a Sume Format output_schema accepts, the 400 output_schema_invalid shape, and how it lines up with OpenAI strict structured outputs.
- Format output filled_by: agent versus projection, exact URLs
Sume Format runs fill structured output either through the agent or by projection. Learn which one ran, what projection can see, and the exact-URL gate.
- Sume webhook missed? POST /v1/format-runs/{run_id}/webhook/redeliver
Replay a Format run webhook without rerunning: the redeliver endpoint, the formats:write scope, and the two 409 errors for no webhook or a run still going.
Written by Sume