AI image model fallback in Python: try the next model on a 502
Image models launch and fail on different days. A Python loop that tries the next Sume model id on 502 or 503, stops on 400, and keeps the 202 job path intact.

To fall back between image models on Sume, loop over model ids and move to the next one only on 502 or 503; stop on 400, 401, 402 and 429 because another model will not fix those. The Image API docs say failed or cancelled generations are not billed and that failed requests return 502, so a retry on a second model does not pay twice.
The alternative is model: "sume/auto", where Sume picks the family for you and does not say which one ran. Use a hand-written list when you care which look you get, or when you want fallbacks to be a model you have tested.
Which status codes should trigger a fallback?
Retry only where a different model could succeed.
| Status | Meaning | Fall back? |
|---|---|---|
| 200 | Image returned | No, done |
| 202 | Still running; job envelope | No, poll the job |
| 400 | Bad field, such as an unsupported parameter | No, fix the request |
| 402 | Insufficient credits | No, add funds |
| 429 | rate_limited or queue_full | No, back off |
| 502 / 503 | Generation failed or provider at capacity | Yes, next model |
What does the loop look like?
Keep the list short and ordered by preference. Different models read the same prompt differently, so log which model produced each image.
import os
import requests
MODELS = ["openai/gpt-image-2.5", "google/nano-banana-2",
"bytedance-seed/seedream-5-lite"]
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
def generate(prompt):
for model in MODELS:
r = requests.post("https://api.sume.com/v1/images", headers=H,
json={"model": model, "prompt": prompt}, timeout=60)
if r.status_code == 200:
return model, r.json()["data"][0]["url"]
if r.status_code == 202:
return model, r.json()["data"]["status_url"]
if r.status_code in (502, 503):
continue
r.raise_for_status()
raise RuntimeError("every model failed")
print(generate("a paper boat on a pond, watercolor"))What can go wrong with fallbacks?
Parameters are per model. A quality: "xhigh" that GPT Image 2.5 accepts is rejected by a model that does not list it, with 400 unsupported_parameter, so a fallback that forwards extra fields can turn one failure into a different one. Keep the fallback request to the fields every model in the list shares, such as prompt and aspect_ratio, and read the catalog descriptors for the rest.
Look also differs. A logo that GPT Image 2.5 rendered cleanly may come back differently from Nano Banana 2, so use fallbacks for drafts and bulk work, not for brand-locked finals.
Limits
A 202 returns a job, not an image, so the caller must still poll status_url. Models can be retired: new rows appear and old ones leave the catalog, so check GET /v1/images/models periodically; the same list drives the fallback ids. This pattern does not cover content-policy rejections, which a second model may also refuse.
Sources
Related posts
More in Developers
- Claude Cost Report API: daily buckets by workspace vs Sume /v1/usage
Anthropic's cost_report endpoint returns USD cost in 1d buckets, groupable by workspace or description. Sume's /v1/usage sums one thread, run or job instead.
- Avatar catalog search: explore mode, seed and diversity
POST /v1/avatar-catalog/search browses reusable avatars. Omit the query for explore mode, pass a seed to keep the order stable, and set diversity from 0 to 1.
- Avatar catalog search returns few results: auto_expand explained
When an avatar catalog search is thin, Sume relaxes filters in a set order and lists them in relaxed_filters. Set auto_expand to false for strict matching.
- Face swap job completed but no video_url: resource_status
For Avatar Face Swap, poll job_status but read the video only when resource_status is ready. How to poll /v1/jobs and fetch the result without an empty URL.
Written by Sume