gpt-image-2-official
GPT Image 2 stable channel — full feature surface with quality tiers, batches up to 10, and mask inpainting.
The stable channel of GPT Image 2 on reAPI — async
/api/v1/images/generations with the full feature surface: quality tiers
(auto / low / medium / high), batches up to 10 images, and
mask-based inpainting. The channel always
returns PNG. See current pricing on the
model page.
Wire id is gpt-image-2-official. The doc / pricing page /
playground all label this variant as "Stable" for clarity, but the
request body must set "model": "gpt-image-2-official". The shorter
gpt-image-2 is a separate variant — see
Differences from gpt-image-2.
Quick example
curl https://reapi.ai/api/v1/images/generations \
-H "Authorization: Bearer rk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2-official",
"prompt": "ancient castle beneath a starry sky",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"n": 1
}'import requests
resp = requests.post(
"https://reapi.ai/api/v1/images/generations",
headers={
"Authorization": "Bearer rk_live_xxx",
"Content-Type": "application/json",
},
json={
"model": "gpt-image-2-official",
"prompt": "ancient castle beneath a starry sky",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"n": 1,
},
timeout=30,
)
print(resp.json())const r = await fetch("https://reapi.ai/api/v1/images/generations", {
method: "POST",
headers: {
Authorization: "Bearer rk_live_xxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-image-2-official",
prompt: "ancient castle beneath a starry sky",
size: "16:9",
resolution: "2k",
quality: "high",
n: 1,
}),
});
console.log(await r.json());package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]any{
"model": "gpt-image-2-official",
"prompt": "ancient castle beneath a starry sky",
"size": "16:9",
"resolution": "2k",
"quality": "high",
"n": 1,
})
req, _ := http.NewRequest("POST",
"https://reapi.ai/api/v1/images/generations", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer rk_live_xxx")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}Submit response
{
"id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
"model": "gpt-image-2-official",
"status": "processing",
"created_at": 1735000000
}Poll GET /api/v1/tasks/{id} (see the Tasks reference) until
status === "completed". The completed payload's output.image_urls
holds the generated image URLs (length = n), valid for 7 days.
Authentication
Every call needs a Bearer token. Generate keys at reapi.ai/settings/apikeys.
Authorization: Bearer YOUR_API_KEYKeys carry the active workspace's billing scope — there is no separate project header.
Endpoint
POST /api/v1/images/generations
GET /api/v1/tasks/{id}Submission is async. The POST returns immediately with an id; the
task endpoint returns the same envelope until completion. Polling does
not consume credits.
Request body
The API and the model-page Playground use the same public field names, values,
and validation whenever a field is shown in the Playground. The Playground
does not silently add a different quality, background, or billing mode.
It initializes size to "1:1"; API image-to-image requests may instead omit
size to inherit the first reference image's ratio. The API additionally
accepts explicit WIDTHxHEIGHT strings; use the API directly when that
custom-size input is not shown in the UI.
model — required
string. Must be "gpt-image-2-official".
prompt — required
string, 1–32,000 characters. English and Chinese both supported.
Detailed prompts produce better results. Every prompt goes through
pre-submission moderation; rejected prompts return 400 at no charge.
Don't restate the ratio in the prompt — pass it via size.
Repeating it confuses the upstream.
Failure modes.
- Missing / empty →
400 prompt is required(code20002). - Longer than 32,000 chars →
400 prompt must be at most 32000 characters(code20007).
size — string, default "1:1"
Output ratio. One of these 16 values (or auto to let the upstream
pick from the prompt / first reference image):
auto
1:1 16:9 9:16 4:3 3:4
3:2 2:3 5:4 4:5
2:1 1:2 21:9 9:21
3:1 1:3This channel additionally accepts a pixel string WIDTHxHEIGHT (e.g.
1024x1024, 1536x864, 3840x2160), returned at exactly those
dimensions. Width and height must both be multiples of 16 — the
upstream rejects anything else with 400 pixel dimensions must be multiples of 16. The aspect ratio must be between 1:3 and 3:1,
and the longest edge must not exceed 3840. Anything outside the
list and not a pixel string is rejected with 400.
When size is omitted:
- T2I (no
image_urls) → defaults to"1:1". - I2I (
image_urlsset) → output mirrors the first reference image's ratio (upstream-side derivation; gateway omits the field).
4K constraint
resolution: "4k" works with every ratio below. size is required
when resolution: "4k" — auto is the one value the upstream cannot
resolve at this tier, so 4K without an explicit ratio is rejected
before the request leaves the gateway.
size | 1k | 2k | 4k |
|---|---|---|---|
1:1 | 1024×1024 | 2048×2048 | 2880×2880 |
3:2 / 2:3 | 1536×1024 | 2048×1360 | 3520×2336 |
4:3 / 3:4 | 1024×768 | 2048×1536 | 3312×2480 |
5:4 / 4:5 | 1280×1024 | 2560×2048 | 3216×2576 |
16:9 / 9:16 | 1536×864 | 2048×1152 | 3840×2160 |
2:1 / 1:2 | 2048×1024 | 2688×1344 | 3840×1920 |
21:9 / 9:21 | 2016×864 | 2688×1152 | 3840×1648 |
3:1 / 1:3 | 1536×512 | 3072×1024 | 3840×1280 |
auto | server picks | server picks | ❌ |
3:2 / 2:3 at 2K resolves to 2048×1360 — 1360 is the nearest
16-aligned approximation of 3:2 (under 0.5% off). Other cells are
exact.
4K needs an explicit ratio. Every ratio in the table above is
valid at resolution: "4k" — the model maps each one to a size that
respects its limits (longest edge ≤ 3840, ≤ 8,294,400 px total), so
1:1 becomes 2880×2880 rather than being rejected. Only auto is
unsupported at 4K, because the server cannot pick a ratio and a 4K
size at the same time; sending 4K with auto or with no size
returns 400 (code 20003).
resolution — string, default "1k"
1k / 2k / 4k. Case-insensitive — "2K" and "2k" are
equivalent. It drives output dimensions and the pre-submit estimate; final
billing uses actual token usage.
quality — string, default "auto"
auto / low / medium / high. Higher tiers are slower and typically
produce more output tokens; final billing uses actual usage.
auto is decided by the model. reAPI forwards auto (and uses it when
quality is omitted). The final charge is calculated from the actual image
output tokens reported for that request. The temporary admission reservation
uses the calculator's medium estimate and is replaced at completion, so do
not assume that auto always has the same cost as low. Set a quality
explicitly when you need predictable quality behavior.
background — string, default "auto"
auto / opaque / transparent. Controls whether the returned PNG
carries an alpha channel.
auto— the model decides (default).opaque— flat, fully opaque background.transparent— returns a real alpha channel, so the subject can be composited directly. Best paired with a prompt that asks for an isolated subject (e.g. "a cartoon cat sticker, isolated on a fully transparent background").
background does not add a pricing multiplier. In particular,
background: "transparent" is not the reason a token-metered request costs
more or less; its final price still comes from the reported text-input,
image-input, and image-output usage.
moderation — string, default "auto"
auto / low. OpenAI's content-moderation level for the request.
auto— the standard filter (default).low— less restrictive filtering. Generated images still go through the provider's safety check, so a request can be rejected at either level.
Stable channel only, through the API. The website playground always submits
auto.
n — integer, default 1
Number of images per request. Range 1–10. Output tokens grow with the
number of generated images, while shared prompt/reference input is metered from
the actual request usage. output.image_urls length matches n.
image_urls — string[]
Reference images for image-to-image. Up to 16 entries. Triggers I2I when set. Public HTTP(S) URLs only.
No data: URIs. reAPI rejects base64 inputs platform-wide. Upload
to your own object storage (S3 / R2 / OSS) and pass the URL.
mask_url — string
PNG mask URL for inpainting. Requires image_urls with at least
one entry. The mask must:
- carry an alpha channel where the model should paint, and
- share dimensions with the first entry in
image_urls.
Public HTTP(S) URL only. Mismatched dimensions or a fully opaque mask
return 400 from upstream.
Response envelope
The submit response contains id, model, status, and created_at. Poll
GET /api/v1/tasks/{id} for output, usage, and error.
The example below uses GET /api/v1/tasks/{id}?include=billing. Omit the query
parameter to preserve the legacy response field set; this does not change the
underlying token-metered charge.
{
"id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
"model": "gpt-image-2-official",
"status": "completed",
"created_at": 1735000000,
"output": {
"image_urls": [
"https://cdn.reapi.ai/media/tasks/018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e/0.png",
"https://cdn.reapi.ai/media/tasks/018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e/1.png"
]
},
"usage": {
"credits": 39
},
"billing": {
"source": "openai_token_usage",
"credits_exact": 38.966,
"cost_usd": 0.038966,
"text_input_tokens": 396,
"image_input_tokens": 2482,
"image_output_tokens": 571
},
"error": null
}| Field | Type | Notes |
|---|---|---|
id | string | Task identifier — keep it for polling and audit |
model | string | Echo of the submitted model |
status | string | processing / completed / failed |
created_at | integer | Submission unix timestamp |
output | object | null | null until completion |
output.image_urls | string[] | Generated image URLs — length = n, valid for 7 days |
usage | object | Backward-compatible settlement summary |
usage.credits | integer | Whole-credit compatibility value, rounded up |
billing | object | Settlement evidence; returned only with ?include=billing |
billing.source | string | openai_token_usage for exact token settlement, or reservation_estimate for the documented fallback |
billing.credits_exact | number | Full formula-derived amount in credits; exact-token source only |
billing.cost_usd | number | Full formula-derived amount in USD; exact-token source only |
billing.credits_charged | integer | Final reservation charge; reservation-estimate source only |
billing.cost_usd_charged | number | Final reservation charge in USD; reservation-estimate source only |
error | object | null | Populated on failed — { code, message } |
Upstream errors (502 / 503)
reAPI does not surface raw upstream 5xx codes to the caller. When
the upstream provider returns 502 Bad Gateway, 503 Service Unavailable, or a connection failure, the worker retries up to 5
attempts with exponential backoff (~30s total budget). If all retries
fail, the task ends with one of these reAPI-specific codes (returned
via GET /api/v1/tasks/{id} as error.code):
| reAPI code | Meaning | Origin |
|---|---|---|
80001 | provider_submit_failed | Upstream 5xx / network on submit |
80002 | provider_polling_timeout | Wall-clock cap reached while polling |
80003 | provider_failed | Upstream returned a terminal failure |
See Errors catalog for the full code list.
Validation errors
All cases below return HTTP 400 with the noted code. Pattern-match on
code, not message — message strings carry request-specific context
(field names, observed values) and are not a stable contract.
| Trigger | Code | Message |
|---|---|---|
prompt missing / empty | 20002 | prompt is required |
prompt longer than 32,000 chars | 20007 | prompt must be at most 32000 characters |
Unknown size value | 20003 | invalid size "..." (allowed: 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 5:4, 4:5, 2:1, 1:2, 21:9, 9:21, 3:1, 1:3, auto, or WxH pixels) |
Unknown resolution value | 20003 | invalid resolution "..." (allowed: 1k, 2k, 4k) |
4k with auto or no size | 20003 | 4K requires one of the 15 documented ratios (listed under size) or a WxH pixel size |
n outside 1–10 | 20003 | n must be between 1 and 10 |
n > 4 together with image_urls | 20003 | n must be 4 or fewer for image-to-image requests on gpt-image-2-official |
image_urls > 16 | 20003 | image_urls accepts at most 16 entries |
mask_url without image_urls | 20003 | mask_url requires at least one entry in image_urls |
Any URL field carrying a data: URI | 20003 | image URL must be a public http(s) URL — data: URIs are rejected (or mask_url must be a public URL …) |
Unknown background | 20003 | invalid <field> "..." (allowed: …) |
The full envelope is { "error": { "code", "message", "request_id" } } —
see Errors catalog for the wire format and
request_id correlation.
Recipes
Text-to-image — minimal
{
"model": "gpt-image-2-official",
"prompt": "ancient castle beneath a starry sky"
}2K poster
{
"model": "gpt-image-2-official",
"prompt": "cyberpunk night cityscape",
"size": "16:9",
"resolution": "2k",
"quality": "high"
}4K wallpaper
{
"model": "gpt-image-2-official",
"prompt": "panoramic snow-capped mountains at sunrise",
"size": "16:9",
"resolution": "4k",
"quality": "high"
}Multi-reference fusion (image-to-image)
{
"model": "gpt-image-2-official",
"prompt": "blend the two references into one cohesive illustrated poster",
"size": "1:1",
"quality": "high",
"image_urls": [
"https://your-cdn.com/input-a.png",
"https://your-cdn.com/input-b.png"
]
}Mask-based inpainting
The mask must match the dimensions of the first image_urls entry
and carry an alpha channel where the model should paint.
{
"model": "gpt-image-2-official",
"prompt": "replace the background with a desert sunset",
"size": "1:1",
"quality": "medium",
"image_urls": ["https://your-cdn.com/photo.png"],
"mask_url": "https://your-cdn.com/mask.png"
}Batch of 4 variations
{
"model": "gpt-image-2-official",
"prompt": "four minimalist poster variations of a red fox",
"size": "1:1",
"quality": "low",
"n": 4
}Polling pattern
Latency depends heavily on quality and resolution:
quality × resolution | Typical end-to-end |
|---|---|
low × 1k | 20 – 40 s |
medium × 1k | 30 – 60 s |
high × 2k | 60 – 120 s |
high × 4k | 120 – 180 s |
Recommended cadence:
0–30s: wait before the first poll
30s–3m: poll every 3–5s
3m+: back off to 10s; cap at 30sSet client-side request timeouts to ≥ 180 seconds when using
quality: "high" with 2k / 4k.
The worker's wall-clock cap is 1 hour (image tasks), comfortably above any realistic queue.
Pricing
The submit response uses the model page / Playground estimate as a temporary credit reservation. Successful completion replaces that estimate with the actual token-metered amount and atomically refunds or deducts the difference.
Final bill formula (OpenAI standard rates; 1 credit = $0.001):
official_usd =
text_input_tokens × $5 / 1,000,000
+ image_input_tokens × $8 / 1,000,000
+ image_output_tokens × $30 / 1,000,000
official_micro_usd =
text_input_tokens × 5
+ image_input_tokens × 8
+ image_output_tokens × 30
final_micro_usd =
ceil(official_micro_usd × factor_basis_points / 10,000)
billing.cost_usd = final_micro_usd / 1,000,000
billing.credits_exact = final_micro_usd / 1,000
charged_micro_usd = final_micro_usd - shortfall_micro_usd
usage.credits = ceil(charged_micro_usd / 1,000)The factor applies to the product as a whole, not to a different rate for each
size, quality, background, or provider route. Billing is retained to micro-USD
precision and rounds upward only once at that boundary (less than one
micro-USD), so integer-credit rounding does not distort small image charges.
The integer usage.credits / credits_actual field remains a rounded-up
summary of the amount collected so existing strongly typed clients keep both
the same wire type and the same field meaning. Reconcile the full formula-derived
amount against billing.credits_exact or billing.cost_usd.
If the winning provider returns images but omits a required usage meter, reAPI
still completes the task and makes the admission reservation the final
whole-credit charge. The same fallback applies when a provider returns at
least one usable image but fewer than n, or when
aggregate token usage cannot be attributed to the retained images. A partial
batch is delivered as a successful task and does not trigger a second paid
provider attempt.
With ?include=billing, these cases return
source: "reservation_estimate", credits_charged, and
cost_usd_charged; they do not return credits_exact or token counts. Because
this fallback is an estimate rather than actual usage, the exact-token error
bound applies only when source is openai_token_usage.
cached_tokens is retained as usage metadata but does not change the sell
formula. Reported text and image input totals use the configured standard input
rates; reAPI does not apply a separate cache discount.
If the actual amount is greater than the reservation and the remaining balance
cannot cover the difference, the generated task still completes, the balance
is reduced to zero, and reAPI records the remainder internally as a shortfall.
The opt-in billing object continues to show the full formula-derived actual
amount, while usage.credits shows the rounded amount collected from the balance.
Failed tasks refund the reservation. Moderated prompts rejected before submit have no balance impact.
Completed-task evidence. GET /api/v1/tasks/{id}?include=billing always
identifies the settlement source. With complete usage it returns
billing.credits_exact, billing.cost_usd, and the reported text/image input
and image-output token counts. Without trustworthy usage it returns the final
reservation charge under credits_charged / cost_usd_charged. The model page
and Playground remain estimates because actual usage does not exist before
generation.
Tips
- Specify ratio in
size, not in the prompt. Repeating "16:9 wide shot" inside the prompt confuses the upstream. Usesizefor shape and the prompt for content / style. - Set
qualityexplicitly for predictability.autois selected by the model and is settled from actual output tokens. - Batches use actual usage. Output work scales with
n; shared prompt and reference input is not blindly multiplied a second time by reAPI. - Mask alpha matters. The mask's transparent regions are where the
model paints; opaque regions are preserved. A fully opaque mask
returns
400from upstream. - Pre-cache reference images. The upstream fetches each
image_urlsentry once per submit; if your CDN is slow, latency shows up as polling time, not as billing.
Differences from gpt-image-2
| Feature | gpt-image-2 | gpt-image-2-official (this page) |
|---|---|---|
| Endpoint | /api/v1/images/generations | /api/v1/images/generations |
| Async / task model | ✅ | ✅ |
size aspect-ratio enums (15, plus auto) | ✅ | ✅ |
Resolution tiers (1k / 2k / 4k) | ✅ | ✅ |
Image-to-image (image_urls) | ✅ | ✅ |
| Pricing | flat per resolution | actual text/image input and image output tokens × product factor |
Batch (n > 1) | ❌ | ✅ up to 10 (t2i) / 4 (i2i) |
| Quality tiers | ❌ | ✅ auto / low / medium / high |
Mask inpainting (mask_url) | ❌ | ✅ |
Background control (background) | ❌ | ✅ auto / opaque / transparent (real alpha) |
Moderation (moderation) | ❌ | ✅ auto / low |
Related
gpt-image-2— cheaper variant, single image, flat per-resolution pricing- Errors catalog
- Authentication
- Quickstart
- Pricing — gpt-image-2