gpt-image-2 Image Generation and Editing

OpenAI-compatible gpt-image-2 text-to-image + image-edit API: drop in by switching base_url, multi-region endpoints, unified billing with your QCode key


title: "gpt-image-2 Image Generation and Editing" description: "OpenAI-compatible gpt-image-2 text-to-image + image-edit API: drop in by switching base_url, multi-region endpoints, unified billing with your QCode key"


gpt-image-2 Image Generation and Editing

QCode.cc exposes a fully OpenAI-compatible gpt-image-2 API covering two endpoints:

  • Text-to-image POST /v1/images/generations — JSON request, generate images from text alone
  • Image edit POST /v1/images/edits — multipart upload of 1–8 source images (optional mask), repaint / modify / composite per the prompt (launched May 2026)

gpt-image-2 is OpenAI's latest image model (released April 2026) and currently has the strongest in-image text rendering of any public model — it can reliably render English and Chinese characters inside generated images.

What QCode.cc adds:

  • Drop-in for the OpenAI SDK — only the base_url changes; request and response shapes are 100% identical (including the multipart edits endpoint)
  • Multi-region access: HK / Japan / US / EU — pick the entry closest to your network
  • Single API key: reuse your existing QCode.cc cr_ key — same quota account as Claude Code, Codex, and Gemini CLI
  • Unified usage view: image calls and chat calls are merged in your dashboard, plus a dedicated self-service usage page
  • Shared quota across endpoints: generations and edits share the same per-key 100 images/day cap and 2-concurrency limit

Common use cases: poster generation, illustrations, product imagery, UI mockups, social-media assets, image editing (local inpainting / multi-image composition / background swap / high-fidelity restoration).


Quick start

Text-to-image (generations)

Three lines of Python for your first image:

from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://api.qcode.cc/qcode-img/v1",
    api_key="cr_YOUR_QCODE_API_KEY",
    timeout=180.0,  # 30–120 s per image; set ≥ 180 s
)

result = client.images.generate(
    model="gpt-image-2",
    prompt="A cyberpunk Tokyo street at night, neon reflecting in rain puddles",
    size="1024x1024",
    quality="low",
    n=1,
)

with open("output.png", "wb") as f:
    f.write(base64.b64decode(result.data[0].b64_json))

Image edit (edits)

Upload an existing image + prompt, optionally with a mask for local inpainting:

from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://api.qcode.cc/qcode-img/v1",
    api_key="cr_YOUR_QCODE_API_KEY",
    timeout=180.0,
)

result = client.images.edit(
    model="gpt-image-2",
    image=open("cat.png", "rb"),
    mask=open("mask.png", "rb"),          # optional: PNG alpha; transparent area = repaint region
    prompt="put a tiny crown on the cat",
    size="1024x1024",
    quality="high",
    extra_body={"input_fidelity": "high"},  # high fidelity preserves original details
)

with open("edited.png", "wb") as f:
    f.write(base64.b64decode(result.data[0].b64_json))

⚠️ Always set timeout ≥ 180 s explicitly: the OpenAI SDK default is too short. gpt-image-2 inference is significantly slower than legacy text-to-image (see Latency & timeout below).


Endpoints

The gpt-image-2 service (both generations and edits) is available on every QCode.cc entry. Just append /qcode-img/v1 to the base:

Your location Recommended base_url Protocol Notes
China (HTTPS required) https://api.qcode.cc/qcode-img/v1 HTTPS Behind global CDN; medium / high may hit 524 (see CDN 100 s hard limit)
HK / SEA https://asia.qcode.cc/qcode-img/v1 HTTPS Hong Kong PoP
Europe https://eu.qcode.cc/qcode-img/v1 HTTPS Frankfurt PoP
North America https://us.qcode.cc/qcode-img/v1 HTTPS Los Angeles PoP

All entries route to the same billing system — usage and quota are unified. Full endpoint reference: Endpoints & API paths.

qcode-img is the path prefix dedicated to image generation and editing, parallel to /api (Anthropic), /openai/v1 (OpenAI chat), and /gemini (Gemini).


API reference

Common request headers

Header Required Value
Authorization Bearer cr_xxxxxxxxxxxxxxxx (your QCode.cc API key)
Content-Type application/json (generations)
multipart/form-data (edits)

Generations endpoint /v1/images/generations

Endpoint: POST {base_url}/images/generations Content-Type: application/json

Request body:

{
  "model": "gpt-image-2",
  "prompt": "A small ceramic vase with sunflower, photorealistic",
  "size": "1024x1024",
  "quality": "low",
  "n": 1
}

Fields:

Field Type Required Default Values
model string Must be gpt-image-2
prompt string Image description, multilingual (incl. English & Chinese)
size string 1024x1024 1024x1024 (square) / 1024x1536 (portrait) / 1536x1024 (landscape)
quality string medium low / medium / high
n integer 1 Images per call (1 – 4)

Edits endpoint /v1/images/edits

Endpoint: POST {base_url}/images/edits Content-Type: multipart/form-data (file uploads require form-data, not JSON)

Fields:

Field Type Required Default Values / notes
model string Must be gpt-image-2
image file (× N) Source image (PNG / JPEG / WebP); 1 – 8 images supported for multi-image composition (repeat the same field name: -F image=@a.png -F image=@b.png)
mask file PNG alpha mask; transparent area = region to repaint; mask resolution must match image (scaled automatically); applies to single-image edits
prompt string Edit instruction (multilingual)
size string auto auto / 1024x1024 / 1024x1536 / 1536x1024 (auto = follow input aspect)
quality string auto auto / low / medium / high
n integer 1 Images per call (1 – 4)
background string auto auto / opaque / transparent (transparent requires PNG / WebP output)
output_format string png png / jpeg / webp
output_compression integer 0 – 100, applies to JPEG / WebP (ignored for PNG)
input_fidelity string low low / high; high preserves faces / logos / text / product details — use for portrait restoration or product-on-background swaps
response_format string b64_json b64_json / url
user string End-user identifier passed through (for upstream abuse detection)

Upload size limits: single file ≤ 25 MB; total across files ≤ 200 MB (over the limit returns 413 image_too_large).

Response (same for both endpoints)

{
  "created": 1777135432,
  "data": [
    {
      "b64_json": "iVBORw0KGgo...(base64 PNG/JPEG/WebP, 1-3 MB)",
      "revised_prompt": "A small ceramic vase with sunflower..."
    }
  ]
}
  • b64_json: base64-encoded image data; render directly with <img src="data:image/<format>;base64,...">
  • revised_prompt: the model's improved version of your original prompt (optional to display)

Error responses

Errors follow the standard OpenAI schema:

{
  "error": {
    "type": "rate_limit_error",
    "code": "image_daily_limit",
    "message": "Daily image generation count limit reached..."
  }
}
HTTP code Meaning
401 invalid_api_key API key invalid or disabled
401 key_expired API key expired
413 image_too_large Single file > 25 MB, or total across files > 200 MB
422 unsupported_size size not in the supported set
429 crs_daily_exhausted Daily account budget reached
429 crs_total_exhausted Lifetime account budget reached
429 image_daily_limit Per-key daily 100-image cap reached (shared between generations and edits; raise on request)
429 concurrency_exhausted Per-key 2-concurrency cap reached (raise on request)
503 service_overloaded Global service load is high — retry later
503 image_provider_unavailable Upstream temporarily unavailable — retry later

Code examples

Text-to-image:

from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://api.qcode.cc/qcode-img/v1",
    api_key="cr_YOUR_QCODE_API_KEY",
    timeout=180.0,
)

result = client.images.generate(
    model="gpt-image-2",
    prompt="A cyberpunk Tokyo street at night, neon reflecting in rain puddles",
    size="1024x1024",
    quality="low",
    n=1,
)

img_bytes = base64.b64decode(result.data[0].b64_json)
with open("output.png", "wb") as f:
    f.write(img_bytes)
print("Saved output.png")

Image edit (single image + mask inpainting):

from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://api.qcode.cc/qcode-img/v1",
    api_key="cr_YOUR_QCODE_API_KEY",
    timeout=180.0,
)

result = client.images.edit(
    model="gpt-image-2",
    image=open("cat.png", "rb"),
    mask=open("mask.png", "rb"),
    prompt="put a tiny crown on the cat",
    size="1024x1024",
    quality="high",
    extra_body={
        "input_fidelity": "high",
        "background": "transparent",
        "output_format": "png",
    },
)

img = base64.b64decode(result.data[0].b64_json)
with open("edited.png", "wb") as f:
    f.write(img)

Image edit (multi-image composition, 2 – 8 images):

result = client.images.edit(
    model="gpt-image-2",
    image=[
        open("scene.png", "rb"),       # 1st image: scene background
        open("product.png", "rb"),     # 2nd image: product to place
    ],
    prompt="Place the product naturally into the scene, match the lighting and shadows.",
    size="1536x1024",
    quality="high",
    extra_body={"input_fidelity": "high"},
)

curl

Text-to-image:

curl https://api.qcode.cc/qcode-img/v1/images/generations \
  -H "Authorization: Bearer cr_YOUR_QCODE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "A cyberpunk Tokyo street at night",
    "size": "1024x1024",
    "quality": "low",
    "n": 1
  }' \
  | jq -r ".data[0].b64_json" | base64 -d > output.png

Image edit:

curl https://api.qcode.cc/qcode-img/v1/images/edits \
  -H "Authorization: Bearer cr_YOUR_QCODE_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image=@cat.png" \
  -F "mask=@mask.png" \
  -F "prompt=put a tiny crown on the cat" \
  -F "size=1024x1024" \
  -F "quality=high" \
  -F "input_fidelity=high" \
  -F "background=transparent" \
  -F "output_format=png" \
  | jq -r ".data[0].b64_json" | base64 -d > edited.png

Multi-image composition (just repeat -F image=@):

curl https://api.qcode.cc/qcode-img/v1/images/edits \
  -H "Authorization: Bearer cr_YOUR_QCODE_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image=@scene.png" \
  -F "image=@product.png" \
  -F "prompt=Place the product naturally into the scene" \
  -F "size=1536x1024" \
  -F "quality=high" \
  -F "input_fidelity=high"

JavaScript / Node.js / browser

Text-to-image:

const r = await fetch("https://api.qcode.cc/qcode-img/v1/images/generations", {
  method: "POST",
  headers: {
    "Authorization": "Bearer cr_YOUR_QCODE_API_KEY",
    "Content-Type":  "application/json",
  },
  body: JSON.stringify({
    model: "gpt-image-2",
    prompt: "A cyberpunk Tokyo street at night",
    size: "1024x1024",
    quality: "low",
    n: 1,
  }),
});
const json = await r.json();
const dataUrl = "data:image/png;base64," + json.data[0].b64_json;
document.querySelector("img").src = dataUrl;

Image edit (browser FormData):

const fd = new FormData();
fd.append("model", "gpt-image-2");
fd.append("image", imageFile);              // File object from <input type="file">
fd.append("mask", maskFile);                // optional
fd.append("prompt", "put a tiny crown on the cat");
fd.append("size", "1024x1024");
fd.append("quality", "high");
fd.append("input_fidelity", "high");
fd.append("background", "transparent");
fd.append("output_format", "png");

const r = await fetch("https://api.qcode.cc/qcode-img/v1/images/edits", {
  method: "POST",
  headers: { "Authorization": "Bearer cr_YOUR_QCODE_API_KEY" },
  // Don't set Content-Type manually — FormData sets multipart/form-data with the boundary
  body: fd,
});
const json = await r.json();
const dataUrl = "data:image/png;base64," + json.data[0].b64_json;
document.querySelector("img").src = dataUrl;

Quotas

Defaults

Dimension Default Notes
Daily image count 100 / day / key Resets at 00:00 Beijing time; shared between generations and edits
Concurrency 2 in flight Returns 429 concurrency_exhausted; shared across both endpoints
Upload size (edits only) 25 MB single file / 200 MB total Returns 413 image_too_large
Account budget Shared with your QCode.cc account dailyCostLimit / totalCostLimit Returns 429 crs_daily_exhausted

Defaults cover the vast majority of users. Contact support to raise.

Usage lookup

  • Dashboard — shows chat + image calls together (last activity, today's cost, lifetime cost, model distribution)
  • Self-service page: https://api.qcode.cc/qcode-img/usage — enter your API key to see the last 30 days of usage, detailed call list, ECharts trend (key is kept locally in your browser, never uploaded)

Billing

Per-image pricing

generations and edits share the same pricing table:

size low medium high
1024×1024 $0.08 (floor) $0.08 (floor) $0.211
1024×1536 $0.08 (floor) $0.08 (floor) $0.165
1536×1024 $0.08 (floor) $0.08 (floor) $0.165
2048×2048 $0.08 (floor) $0.08 (floor) $0.285

$0.08 minimum

  • When actual cost is below $0.08 you pay $0.08 (low / medium typically hit this floor)
  • When actual cost is ≥ $0.08 you pay the real amount (no markup)

Multiple outputs & multi-input edits

  • n > 1 scales linearly on output count, e.g. n=2 + 1024×1024 high = 2 × $0.211 = $0.422
  • For edits multi-input (image=[…N]): billing is per output (n), not per input
  • mask does not affect billing

Failures don't charge

Any 4xx / 5xx error is not billed; client disconnects (closed connection) are not billed either.

Currency

Costs are denominated in USD and settled per your QCode.cc account's currency policy (CNY / USD).


Latency & timeout settings

gpt-image-2 is an inference-based model and is significantly slower than legacy text-to-image (DALL·E 3 / SDXL):

quality Typical Complex-prompt extreme
low 20 – 35 s ~50 s
medium 50 – 90 s ~120 s
high 70 – 120 s ~150 s

Edits latency is comparable to generations. Multi-image input / higher resolution / input_fidelity=high push toward the long end.

Practical advice:

  • The OpenAI Python SDK's default timeout is too short — always set timeout=180.0 or higher explicitly
  • Browser fetch has no default timeout, but if you use AbortController give it at least 180 s
  • For medium / high from mainland China, prefer asia.qcode.cc (direct, no CDN 100 s limit)

CDN 100 s hard limit (524 errors)

HTTPS requests to api.qcode.cc / asia.qcode.cc / eu.qcode.cc / us.qcode.cc go through the global CDN (CloudFlare). The CDN forcibly returns 524 for any request that waits longer than 100 s for the origin to respond.

quality Safe behind CDN 100 s?
low ✅ Safe (< 35 s)
medium ⚠️ Occasionally near the ceiling (close to 100 s)
high ❌ Frequent 524

Mitigations (recommended for medium / high):

  1. Use the qcode-img direct entry: https://api.qcode.cc/qcode-img/v1 (no CDN, no 100 s limit)
  2. Or accept occasional 524 + client-side retry

Prompting tips

Text-to-image (generations)

  • Multilingual: Chinese, English, or mixed prompts all work
  • More detail is better: environment, composition, lighting, style, lens distance / focal length / angle
  • Avoid brand names / well-known people: the model may refuse or return blurry results (OpenAI content policy)
  • In-image text: gpt-image-2 is exceptional at rendering English / Chinese text inside images (poster titles, slogans, signage) — just put the literal text in the prompt, no special syntax

Example:

A vintage poster in Bauhaus style, bold black text "MORNING COFFEE" centered,
warm orange and cream color palette, geometric shapes, slightly textured paper background

Image edit (edits)

  • Mask says "where", not "what": transparent area = region to repaint, opaque area is preserved. The prompt describes what to paint. Mask resolution must match image (system rescales).
  • For multi-image inputs, name each image's role in the prompt — e.g. "First image is the scene, second image is the product to place into it" — gpt-image-2 reads inputs in order.
  • input_fidelity=high preserves faces / logos / text / product details — use for portraits, brand assets, product-in-scene composites. low for sweeping style changes.
  • Without a mask, the whole image is repainted per the prompt (the semantic structure is preserved, but every region may change).

Example:

# Local inpaint with high fidelity: add a crown, keep the rest unchanged
prompt = "Put a tiny golden crown on the cat's head. Keep everything else unchanged."
input_fidelity = "high"
mask = (alpha PNG with only the head area transparent)

Differences vs the official OpenAI API

Dimension OpenAI official QCode.cc
SDK compatibility ✅ 100% compatible, only base_url changes
Pricing Per-token Per the table above, $0.08 / image floor
/v1/images/generations (text-to-image)
/v1/images/edits (image edit) Launched May 2026: 1–8 image composition, mask inpainting, input_fidelity high preservation, background transparent output
stream + partial_images (incremental return) ⏳ Not yet supported (full result returned at once)
/v1/images/variations (pure variants) ✅ (legacy DALL·E endpoint) ⏳ Not yet supported (use edits + high fidelity + empty prompt as a workaround)

Online Playground

https://api.qcode.cc/qcode-img/ — try in your browser:

  • Both Text-to-image and Image-edit modes are wired up visually (upload, draw mask, pick input_fidelity / background / output_format, etc.)
  • Enter your API key + prompt to generate immediately
  • English / Chinese UI toggle
  • Defaults to low quality (avoids CDN 524)
  • Includes full API reference inline (curl / Python / JavaScript tabs + parameter table + error codes)
  • One-click download as PNG / JPEG / WebP

Related Documents

Adaptive Thinking Configuration Guide
Adaptive thinking on Claude Opus 4.7 / Sonnet 4.6 / Haiku 4.5: thinking + effort parameters, differences from the legacy budget_tokens, and quality vs. cost trade-offs
AGENTS.md Configuration Guide
AGENTS.md is Codex's project configuration file -- define your AI coding assistant's behavior rules, similar to Claude Code's CLAUDE.md
Model Selection Guide
Understand the characteristics and applicable scenarios of different AI models to make the best choice.
🚀
Get Started with QCode — Claude Code & Codex
One plan for both Claude Code and Codex, Asia-Pacific low latency
View Pricing Plans → Create Account
Team of 3+?
Enterprise: dedicated domain + sub-key management + ban protection, from ¥250/person/mo
Learn Enterprise →