GPT Image 2.5 is live — OpenAI's newest image model, targeted edits that leave the rest of the frame alone
rreAPI Docs

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_KEY

Keys 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 (code 20002).
  • Longer than 32,000 chars → 400 prompt must be at most 32000 characters (code 20007).

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:3

This 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_urls set) → 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.

size1k2k4k
1:11024×10242048×20482880×2880
3:2 / 2:31536×10242048×13603520×2336
4:3 / 3:41024×7682048×15363312×2480
5:4 / 4:51280×10242560×20483216×2576
16:9 / 9:161536×8642048×11523840×2160
2:1 / 1:22048×10242688×13443840×1920
21:9 / 9:212016×8642688×11523840×1648
3:1 / 1:31536×5123072×10243840×1280
autoserver picksserver 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
}
FieldTypeNotes
idstringTask identifier — keep it for polling and audit
modelstringEcho of the submitted model
statusstringprocessing / completed / failed
created_atintegerSubmission unix timestamp
outputobject | nullnull until completion
output.image_urlsstring[]Generated image URLs — length = n, valid for 7 days
usageobjectBackward-compatible settlement summary
usage.creditsintegerWhole-credit compatibility value, rounded up
billingobjectSettlement evidence; returned only with ?include=billing
billing.sourcestringopenai_token_usage for exact token settlement, or reservation_estimate for the documented fallback
billing.credits_exactnumberFull formula-derived amount in credits; exact-token source only
billing.cost_usdnumberFull formula-derived amount in USD; exact-token source only
billing.credits_chargedintegerFinal reservation charge; reservation-estimate source only
billing.cost_usd_chargednumberFinal reservation charge in USD; reservation-estimate source only
errorobject | nullPopulated 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 codeMeaningOrigin
80001provider_submit_failedUpstream 5xx / network on submit
80002provider_polling_timeoutWall-clock cap reached while polling
80003provider_failedUpstream 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.

TriggerCodeMessage
prompt missing / empty20002prompt is required
prompt longer than 32,000 chars20007prompt must be at most 32000 characters
Unknown size value20003invalid 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 value20003invalid resolution "..." (allowed: 1k, 2k, 4k)
4k with auto or no size200034K requires one of the 15 documented ratios (listed under size) or a WxH pixel size
n outside 1–1020003n must be between 1 and 10
n > 4 together with image_urls20003n must be 4 or fewer for image-to-image requests on gpt-image-2-official
image_urls > 1620003image_urls accepts at most 16 entries
mask_url without image_urls20003mask_url requires at least one entry in image_urls
Any URL field carrying a data: URI20003image URL must be a public http(s) URL — data: URIs are rejected (or mask_url must be a public URL …)
Unknown background20003invalid <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 × resolutionTypical end-to-end
low × 1k20 – 40 s
medium × 1k30 – 60 s
high × 2k60 – 120 s
high × 4k120 – 180 s

Recommended cadence:

0–30s:    wait before the first poll
30s–3m:   poll every 3–5s
3m+:      back off to 10s; cap at 30s

Set 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. Use size for shape and the prompt for content / style.
  • Set quality explicitly for predictability. auto is 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 400 from upstream.
  • Pre-cache reference images. The upstream fetches each image_urls entry once per submit; if your CDN is slow, latency shows up as polling time, not as billing.

Differences from gpt-image-2

Featuregpt-image-2gpt-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)✅✅
Pricingflat per resolutionactual 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

Table of Contents