Sume 401 halfway through a batch: stop every worker, do not retry
A 401 on a Sume submit means a missing, malformed or revoked key. The SDK does not retry it, and neither should you. Python sample that keeps job ids.

If a batch of image submits starts getting 401 in the middle, the usual cause is a key that was revoked during a rotation. The authentication docs list 401 as a missing, malformed or revoked key and the next step as checking the header and, if necessary, creating a new key. A 403 is different: insufficient_scope means the key was created before the scope you need, and workspace_key_required means a personal key was used on a team Format.
Neither is retryable. The SDK retries only 408, 429, 5xx and transport failures, and a plain loop should follow the same rule.
Stop and keep what you have
The sample treats 401 and 403 as a stop signal and prints the job ids accepted so far. It also builds the idempotency key from the prompt with a hash, so a resumed run after the key is fixed replays instead of duplicating.
import hashlib, json, urllib.error, urllib.request
def submit_all(prompts, key):
done = []
for prompt in prompts:
req = urllib.request.Request(
"https://api.sume.com/v1/images",
data=json.dumps({"model": "ideogram/ideogram-v4.5", "prompt": prompt,
"mode": "async"}).encode(),
headers={"x-api-key": key, "content-type": "application/json",
"idempotency-key": "batch-" + hashlib.sha256(prompt.encode()).hexdigest()[:16]},
)
try:
with urllib.request.urlopen(req, timeout=40) as res:
done.append(json.load(res)["data"]["job"]["id"])
except urllib.error.HTTPError as err:
if err.code in (401, 403): # revoked, malformed or under-scoped key
raise SystemExit(f"stop the batch: HTTP {err.code}; jobs so far: {done}")
raise
return doneStatus triage
| Status | Retry? | Action |
|---|---|---|
| 401 | No | Stop all workers; check the key |
| 403 | No | Fix scope or use a workspace key |
| 402 | No | Add credits, then resume |
| 429 | Yes, after retry-after | Back off; keep the same key |
| 5xx | Yes, with the same key | Backoff and jitter |
Recover cleanly
- Create a new key, verify it with
GET /v1/me, deploy it, then resume. - Jobs the server already accepted keep running; record their ids before the stop so you can poll them.
- Skip prompts whose job ids you stored, and resubmit the rest with their original keys.
- Revoke a key only after the replacement is live.
Sources
Related posts
More in Developers
- Sume SDK idempotencyKey: null sends no key, so POST retries stop
subscribeFormatRun mints a UUID Idempotency-Key by default. Pass null and the create call carries no key, so the SDK will not retry it on a 429 or 5xx.
- Sume SDK maxRetries: 0 when your job queue already retries the call
The SDK retries 408, 429 and 5xx twice by default. Under a queue with five attempts that is up to 15 tries. Set maxRetries to 0 and let one layer retry.
- Sume STT mode sync: transcribe a short clip in one request
Send mode sync with wait_timeout_seconds up to 30. A short clip answers 200 with the finished job. A longer one answers 2xx with the queued job to poll.
- Sume STT to an SRT file: build subtitles from sentence segments
Sume returns timed sentence segments, not an SRT. Turn them into a valid .srt file in Python for YouTube, Vimeo or a player, with the timestamp format.
Written by Sume