Retry a failed image batch on Sume: not billed, same Idempotency-Key

On Sume a failed image generation is not billed, but a retry after a timeout can double-submit. Send an Idempotency-Key per image and retry only the submit.

5 min readSume
All posts

On Sume, a failed image generation is not billed, and failed requests return 502. A timeout is different: your client does not know whether the job ran. Send an Idempotency-Key that is stable per image, retry the submit with the same key, and the retry returns the original job instead of billing a second one. Do not submit a new paid job for the same intent.

What the docs promise

The Image API page says generation billing is all-or-nothing: a generation is either completed and billed in full, or it fails and is not billed. Failed or cancelled generations are not billed, and requests that end early because the client disconnected are billed as failed generations, meaning not at all.

Jobs and results adds the retry rule: when the wait expires the response is still 2xx, you must continue with GET status_url, you must not submit a new paid job for the same intent, and retrying the submit itself is fine if you reuse the same Idempotency-Key.

What to do when an image call does not return an image (read 2026-10-04)
What you seeBilled?Next step
200 with data[].urlYes, completedStore the URLs
202 job envelopeNot yetPoll status_url, then fetch result_url
502 Bad GatewayNoRetry the submit with the same key
Client timeout or disconnectNot for a failed callRetry the submit with the same key, then poll

A key per image, not per run

Derive the key from your own record: a row id plus the variant number, such as listing-4821-v2. That way a rerun of the whole batch after a crash re-submits the same keys, and Sume returns the existing jobs for images that already went through. A random key per attempt defeats the purpose.

Use async mode for batches so each submit returns fast and the wait lives in your poller. For hundreds of images prefer mode: "webhook" and handle the terminal event on your server, verifying the signature as described in Webhooks.

A safe submit loop

The function below retries only the submit and keeps the key fixed.

import os
import time
import requests

H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}

def submit(key: str, prompt: str, tries: int = 3) -> dict:
    last = None
    for attempt in range(tries):
        try:
            r = requests.post(
                "https://api.sume.com/v1/images",
                headers={**H, "Idempotency-Key": key},
                json={"model": "openai/gpt-image-2.5", "prompt": prompt,
                      "quality": "medium", "mode": "async"},
                timeout=30,
            )
            r.raise_for_status()
            return r.json()["data"]
        except requests.RequestException as err:
            last = err
            time.sleep(2 ** attempt)
    raise RuntimeError(f"submit failed for {key}: {last}")

print(submit("listing-4821-v1", "A linen tote bag on a hook")["status_url"])

Limits

Reusing a key with a different payload is the mistake to avoid: the docs say to reuse the same key only for the same operation. Check the Errors and credits page for what a low balance does to a batch.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume