Language
Inference Space Docs

GPT-Image 2 Image Generation and Editing

Inference Space GPT-Image 2 text-to-image, image-to-image, and multi-image editing API with OpenAI compatibility.

GPT-Image 2 is Inference Space's image generation and editing model, with an interface compatible with the OpenAI Images API. It supports text-to-image generation, single-image editing, and multi-image fusion editing with up to 16 reference images. The model performs consistently with Chinese prompts, layout control, and image-text consistency, making it suitable for e-commerce hero images, posters, illustrations, and product-image compositing.

Overview

  • Text-to-image: POST https://ai.inf.space/v1/images/generations, application/json.
  • Image-to-image / multi-image editing: POST https://ai.inf.space/v1/images/edits, multipart/form-data.
  • model is fixed at gpt-image-2.
  • Multi-image editing is the core capability: upload multiple reference images with repeated image[] fields, then refer to them in upload order as “image 1 / image 2 / image 3” in the prompt.

The interface is compatible with the OpenAI Images API. Existing OpenAI image clients can connect by changing only the Base, Key, and model. Note that this gateway forwards only the parameters it actually supports; other OpenAI parameters are ignored. See the “Parameters” and “OpenAI compatibility” sections below for details.

Authentication and Base

  • API Base: https://ai.inf.space/v1 (the browser console shares the host; use the /v1 path for API requests)
  • Authentication header: Authorization: Bearer $AI_TOS_API_KEY

Create an API Key in the console and pass it in the Authorization header for each request. In production, keep the Key on the server and do not expose it in the browser.

Text-to-image

Send a JSON request to /v1/images/generations with model and prompt, plus optional size and quality parameters. Text-to-image generates one image only, with the output format fixed to the upstream default PNG.

curl "https://ai.inf.space/v1/images/generations" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "A white ceramic mug on a gray tabletop, soft natural light, e-commerce hero-image style",
    "size": "1024x1024",
    "quality": "auto"
  }'

In addition to OpenAI's standard size, text-to-image supports the gateway extensions aspectRatio (for example, "3:4", automatically aligned to a supported widthxheight at the 1K / 2K / 4K tier) and provider (to override the provider selection).

Image-to-image and multi-image editing

Send a multipart/form-data request to /v1/images/edits.

Quick verification with a public image URL

For a quick end-to-end verification, pass a publicly accessible image URL as JSON without downloading it locally first:

curl "https://ai.inf.space/v1/images/edits" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "Improve the e-commerce image layout and typography, and change the model's hairstyle to loose waves",
    "input_images": [
      "https://tos.cn-sh2.ufileos.com/public/image-curl-verify/2026-07-02/test_image-d9d3d81e4d88.png"
    ],
    "size": "1024x1024",
    "quality": "low"
  }'

input_images / images support public https:// image URLs, data URLs, or raw base64. For production integrations, your own CDN is still recommended to avoid broken third-party image links.

Single-image editing

Send one image field:

curl "https://ai.inf.space/v1/images/edits" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image=@product.png" \
  -F "prompt=Replace the background with a pure-white e-commerce hero-image background while preserving the product details" \
  -F "size=1024x1024"

Multi-image editing (core capability)

Upload multiple reference images with repeated image[] fields (OpenAI array syntax), up to 16 images, each in PNG / JPEG / WebP format. Upload order determines reference order; refer to the corresponding images as “image 1 / image 2 / image 3” in the prompt.

curl "https://ai.inf.space/v1/images/edits" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image[]=@bag.png" \
  -F "image[]=@scarf.png" \
  -F "image[]=@model.png" \
  -F "prompt=Have the model in image 3 carry the handbag from image 1 and wear the silk scarf from image 2, with an overall street-style look" \
  -F "size=1024x1536"

Upload order determines image numbering: the first image[] is “image 1,” the second is “image 2,” and so on. Make sure numbered references in the prompt match upload order.

Local editing (mask)

Use the mask field for inpainting: only transparent areas of the mask are redrawn, while opaque areas are preserved. mask is effective only with multipart/form-data on the edits endpoint, and the gateway forwards it unchanged to the upstream (without lossy compression, preserving the complete alpha channel).

curl "https://ai.inf.space/v1/images/edits" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image=@room.png" \
  -F "mask=@room-mask.png" \
  -F "prompt=Replace the masked area with a floor-to-ceiling window" \
  -F "size=1024x1024"
  • The mask must be a PNG with an alpha channel: transparent areas = areas to redraw, opaque areas = areas to preserve.
  • The mask applies to the first reference image (the first image / image[]).
  • Only multipart is supported (not a JSON body); the default path and the policy-routing / failover editing paths all support it.
  • All production gpt-image-2 providers (ap-image2 / pi-image2 / we-image2 / zm-image2 / codexpool) support masks.

The mask semantics follow OpenAI gpt-image: areas with transparent alpha are redrawn, and areas with opaque alpha are preserved. The areas to redraw must therefore be transparent in the mask; do not invert them.

Hard requirements for mask dimensions and format

  • The mask dimensions must match the first source image pixel for pixel: even a one-pixel difference causes an error. The safest approach is to derive the mask from the source image (original.size) so the dimensions align automatically.
  • The mask must be an RGBA PNG. RGB / L / P modes are rejected (a missing alpha channel returns invalid_image_file).
  • Each mask file should be under 4 MB.
  • The redraw region is determined by the alpha channel itself, not by visible black and white. Convert a black-and-white mask to alpha with putalpha before using it.

Programmatically generate a mask (transparent area = area to redraw):

from PIL import Image, ImageDraw

# Method 1: draw a transparent rectangle for the redraw area at the source-image size
mask = Image.new("RGBA", original.size, (255, 255, 255, 255))  # opaque = preserve
ImageDraw.Draw(mask).rectangle((300, 250, 750, 800), fill=(0, 0, 0, 0))  # transparent = redraw
mask.save("mask.png")

# Method 2: convert an existing black-and-white mask to alpha (black 0 -> redraw, white 255 -> preserve)
bw = Image.open("mask_bw.png").convert("L")
rgba = Image.new("RGBA", bw.size, (255, 255, 255, 255))
rgba.putalpha(bw)
rgba.save("mask.png")

Describe the full image in the prompt

The gpt-image mask provides prompt-guided editing through full-image regeneration, rather than hard pixel compositing like DALL·E 2. The prompt should therefore not describe only the local area to redraw. Describe the desired complete image and explicitly state what must remain unchanged:

Modify only the transparent area of the mask and replace the person's top with a solid-red, crew-neck cotton T-shirt;
keep the person's face, hairstyle, body pose, and background unchanged.

The mask is not an absolute pixel-level crop: because the whole image is regenerated, unmasked areas may also change slightly (for example, shadows, lighting, reflections, or background-edge transitions). If the business requirement is byte-for-byte preservation of unmasked pixels, composite the original back onto unmasked areas after receiving the result (Image.composite + feathered edges).

Common pitfalls: 1) inverting the mask (the easiest mistake; inspect alpha, not color); 2) a one-pixel dimension mismatch with the source image, which causes an error—use NEAREST resampling when resizing; 3) lossy re-saving by an image tool, which can damage the alpha channel—re-export consistently with .convert("RGBA").save(...).

Output format and count

  • output_format (default png, options png / jpeg / webp) is effective only on the edits endpoint and specifies the encoding format of returned images.
  • n (number of generated images) is sent only on the edits endpoint when n > 1; when omitted or set to 1, one image is returned. Text-to-image does not support n and always returns one image.
curl "https://ai.inf.space/v1/images/edits" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image=@product.png" \
  -F "prompt=Replace the background with a pure-white e-commerce hero-image background while preserving the product details" \
  -F "size=1024x1024" \
  -F "output_format=webp"

Input-image compression (edits only)

For heavy multi-image fusion edits, enable lossy compression of input reference images with the x-input-image-compress: true request header. This can significantly reduce the bytes uploaded to and stored by the upstream, with nearly imperceptible quality loss.

  • Enable it with: x-input-image-compress: true (exact match for true, case-insensitive).
  • Scope: applies only to reference images uploaded to edits; it takes effect only for images larger than 200 KB, while smaller images are forwarded unchanged.
  • Encoding: sharp (libvips) lossy re-encoding at q85 while preserving the original format—JPEG → mozjpeg q85; PNG → lossy palette (libimagequant) q85 + maximum compression level; WebP → q85. gif / svg / unknown formats are forwarded unchanged.
  • Never increases size: if re-encoding produces a larger file, the original is retained.
  • Best effort: if sharp is unavailable or encoding fails, the image is forwarded unchanged and the request itself is not affected.
curl "https://ai.inf.space/v1/images/edits" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -H "x-input-image-compress: true" \
  -F "model=gpt-image-2" \
  -F "image[]=@bag.png" \
  -F "image[]=@scarf.png" \
  -F "image[]=@model.png" \
  -F "prompt=Have the model in image 3 carry the handbag from image 1 and wear the silk scarf from image 2, with an overall street-style look" \
  -F "size=1024x1536"

x-input-image-compress compresses the input image, whereas OpenAI's output_compression compresses the output image. They are different features, and this gateway currently does not support output_compression.

Parameters

The table below lists the parameters this gateway actually forwards or applies. Unlisted OpenAI parameters are ignored; see “OpenAI compatibility” below.

ParameterTypeApplicable interfaceRequiredDescription
modelstringGeneralYesFixed at gpt-image-2
promptstringGeneralYesGeneration or editing instruction; Chinese is supported natively
sizestringGeneralNoTarget size; see the size details below
qualitystringGeneralNoDefaults to auto (the model selects quality automatically when omitted); options are auto / low / medium / high, affecting quality and billing tier (auto is billed at the high-tier baseline)
aspectRatiostringText-to-imageNoGateway extension, such as "3:4", automatically aligned to a supported widthxheight at the selected size tier
providerstringText-to-imageNoGateway extension for overriding the provider selection
image[]fileEditingYesReference image; repeat the field for multiple uploads, up to 16 images, PNG / JPEG / WebP; single-image editing may also use one image field
maskfileEditingNoAlpha PNG; transparent areas are redrawn and it applies to the first image; multipart only, forwarded unchanged
output_formatstringEditingNoDefaults to png, options are png / jpeg / webp; effective only on edits
nintegerEditingNoNumber of generated images; sent only on edits when n > 1, otherwise one image is returned

The text-to-image endpoint (JSON body) accepts model / prompt / quality / size, plus the extensions aspectRatio / provider. The editing endpoint (multipart) accepts image / image[] / model / prompt / size / quality, plus output_format and n.

Size details

size has two uses:

  1. Quick experimentation: send 1K / 2K / 4K, and send aspectRatio for text-to-image.
  2. Specify the request canvas: send a widthxheight value from the table. These are the specifications that the default providers reproduce reliably; aspectRatio is not also required.

The table below shows the sizes actually applied by the default providers. Explicit sizes outside the table are aligned by aspect ratio to the nearest supported specification. Some advanced providers may retain more sizes, but that behavior should not be treated as a cross-provider contract.

Aspect ratio1K2K4K
1:11280x12802048x20482880x2880
16:91280x7202048x11523840x2160
9:16720x12801152x20482160x3840
4:31280x9602048x15363312x2480
3:4960x12801536x20482480x3312
3:21280x8482048x13603520x2336
2:3848x12801360x20482336x3520
5:41280x10242048x16323216x2560
4:51024x12801632x20482560x3216
21:91280x5442048x8643840x1632

Explicit dimensions select the aspect ratio and tier, but the final returned pixels still depend on the actual provider. When a fixed delivery size is required, use a value from the table, pin a verified provider, and read the actual returned image pixels after generation. quality affects quality, latency, and billing, but does not change the requested aspect ratio.

Use a lowercase half-width x in size strings (for example, 1728x2304), not an uppercase X or full-width ×. For general semantics of advanced size and quality options, see the OpenAI Image Generation guide.

OpenAI compatibility

This interface is compatible with the OpenAI Images API. When migrating from OpenAI, note that the following parameters are not currently forwarded or supported by this gateway and are silently ignored when set:

  • output_compression: compresses the output image—unsupported by this gateway. To compress, use x-input-image-compress on edits to compress input reference images (a different use case; see above).
  • background (opaque / transparent / auto): unsupported; gpt-image-2 outputs an opaque background by default.
  • output_format: unsupported on the text-to-image endpoint (the upstream default PNG is always returned); effective only on edits.
  • n: unsupported on the text-to-image endpoint (always one image); effective only on edits when n > 1.
  • Caller-facing stream / partial_images: unsupported; callers always receive one complete JSON response (see “Response” below).

Response

The response is always one complete JSON response, with no caller-facing streaming. The gateway and upstream may use internal streaming to avoid Cloudflare 524 timeouts, but this is transparent to callers, who receive only the complete JSON body.

Each image in data[] is returned as b64_json (raw base64) or url (a serve URL); usage provides usage information.

{
  "created": 1717488000,
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAAANSUhEUgAA..."
    }
  ],
  "usage": {
    "input_tokens": 256,
    "output_tokens": 1568,
    "total_tokens": 1824,
    "generated_images": 1
  }
}
  • b64_json is a raw base64 string. Before saving it or displaying it in a frontend, prepend the data:image/png;base64, prefix yourself.
  • url is a time-limited serve link; copy the image to your own storage promptly.
  • usage contains input_tokens (forwarded when reported by the upstream), output_tokens, total_tokens, and generated_images.

Asynchronous Jobs API (/api/jobs)

For long-running generation such as 4K, multi-image fusion, or local redrawing, use asynchronous jobs: submit once to receive a job ID, then poll for the result so long-lived connections are not interrupted by releases or timeouts.

Asynchronous and synchronous requests use the same processing pipeline—the same authentication, routing, quota, billing middleware, request-body parsing, and parameter conversion. The asynchronous endpoint accepts exactly the same generation parameters as synchronous /v1/images/* endpoints and forwards them unchanged to the upstream. Therefore, every parameter supported synchronously is supported equivalently asynchronously; parameters unsupported synchronously (such as output_compression / background) are also unsupported asynchronously. This asynchronous protocol is shared by gpt-image-2 and Gemini (Nano Banana): submission, polling, and cancellation endpoints and response structures are identical; only model changes.

Full parameter set

In addition to model / prompt / size / aspectRatio, asynchronous submission supports the following parameters, consistent with synchronous requests:

ParameterApplicable interfaceDescription
nEditingNumber of generated images; when n > 1, multiple images are returned, outputs contains multiple entries, and outputs_count reports the actual count
maskEditingAlpha PNG for local redrawing, applied to the first reference image; upload with multipart/form-data, and the gateway forwards it unchanged to the upstream (without lossy compression, preserving the complete alpha channel)
output_formatEditingEncoding format for returned images; default png, options png / jpeg / webp
qualityGeneralauto / low / medium / high, affecting quality and billing tier
response_formatGeneralAccepted for synchronous-interface alignment; asynchronous results are always downloadable URLs in outputs
media_resolutionGeneralEffective only for Gemini models; mapped to upstream generationConfig.mediaResolution

n / output_format / mask have exactly the same semantics as the synchronous edits endpoint (see “Image-to-image and multi-image editing” and “Local editing (mask)” above). These parameters were previously discarded by asynchronous jobs and are now supported—async == sync.

Submission

POST https://ai.inf.space/api/jobs. Use JSON for text-to-image and multi-image fusion; use multipart/form-data for local redrawing or edits with reference images:

# Text-to-image (OpenAI shape): multiple images + specified output format
curl "https://ai.inf.space/api/jobs" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "gpt-image-2", "prompt": "A cyberpunk city at night", "size": "4K", "aspectRatio": "16:9" }'

# Local redrawing (mask): multipart, reference image + mask + WebP output
curl "https://ai.inf.space/api/jobs" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image=@room.png" \
  -F "mask=@room-mask.png" \
  -F "prompt=Replace the sofa with a fabric sofa while preserving the rest of the furnishings" \
  -F "output_format=webp"

# Switch to Gemini: same endpoint, only model differs; media_resolution takes effect
curl "https://ai.inf.space/api/jobs" \
  -H "Authorization: Bearer $AI_TOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "gemini-3-pro-image", "prompt": "A high-definition city at night", "aspectRatio": "16:9", "media_resolution": "high" }'

Submission returns a job object (id / status / progress, and so on). Polling, cancellation, listing, and the seven-day retention period are identical to Nano Banana asynchronous jobs, so they are not repeated here. When complete, outputs contains downloadable URLs rather than inline base64.

Pricing

Billing is per image based on image specification and quality tier; image tokens are not billed separately. Actual prices are shown in the console, with organization-specific prices taking precedence.

Latency and error handling

Image generation and editing latency varies significantly with quality and resolution. Set the client timeout to at least 600 seconds:

  • auto (default): the model selects quality automatically based on content; latency falls within the ranges below.
  • low: approximately 10–40s
  • medium: approximately 30–90s
  • high or complex 2K / 4K editing: 3–5 minutes
  • Multi-image editing takes longer; reserve timeout according to the most complex scenario.

Integration guidance:

  • Keep the API Key on the server and do not expose it in the browser.
  • Complex, high-resolution edits may be slow. Limited retries are appropriate for transient network errors such as connection timeouts and 5xx network jitter.
  • For system-busy errors such as “An error occurred while processing your request.”, tell the user to try again later instead of repeatedly retrying and extending the overall timeout.
  • When url is returned, copy the image to your own storage promptly because the link is time-limited.

On this page