GPT Image 2 — image generation and editing API
Generate new images, edit uploaded images, replace backgrounds, and compose product visuals with gpt-image-2 through Quotaflow's OpenAI-compatible image API.

What is GPT Image 2 on Quotaflow?
gpt-image-2 is the recommended default when your app expects OpenAI-style /images/generations, /images/edits, or Responses image_generation request and response shapes. It supports text-to-image generation, reference-image edits through Responses input_image.image_url, optional masks through /images/edits, multi-image composition, and direct image-byte responses.
| Property | Value |
|---|---|
| Model id | gpt-image-2 |
| Generate endpoint | POST https://api.quotaflow.ai/openai/v1/images/generations |
| Edit endpoint | POST https://api.quotaflow.ai/openai/v1/images/edits |
| Async status endpoint | GET https://api.quotaflow.ai/openai/v1/images/jobs/{id} |
| Input images | Responses input_image.image_url, multipart files, or JSON image URLs |
| Masks | Optional for localized edits |
| High-fidelity edit control | input_fidelity: "high" for stronger preservation of the source image, subject, product geometry, and layout |
| Usage accounting | Responses normally include OpenAI-style image usage; for rare successful requests where exact accounting is unavailable, usage may be omitted rather than estimated |
| Best for | Product images, ecommerce edits, marketing creative, OpenAI-compatible apps |
Why use GPT Image 2?
Use this model when integration compatibility matters as much as image quality. Existing OpenAI-style clients can keep the same endpoint shape while Quotaflow manages key access, model enablement, package limits, and usage visibility.
Curated models
| Need | Start with |
|---|---|
| OpenAI-compatible image generation | gpt-image-2 |
| OpenAI-compatible masked edits | gpt-image-2 |
| Fast Gemini-style image iteration | gemini-3.1-flash-image-preview |
| Higher-quality Gemini image candidates | gemini-3-pro-image-preview |
Key features
- Text-to-image: create a new image from a prompt.
- Image editing: upload one or more images and describe the desired change.
- Masked local edits: include a mask when only one region should change.
- High-fidelity preservation: add
input_fidelity: "high"when a person, product, object, pose, or layout should stay close to the input image while the requested area changes. - Reference-image generation: send Responses
input_image.image_urlitems with theimage_generationtool. - Multi-image composition: repeat
imagemultipart fields or pass multiple image URLs. - Direct output bytes: use
response_format: "b64_json"when your app needs image bytes immediately. - Optional hosted URLs: for non-streaming
/images/generationsand/images/edits, useresponse_format: "url"when your app should receive a temporary Quotaflow-hosted URL instead of inline base64. - Compatible usage: successful responses normally include OpenAI-style image token usage. When exact image accounting is unavailable for a successful response, Quotaflow omits
usageinstead of returning an estimated value; clients should handle imageusageas optional. - Size validation:
sizemust be a supported image size for the selected image model. Oversized or malformed sizes are rejected before processing with an OpenAI-styleinvalid_request_error. Forgpt-image-2, useautoorWIDTHxHEIGHTwhere each side is a multiple of 16, no side exceeds 3840, aspect ratio is at most 3:1, and total pixels are between 655,360 and 8,294,400. Common examples:1024x1024,1536x1024,2048x2048,2880x2880,3840x2160, and2160x3840. - Async long-running jobs: JSON generation and edit requests can set
async: trueorPrefer: respond-asyncto receive202 Acceptedand poll/images/jobs/{id}for the final OpenAI-compatible image response.
How to generate images
curl https://api.quotaflow.ai/openai/v1/images/generations \
-H "Authorization: Bearer $QUOTAFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "A premium ecommerce hero image of a teal API dashboard on a modern desk, soft studio lighting.",
"size": "1024x1024",
"quality": "high",
"response_format": "b64_json"
}'
Use GPT Image 2 from Codex Desktop
Codex Desktop has its own built-in image generation path. If you want Codex Desktop to generate images through your Quotaflow key instead, install a small local Codex skill that calls Quotaflow's OpenAI-compatible Responses API and displays the returned PNG in the Codex chat.
Prerequisites
- Codex Desktop installed on the local machine.
- Node.js 18 or newer, because the helper script uses the built-in
fetchAPI. - A Quotaflow API key with OpenAI-compatible Responses access and image generation enabled.
- A main Responses model such as
gpt-5.4orgpt-5.4-mini, plus the image tool modelgpt-image-2. - The API base URL must be
https://api.quotaflow.ai/openai/v1. Do not usehttps://app.quotaflow.aifor API calls.
Before installing the skill, you can verify model access:
curl https://api.quotaflow.ai/openai/v1/models \
-H "Authorization: Bearer $QUOTAFLOW_API_KEY"
Confirm the response includes gpt-image-2 and at least one GPT/Codex model you can use as QUOTAFLOW_RESPONSE_MODEL.
Quick install
Run the installer on the machine where Codex Desktop runs:
QUOTAFLOW_API_KEY="qf_your_key_here" \
bash -c "$(curl -fsSL https://docs.quotaflow.ai/install/codex-imagegen.sh)"
The installer creates ~/.codex/quotaflow-imagegen.env, installs the quotaflow-imagegen skill, writes the helper script, and appends the Codex Desktop preference to ~/.codex/AGENTS.md if it is not already present.
If you prefer to inspect the script first:
curl -fsSL https://docs.quotaflow.ai/install/codex-imagegen.sh -o /tmp/quotaflow-codex-imagegen.sh
less /tmp/quotaflow-codex-imagegen.sh
QUOTAFLOW_API_KEY="qf_your_key_here" bash /tmp/quotaflow-codex-imagegen.sh
You can also set optional environment variables before installing, such as QUOTAFLOW_RESPONSE_MODEL, QUOTAFLOW_IMAGE_SIZE, or QUOTAFLOW_IMAGE_QUALITY.
Manual install
Use the manual steps below when you cannot run the installer or need to customize every file.
1. Save your Quotaflow image settings
Create ~/.codex/quotaflow-imagegen.env on the machine running Codex Desktop:
cat > ~/.codex/quotaflow-imagegen.env <<'EOF'
QUOTAFLOW_API_KEY="qf_your_key_here"
OPENAI_BASE_URL="https://api.quotaflow.ai/openai/v1"
QUOTAFLOW_IMAGE_MODEL="gpt-image-2"
QUOTAFLOW_IMAGE_SIZE="1024x1024"
QUOTAFLOW_IMAGE_QUALITY="low"
EOF
chmod 600 ~/.codex/quotaflow-imagegen.env
Use quality="medium" or quality="high" when you prefer quality over latency and your key/package allows it.
2. Install the Codex skill
Create ~/.codex/skills/quotaflow-imagegen/SKILL.md:
mkdir -p ~/.codex/skills/quotaflow-imagegen ~/.codex/quotaflow-imagegen-output
cat > ~/.codex/skills/quotaflow-imagegen/SKILL.md <<'EOF'
---
name: quotaflow-imagegen
description: Generate and display images through Quotaflow GPT Image 2. Use when the user asks to 生图, 生成图片, 画图, create an image, generate a photo, render an illustration, or display a generated picture.
---
# Quotaflow Image Generation
When the user asks for image generation, do not use Codex built-in image generation. Run `node ~/.codex/skills/quotaflow-imagegen/generate-image.mjs "<user image prompt>"`, then reply with the Markdown image tag printed by the script so Codex Desktop displays the local PNG.
EOF
Create ~/.codex/skills/quotaflow-imagegen/generate-image.mjs:
cat > ~/.codex/skills/quotaflow-imagegen/generate-image.mjs <<'EOF'
#!/usr/bin/env node
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { existsSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import crypto from 'node:crypto';
const envPath = join(homedir(), '.codex', 'quotaflow-imagegen.env');
const defaultBaseURL = 'https://api.quotaflow.ai/openai/v1';
async function loadEnvFile() {
if (!existsSync(envPath)) return;
const content = await readFile(envPath, 'utf8');
for (const line of content.split(/\r?\n/)) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#') || !trimmed.includes('=')) continue;
const index = trimmed.indexOf('=');
const key = trimmed.slice(0, index).trim();
const value = trimmed.slice(index + 1).trim().replace(/^['"]|['"]$/g, '');
if (key && process.env[key] === undefined) process.env[key] = value;
}
}
function getPrompt() {
const prompt = process.argv.slice(2).join(' ').trim();
if (!prompt) throw new Error('Missing image prompt.');
return prompt;
}
function getApiKey() {
const apiKey = process.env.QUOTAFLOW_API_KEY || process.env.OPENAI_API_KEY || '';
if (!apiKey) throw new Error('Missing QUOTAFLOW_API_KEY in ~/.codex/quotaflow-imagegen.env.');
return apiKey;
}
function extractImageBase64(payload) {
const output = Array.isArray(payload.output) ? payload.output : [];
const imageCall = output.find((item) => item?.type === 'image_generation_call' && typeof item.result === 'string');
if (!imageCall) throw new Error(`No image_generation_call result found. status=${payload.status || 'unknown'}`);
return imageCall.result;
}
await loadEnvFile();
const prompt = getPrompt();
const baseURL = (process.env.OPENAI_BASE_URL || defaultBaseURL).replace(/\/$/, '');
const response = await fetch(`${baseURL}/responses`, {
method: 'POST',
headers: {
Authorization: `Bearer ${getApiKey()}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: process.env.QUOTAFLOW_RESPONSE_MODEL || 'gpt-5.4',
input: prompt,
tools: [{
type: 'image_generation',
model: process.env.QUOTAFLOW_IMAGE_MODEL || 'gpt-image-2',
size: process.env.QUOTAFLOW_IMAGE_SIZE || '1024x1024',
quality: process.env.QUOTAFLOW_IMAGE_QUALITY || 'low'
}],
tool_choice: { type: 'image_generation' },
stream: false
}),
signal: AbortSignal.timeout(600000)
});
const text = await response.text();
if (!response.ok) throw new Error(`Quotaflow image request failed: HTTP ${response.status} ${text.slice(0, 1000)}`);
const imageBase64 = extractImageBase64(JSON.parse(text));
const outputDir = join(homedir(), '.codex', 'quotaflow-imagegen-output');
const outputPath = join(outputDir, `quotaflow-image-${crypto.randomUUID()}.png`);
await mkdir(outputDir, { recursive: true });
await writeFile(outputPath, Buffer.from(imageBase64, 'base64'));
console.log(``);
EOF
chmod +x ~/.codex/skills/quotaflow-imagegen/generate-image.mjs
3. Tell Codex Desktop to prefer the Quotaflow skill
Add this instruction to your Codex user instructions or ~/.codex/config.toml instructions block:
When I ask to generate, draw, render, or display an image, use the local quotaflow-imagegen skill. Do not use Codex built-in image generation. After the skill saves the PNG, display it with Markdown image syntax.
4. Test with one sentence
In Codex Desktop, ask:
生图:polished steel hummingbird, anime-style photo illustration, glowing cyan core, no text
The expected result is a normal Codex Desktop reply that displays a local PNG. Under the hood, the skill sends a Responses request to https://api.quotaflow.ai/openai/v1/responses with an image_generation tool whose model is gpt-image-2.
Troubleshooting
| Symptom | What to check |
|---|---|
| Codex uses built-in image generation instead | Repeat the instruction: use the local quotaflow-imagegen skill and do not use built-in image generation. |
HTTP 401 or HTTP 403 | Check QUOTAFLOW_API_KEY, key status, package limits, and whether image generation is enabled for the key. |
HTTP 404 or HTTP 405 | Confirm OPENAI_BASE_URL is https://api.quotaflow.ai/openai/v1, not https://app.quotaflow.ai. |
No image_generation_call result found | Confirm the request uses the Responses image_generation tool and that QUOTAFLOW_IMAGE_MODEL is gpt-image-2. |
| The PNG path prints but no image appears | Make sure the reply uses the exact Markdown image tag printed by the script, including the absolute local file path. |
| The request times out | Try QUOTAFLOW_IMAGE_QUALITY="low" first, then increase quality after the setup is confirmed. |
For backend applications that do not need Codex Desktop display, call /images/generations or /images/edits directly instead of installing the local Codex skill.
How to edit images
Responses clients can edit from a reference image by sending input_image.image_url in the user message content and attaching the image_generation tool. Use /images/edits directly for multipart uploads, masks, or full edit controls.
Use multipart when the source image is on disk:
curl https://api.quotaflow.ai/openai/v1/images/edits \
-H "Authorization: Bearer $QUOTAFLOW_API_KEY" \
-F "model=gpt-image-2" \
-F "image=@./product.png" \
-F "mask=@./mask.png" \
-F "prompt=Change only the masked background to a clean teal gradient. Keep the product and label unchanged." \
-F "size=1024x1024" \
-F "quality=high" \
-F "input_fidelity=high" \
-F "response_format=b64_json"
Use JSON when the source images are already hosted by your app:
curl https://api.quotaflow.ai/openai/v1/images/edits \
-H "Authorization: Bearer $QUOTAFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "Place the product naturally into a bright kitchen scene. Keep the product label readable.",
"images": [
{ "image_url": "https://example.com/product.png" },
{ "image_url": "https://example.com/kitchen-reference.png" }
],
"size": "1536x1024",
"quality": "high",
"response_format": "b64_json"
}'
High-fidelity edits
Use input_fidelity: "high" on /images/edits when the source image is not just a loose style reference. It is intended for background replacement, product retouching, identity-sensitive character work, and layouts where the original subject, object position, pose, camera angle, or product geometry should remain stable.
High-fidelity edits can take longer than broad style edits. Pair input_fidelity: "high" with a focused prompt and, when possible, a mask that describes the region allowed to change.
Long-running async jobs
For 4K, high-fidelity, or otherwise long-running JSON requests, enable async mode instead of holding the HTTP request open:
{
"model": "gpt-image-2",
"prompt": "A detailed high-resolution ecommerce hero image.",
"size": "2880x2880",
"response_format": "b64_json",
"async": true
}
The initial response is a public Quotaflow job object with id, status, expires_at, and status_url. Poll GET /openai/v1/images/jobs/{id} with the same API key. Successful jobs return status: "succeeded" and a nested response object whose shape matches the synchronous Images API response. Async jobs are scoped to the creating API key and do not expose upstream routing details.
Async mode currently supports JSON request bodies. For edits, pass images[].image_url and optional mask.image_url; use the synchronous edit endpoint for multipart uploads.
Pricing
Image generation and editing usually take longer than text calls. Use timeouts appropriate for media generation, keep prompts scoped, and avoid generating unnecessary variants in one user action.
Use cases
| Use case | Recommended request |
|---|---|
| Product hero image | /images/generations with a detailed scene, lighting, and aspect ratio prompt. |
| Background replacement | /images/edits with a source image and optional mask. |
| Marketplace variants | Several small edit requests, each with one specific background or prop change. |
| Brand creative | Use reference images and state which logos, colors, or layout elements must stay unchanged. |
FAQ
Do I need a mask for image edits?
No. Use a mask when only one region should change. Omit the mask for broader style edits, reference-image edits, or scene composition.
How many input images can I send?
Quotaflow supports multi-image edits. Keep total request size reasonable and confirm package limits for your deployment.
Should I use URLs or multipart files?
Use multipart for local files from a browser or backend upload. Use JSON image URLs when your images already live in object storage or a CDN.
What response format should I request?
Use b64_json when your application needs image bytes directly. Use response_format: "url" only for non-streaming image generation or edits when your integration is designed to fetch hosted media. URL output is a Quotaflow extension: URLs are temporary, include expires_at, and should be copied to your own storage for long-term retention.
Next steps
- Read the Images endpoint guide.
- Compare creative models in the Model Library.
- Try Gemini 3.1 Flash Image for fast iteration.