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/v1path 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
putalphabefore 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(defaultpng, optionspng/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 whenn > 1; when omitted or set to 1, one image is returned. Text-to-image does not supportnand 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 fortrue, 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.
| Parameter | Type | Applicable interface | Required | Description |
|---|---|---|---|---|
model | string | General | Yes | Fixed at gpt-image-2 |
prompt | string | General | Yes | Generation or editing instruction; Chinese is supported natively |
size | string | General | No | Target size; see the size details below |
quality | string | General | No | Defaults 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) |
aspectRatio | string | Text-to-image | No | Gateway extension, such as "3:4", automatically aligned to a supported widthxheight at the selected size tier |
provider | string | Text-to-image | No | Gateway extension for overriding the provider selection |
image[] | file | Editing | Yes | Reference image; repeat the field for multiple uploads, up to 16 images, PNG / JPEG / WebP; single-image editing may also use one image field |
mask | file | Editing | No | Alpha PNG; transparent areas are redrawn and it applies to the first image; multipart only, forwarded unchanged |
output_format | string | Editing | No | Defaults to png, options are png / jpeg / webp; effective only on edits |
n | integer | Editing | No | Number 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:
- Quick experimentation: send
1K/2K/4K, and sendaspectRatiofor text-to-image. - Specify the request canvas: send a
widthxheightvalue from the table. These are the specifications that the default providers reproduce reliably;aspectRatiois 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 ratio | 1K | 2K | 4K |
|---|---|---|---|
| 1:1 | 1280x1280 | 2048x2048 | 2880x2880 |
| 16:9 | 1280x720 | 2048x1152 | 3840x2160 |
| 9:16 | 720x1280 | 1152x2048 | 2160x3840 |
| 4:3 | 1280x960 | 2048x1536 | 3312x2480 |
| 3:4 | 960x1280 | 1536x2048 | 2480x3312 |
| 3:2 | 1280x848 | 2048x1360 | 3520x2336 |
| 2:3 | 848x1280 | 1360x2048 | 2336x3520 |
| 5:4 | 1280x1024 | 2048x1632 | 3216x2560 |
| 4:5 | 1024x1280 | 1632x2048 | 2560x3216 |
| 21:9 | 1280x544 | 2048x864 | 3840x1632 |
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, usex-input-image-compresson 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 whenn > 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_jsonis a raw base64 string. Before saving it or displaying it in a frontend, prepend thedata:image/png;base64,prefix yourself.urlis a time-limited serve link; copy the image to your own storage promptly.usagecontainsinput_tokens(forwarded when reported by the upstream),output_tokens,total_tokens, andgenerated_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:
| Parameter | Applicable interface | Description |
|---|---|---|
n | Editing | Number of generated images; when n > 1, multiple images are returned, outputs contains multiple entries, and outputs_count reports the actual count |
mask | Editing | Alpha 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_format | Editing | Encoding format for returned images; default png, options png / jpeg / webp |
quality | General | auto / low / medium / high, affecting quality and billing tier |
response_format | General | Accepted for synchronous-interface alignment; asynchronous results are always downloadable URLs in outputs |
media_resolution | General | Effective 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–40smedium: approximately 30–90shighor 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
urlis returned, copy the image to your own storage promptly because the link is time-limited.
Image Generation and Editing
OpenAI-compatible `/v1/images/generations` text-to-image and `/v1/images/edits` image-to-image, multi-image fusion, and mask-based inpainting.
Nano Banana Image Generation and Editing
Inference Space Nano Banana (Gemini image generation) series text-to-image and image-to-image API, centered on the native Google generateContent protocol, compatible with OpenAI Images, with unified asynchronous jobs and per-image billing.