Shadow-run gpt-image-2.5 beside your current model before October 23
Render one prompt on a Sume image id and your current model with a separate idempotency key per model, then compare cost and output before gpt-image-1 ends.

A shadow run sends each real prompt to the new model as well as the old one, and keeps only the new result for comparison. On Sume, give every shadow request its own Idempotency-Key, built from the order id and the model id. The same key with a different payload returns 409 idempotency_conflict, and a key shared across models would trigger exactly that.
Run it before OpenAI's gpt-image-1 shutdown on October 23, 2026, while the old model still answers.
What to record
modelas requested andusage.costas billed USD from the response, so cost per model is measured, not guessed.- The
data[0].urlfor each model, so a person can open both. - The HTTP status, since a slow job returns
202and its cost arrives on the job result.
The shadow function
The function returns one row per model id. Wire the old model through your existing client, and only the Sume side is shown.
import json, os, urllib.request
def sume(model, prompt, key):
req = urllib.request.Request(
"https://api.sume.com/v1/images",
json.dumps({"model": model, "prompt": prompt}).encode(),
{"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
"Content-Type": "application/json", "Idempotency-Key": key})
with urllib.request.urlopen(req, timeout=60) as r:
return r.status, json.load(r)
def shadow(order_id, prompt, models):
rows = []
for model in models:
status, body = sume(model, prompt, f"{order_id}:shadow:{model}")
if status == 200:
rows.append((model, body["data"][0]["url"], body["usage"]["cost"]))
else:
rows.append((model, "pending", None))
return rowsCandidates worth shadowing
Pick a winner on your own prompts, then flip the config as in the model-map post. A traffic-percentage version of the same test is in the canary post.
| Sume id | Why it is in the test |
|---|---|
| openai/gpt-image-2.5-sunburst | The vendor's named gpt-image-1 replacement |
| openai/gpt-image-2.5 | Flare, same limits as Sunburst |
| google/nano-banana-2 | Different family, lower list price |
Sources
Related posts
More in Developers
- Shortest and longest values Sume accepts for a Short: one table
Minimum clip, slot, spine and fade values and the maximums for trim, transitions and soundtrack on Sume, in one table with an offline slot checker in Python.
- Shorts season webhooks: a Python receiver that counts episodes
Receive Sume job webhooks for a season of Shorts renders: verify sume-v1, reject an empty secret, de-dupe by job_id, and know when every episode is terminal.
- Sora API gone: 9:16 portrait video on Sume, model by model
Which Sume video models return 9:16 after the Sora API ended on 2026-09-24, how to ask for it, and a script that reads the catalog instead of trusting a table.
- Parse a Sume video poll response with a dataclass, no network
A stdlib Python dataclass for the /v1/videos poll response (status, unsigned_urls, usage.cost, error), tested on sample JSON so a ported client fails early.
Written by Sume