Image retry returns 409 idempotency_conflict: new key per payload

A 409 idempotency_conflict on a Sume image job means the same Idempotency-Key was reused with a different payload. Derive the key from the payload in Python.

4 min readSume
All posts

A 409 idempotency_conflict on a Sume image job means you reused an Idempotency-Key for a request that is not the same operation and payload. The generation admission page defines it exactly that way: the same key was reused for a different operation or payload, and the client should reuse keys only for exact retries. If you changed quality, the prompt, or a reference image and kept the old key, you will see this error instead of a new image.

The fix is not to retry harder. It is to give each distinct request its own key, and to give an actual retry (same body, after a timeout) the key it already had. Sume's Jobs and results page says a retried submit with the same key returns the original job instead of billing a second one.

When is the same key correct, and when is it a conflict?

Think of the key as the name of one intended image. Two calls that mean the same image should share it; two calls that mean different images must not.

Key reuse rules. Source: docs.sume.com generation admission and jobs pages, read 2026-10-03.
SituationKeyResult
Client timed out; resend the identical bodySame keyThe original job comes back; no second charge
Submit got 429 queue_full or provider_capacity_exceededSame keyRetry later with the same key
You raised quality from medium to high and resubmitNew keyA new job; reusing the old key returns 409 idempotency_conflict
Same key sent to a different endpoint or modelNew key409 idempotency_conflict

How do I derive a key that follows the payload?

Hash the canonical JSON of the request, and add a version prefix you can bump to force a fresh run on purpose. Identical payloads then map to one key, and any change to the body (including quality) produces another.

import hashlib
import json

def idem_key(payload, version="v1"):
    body = json.dumps(payload, sort_keys=True, separators=(",", ":"))
    return version + "-" + hashlib.sha256(body.encode()).hexdigest()[:32]

a = {"model": "openai/gpt-image-2.5", "prompt": "red mug", "quality": "medium"}
b = {**a, "quality": "high"}
print(idem_key(a) == idem_key(a))  # True
print(idem_key(a) == idem_key(b))  # False

What if I want the same image again on purpose?

Bump the version prefix. That is a new intent, so it gets a new key and a new, billed job. Remember that Sume's image API does not accept seed, so a second run of the same prompt is not guaranteed to match the first; a key replay is the only way to get the original result back.

Check the request_id in the 409 body before you debug further, and log it with your own key. Do not include API keys or signed URLs when you share logs.

What should my retry code do on each status?

Treat 409 idempotency_conflict as a bug in your key logic, not a transient fault: do not loop on it. Log the key and the payload hash, fix the derivation, and resubmit with a key that matches the new body. For 429 and 503 capacity errors, the guidance is the opposite: retry later with the same key.

A related 409 family exists for jobs, such as job_not_cancelable and job_generation_already_started; those say the job is past the point where the operation is valid, and they are unrelated to key reuse.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume