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 triedResultWhy
POST /v1/images/edits404The platform has no such endpoint (see below)
POST /v1/images/generations with imageThe reference is ignored (image_tokens: 0) and the output is unrelated to the originalThe gpt-image-2 upstream is a text-to-image surface and never reads the image field
POST /v1/chat/completions with gpt-image-2No channel for that modelgpt-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 an image array and it's image-to-image, omit it and it's text-to-image. So there is no separate /edits route; models that can edit just use /generations.


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 IDDisplay namePrice (per image)How to pass the reference
doubao-seedream-4-0-250828Seedream 4.0$0.029URL or data-URI, size ≥ 960×960
doubao-seedream-4-5-251128Seedream 4.5$0.037URL or data-URI, size must be ≥ 1920×1920
doubao-seedream-5-0-260128Seedream 5.0$0.032URL or data-URI, size must be ≥ 1920×1920
doubao-seedream-5-0-pro-260628Seedream 5.0 Pro$0.044 for output ≤ 2.36 MP, $0.088 above, plus $0.003 per input reference imageURL or data-URI, size ≥ 960×960 is enough
nano-bananaNano Banana$0.039public URL only (no data-URI)
nano-banana-proNano Banana Pro$0.134public URL only (no data-URI)
nano-banana-2Nano Banana 2$0.04URL 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"
}
FieldRequiredNotes
modelany editing-capable model ID from the table above
promptthe 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
nhow 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" } }
      ]
    }]
  }'
PointNotes
Modelgpt-5.4 / gpt-5.5 / gpt-5.6-* (chat models that support the image_generation tool)
streammust be true — turns carrying image_generation are forced to stream
toolsmust explicitly include [{ "type": "image_generation" }]
Reference imagegoes in an image_url block inside the content array; url accepts an https URL or a data:image/...;base64, data-URI
Sizeoptional, 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":"![](https://...generated...)"}}]}

Regex ![](url) out of the accumulated delta.content to get the link.

This route bills by token, not per image: an image_generation turn 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 shapeone synchronous responsestreaming (SSE)
Billingper image (e.g. Seedream 4.5 at $0.04)per token
Images per callup to n (≤10)always 1
Reference images1–10multimodal array, several
Best forfast batch edits with predictable costfine 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-2 for editing — it's text-to-image only and the image parameter does nothing.
  • Don't call /v1/images/edits — the endpoint doesn't exist here (editing goes through /generations with an image array).
  • 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_models allowlist, add the editing model to it first or you'll get a 403.
  • Full image / video / music endpoint documentation: Image / video / music APIs.