Two different questions lead here, so both answers come first.
If you are building with the OpenAI API, the public Images API has exactly two live endpoints as of October 9, 2026: POST https://api.openai.com/v1/images/generations for an image from a prompt and POST https://api.openai.com/v1/images/edits for changing or extending images you already have. POST /v1/images/variations is retired. The third route, the image_generation tool inside the Responses API, is for conversations and multi-step flows where a text model decides when to draw. The current model IDs are gpt-image-2.5-sunburst (editing precision) and gpt-image-2.5-flare (fast everyday generation); gpt-image-1 shuts down on October 23, 2026 and gpt-image-1.5 on December 1, 2026.
If what you have is a ChatGPT gen_id (or parent_gen_id, referenced_image_ids, or a file-service:// asset_pointer) and you are looking for the endpoint that downloads or retrieves that image: there is none. Those are fields of ChatGPT's internal image_gen tool, no public API endpoint accepts them, and the API itself never hands out an id you could fetch bytes with later, because GPT Image models return every image inline as base64. The image you want is in one of three places: the ChatGPT conversation or Library (download button), a ChatGPT data export, or a fresh API generation that you store yourself. The gen_id section below walks through each.
Which OpenAI image endpoint to call: the current map

The image generation guide describes "two main ways" to generate or edit images and recommends the Image API when you only need a single image from one prompt. The Images API reference lists the raw endpoints. Put together, the routing looks like this:
| Job | Route | Raw path or SDK call | What goes in model | Pick it when... | Mistake to avoid |
|---|---|---|---|---|---|
| Generate one image from a prompt | Images API | POST https://api.openai.com/v1/images/generations, client.images.generate() | gpt-image-2.5-sunburst or gpt-image-2.5-flare (required, no default) | You want the shortest path to a working request | Leaving model empty, or sending a retired id such as dall-e-3 |
| Edit, combine or extend images you already have | Images API | POST https://api.openai.com/v1/images/edits, client.images.edit() | Same two IDs; gpt-image-2.5-sunburst is the default here | You have input images, up to 16 for GPT Image models, optionally a mask | Looking for /v1/images/variations; it is retired, edits with a prompt replaces it |
| Generate images inside a conversation or agent flow | Responses API with the image_generation tool | client.responses.create() with tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }] | Top level: a current mainline text model (gpt-5 family or newer per the guide); image model goes in the tool object | The same request may return text and images, or edits chain across turns | Putting gpt-image-2.5-sunburst in the top-level model field |
| Fetch an image generated earlier by its id | None | — | — | — | Expecting a GET /v1/images/{id}; the reference has no retrieval endpoint, and ChatGPT's gen_id is not an API id |
The last row is the common surprise. Both API routes return the image inline, so storing the bytes is your job and happens at the moment of the response. The next section covers what that means when the image was made in ChatGPT instead of through your own code.
ChatGPT gen_id download or retrieve endpoint: there is none
No public endpoint accepts a gen_id and returns an image, not under https://api.openai.com/v1/images/..., not in the Responses API, and not anywhere else in the API reference. That is not a missing docs page. It follows from how the two systems work:
gen_idis a ChatGPT product field, not an API field. When ChatGPT draws, it calls an internal tool namedimage_gen. The tool call carries metadata such asgen_id,parent_gen_id(the generation this one was edited from) andreferenced_image_ids(images the new generation should use as references). In Reddit threads from late 2023 and 2024, the DALL·E 3 era, users asked ChatGPT for an image'sgen_idand pasted it into later prompts for consistency, which is why the field feels like an identifier you should be able to call. It only has meaning inside ChatGPT.- The API never issues a fetchable id either. On
/v1/images/generationsand/v1/images/edits, GPT Image models return the image asdata[].b64_json; theurlresponse format is "Unsupported for GPT image models, which always return base64-encoded images" (reference). There is nothing to retrieve later because the bytes were already in the response. - Asset pointers are storage internals. Third-party write-ups of ChatGPT exports describe images stored behind
file-service://file-...asset pointers, withgen_idas metadata next to them, and image links onbackend-api/files.oaiusercontent.comas temporary signed URLs that return 422 when query fields are dropped and 404 once they expire. OpenAI does not document any of this, so treat it as a description of behavior, not a contract.
Here is where the image actually is on each surface, and what you can do from there:
| Surface | Where the image bytes are | What identifier exists | What you can do with it |
|---|---|---|---|
| ChatGPT conversation and Library (web, desktop, mobile) | Rendered in the chat; served through links that expire (reports) | gen_id, parent_gen_id, referenced_image_ids, asset_pointer inside the image_gen call | Download from the UI; reference it in the same chat; nothing callable from code |
| ChatGPT data export ZIP | Reports: image files in the archive, matched by the file-... id in conversations.json (image_asset_pointer); the help page itself only promises "chat history and other relevant account data" | Same ids as above, now in JSON you can parse offline | Match pointers to files with a script; one-time bulk recovery |
Images API response (/v1/images/generations, /v1/images/edits) | Inline, data[].b64_json | None you can query later; created timestamp and usage counters only | Decode, store, and assign your own id at response time |
| Responses API output | Inline, result (base64) on an image_generation_call item | The item id (ig_...) and the response id | Chain edits with previous_response_id; still store the bytes yourself |
Download it from the ChatGPT conversation or Library
If the chat still exists, this is the ordinary route: open the conversation or the Library view, select the image, and use the download control. That is the supported way to get a single ChatGPT-generated image out of ChatGPT. Copying the image URL out of the browser's network panel is not a substitute; those links are the expiring signed URLs described above, and nothing you can store will keep working.
Pull it from a ChatGPT data export
For many images, or when the chat is hard to find, request a data export. Per the help center: Settings → Data controls → Export data (or the Privacy Portal); available on Free, Go, Plus, Pro and eligible Edu accounts but not Business, Enterprise or Healthcare workspaces; the export "can take up to 7 days"; the download link expires 24 hours after you receive it; deleted chats cannot be restored. OpenAI's text says the ZIP "includes your chat history and other relevant account data" and does not list image files explicitly. Third-party accounts of real exports report that conversations.json contains image_asset_pointer entries whose file-... id matches asset files shipped in the archive, which is what makes a bulk recovery script possible. Plan for that but verify against your own archive, since the official page does not promise it.
Regenerate through the API and store the bytes yourself
If the image is gone, or you wanted a programmatic pipeline in the first place, the fix is not to find a hidden endpoint but to move the work to the API, where storage is explicit. A minimal Node example that generates one image and keeps it under an id you control:
import fs from "node:fs/promises";
import { randomUUID } from "node:crypto";
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const result = await client.images.generate({
model: "gpt-image-2.5-flare",
prompt: "A flat-color icon of a paper airplane on a white background",
size: "1024x1024",
quality: "medium",
output_format: "webp",
});
// The API gives you bytes, not a retrievable id. Assign your own.
const imageId = `img_${result.created}_${randomUUID()}`;
await fs.writeFile(`./images/${imageId}.webp`, Buffer.from(result.data[0].b64_json, "base64"));
console.log(imageId, result.usage); // keep prompt + usage next to the file for later editsStore the prompt and the file together; that pair is what lets you do later the thing referenced_image_ids does in ChatGPT.
backend-api gen_id endpoints are ChatGPT's private interface, not an API
The backend-api paths that show up in a browser's network panel next to a ChatGPT image, and in gen_id discussions, are the paths the ChatGPT web client calls behind the scenes. They are not part of the OpenAI API, are not documented, and are not covered by API keys, terms or stability guarantees; they change without notice, and their image links are the short-lived signed URLs described above. Nothing built on them can be relied on, which is why there is no "backend-api gen_id endpoint" to recommend. The supported equivalents are the three routes above: UI download, data export, or the public API.
referenced_image_ids, parent_gen_id and gen_id mapped to API fields
If you went looking for referenced_image_ids image editing docs in the OpenAI API documentation, there is no page to find: referenced_image_ids is a ChatGPT tool field, not an API parameter. The capability exists in the API under different names. Use this mapping to translate a ChatGPT workflow into API calls:
| ChatGPT field or name | What it means inside ChatGPT | Closest API mechanism |
|---|---|---|
gen_id | Identifier of one generated image within the image_gen tool call | Responses API: the id on the image_generation_call output item (placeholder ig_123 in the docs). Images API: none; assign your own at response time |
parent_gen_id | The generation the current image was edited from (a chain of edits) | previous_response_id on the next responses.create call, or pass the earlier image_generation_call item ({"type":"image_generation_call","id": ...}) as an input item |
referenced_image_ids (also written reference_image_ids) | Earlier images the tool should use as references for a new picture | POST /v1/images/edits with those images in image (up to 16, as base64 or file IDs, optional mask); or Responses multi-turn with the image already in context and action: "edit" |
asset_pointer (file-service://file-...) | Internal storage pointer to the file | The bytes themselves: data[].b64_json (Images API) or result (Responses) that you store |
image_gen | ChatGPT's internal tool name | Tool type image_generation in Responses; the two Images API endpoints for direct calls |
backend-api | Private web client interface | Public endpoints under https://api.openai.com/v1/ |
Two documentation pages hold everything on the right-hand side: the Images API reference for /v1/images/edits parameters and the image generation tool guide for previous_response_id, action and the image_generation_call item. If you were hoping for "ChatGPT API" image editing, ChatGPT API Generate Image: Use OpenAI Images API explains why that product does not exist as a separate endpoint.
Start with POST /v1/images/generations for one-shot image output
For a fresh integration this is the right first proof that the key, project and payload shape work. The Images API reference lists POST /images/generations, which you call as https://api.openai.com/v1/images/generations from your backend. The reference says to specify a model explicitly; there is no default on this endpoint. As of October 9, 2026 the guide names two current models: gpt-image-2.5-sunburst when editing precision matters most and gpt-image-2.5-flare for fast everyday generation.
curl https://api.openai.com/v1/images/generations \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2.5-sunburst",
"prompt": "Clean editorial illustration of a robot camera operator in a bright studio",
"size": "1024x1024",
"quality": "medium",
"output_format": "png"
}'Parameters that matter on the first call, per the reference: size is auto, 1024x1024, 1536x1024 or 1024x1536 (the gpt-image-2 family also accepts a free WIDTHxHEIGHT); quality is low, medium, high or auto, with xhigh and max only on the gpt-image-2.5 models; output_format is png (default), jpeg or webp, with output_compression 0–100 for the latter two; background: "transparent" needs png or webp; n is 1–10; partial_images 0–3 with stream; moderation is auto or low; the prompt can be up to 32,000 characters. GPT Image models do not return revised_prompt on this endpoint.
The response carries data[].b64_json, plus usage (input_tokens, output_tokens, input_tokens_details.image_tokens / text_tokens, total_tokens) and the resolved background, output_format, quality and size. A successful first test therefore means more than a 200: your code decoded the base64 and wrote a file you can open. Copy-ready request bodies for both endpoints are in OpenAI Image Generation API cURL: Current Generate and Edit Requests; the same calls in Python and JavaScript are in OpenAI Image Generation API Example: Current JavaScript, Python, and cURL.
Use POST /v1/images/edits when you already have source images

Many jobs that start as "generate an image" turn out to be edit jobs: a product shot to restage, a reference character to keep consistent, a canvas to extend. That stays on the direct Images API, on the edit branch. The reference lists POST /images/edits with gpt-image-2.5-sunburst as the default model, up to 16 input images for GPT Image models, an optional mask given as image_url or file_id, and input images supplied as file IDs or base64.
import fs from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const result = await client.images.edit({
model: "gpt-image-2.5-sunburst",
image: [fs.createReadStream("product-shot.png"), fs.createReadStream("shelf-reference.png")],
prompt: "Keep the product shape and label; place it on the shelf from the second image with warm lighting",
input_fidelity: "high",
});Three details from the reference and guide decide whether this request behaves:
input_fidelityishighorlow;gpt-image-1-minionly supportslow, and forgpt-image-2you should omit it, because that model always runs at high fidelity (and reference-image edits may therefore use more input tokens).gpt-image-2sizes are bounded: longest edge 3,840 px, both edges multiples of 16, aspect ratio no wider than 3:1, total pixels between 655,360 and 8,294,400. The guide excerpt does not restate these for the 2.5 models, so check the model page before relying on them there.- Variations are gone. If an old snippet calls
/v1/images/variations, the reference now says "This endpoint is retired and no longer available"; send the source image to edits with a prompt describing the variation you want.
In ChatGPT terms, the image array is your referenced_image_ids. For the fidelity-versus-cost question and multi-image compositing patterns, see OpenAI Image Editing API: GPT Image 2 Edits and Variations.
Only move to Responses when image generation is one part of a larger flow
Responses is the right route when the image step is not the whole product: a model reads instructions, maybe inspects context or calls other tools, and sometimes draws. The image generation tool guide adds {"type": "image_generation", "model": "gpt-image-2.5-sunburst"} to tools, and the top-level model is a mainline text model. The guide says the tool requires "gpt-5 or a newer model"; the tool page lists a wider set of mainline models, so use a current gpt-5-or-newer model and confirm support on its model page rather than assuming an older one works.
import fs from "node:fs/promises";
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const first = await client.responses.create({
model: "gpt-5.5", // mainline text model; the image model lives in the tool object
input: "Draw a sticker-style icon of a paper airplane for a travel app",
tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst" }],
});
const call = first.output.find((item) => item.type === "image_generation_call");
await fs.writeFile("airplane.png", Buffer.from(call.result, "base64"));
console.log(call.id); // ig_... — the only API-side "generation id"
// Edit in the next turn: this is what parent_gen_id does in ChatGPT
const second = await client.responses.create({
model: "gpt-5.5",
previous_response_id: first.id,
input: "Same icon, but make the airplane red and add motion lines",
tools: [{ type: "image_generation", model: "gpt-image-2.5-sunburst", action: "edit" }],
});What the tool gives you that the direct endpoints do not: a revised_prompt on the output item, action (auto / generate / edit; edit with no image in context errors), streaming of 1–3 partial_images through response.image_generation_call.partial_image events, tool_choice: {"type": "image_generation"} to force a draw, and the ig_ item id you can pass back as an input item instead of previous_response_id. What it costs you: the mainline model's tokens are billed on top of the image tokens, and debugging goes through tool output parsing. If orchestration is not the job yet, the direct endpoints remain the better first move; the broader walkthrough is OpenAI Image API Tutorial: Images API vs Responses API.
Model IDs to use now, and the gpt-image-1 and gpt-image-1.5 shutdown dates
The reference's model enum still lists every id the endpoints have ever accepted, including ones that no longer run, so "it's in the enum" is not the same as "it works." The deprecations page, as of October 9, 2026:
| Model ID | Status | Shutdown date | Recommended replacement |
|---|---|---|---|
gpt-image-2.5-sunburst, gpt-image-2.5-flare (and -2026-09-08 snapshots) | Current | — | — |
gpt-image-2 (gpt-image-2-2026-04-21) | Available, not listed as deprecated | — | — |
gpt-image-1 | Deprecated (announced April 22, 2026) | October 23, 2026 | gpt-image-2.5-sunburst or gpt-image-2.5-flare |
gpt-image-1.5, gpt-image-1-mini, chatgpt-image-latest | Deprecated (announced June 2, 2026) | December 1, 2026 | gpt-image-2.5-sunburst or gpt-image-2.5-flare |
dall-e-2, dall-e-3 | Shut down | May 12, 2026 | gpt-image family |
Two notes on that table. chatgpt-image-latest is described on its model page as the "Previous image model used in ChatGPT", and the page recommends GPT-Image-2.5 Sunburst for API use; if you were choosing it to match what ChatGPT draws, it no longer does that, and it stops on December 1, 2026 anyway. And earlier GPT Image models cap quality at high; xhigh and max exist only on the 2.5 models, so a payload tuned for 2.5 can fail on an older id for a reason that has nothing to do with the endpoint.
When a correct endpoint still returns an error, check in this order before touching the URL:
- Model id: retired (
dall-e-3), about to retire (gpt-image-1), or placed on the wrong surface (an image model in the top-level Responsesmodel). moderation_blocked: the error code for refused content, withmoderation_details.categoriesandmoderation_stage(inputoroutput). Rewording the prompt fixes this; switching endpoints does not.- Parameters the model does not accept:
xhigh/maxon a pre-2.5 model,input_fidelityongpt-image-2, a free-form size on a model that only takes the fixed set. - Account state: if the error text is about organization verification, see Fix GPT Image 2's 'Your organization must be verified' Error.
Model-by-model trade-offs are in OpenAI Image Generation API Models: Which One Should You Use in 2026?; if the failure is on the ChatGPT side rather than the API, ChatGPT Image Generation Not Working? Check Status, Fix the Right Branch, and Stop Wasting Retries covers that branch.
GPT Image 2.5 cost per call: token rates, not a flat price
Both routes bill the same image tokens, but the totals differ. Per the image generation guide, GPT Image 2.5 is priced at $8 per million image input tokens, $2 per million cached image input tokens, $30 per million image output tokens, $5 per million text input tokens and $1.25 per million cached text input tokens, and the guide warns that "Equal token rates don't mean equal cost per image." Three consequences for endpoint choice:
- Cached input pricing applies only through the Responses tool. A direct
/v1/images/editscall that re-sends the same reference images pays full input price every time; a Responses conversation that carries the image in context can hit the cached rate. Responses also bills the mainline model's tokens, so it is not automatically cheaper. - Output tokens scale with quality. The guide gives 272, 1,056 and 4,160 output tokens for a 1024×1024 image at
low,mediumandhighon earlier GPT Image models; those are the earlier models' figures, so measureusage.output_tokenson your own 2.5 calls before budgeting. - Streaming adds cost. Each
partial_imagesframe adds 100 output tokens.
For a fixed per-image reference point while it lasts, chatgpt-image-latest lists $0.009 (low), $0.034 (medium) and $0.133 (high) per 1024×1024 image on its model page, but it shuts down on December 1, 2026. Per-image budgeting for the current models, with worked examples, is in GPT Image 2 API Pricing: Cost per Image and Project Budget.
FAQ: gen_id, referenced_image_ids and endpoint errors
Can I download a ChatGPT image through the OpenAI API if I have its gen_id?
No. gen_id belongs to ChatGPT's internal image_gen tool, and no public endpoint accepts it. The API also never returns an id you could fetch bytes with later; /v1/images/generations and /v1/images/edits return the image inline as b64_json. Download the image from the ChatGPT conversation or Library, request a data export, or regenerate it through the API and store the result yourself.
Where are the referenced_image_ids image editing docs?
There is no API documentation page for referenced_image_ids because it is not an API parameter. The equivalent is the image array on POST /v1/images/edits (up to 16 images, base64 or file IDs, optional mask), documented in the Images API reference, or a Responses multi-turn edit with previous_response_id, documented in the image generation tool guide.
Does parent_gen_id have an API equivalent?
Yes, in the Responses API: pass previous_response_id from the response that produced the image, or include the earlier image_generation_call item id as an input item, and set the tool's action to edit. On the direct Images API the chain is yours to keep: store each output with your own id and send it back as an input image for the next edit.
Do I need Responses for ordinary image editing?
No. POST /v1/images/edits with gpt-image-2.5-sunburst (the default there) handles edits, multi-image composites and masked changes directly. Responses is the better fit only when the image step sits inside a conversation or agent flow.
Should I still send gpt-image-1 or gpt-image-1.5?
Only until their shutdown dates. The deprecations page lists gpt-image-1 for October 23, 2026 and gpt-image-1.5, gpt-image-1-mini and chatgpt-image-latest for December 1, 2026, with gpt-image-2.5-sunburst or gpt-image-2.5-flare as the replacement. Switch the model string now; the endpoints and request shape stay the same.
Why can a correct endpoint still fail?
Because the model id, the parameters and the content are checked separately from the path. A retired id, xhigh on a pre-2.5 model, input_fidelity on gpt-image-2, or a moderation_blocked refusal all fail on a perfectly correct https://api.openai.com/v1/images/generations call. Fix the payload or prompt; changing endpoints is rarely the answer.



