Image-to-image editing
gpt-image-2 is text-to-image only — for editing an existing image, use the Seedream / Nano-Banana image array, or GPT-5.x chat with the image_generation tool
If you've been trying to edit an existing image with gpt-image-2 and nothing changes — your reference image is ignored, /v1/images/edits returns 404 — that isn't a bug, it's the model's capability boundary. This page explains why, and gives you two working routes.
Why gpt-image-2 can't edit images#
On this platform gpt-image-2 is a pure text-to-image model: it accepts a prompt and does not consume reference images.
| What you tried | Result | Why |
|---|---|---|
POST /v1/images/edits | 404 | The platform has no such endpoint (see below) |
POST /v1/images/generations with image | The reference is ignored (image_tokens: 0) and the output is unrelated to the original | The gpt-image-2 upstream is a text-to-image surface and never reads the image field |
POST /v1/chat/completions with gpt-image-2 | No channel for that model | gpt-image-2 is an image SKU and isn't on the chat endpoint |
About
/v1/images/edits: that was OpenAI's early (DALL·E-2) multipart-only editing endpoint. Here, image-to-image is folded into/v1/images/generations— pass animagearray and it's image-to-image, omit it and it's text-to-image. So there is no separate/editsroute; models that can edit just use/generations.
Route 1: use a model that supports image-to-image (recommended)#
The Seedream and Nano-Banana families support image-to-image natively on the same /v1/images/generations endpoint — put your reference into the image array and it's done in one call.
Models that can edit#
| Model ID | Display name | Price (per image) | How to pass the reference |
|---|---|---|---|
doubao-seedream-4-0-250828 | Seedream 4.0 | $0.029 | URL or data-URI, size ≥ 960×960 |
doubao-seedream-4-5-251128 | Seedream 4.5 | $0.037 | URL or data-URI, size must be ≥ 1920×1920 |
doubao-seedream-5-0-260128 | Seedream 5.0 | $0.032 | URL or data-URI, size must be ≥ 1920×1920 |
doubao-seedream-5-0-pro-260628 | Seedream 5.0 Pro | $0.044 for output ≤ 2.36 MP, $0.088 above, plus $0.003 per input reference image | URL or data-URI, size ≥ 960×960 is enough |
nano-banana | Nano Banana | $0.039 | public URL only (no data-URI) |
nano-banana-pro | Nano Banana Pro | $0.134 | public URL only (no data-URI) |
nano-banana-2 | Nano Banana 2 | $0.04 | URL or data-URI |
Reference-image input formats differ slightly per model, so a publicly reachable https URL is the safest bet (every model accepts one). data-URIs are only accepted by the whole Seedream line and
nano-banana-2.
The request#
{
"model": "doubao-seedream-4-5-251128",
"prompt": "Make the sofa blue, leave everything else unchanged",
"image": ["https://your-host.com/original.png"],
"size": "2048x2048"
}
| Field | Required | Notes |
|---|---|---|
model | ✓ | any editing-capable model ID from the table above |
prompt | ✓ | the edit instruction (describe what you want changed) |
image | ✓ (for editing) | array of reference images, 1–10; omit it and this degrades to text-to-image |
size | "WxH", passed upstream; Seedream 4.5/5.0 require ≥ 1920×1920 | |
n | how many images, default 1, max 10 |
image can also be written as image_urls (equivalent). With several references, the upstream treats the first as the primary edit target and the rest as style or element references.
curl#
curl https://jiuye.zsopc.com/v1/images/generations \
-H "Authorization: Bearer $PLATFORM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedream-4-5-251128",
"prompt": "Make the sofa blue, leave everything else unchanged",
"image": ["https://your-host.com/original.png"],
"size": "2048x2048"
}'
The response#
The same OpenAI Images shape as text-to-image, with data[].url holding the edited image:
{
"model": "doubao-seedream-4-5-251128",
"created": 1765432100,
"data": [{ "url": "https://...", "size": "2048x2048" }],
"usage": { "generated_images": 1 }
}
Route 2: GPT-5.x chat with the image_generation tool#
If you'd rather stay in the GPT pipeline, use the built-in image_generation tool on a gpt-5.x chat model: pass the reference as a multimodal message, and the model looks at the image and redraws it.
The request#
curl https://jiuye.zsopc.com/v1/chat/completions \
-H "Authorization: Bearer $PLATFORM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.5",
"stream": true,
"tools": [{ "type": "image_generation" }],
"messages": [{
"role": "user",
"content": [
{ "type": "text", "text": "Make the sofa in this image blue, leave the rest alone" },
{ "type": "image_url", "image_url": { "url": "https://your-host.com/original.png" } }
]
}]
}'
| Point | Notes |
|---|---|
| Model | gpt-5.4 / gpt-5.5 / gpt-5.6-* (chat models that support the image_generation tool) |
stream | must be true — turns carrying image_generation are forced to stream |
tools | must explicitly include [{ "type": "image_generation" }] |
| Reference image | goes in an image_url block inside the content array; url accepts an https URL or a data:image/...;base64, data-URI |
| Size | optional, written into the tool spec: {"type":"image_generation","size":"1024x1536"}, supporting 1024x1024 / 1024x1536 / 1536x1024 / auto |
The response#
The edited image arrives inline in the streamed body, as markdown image syntax:
data: {"choices":[{"delta":{"content":""}}]}
Regex  out of the accumulated delta.content to get the link.
This route bills by token, not per image: an
image_generationturn carries a fixed overhead of roughly 2,300 input tokens, plus the vision tokens for any reference image (roughly doubling it), with very few output tokens. It suits complex edits that need the model to understand the image before changing it.
Which route to pick#
| Route 1 (Seedream / Nano) | Route 2 (GPT-5.x + tool) | |
|---|---|---|
| Endpoint | /v1/images/generations | /v1/chat/completions |
| Call shape | one synchronous response | streaming (SSE) |
| Billing | per image (e.g. Seedream 4.5 at $0.04) | per token |
| Images per call | up to n (≤10) | always 1 |
| Reference images | 1–10 | multimodal array, several |
| Best for | fast batch edits with predictable cost | fine edits that need image understanding |
For ordinary edits — recolouring, swapping elements, style transfer — prefer route 1: faster, cheaper and predictable.
Limitations#
- Don't use
gpt-image-2for editing — it's text-to-image only and theimageparameter does nothing. - Don't call
/v1/images/edits— the endpoint doesn't exist here (editing goes through/generationswith animagearray). - Image URLs returned by route 1 are upstream pre-signed links that expire in about 24 hours — download and store them promptly.
- If your key has an
allowed_modelsallowlist, add the editing model to it first or you'll get a 403. - Full image / video / music endpoint documentation: Image / video / music APIs.