---
title: Image Editing API: GPT Image 2 vs Nano Banana 2
description: "Image editing API guide: build a production edit workflow on GPT Image 2 or Nano Banana 2 — reference contracts, cost math, validation, safe retries."
url: https://apitoken.sale/docs/learn/image-editing-api-guide
language: en
---

# Edit images through GPT Image 2 or Nano Banana 2

GPT Image 2 exposes a multipart edit route: PNG, JPEG or WebP in, one base64 PNG out. Nano Banana 2 treats references as native multimodal input — more formats, more images, explicit sizes. Choose by the reference contract your pipeline can validate, and bill on terminal usage.

## Pick the route your reference contract can satisfy

An image edit is a generation request that carries reference images as billable input plus a prompt naming the one change you allow. A single prepaid apiToken.sale key reaches both production edit routes: GPT Image 2 on the OpenAI Images edits endpoint, which takes one to five PNG, JPEG or WebP references (each ≤50 MB) and returns one non-streaming base64 PNG, and Nano Banana 2 — model gemini-3.1-flash-image — on the native Gemini generateContent route, which accepts up to 14 references in PNG, JPEG, WEBP, HEIC or HEIF and answers with an inlineData image part. Decide by the reference contract your application can validate, not by brand preference.

| Capability | GPT Image 2 | Nano Banana 2 |
| --- | --- | --- |
| Route | POST /v1/images/edits (multipart) | generateContent with inlineData parts |
| References | 1–5 | up to 14 |
| Input files | PNG, JPEG, WebP; each ≤50 MB | PNG, JPEG, WEBP, HEIC, HEIF |
| Output | one non-streaming base64 PNG | image inlineData part |
| Region inpaint | POST /v1/responses image_generation (+ jpeg/webp, partial_images) | prompt + reference parts on generateContent |
| Published controls | background opaque or transparent, quality low, size as proportion (auto/1:1/3:2/2:3/4:3/16:9/9:16) | 1K/2K/4K + published aspect ratios |

> The two protocols are not interchangeable. A client written for the OpenAI Images schema cannot parse a Gemini inlineData response. GPT Image 2 edits accept PNG, JPEG or WebP under 50 MB and still return one PNG. Commit to a route per asset class at design time; switching protocols inside a retry loop corrupts both output parsing and cost attribution.

## The GPT Image 2 edit: PNG, JPEG or WebP in, one base64 PNG out

The edits endpoint is multipart form data: model, prompt and one image field per reference. The published profile is background opaque or transparent, quality low, and size as a proportion (auto, 1024x1024/1:1, 1536x1024/3:2, 1024x1536/2:3, 4:3, 16:9, 9:16). The response is a single JSON document whose data array holds one base64-encoded PNG. 2K/4K and other pixel sizes are rejected.

```
curl https://router.apitoken.sale/v1/images/edits \
  -H "Authorization: Bearer $APITOKEN_API_KEY" \
  -F "model=gpt-image-2" \
  -F "prompt=Replace only the background with a neutral studio backdrop; keep the product untouched" \
  -F "image=@reference.png;type=image/png" \
  -F "background=opaque" \
  -F "quality=low" \
  -F "size=auto"
```

> Repeat the field name image for each reference, or send image[]. Multipart mask is ignored on /v1/images/edits; inpaint uses Responses input_image_mask.

```
// Response (abridged): decode data[0].b64_json into a PNG file.
{
  "data": [
    { "b64_json": "<BASE64 PNG>" }
  ]
}
```

Decoding the payload does not finish the request. Store the request ID and the terminal usage next to the source and result files: PNG byte size is not the billing formula, the terminal usage event is the billing authority, and it is what the dashboard charge reconciles against.

## Region inpaint: Responses mask, not Images mask

A multipart mask field on POST /v1/images/edits is rejected. That OpenAI Images shape is not available on this ChatGPT pool. To change only part of a picture — or to run hosted image_generation from a GPT text model — call POST /v1/responses (Chat Completions maps the same tool): put the source PNG in input as input_image, and add tools: [{type:"image_generation", …}]. For a mask, set input_image_mask.image_url to a data:image/png;base64,… string. The mask must match the source size. Transparent pixels are the region to edit; opaque pixels stay. Responses also forwards output_format jpeg/webp and partial_images 1..=3 (SSE response.image_generation_call.partial_image); background=transparent is rewritten to opaque and input_fidelity is dropped. file_id masks fail — there is no Files API here — so official samples that files.create a mask will not run. Billing follows image tokens; the mask is not a second reference image. Separate POST /v1/images/* routes still return only non-streaming PNG.

```
import base64, os
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["APITOKEN_API_KEY"],
    base_url="https://router.apitoken.sale/v1",
)

def png_url(path):
    return "data:image/png;base64," + base64.b64encode(Path(path).read_bytes()).decode()

response = client.responses.create(
    model="gpt-5.6-sol",
    input=[{
        "role": "user",
        "content": [
            {"type": "input_text", "text": "Change only the masked region."},
            {"type": "input_image", "image_url": png_url("photo.png")},
        ],
    }],
    tools=[{
        "type": "image_generation",
        "output_format": "webp",
        "partial_images": 2,
        "input_image_mask": {"image_url": png_url("mask.png")},
    }],
)
```

## The Nano Banana 2 edit: references as multimodal input

Nano Banana 2 has no separate edits endpoint. An edit is an ordinary generateContent call whose parts array mixes the instruction text with one inline_data part per reference, up to 14 supported images. Because a reference is just another part, JPEG or WEBP catalog photos go in without a conversion step — a real pipeline saving when the source archive is not PNG.

```
curl https://router.apitoken.sale/v1beta/models/gemini-3.1-flash-image:generateContent \
  -H "x-goog-api-key: $APITOKEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d @edit-request.json

// edit-request.json
{
  "contents": [{
    "parts": [
      { "text": "Replace only the background with a neutral studio backdrop; keep the product untouched" },
      { "inline_data": { "mime_type": "image/jpeg", "data": "<BASE64 REFERENCE>" } }
    ]
  }],
  "generationConfig": {
    "responseModalities": ["TEXT", "IMAGE"],
    "imageConfig": { "imageSize": "1K", "aspectRatio": "1:1" }
  }
}
```

generationConfig pins the output contract: responseModalities TEXT plus IMAGE, an explicit imageSize of 0.5K, 1K, 2K or 4K, and one of the published aspect ratios. The response carries its own parts array — the image arrives as an inlineData part with a MIME type and base64 payload, next to any text parts. Send 0.5K or 512 for the cheapest live size; the subscription wire uses 512.

## Run edits as a validated pipeline

1. Normalize and inspect every reference server-side: decode the file, confirm a supported MIME type and reject empty or oversized payloads before any paid call.
2. Write an edit brief that separates immutable traits — product geometry, logo, label text — from the single named change; one change per request keeps failures diagnosable.
3. Choose the route whose output contract your client can decode, and never mix inlineData parsing with OpenAI Images parsing.
4. Dispatch one bounded candidate per source asset; do not fan out paid variants before the first output passes review.
5. Validate the delivered image — format, plausible dimensions, product identity and the absence of prohibited changes — before anything downstream sees it.
6. Persist request ID, terminal usage, prompt version, source and result together; that record is both your rollback path and your cost attribution.

## Edit cost math on published rates

For regular B2C accounts, both models bill at exactly 50% of the official usage total. GPT Image 2 settles per token: $2.50 per 1M fresh text input, $4 per 1M fresh image input and $15 per 1M image output after the discount, with cached input recognized at one quarter of the fresh rate before the discount. Every reference you attach is billed image input, so reference count is a cost control, not only a quality control.

| Worked example | What is billed | Regular B2C total |
| --- | --- | --- |
| GPT Image 2 edit reporting 1,200 text-input, 4,000 image-input and 4,200 image-output tokens | (1,200 × $2.50 + 4,000 × $4 + 4,200 × $15) / 1M | $0.082 settled |
| Nano Banana 2 edit at 1K | fixed 1,120 image-output tokens + measured input legs | $0.0336 image output + input |
| Nano Banana 2 edit at 4K | fixed 2,520 image-output tokens + measured input legs | $0.0756 image output + input |

The token counts in the first row are an illustration, not a tariff: GPT Image 2 output usage varies per request, and only terminal usage is authoritative. Nano Banana 2 is the opposite shape — the image-output leg is fixed by size ($0.0336 at 1K, $0.0504 at 2K, $0.0756 at 4K after the B2C discount), while text input, reference image input and any text or thinking output stay variable. An edit normally costs more input than a prompt-only generation; it earns that back when a good reference raises the acceptance rate and kills retries.

[Every token rate behind an edit bill, explained](/docs/learn/image-generation-api-pricing)

## Cost and retry discipline

- Send only references that constrain the requested edit; each one is billable image input on both routes.
- Never replay an edit automatically after an ambiguous timeout — the provider may have completed the work, and a blind retry is a second paid render. Reconcile by request ID first.
- Cap variants and attempts per source asset, and let the quality gate terminate the loop; a 50% discount halves the price of waste, it does not eliminate it.
- Give the image-editing worker its own key with a lifetime spending limit, separate from experiments, so a batch bug cannot drain the shared balance.
- Estimate before you spend: countTokens on gemini-3.1-flash-image measures input for free, and new accounts created with Google or GitHub start with a $5 welcome bonus that covers early pipeline tests.

## Frequently asked questions

### Which API accepts more reference images?

Nano Banana 2 accepts up to 14 supported image inputs on its generateContent route. GPT Image 2 accepts one to five PNG, JPEG or WebP files (each ≤50 MB) on its edits route.

### Can GPT Image 2 edit JPEG or WEBP references directly?

Edits accept PNG, JPEG or WebP, each at most 50 MB. GIF, HEIC and other types are rejected. Output is still one PNG. Use Nano Banana 2 when you need HEIC/HEIF or more than five references.

### Do edits cost more than prompt-only generation?

They add billable image input, so an otherwise comparable edit normally has more input cost. It can still be cheaper per accepted asset when references raise the acceptance rate and remove retries — measure settled cost per accepted asset, not per request.

### Is it safe to retry an edit after a timeout?

Only when you can prove the prior attempt was not accepted. An ambiguous timeout may hide completed provider work; preserve the request ID and reconcile before another paid attempt, otherwise the retry is a second paid render of the same job.

### What does the editing response look like on each route?

GPT Image 2 returns one JSON document with a single base64 PNG in data[0].b64_json. Nano Banana 2 returns the Gemini candidates structure, where the image is an inlineData part with a MIME type and base64 payload. Neither route hands you a hosted URL: decode, validate and store the bytes yourself.

### How can I test the edit routes cheaply?

Register with Google or GitHub to receive the $5 welcome bonus, run GPT Image 2 at its published low/auto profile, and use countTokens to preview Nano Banana 2 input before any image is rendered. Validate the whole pipeline at 1K before reserving 2K or 4K output.

---
Get a key: https://apitoken.sale/register
More guides: https://apitoken.sale/docs/learn
