Let QA override the image model per request, with an allowlist
An internal render endpoint that honors an X-Image-Model header only for allowlisted Sume ids, so QA can test gpt-image-2.5 before the config flips. Python.

Add an optional X-Image-Model header to your own internal render endpoint, and honor it only when the value is on a short allowlist of Sume ids. QA can then test openai/gpt-image-2.5-sunburst against real traffic shapes while the production default still points at the old id. When the test passes, you change the default, and the header stays as a debugging tool.
The allowlist matters because the id goes straight into the model field of POST /v1/images. An unlisted id returns 404 model_not_found, and an unchecked header would let any caller spend your budget on the most expensive id.
Pick the model
The function below is the whole policy. Put it in the handler of your own service, ahead of the call to Sume.
ALLOWED = {
"openai/gpt-image-2.5-sunburst",
"openai/gpt-image-2.5",
"google/nano-banana-2",
}
DEFAULT = "openai/gpt-image-2.5-sunburst"
def choose_model(headers):
asked = headers.get("X-Image-Model")
if asked is None:
return DEFAULT
if asked not in ALLOWED:
raise ValueError(f"model {asked!r} is not on the allowlist")
return asked
if __name__ == "__main__":
print(choose_model({}))
print(choose_model({"X-Image-Model": "google/nano-banana-2"}))
try:
choose_model({"X-Image-Model": "gpt-image-1"})
except ValueError as err:
print(err)Keep the allowlist small
Return the chosen id in the response so QA can see what ran. Do not put sume/auto on the list if the point is a controlled comparison: Sume never discloses the model behind it. The config-file side of this change is in the model-map post, and the traffic-split variant is in the canary post.
| Id | Reason to allow |
|---|---|
| openai/gpt-image-2.5-sunburst | Default replacement for gpt-image-1 |
| openai/gpt-image-2.5 | Flare variant, same limits |
| google/nano-banana-2 | Lower-priced alternative to compare |
Sources
Related posts
More in Developers
- List your transcription jobs: GET /v1/jobs by type, status, cursor
GET /v1/jobs?type=speech_to_text pages 100 jobs at a time, newest first. Join on each row's idempotency_key, not array position, to rebuild a batch.
- Live webinar captions: Sume has no streaming STT, so use chunks
MAI-Transcribe-2-Streaming is $0.54 an hour. Sume STT is $0.60, async and capped at 10 minutes a job. How to caption a webinar recording in chunks.
- Log Sume ratelimit-remaining on every Python urllib response
A urllib handler that logs ratelimit-remaining and ratelimit-reset on each Sume response, warning under 10 percent. It also sees 429 replies.
- Make an AI voiceover louder: generation_config volume and a peak check
Sume TTS takes generation_config.volume from 0.5 to 2. Raise it, then check the WAV peak in Python so you never ship a clipped voiceover.
Written by Sume