# GPT Image 2.6

GPT Image 2.6 comes as two models, Flare and Sunburst, and both take the same request body. On top of GPT Image 2.5's fields it adds `complexity`, `markup`, animated GIF output and SVG output. A request returns a task ID straight away; the files arrive on that task when rendering finishes. Generation, reference edits, masked edits and markup edits all go to one endpoint.

## Model IDs

| Model ID                          | Model                                           | Billing                 |
| --------------------------------- | ----------------------------------------------- | ----------------------- |
| `gpt-image-2.6-flare`             | Flare, built for fast iteration                 | Fixed price per image   |
| `gpt-image-2.6-sunburst`          | Sunburst, more detail and steadier across edits | Fixed price per image   |
| `gpt-image-2.6-flare-official`    | Flare                                           | Input and output tokens |
| `gpt-image-2.6-sunburst-official` | Sunburst                                        | Input and output tokens |

The request body is the same for all four. Current rates for each one are on the [GPT Image 2.6 page](https://toklab.ai/models/gpt-image-2-6#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.6-flare",
    "prompt": "A ceramic espresso cup on a terrazzo counter, hard noon shadow",
    "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.6-flare",
        "prompt": "A ceramic espresso cup on a terrazzo counter, hard noon shadow",
        "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.6-flare',
    prompt: 'A ceramic espresso cup on a terrazzo counter, hard noon shadow',
    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.6-flare",
      "prompt": "A ceramic espresso cup on a terrazzo counter, hard noon shadow",
      "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`    |

The body decides the operation: a prompt alone generates, a prompt with `images` edits, and `mask` or `markup` points the edit at one area. The response is a task, never file 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://..."}`. Needs `images`; cannot be sent with `markup`.                 |
| `markup`             | object    | No       | —              | `{"image_url":"https://..."}`. Needs `images`; cannot be sent with `mask`.                   |
| `size`               | string    | No       | `auto`         | `auto` or `WIDTHxHEIGHT` within the size rules below.                                        |
| `quality`            | enum      | No       | `auto`         | `auto`, `low`, `medium`, `high`, `xhigh`, `max`.                                             |
| `complexity`         | enum      | No       | `high`         | `low`, `medium`, `high`. How much the model plans before it renders.                         |
| `background`         | enum      | No       | `auto`         | `auto`, `opaque`, `transparent`.                                                             |
| `output_format`      | enum      | No       | `png`          | `png`, `jpeg`, `gif`, `svg`.                                                                 |
| `output_compression` | integer   | No       | `100` for JPEG | 0 to 100, JPEG only.                                                                         |
| `frame_count`        | integer   | No       | `9`            | 2 to 16, GIF only.                                                                           |
| `frame_duration_ms`  | integer   | No       | `200`          | At least 20, GIF only.                                                                       |
| `svg`                | object    | No       | —              | SVG only. `{"model": "...", "reasoning": {"effort": "..."}}`; see SVG below.                 |
| `n`                  | integer   | No       | `1`            | 1 to 10. SVG requires 1.                                                                     |
| `moderation`         | enum      | No       | `auto`         | `auto` or `low`.                                                                             |
| `safety_identifier`  | string    | No       | —              | A stable ID for your end user, at most 128 characters. Keep personal data out of it.         |
| `user`               | string    | No       | —              | Older end-user identifier. Prefer `safety_identifier`.                                       |

`null` counts as not sent. Fields not in this table are dropped before the request reaches the model, so a misspelt field is ignored rather than rejected. That includes `stream`, `partial_images`, `response_format` and `input_fidelity`.

### Size rules

For PNG, JPEG and SVG, 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.

`1024x1024`, `1536x1024` and `1024x1536` are the usual picks; `3840x2160` passes and `4096x2304` fails on the edge limit. With `auto` the model picks the dimensions.

GIF sizes only need both sides to be multiples of 16, so `512x512` works. Every frame, and every image when `n` is above 1, draws on one pixel budget that OpenAI does not publish. Long or large GIFs can fail; keep frames small or use `auto`.

### Quality and complexity

`quality` sets rendering detail and, on the `-official` IDs, the output token count. `complexity` sets how much the model plans first. `low` suits a background swap or a sign change; `high` helps with dense text, busy layouts and objects that interact. Complexity has no separate charge, but a higher setting can take longer and change things you did not ask to change, so compare settings on your own task.

### Transparent backgrounds

`background: "transparent"` works with PNG, GIF and SVG. It is rejected with `output_format: "jpeg"`, and `output_compression` is rejected unless the format is JPEG.

## Animated GIF

```json
{
  "model": "gpt-image-2.6-flare",
  "prompt": "A paper boat bobbing on small waves, seamless loop, flat colours",
  "output_format": "gif",
  "size": "512x512",
  "quality": "low",
  "frame_count": 6,
  "frame_duration_ms": 150
}
```

Describe the motion and say the loop should be seamless. Frame durations are rounded to the nearest 10 ms. A GIF can start from reference images but cannot use a mask or compression. OpenAI's guide says edits do not return GIFs, so a GIF request with `images` can fail; a failed task is not charged.

OpenAI's image guide gives 2–64 frames and 20–2,000 ms per frame, while its Images API reference gives 2–16 frames and no maximum duration. In tests on November 5, 2026 the API rejected 17 frames and accepted 3,000 ms frames, so TokLab follows the reference.

## SVG

```json
{
  "model": "gpt-image-2.6-sunburst",
  "prompt": "A flat geometric paper-boat logo, two colours, clean editable paths",
  "output_format": "svg",
  "n": 1
}
```

SVG is for generation only: send `n: 1` and no `images`, `mask`, `markup` or `output_compression`. The model first renders a reference image, and `quality` applies to that image; a second model then writes the SVG. The result is static XML with vector shapes, delivered byte for byte. An SVG that contains scripts, external resources or embedded raster images is not delivered: the task fails and is not charged.

To choose the model that writes the SVG, add `"svg": {"model": "MODEL_ID"}`. A `svg` object needs a non-empty `model`. You can also set `svg.reasoning.effort` to `none`, `minimal`, `low`, `medium`, `high`, `xhigh` or `max`; which values work depends on that model. Leave `svg` out to use the default writer.

## Reference images, mask and markup

```json
{
  "model": "gpt-image-2.6-sunburst",
  "prompt": "Replace the circled sign with a blank wooden board",
  "images": [{"image_url": "https://example.com/street.png"}],
  "markup": {"image_url": "https://example.com/circle-overlay.png"},
  "complexity": "low"
}
```

| Operation      | Send                           |
| -------------- | ------------------------------ |
| Text to image  | `prompt`                       |
| Reference edit | `prompt` + `images`            |
| Masked edit    | `prompt` + `images` + `mask`   |
| Markup edit    | `prompt` + `images` + `markup` |

Inputs are URLs only. Base64, `data:` and `blob:` URLs, multipart uploads and OpenAI Files IDs are 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. An SVG is not accepted as input.
* Mask: a PNG under 50 MB with the same pixel dimensions as the first reference image. Transparent pixels mark the area to change.
* Markup: a PNG under 50 MB, drawn over the first reference image, with the same dimensions and some transparent pixels. Both it and the first image may hold at most 16,777,216 pixels. Draw a circle, an arrow or a scribble, then say in the prompt what should change there.

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 plain IDs charge a fixed amount for each delivered image. The `-official` IDs charge for the tokens the render uses, so quality, size, reference images, prompt length and `n` all move the total. An SVG also includes the tokens of the model that wrote it, reported as `svg_usage` and charged at that model's own TokLab rate. Rates are on the [model page](https://toklab.ai/models/gpt-image-2-6#pricing) and come from the same ledger that bills your account.

The Playground estimate covers still images only. GIF and SVG have no estimate; the actual charge for each task is in your usage history.

## Response

Submitting returns the task:

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

### 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`. A poll that times out does not mean the render failed; ask about the same task ID again. Submitting a second request to see where the first one is just creates a second paid task.

### Completed task

```json
{
  "id": "task_...",
  "model": "gpt-image-2.6-sunburst",
  "status": "completed",
  "created_at": 1793836800,
  "finished_at": 1793836841,
  "output": {
    "created": 1793836838,
    "data": [{"url": "https://.../task_example/0.svg"}],
    "output_format": "svg",
    "usage": {"input_tokens": 24, "output_tokens": 903, "total_tokens": 927},
    "svg_usage": {
      "model": "...",
      "input_tokens": 2310,
      "output_tokens": 1480,
      "reasoning_tokens": 0,
      "total_tokens": 3790
    }
  }
}
```

| 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 file URLs. Download them to keep the original format and, for a GIF, every frame. Copy them to your own storage if you need them long term. |
| `output.size`, `output.quality`, `output.background`, `output.output_format` | What was rendered, when the model reports it.                                                                                                      |
| `output.usage`                                                               | Image token usage, when reported.                                                                                                                  |
| `output.svg_usage`                                                           | SVG only: the writing model and its tokens, separate from `usage`.                                                                                 |
| `output.safety_identifier`                                                   | The value you sent, if any.                                                                                                                        |
| `error`                                                                      | Present on failed tasks.                                                                                                                           |

Delivery is asynchronous, so this is not a drop-in for the synchronous OpenAI Images SDK.

## 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. 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, check 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.6-flare · gpt-image-2.6-sunburst

| Image (per image) |
| --- |
| $0.021 |

### gpt-image-2.6-flare-official · gpt-image-2.6-sunburst-official

| Input (per 1M tokens) | Output (per 1M tokens) | Cache read (per 1M tokens) | Image input (per 1M tokens) | Image cache read (per 1M tokens) | Image output (per 1M tokens) |
| --- | --- | --- | --- | --- | --- |
| $3.75 | $22.50 | $0.9375 | $6.00 | $1.50 | $22.50 |

## Related

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