# GPT Image 2.5 on TokLab

> GPT Image 2.5 API reference for Flare and Sunburst on TokLab. One async endpoint for generation and edits, six quality levels, URL inputs.

Model ID: `gpt-image-2.5-flare`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-flare-official`, `gpt-image-2.5-sunburst-official`. [Playground and pricing](https://toklab.ai/models/gpt-image-2-5).
Use an API key from https://toklab.ai/apikeys as Authorization: Bearer $TOKLAB_API_KEY. Store the key on your server.

## Current pricing and worked estimates

Rates use the same source and one-minute refresh interval as the model page. All amounts are in USD.

GPT Image 2.5 prices are listed separately for each model ID. Per-image prices follow the selected quality; token-billed prices follow reported usage.

| Channel | Model IDs | Billed by | Current rate (USD) |
| --- | --- | --- | --- |
| Standard | `gpt-image-2.5-flare` | Per delivered image at the selected model and quality rate | Per delivered image: xhigh $0.0225; max $0.0225; other quality values $0.021 |
| Standard | `gpt-image-2.5-sunburst` | Per delivered image at the selected model and quality rate | Per delivered image: xhigh $0.0225; max $0.0225; other quality values $0.021 |
| Official | `gpt-image-2.5-flare-official` | Tokens each render reports (text input + image output) | $3.75 per 1M input tokens; $22.5 per 1M output tokens |
| Official | `gpt-image-2.5-sunburst-official` | Tokens each render reports (text input + image output) | $3.75 per 1M input tokens; $22.5 per 1M output tokens |

Token rates are the published first-tier rates; usage in a different tier may be charged differently.

### Cost of one 1024x1024 image by quality

Token counts are measured samples on the Official channel, with 18 input tokens for the prompt. Actual usage varies with the prompt, dimensions, references, and image count, so token-billed figures are estimates, not fixed prices. Per-image rates below follow each model's current quality pricing.

| Quality | Sample output tokens | Standard · GPT Image 2.5 Flare USD | Standard · GPT Image 2.5 Sunburst USD | Official · GPT Image 2.5 Flare USD | Official · GPT Image 2.5 Sunburst USD |
| --- | --- | --- | --- | --- | --- |
| low | 196 | $0.021 | $0.021 | $0.0044775 | $0.0044775 |
| medium | 439 | $0.021 | $0.021 | $0.009945 | $0.009945 |
| high | 1756 | $0.021 | $0.021 | $0.0395775 | $0.0395775 |
| xhigh | 3122 | $0.0225 | $0.0225 | $0.0703125 | $0.0703125 |
| max | 7024 | $0.0225 | $0.0225 | $0.1581075 | $0.1581075 |
| auto | 229 | $0.021 | $0.021 | $0.00522 | $0.00522 |

Formula (Official): (input tokens × 3.75 + output tokens × 22.5) / 1,000,000 USD.
A request for n images is billed for the images delivered. Final charges are available in account usage history. Failed requests are not charged.

## API reference

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](https://toklab.ai/models/gpt-image-2-5#pricing).

## Quick example

```bash
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"
  }'
```

```python
import os
import requests

response = requests.post(
    "https://api.toklab.ai/v1/images/generations",
    headers={"Authorization": f"Bearer {os.environ['TOKLAB_API_KEY']}"},
    json={
        "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",
    },
    timeout=60,
)
response.raise_for_status()
task_id = response.json()["id"]
```

```javascript
const response = await fetch('https://api.toklab.ai/v1/images/generations', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TOKLAB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    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',
  }),
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const { id: taskId } = await response.json();
```

```go
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "strings"
    "time"
)

func main() {
    body := strings.NewReader(`{
      "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"
    }`)
    req, err := http.NewRequest("POST", "https://api.toklab.ai/v1/images/generations", body)
    if err != nil { panic(err) }
    req.Header.Set("Authorization", "Bearer " + os.Getenv("TOKLAB_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    client := &http.Client{Timeout: 60 * time.Second}
    res, err := client.Do(req)
    if err != nil { panic(err) }
    defer res.Body.Close()
    if res.StatusCode != http.StatusOK { panic(res.Status) }
    var task struct { ID string `json:"id"` }
    if err := json.NewDecoder(res.Body).Decode(&task); err != nil { panic(err) }
    fmt.Println(task.ID)
}
```

## Endpoint

```text
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`) treat `null` as not sent.
* Any field not listed above is rejected, including `style`, `response_format` and `input_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

```bash
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](https://toklab.ai/models/gpt-image-2-5#pricing) 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:

```json
{
  "id": "task_...",
  "model": "gpt-image-2.5-flare",
  "status": "processing",
  "created_at": 1789970508
}
```

### Poll the task

```bash
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.

```python
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

```json
{
  "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:

```json
{
  "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](https://toklab.ai/docs/api/errors). If the submit call itself times out, look in your task history before retrying, since the first request may already have been accepted.

## Related

* [GPT Image 2.5 Playground and pricing](https://toklab.ai/models/gpt-image-2-5)
* [Task lifecycle](https://toklab.ai/docs/api/tasks)
* [OpenAPI schema](https://toklab.ai/docs/gpt-image-2-5.openapi.json)
* [This page as Markdown](https://toklab.ai/docs/gpt-image-2-5.md)

## More resources

- [GPT Image 2.5 API pricing: what one image costs at each quality](https://toklab.ai/blog/gpt-image-2-5-api-pricing.md): OpenAI bills GPT Image 2.5 by token. We measured the tokens a 1024×1024 image uses at each quality and priced them on OpenAI and on both TokLab routes. (HTML: https://toklab.ai/blog/gpt-image-2-5-api-pricing)
- [GPT Image 2.5 Flare vs Sunburst: what 23 renders told us](https://toklab.ai/blog/gpt-image-2-5-flare-vs-sunburst.md): Flare and Sunburst used the same tokens at every quality level we could compare, so they cost the same. Here is where they differed in speed and output. (HTML: https://toklab.ai/blog/gpt-image-2-5-flare-vs-sunburst)
- [OpenAPI request and response schemas](https://toklab.ai/docs/gpt-image-2-5.openapi.json)
- [API reference as Markdown](https://toklab.ai/docs/gpt-image-2-5.md)
- [Task lifecycle](https://toklab.ai/docs/api/tasks.md)
- [Error catalog and retry guidance](https://toklab.ai/docs/api/errors.md)
- [Account usage](https://toklab.ai/usage)
- [All model guides](https://toklab.ai/llms.txt)
- [Documentation index](https://toklab.ai/docs/llms.txt)
