Retry a Sume video submit safely: Idempotency-Key and the 409 conflict
Send the same Idempotency-Key and the same body to retry a Sume video submit without a second charge. A different body under the same key returns 409.

Add an Idempotency-Key header to POST /v1/videos. If a network error hides the response, resend the same key with the same body, and you get the original job back instead of a second one. If you reuse the key with a different body, Sume answers 409, so a typo cannot silently start a different job.
This matters most for long and expensive jobs, where a duplicate would hold the reserve twice.
What the key does
The docs say an idempotent replay gets the same route and the same price, because the sume/auto resolution is a pure function of the normalized request and the catalog version. The key ties the request to one job.
The key is yours to choose. Use something stable and unique, like an order id plus the shot number.
| Request | Result |
|---|---|
| new key, any body | new job, 202 |
| same key, same body | the original job |
| same key, different body | 409 conflict |
| no key | a new job every time |
A retry in Python
The script retries the submit up to three times on a network error and keeps the same key for each attempt. It stops on an HTTP error, because a 400 or 402 will not change on a retry.
import json, os, time, urllib.error, urllib.request
body = json.dumps({"model": "gemini-omni-flash-1.1",
"prompt": "A paper boat drifting down a rain gutter",
"duration": 5, "resolution": "720p"}).encode()
headers = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
"Content-Type": "application/json", "Idempotency-Key": "boat-shot-001"}
for attempt in range(3):
req = urllib.request.Request("https://api.sume.com/v1/videos",
data=body, headers=headers, method="POST")
try:
with urllib.request.urlopen(req, timeout=60) as r:
print(json.load(r))
break
except urllib.error.HTTPError as e:
print(e.code, e.read().decode())
break
except OSError:
time.sleep(2 ** attempt)Which errors to retry
Retry only when you got no response. A 402 insufficient_credits means the wallet is below the reserve, so add credit first. A 400 means the request is invalid, and the same request fails again. A 429 is rate limiting, so wait before the next try.
A 502 means the provider submission failed, and a retry with the same key is reasonable.
Key hygiene
Never reuse a key for a new shot, even a similar one, or you will get the old job or a 409.
- Build the key from your own record id.
- Keep the body byte-for-byte the same on a retry.
- Store the key with the job id.
- Change the key when you change the prompt on purpose.
Related posts
More in Developers
- Retry a video-trim: same key for the same body, new key for new start
A trim that timed out can be retried with the same Idempotency-Key and body. Changing start, duration or precision is a new operation and needs a new key.
- Rolling a webhook secret: Stripe's 24-hour overlap vs Sume's header
Stripe can keep an old signing secret live for up to 24 hours. Sume sends one sume-v1 entry per live secret; verify any match. Python verifier included.
- Route a Kling video job in Python: scene, motion clip or 30 seconds
A small Python router for Sume: performance copies go to Kling motion control, 4-15 s scenes to kling-3, and longer jobs to a catalog id that lists 30 s.
- Route low-confidence transcripts to review: STT language_probability
Sume STT returns language_code and language_probability. Flag results under a threshold you set and send them to a person. Python, about 10 cents per file.
Written by Sume