What is shutting down, and what you can and cannot confirm
OpenAI's image retirement came in two waves. gpt-image-1 shut down on 23 October. gpt-image-1.5, gpt-image-1-mini and chatgpt-image-latest follow on 1 December 2026, and OpenAI names gpt-image-2.5-sunburst or gpt-image-2.5-flare as the replacement for all of them 1. Today is 3 November, so you have 28 days.
I could not re-read OpenAI's own pricing or deprecations pages for this checklist (the pricing page refused the request). The dates, replacements and rates below are as INFRO's October post reports them from OpenAI's pages. Confirm them on OpenAI's pages before you commit a plan, especially the exact hour of the cutoff.
What the post does say about the replacements is useful for planning 1:
- Both are token-priced and share rates, so choosing between them is a quality and latency decision, not a price decision.
- OpenAI describes Sunburst as its most capable model for workflows where editing precision matters most, and Flare as its fastest model for high-quality everyday generation.
- The default
qualityisauto, andxhighandmaxare new values besidelow,mediumandhigh. - OpenAI warns that equal token rates do not mean equal cost per image, because token use differs by model and quality.
That last point matters most for gpt-image-1-mini workloads. They were built on a small model, and the only named destinations are two full-size models. Treat per-image cost as unknown until you have measured it (step 6).
1. Find every pin
A pin is any place that fixes a model id. Most are not in your main service.
- Search code and config for
gpt-image-1.5,gpt-image-1-miniandchatgpt-image-latest. The alias counts: it is a pin to a retiring model. - Search the places code search misses: prompt-template tables, feature-flag payloads, no-code automations, Zapier-style workflows, CMS fields, saved presets in internal tools.
- Search customer-facing settings. If a customer picked "Mini" or "1.5" in a dropdown, or stored it in a saved brand template, you have data to migrate, not just code.
- Check anything that renders again on demand ("make it again", "variations", scheduled re-renders). Existing images you already stored are unaffected, but the next render will come from a different model.
- Check gateway logs for what actually ran in the last 30 days. Logs find the callers nobody remembered.
If you call OpenAI through INFRO, the console marks a retiring model with its shutdown date in the pickers, and an organization that sent the model in the last 30 days gets a model.retiring alert naming the keys and projects that called it 2. INFRO also reads the model list your own provider key returns every three hours and stops offering a model your key stops listing, with the date it stopped. Neither replaces the code search; they cover the callers that search misses.
Then put the id behind one mapping layer, so the next retirement is a config change:
# feature -> model id. One place to change, one place to test.
IMAGE_MODELS = {
"product_hero": "openai/gpt-image-2.5-sunburst",
"social_thumbnail": "openai/gpt-image-2.5-flare",
"avatar_batch": "openai/gpt-image-2.5-flare",
}Verify the exact ids in the model catalog before using them; ids are vendor/model-name 2.
2. Freeze a baseline while the old ids still answer
After 1 December you cannot generate reference outputs from the old model. Do this first.
- Pull 30 to 50 real requests per template or feature from your logs: prompt, size, quality, whether it is an edit with input images, and the template id. Stratify so rare-but-important cases (text in image, transparent background, edits with reference images) are over-represented.
- Run each request on the old id at least three times. The spread between runs of the same model is your noise floor; a candidate is only "different" if it differs by more than that.
- Store the outputs outside any URL that expires. A generated-image link returned through INFRO is a signed link to a copy stored for 24 hours, unless you ask for
b64_json3. Copy the files into your own bucket at once. - Record what each run cost and how long it took, as the response reports it. Image responses carry the estimated provider cost in
usage.cost3.
Do not rely on seeds to make outputs match. The seed field is best-effort, forwarded on generations only and only to providers whose model takes one 3, and a different model will not reproduce the old model's image from the same seed anyway.
3. Test prompt and output parity on candidates
Candidates are at least the two named replacements. If a template depends on something the new models do badly, add one from another vendor; the docs show examples such as google/nano-banana-pro, bfl/flux-2-pro and ideogram/ideogram-3 as ids you can pass 3, and our image model comparison is a starting list. Whatever you add, it needs the same test.
Run the same stored requests on each candidate, with quality and size set explicitly. Setting them matters: on the 2.5 models the default is auto, so a request that omitted quality may now render at another setting 1.
import json, pathlib, time, requests
URL = "https://api.infro.io/v1/images/generations"
HEADERS = {"Authorization": "Bearer " + INFRO_API_KEY}
CANDIDATES = [
"openai/gpt-image-1.5", # baseline, until 1 Dec
"openai/gpt-image-2.5-sunburst",
"openai/gpt-image-2.5-flare",
]
def run(case, model, rep):
body = {
"model": model,
"prompt": case["prompt"],
"size": case["size"], # explicit, never the default
"quality": case["quality"], # explicit: default is now auto
"n": 1,
}
t0 = time.time()
r = requests.post(URL, headers=HEADERS, json=body, timeout=180)
out = {"case": case["id"], "model": model, "rep": rep,
"status": r.status_code, "seconds": time.time() - t0,
"response": r.json()}
pathlib.Path(f"runs/{case['id']}-{model.replace('/', '_')}-{rep}.json").write_text(json.dumps(out))
return outUse a long timeout. OpenAI's image guide still warns that complex prompts can take up to two minutes 1, and the INFRO docs say the highest-quality models can take up to a minute 3.
Score in two layers.
Hard checks, automated. These fail or pass without opinion:
- Output dimensions and aspect ratio match what the template needs.
- File format, and for transparent templates an actual alpha channel. The pages read do not say whether the 2.5 models keep your current
background: "transparent"behaviour with png or webp, so test it 1. - Text in the image: run OCR on the expected string for templates that print a name, price or slogan.
- Edit calls: if you set
input_fidelityon gpt-image-1.5 edits, test what the 2.5 models do with it. OpenAI's guide says to omit it for gpt-image-2 because every input is processed at high fidelity 1. - Refusal and error rate, latency p50 and p95.
Soft checks, reviewed. Layout, brand feel, faces, hands, product shape. Have two people do a blind side-by-side on a sample, or use a model grader you have calibrated against people first; see how to calibrate an LLM judge and the fallback method in is your fallback good enough.
Parity here means the template still does its job, not that the picture is the same. Expect different composition. Where a template hard-codes style words tuned to the old model, expect to edit the prompt; keep the edited prompt under version control next to the model id it was tested with.
4. Wire an image fallback
A fallback protects you from an outage or a rate limit on the primary. It does not protect the look of a brand template, so decide per feature whether a different model's output is acceptable.
How it works through INFRO: connection failover tries the same model on another of your connections, and model fallbacks are an ordered list of up to five catalog model ids, tried once every connection for the primary has failed before the first token. Both apply to image requests, and the response names the model, provider and connection that served it 4 3.
{
"model": "openai/gpt-image-2.5-flare",
"prompt": "...",
"size": "1024x1024",
"quality": "medium",
"fallbacks": ["openai/gpt-image-2.5-sunburst"]
}Things that bite:
- A fallback target must accept the request. A
qualityorresolutionthe model cannot render on a target is refused before that target is called, and a known model with no connection that can serve it right now is skipped 3 4. Grok Imagine, for instance, takes onlylowormedium3, so ahighrequest cannot land there. - A fallback to another vendor changes the look. Put brand-critical templates on a same-vendor list and let throwaway features fall back more widely.
- Fallbacks apply when
modelnames a model; when it names a route, the route's own targets are used 4. Pick one style per feature. - Test the fallback target through the full parity run in step 3, not just a smoke call.
Drill it in staging before 1 December: list an id your key does not serve as the primary, confirm the request is served by the fallback, and confirm the serving model is in the response and your logs. More on drills is in failover drills.
5. Do not count on a redirect on the day
Through INFRO, from 00:00 UTC on a shutdown date a request for a retired model is refused before any provider call with 404 model_not_found and code model_shut_down, naming the date and the replacement. INFRO never answers with a different model on your behalf 2. That is the behaviour you want, because a silent swap would change output and cost without a trace.
It also means the cutover is your change. A good order:
- Merge the mapping layer (step 1) with the old ids still in it.
- Switch staging to the replacements and run the parity suite there.
- Move production by feature, lowest-risk first, using a weighted route or an if-rule on the feature, so a small share runs on the new model before the rest.
- Watch error rate, latency and cost per image for each feature for a few days.
- Remove the old ids and the dropdown options at least a week before 1 December, so the last week is for fixing, not for finding.
6. Estimate cost before the cutoff
Per-image prices for the old models were a lookup by quality and size. For the replacements, rates are per token, so cost depends on tokens consumed. The post gives $5 per million text input tokens, $8 per million image input tokens and $30 per million image output tokens for both, with image output at $15 under Batch, and notes OpenAI's GPT Image 2 calculator does not estimate 2.5 token use 1. Those are what your OpenAI account is billed at list; your contract may differ.
So measure instead of calculating:
- Take the parity run from step 3 and read the cost and usage of every response, per template and quality. Use the median and p95, not the mean of three.
- Multiply by last month's real volume per template to get a monthly figure per feature.
- Enter your contract rates if you have them. INFRO can use negotiated rates, entered per model, before the vendor's list rate when it estimates cost.
- Ask for an estimate before a request when a customer-facing feature needs one; the docs list
POST /v1/estimatesfor cost estimates before a request, with its own section on the billing page 5 6. - Set a project budget on image traffic before cutover, with alerts at your own thresholds, so a quality setting that costs more than expected stops at a ceiling rather than at an invoice.
The point of the sheet is the right-hand column per feature, not a single average. A cost change of this kind arrives with no error, so also watch the cost per image after cutover; INFRO's records show estimated provider cost per request, queryable by project and key 5, and you can reconcile with your OpenAI invoice at month end.
What INFRO does here, in one paragraph
If your image traffic already runs through INFRO, the pieces above are features you configure on your own OpenAI connection: the image endpoints with one request shape, model fallbacks and routes, retirement warnings and the model_shut_down refusal, estimated cost per request, and budgets. INFRO takes 0% of model spend; OpenAI bills you directly 6. None of it does the parity judgement for you, and INFRO sees request metadata rather than judging the image.
Dated plan
- By 7 Nov: inventory complete, mapping layer merged, baseline outputs stored.
- By 14 Nov: candidates run through the hard checks and the blind review; prompt edits committed.
- By 18 Nov: fallbacks configured and drilled in staging; cost sheet per feature done; budgets set.
- By 21 Nov: production moved feature by feature behind a weighted route.
- By 24 Nov: old ids and customer-facing options removed; stored customer settings migrated.
- 30 Nov: confirm no request for the old ids appears in your logs for 7 days.
- 1 Dec: shutdown. Expect refusals for any id you missed.
