Image
GPT Image 2.5
GPT Image 2.5 API reference for Flare and Sunburst on TokLab. One async endpoint for generation and edits, six quality levels, URL inputs.
GPT Image 2.5 comes as two models, Flare and Sunburst, and both take exactly the same request body. A request returns a task ID straight away; the images arrive on that task when rendering finishes. Text-to-image, reference edits and masked edits all go to the same endpoint.
Model IDs
| Model ID | Model | Billing |
|---|---|---|
gpt-image-2.5-flare | Flare, the faster of the two | Fixed price per image, set by quality |
gpt-image-2.5-sunburst | Sunburst, slower, holds detail better through edits | Fixed price per image, set by quality |
gpt-image-2.5-flare-official | Flare | Input and output tokens |
gpt-image-2.5-sunburst-official | Sunburst | Input and output tokens |
Switching between the four IDs never requires a change to the request body. Current rates for each one are on the GPT Image 2.5 page.
Quick example
curl https://api.toklab.ai/v1/images/generations \
-H "Authorization: Bearer $TOKLAB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2.5-flare",
"prompt": "A stack of three linen-bound notebooks on a walnut desk, morning side light",
"size": "1024x1024",
"quality": "low"
}'Endpoint
POST https://api.toklab.ai/v1/images/generations| Header | Value |
|---|---|
| Authorization | Bearer YOUR_API_KEY |
| Content-Type | application/json |
What the request contains decides the operation: a prompt alone generates, a prompt with images edits, and adding mask limits the edit to a region. The response is a task, never image bytes. Call the endpoint from your server so the key stays out of the browser.
Parameters
| Name | Type | Required | Default | Notes |
|---|---|---|---|---|
model | string | Yes | — | One of the four IDs above. |
prompt | string | Yes | — | Must contain non-whitespace text; at most 32,000 characters. |
images | object[] | No | — | 1 to 16 entries, each {"image_url":"https://..."}. Sending this makes the request an edit. |
mask | object | No | — | {"image_url":"https://..."}. Only valid together with images. |
size | string | No | auto | auto or WIDTHxHEIGHT within the size rules below. |
quality | enum | No | auto | auto, low, medium, high, xhigh, max. |
background | enum | No | auto | auto, opaque, transparent. |
output_format | enum | No | png | png or jpeg. |
output_compression | integer | No | 100 for JPEG | 0 to 100, JPEG only. 0 is a valid value. |
n | integer | No | 1 | 1 to 10 images per request. |
moderation | enum | No | auto | auto or low. |
user | string | No | — | Your own identifier for the end user. Keep personal data out of it. |
Size rules
1024x1024, 1536x1024 and 1024x1536 are the usual picks. A custom size passes only if all four of these hold:
- Width and height are both multiples of 16.
- Neither side is longer than 3840 pixels.
- Width divided by height is between 1:3 and 3:1.
- Width times height is between 655,360 and 8,294,400 pixels, both ends included.
So 3840x2160 and 2880x2880 pass, while 4096x2304 fails on the edge limit. With auto the model picks the dimensions. Ratio strings such as 16:9 are not accepted as size.
In the Playground, Ratio mode turns an aspect ratio plus a 1K, 2K or 4K preset into a single size value and shows it before you submit. There is no resolution or aspect_ratio field in the API; send the computed size. OpenAI labels output above 2560×1440 experimental: those sizes are accepted, but a bigger canvas does not promise more detail.
Quality
GPT Image 2 tops out at high; GPT Image 2.5 adds xhigh and max. Each step up renders more slowly. On the token-billed IDs it also produces more output tokens: at 1024x1024 we recorded 196 for low, 439 for medium, 1,756 for high, 3,122 for xhigh and 7,024 for max. Treat those as single observations. Size and image content move the count.
auto hands the choice to the model, so neither the tier nor the cost is fixed in advance. Iterating at low and moving up only for the keeper is the cheapest way to work.
Transparent backgrounds
Set background: "transparent" with PNG output. A transparent request with output_format: "jpeg" is rejected, because JPEG has no alpha channel. output_compression is likewise rejected unless the format is JPEG.
Other request rules
- The scalar options (
n,size,quality,background,output_format,output_compression,moderation) treatnullas not sent. - Any field not listed above is rejected, including
style,response_formatandinput_fidelity. - The Playground does not send
user; it exists for API callers.
Modes
| Operation | Send |
|---|---|
| Text to image | prompt |
| Reference edit | prompt + images |
| Masked edit | prompt + images + mask |
Edit example
curl https://api.toklab.ai/v1/images/generations \
-H "Authorization: Bearer $TOKLAB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2.5-sunburst",
"prompt": "Recolour the mug to deep forest green. Keep the table, the light and the steam exactly as they are.",
"images": [{"image_url": "https://example.com/mug.png"}],
"mask": {"image_url": "https://example.com/mug-mask.png"},
"output_format": "jpeg",
"output_compression": 90
}'Point both URLs at images you host. Drop mask to let the model edit the whole picture.
Media inputs
Inputs are URLs only. Base64, data: and blob: URLs, multipart uploads, raw bytes and OpenAI Files IDs are all refused. The Playground uploads the files you pick and sends their URLs for you.
- Reference images: public HTTP(S) URLs to PNG, JPEG or WebP, each under 50 MB.
- Mask: a PNG under 4 MB with the same pixel dimensions as the first reference image. Transparent pixels mark the area to change. With several references, the mask applies to the first.
The model treats the mask as guidance, so edges are not guaranteed to be pixel-exact. Media is fetched while the task runs; a URL that cannot be read fails the task, and a failed task is not charged.
Billing
The Standard IDs charge a fixed amount for each delivered image, and the amount depends on the model and the quality you pick. The -official IDs charge for the input and output tokens the render actually uses, so quality, size, reference images, prompt length and n all change the total. Rates are listed on the model page and read from the same ledger that bills your account.
The Playground estimate combines a measured sample with the current rate. It is a guide, not a quote; the actual charge for each task is in your usage history.
Response
Submitting returns the task:
{
"id": "task_...",
"model": "gpt-image-2.5-flare",
"status": "processing",
"created_at": 1789970508
}Poll the task
curl https://api.toklab.ai/v1/tasks/YOUR_TASK_ID \
-H "Authorization: Bearer $TOKLAB_API_KEY"Check every few seconds until status becomes completed or failed. If a poll times out, the render has not failed; ask about the same task ID again. Submitting a second request to find out where the first one is just creates a second paid task.
Polling example
This continues the Python example above. It stops waiting after ten minutes, which ends only the local loop: the task keeps running and the same ID can be queried later.
import time
print(f"Task ID: {task_id}")
deadline = time.monotonic() + 600
while time.monotonic() < deadline:
result = requests.get(
f"https://api.toklab.ai/v1/tasks/{task_id}",
headers={"Authorization": f"Bearer {os.environ['TOKLAB_API_KEY']}"},
timeout=30,
)
result.raise_for_status()
task = result.json()
if task["status"] == "completed":
for image in task["output"]["data"]:
print(image["url"])
break
if task["status"] == "failed":
raise RuntimeError(task["error"]["message"])
time.sleep(3)
else:
raise TimeoutError(f"Still waiting. Resume polling task {task_id}.")Completed task
{
"id": "task_...",
"model": "gpt-image-2.5-flare",
"status": "completed",
"created_at": 1789970508,
"finished_at": 1789970538,
"output": {
"created": 1789970532,
"data": [{"url": "https://.../task_example/0.png"}],
"usage": {
"input_tokens": 29,
"output_tokens": 196,
"total_tokens": 225
}
}
}| Field | Meaning |
|---|---|
id | The task ID to query. |
status | processing, completed or failed. |
created_at, finished_at | Unix seconds. finished_at is empty or zero until the task ends. |
output.data[].url | Hosted image URLs, present once the task completes. Copy them to your own storage if you need them long term. |
output.size, output.quality, output.background, output.output_format | What was actually rendered, when the model reports it. |
output.usage | Token usage, when reported. May include a text and image breakdown. |
error | Present on failed tasks. |
Delivery is asynchronous, so this is not a drop-in for the synchronous OpenAI Images SDK, and stream and partial_images are not available.
Errors
A request refused before a task exists gets an HTTP error status and an error object. A task that fails later still answers the poll with HTTP 200, status: "failed" and an error object:
{
"id": "task_...",
"status": "failed",
"error": {
"code": 60002,
"message": "Generation could not be completed. Please try again."
}
}Every model shares one error format; codes, statuses and when to retry are in the error catalog. If the submit call itself times out, look in your task history before retrying, since the first request may already have been accepted.
Pricing
Every rate this model is billed at, read live from the price list billing uses. A tier applies when its condition matches, checked top to bottom.
gpt-image-2.5-flaregpt-image-2.5-sunburst
per image| When | |
|---|---|
| Quality: xhigh or Quality: max | $0.0225 |
| Otherwise | $0.021 |
gpt-image-2.5-flare-officialgpt-image-2.5-sunburst-official
per 1M tokens| Input | $3.75 |
|---|---|
| Output | $22.50 |
| Cache read | $0.9375 |
| Image input | $6.00 |
| Image cache read | $1.50 |