Quotaflow
llms.txtOpenAPIDashboard
Model Library

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.

Quotaflow Image Editing
Quotaflow Image Editing

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.

PropertyValue
Model idgpt-image-2
Generate endpointPOST https://api.quotaflow.ai/openai/v1/images/generations
Edit endpointPOST https://api.quotaflow.ai/openai/v1/images/edits
Async status endpointGET https://api.quotaflow.ai/openai/v1/images/jobs/{id}
Input imagesResponses input_image.image_url, multipart files, or JSON image URLs
MasksOptional for localized edits
High-fidelity edit controlinput_fidelity: "high" for stronger preservation of the source image, subject, product geometry, and layout
Usage accountingResponses normally include OpenAI-style image usage; for rare successful requests where exact accounting is unavailable, usage may be omitted rather than estimated
Best forProduct 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

NeedStart with
OpenAI-compatible image generationgpt-image-2
OpenAI-compatible masked editsgpt-image-2
Fast Gemini-style image iterationgemini-3.1-flash-image-preview
Higher-quality Gemini image candidatesgemini-3-pro-image-preview

Key features

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

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(`![Quotaflow generated image](${outputPath})`);
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

SymptomWhat to check
Codex uses built-in image generation insteadRepeat the instruction: use the local quotaflow-imagegen skill and do not use built-in image generation.
HTTP 401 or HTTP 403Check QUOTAFLOW_API_KEY, key status, package limits, and whether image generation is enabled for the key.
HTTP 404 or HTTP 405Confirm OPENAI_BASE_URL is https://api.quotaflow.ai/openai/v1, not https://app.quotaflow.ai.
No image_generation_call result foundConfirm the request uses the Responses image_generation tool and that QUOTAFLOW_IMAGE_MODEL is gpt-image-2.
The PNG path prints but no image appearsMake sure the reply uses the exact Markdown image tag printed by the script, including the absolute local file path.
The request times outTry 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 caseRecommended 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 variantsSeveral small edit requests, each with one specific background or prop change.
Brand creativeUse 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