Python 3.14 uuid.uuid7() as a Sume Idempotency-Key: when it is safe
uuid.uuid7() is new in Python 3.14 and makes a tidy Idempotency-Key for Sume submits, if you generate it once per intent and store it. A runnable stdlib sample.

Yes, uuid.uuid7() works as a Sume Idempotency-Key, as long as you call it once per intent, save the value before the first send, and reuse that same value on every retry. The function is new: the Python uuid docs (read 2026-10-10) say it was added in Python 3.14 and follows RFC 9562 section 5.7.
The danger is not the UUID version. It is calling uuid7() inside the retry loop, which turns every retry into a new paid job.
What uuid7 gives you that uuid4 does not
A version 7 UUID starts with a 48-bit timestamp and adds a 42-bit counter, per the Python docs read on 2026-10-10. Two keys made a moment apart sort in creation order, which helps when you read keys back out of your own database or a log and want them in submit order. A version 4 UUID is random and carries no order.
Sume does not care which version you send. The API treats the header as an opaque string tied to the submit, and the job record echoes it back as idempotency_key, which is the column you join on when you need to find a job again after a crash. What matters to Sume is that the same string always means the same request.
A runnable stdlib sample
This file needs Python 3.14 and nothing else. It makes the key once, prints it so you can see what to persist, and retries only on the codes that can succeed later. Note that a 429 queue_full also lands in the retry set here, so keep tries small.
import json, os, time, urllib.error, urllib.request, uuid
BASE = "https://api.sume.com"
RETRYABLE = {408, 429, 500, 502, 503, 504}
def submit(body: dict, key: str, tries: int = 3) -> dict:
req = urllib.request.Request(
f"{BASE}/v1/image-1.0/generate",
json.dumps(body).encode(),
{"x-api-key": os.environ["SUME_API_KEY"],
"Content-Type": "application/json", "Idempotency-Key": key},
)
for attempt in range(tries):
try:
with urllib.request.urlopen(req, timeout=30) as r:
return json.load(r)["data"]
except urllib.error.HTTPError as e:
if e.code not in RETRYABLE or attempt == tries - 1:
raise
except (urllib.error.URLError, TimeoutError):
if attempt == tries - 1:
raise
time.sleep(2**attempt)
key = str(uuid.uuid7()) # once per intent: save it before the first send
print("key", key)
print(submit({"prompt": "Matte black bottle on marble", "mode": "async"}, key))Rules that keep a retry from becoming a second job
The errors page says to retry rate limits with backoff and an idempotency key, and the job docs describe 409 idempotency_conflict when the same key arrives with a different body. Both rules point at the same habit: bind a key to one exact request.
- Create the key where the user intent is created, for example when a row is inserted, and store it on that row.
- Reuse it for every retry of that request, including retries after a process restart.
- Never reuse it for a different prompt or settings. A changed body under the same key gets a 409, and that is the API protecting you.
- A uuid7 holds a creation time. If you do not want submit times visible in logs shared outside your team, use uuid4 instead.
When uuid7 is the wrong tool
If the same business event can be submitted from two machines, a random-looking UUID created on each machine defeats idempotency, because the two keys differ. Derive the key from the business id instead, for example promo-8823-v1, and the second machine sends the same string. Use uuid7() when exactly one place creates the intent.
One more habit pays off: log the key next to the request_id from the error envelope. When support or you must trace a double charge, those two strings connect your row to the API side in one search.
There is also the older-runtime case. Python 3.13 and earlier have no uuid7, so code that must run on both needs a fallback to uuid4, and a version check at startup is clearer than an AttributeError at the first submit.
Sources
Related posts
More in Developers
- Python urllib gets 403 'error code: 1010' from api.sume.com: set a UA
Python's default urllib User-Agent got a plain-text HTTP 403 from api.sume.com in my test while other clients passed. Add a User-Agent and parse errors safely.
- Recover Sume jobs after a crash: match your key to GET /v1/jobs
Your worker died after submit and lost the job ids. Page GET /v1/jobs, match idempotency_key to your own keys, stop at the last page. A 29-line sample.
- Silent reference clip: stt_skipped_silent, no-audio and caption errors
A silent clip does not fail a Sume reference ingest, and STT settles to zero. Video inspect and captions do raise errors on silence.
- Retry or not: a decision table for failed Sume submit calls
Which Sume errors deserve a retry with the same Idempotency-Key, which mean poll the job, and which mean fix the request. One table and a 15-line classifier.
Written by Sume