GPT Image 2.6
Generate 1–4 images from a prompt as PNG, JPEG, WebP, animated GIF or SVG, at an aspect ratio or an exact size, billed per image.
GPT Image 2.6 (product gpt_image) generates images from a prompt, optionally guided by up to 16 reference images. Like GPT Image 2.5 it has two variants (flare and sunburst), five quality levels and transparent backgrounds, at the same price; it adds the output format (png, jpeg, webp, an animated gif or a vector svg) and an exact width and height (size). One task makes 1–4 images, billed per image by quality and resolution.
Create a task
https://api.nanoapi.ai/v1/tasksUse the shared create endpoint with model: "gpt-image-2.6". It usually responds in under 1 second, and the cost of num_outputs images is frozen within a few seconds. Get the result once the task has finished.
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <API key>, see Authentication. |
Content-Type | Yes | application/json |
Idempotency-Key | No | A unique string for every new task, ideally a UUID (1–255 characters). See Preventing duplicate tasks. |
Body
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | gpt-image-2.6. |
prompt | string | Yes | What to generate, at most 8000 characters. Refer to the reference images as @Image1, @Image2…, see Referring to images. |
image_urls | string[] | No | Up to 16 reference images; leave it out to generate from the prompt alone. Not with svg. See Media. |
variant | string | Yes | flare or sunburst, with the same parameters and price. flare is fast, for everyday creation and high-volume generation; sunburst gives more precise details and edits for polished, final-quality images and takes longer. |
quality | string | Yes | low, medium, high, xhigh or max. Sets the price. |
resolution | string | Yes | 1k, 2k or 4k. Sets the price. gif and svg take 1k only. |
output_format | string | Yes | png, jpeg, webp, gif (animated) or svg (vector). Doesn't change the price; rules per format in Output formats. |
aspect_ratio | string | See description | auto, 1:1, 3:2, 2:3, 4:3, 3:4, 16:9, 9:16, 21:9, 27:16, 16:27, 9:8, 8:9, 4:5 or 5:4. auto follows the first reference image, or gives 1:1 without any. Not gif: send either aspect_ratio or size, not both. gif: not allowed. |
size | string | See description | An exact width and height, <width>x<height> with a lowercase x, for example 1024x768 (no auto), within the size rules. Not gif: send either aspect_ratio or size. gif: required, the size of each frame. |
frame_count | integer | gif: yes | Number of frames, 2–64. gif only. |
frame_duration_ms | integer | gif: yes | How long each frame shows, 20–2000 milliseconds. gif only. |
background | string | No | auto, opaque or transparent. Left out, auto and opaque all give an opaque background; only transparent gives a transparent one (reference images work too): png and webp with an alpha channel, gif with a transparent colour, svg without a background shape. jpeg can't be transparent. Asking for a transparent background in the prompt alone doesn't work: the model paints a grey-and-white checkerboard that looks transparent but isn't. |
num_outputs | integer | Yes | How many images, 1–4. All of them are frozen; only the ones generated are charged, see Pricing. |
webhook_url | string | No | Notified when the task succeeds or fails: https, up to 2048 characters, not a private, loopback or reserved address. See Webhooks. |
Any other parameter, such as the other image models' seed or remove_bg, returns 400 invalid_request, see Errors.
Output formats
output_format | resolution | Image size | Also |
|---|---|---|---|
png, webp | 1k, 2k, 4k | aspect_ratio or size | background: "transparent" keeps the alpha channel. |
jpeg | 1k, 2k, 4k | aspect_ratio or size | No background: "transparent". |
gif | 1k | size (each frame) | frame_count and frame_duration_ms required. No aspect_ratio. |
svg | 1k | aspect_ratio or size | No image_urls. |
frame_count and frame_duration_ms are only accepted with gif: remove them when you switch to another format.
Size rules
A size that breaks these rules returns 400 invalid_request with param "size":
| Rule | Not gif | gif |
|---|---|---|
| Width and height | Multiples of 16 | Multiples of 16 |
| Long side | At most 3 × the short side, at most 3840 | At most 3 × the short side, at most 1280 |
| Total pixels (width × height) | 655360–8294400 | 72818–921600 |
The total pixels can't go over the resolution's cap (only the total counts, not the long side):
resolution | Most pixels | For example |
|---|---|---|
1k | 1075200 | 1024x1024, 1024x768, 1120x960, 1536x512 |
2k | 4194304 | 2048x2048, 2048x1152 |
4k | 8294400 | 3840x2160, 2160x3840 |
For a larger image, raise resolution (svg only takes 1k, so at most 1075200 pixels). A size smaller than the tier works but is billed at the tier you sent: 4k with 1024x768 gives a 1024×768 image at the 4k price, so pick the lowest resolution that fits. Sizes that work for gif: 288x288, 512x512, 768x768, 512x288, 288x512, 912x304.
Two 16:9 WebP images from one reference image, at an exact 2048×1152 and high quality:
curl https://api.nanoapi.ai/v1/tasks \
-H "Authorization: Bearer $NANOAPI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7c3f1e92-4a6b-4d0e-9b8f-5e2a1c7d9f34" \
-d '{
"model": "gpt-image-2.6",
"prompt": "Put a red apple next to the mug in @Image1",
"image_urls": ["https://example.com/mug.jpg"],
"variant": "flare",
"quality": "high",
"resolution": "2k",
"output_format": "webp",
"size": "2048x1152",
"num_outputs": 2
}'An animated GIF: 4 frames of 512×512, 100 ms each (gif needs 1k, size, frame_count and frame_duration_ms, and no aspect_ratio):
curl https://api.nanoapi.ai/v1/tasks \
-H "Authorization: Bearer $NANOAPI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 1b8d4f60-2e7a-4c93-a5d1-8f0e6b3c2a17" \
-d '{
"model": "gpt-image-2.6",
"prompt": "A red ball bouncing up and down, simple looping animation",
"variant": "flare",
"quality": "low",
"resolution": "1k",
"output_format": "gif",
"size": "512x512",
"frame_count": 4,
"frame_duration_ms": 100,
"num_outputs": 1
}'A square SVG logo (svg needs 1k and takes no image_urls):
curl https://api.nanoapi.ai/v1/tasks \
-H "Authorization: Bearer $NANOAPI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9e2a7c15-6d3b-4f8e-b0a4-3c1f5d7e9b62" \
-d '{
"model": "gpt-image-2.6",
"prompt": "A flat minimalist fox logo",
"variant": "flare",
"quality": "medium",
"resolution": "1k",
"output_format": "svg",
"aspect_ratio": "1:1",
"num_outputs": 1
}'Response: 200 OK. data is the newly created task, with only these fields; each one is described in Create a task: Response. Keep data.id to get the result. The task can still fail after it's created (for example if your balance can't cover it), so go by what retrieving the task or the webhook tells you.
{
"code": 200,
"message": "success",
"data": {
"object": "task",
"id": "tk_01jbm2r7c5x8v1n4q6t9w3e0y2",
"model": "gpt-image-2.6",
"status": "queued",
"error": null,
"created_at": "2026-11-05T08:30:00Z"
}
}Get the result
As a rough guide (generation only, not counting the queue, plus a few seconds to store the files; slower when the provider is busy): png at 1k about 20 seconds, gif and svg about 25–45 seconds; higher quality, sunburst and reference images take longer. The images of a task are generated in parallel, so several take about as long as one. Once the task has finished (succeeded or failed), get the result either way:
- Webhook (recommended in production): if you passed
webhook_url, the full task is pushed to it once when the task finishes. See Webhooks. - Polling: call
GET /v1/tasks/{task_id}withdata.idat most once every 15 seconds untilstatusissucceededorfailed. Check several tasks at once withidsin List tasks.
The WebP request above, once it has succeeded (other fields left out):
{
"status": "succeeded",
"input": {
"prompt": "Put a red apple next to the mug in @Image1",
"image_urls": ["https://example.com/mug.jpg"],
"variant": "flare",
"quality": "high",
"resolution": "2k",
"output_format": "webp",
"size": "2048x1152"
},
"num_outputs": 2,
"outputs": [
{
"index": 0,
"type": "image",
"url": "https://cdn.nanoapi.ai/h/tk_01jbm2r7c5x8v1n4q6t9w3e0y2_1_1793867400.webp",
"preview_url": "https://cdn.nanoapi.ai/h/tk_01jbm2r7c5x8v1n4q6t9w3e0y2_1_1793867400_compressed.jpg"
},
{
"index": 1,
"type": "image",
"url": "https://cdn.nanoapi.ai/h/tk_01jbm2r7c5x8v1n4q6t9w3e0y2_2_1793867400.webp",
"preview_url": "https://cdn.nanoapi.ai/h/tk_01jbm2r7c5x8v1n4q6t9w3e0y2_2_1793867400_compressed.jpg"
}
],
"billing": {
"currency": "USD",
"frozen": "…", // 2 × the high 2k price per image
"charged": "…", // the same: both images were generated
"refunded": "0.00",
"billed_seconds": null
}
}| Field | GPT Image 2.6 |
|---|---|
outputs | One item per generated image, at most num_outputs. |
outputs[].type | image, for every format. |
outputs[].url | The original file in the output_format you asked for, with the matching extension (.png, .jpeg, .webp, .gif, .svg); use that extension when you save it. Use it to download or show the image full size, and for gif to show the animation. |
outputs[].preview_url | A JPEG preview, at most 1024 pixels on the long side (smaller images aren't enlarged), with any transparency shown as white. Use it for lists and thumbnails, or url when it's null. For gif it's only the first frame. For svg it's always null: show url. |
billing.billed_seconds | Always null: images are billed per image. |
input | The parameters you sent: always variant, quality, resolution and output_format, and one of aspect_ratio and size (gif: size, frame_count and frame_duration_ms); the optional image_urls and background only if you sent them. |
An SVG file can contain scripts. Show it on a web page with <img src="…">; never insert its markup into the page. If you store SVG files on your own domain, serve them with Content-Disposition: attachment.
On failure the frozen amount is returned in full and the reason is in data.error.type, see Errors. Every field is described in The task object.
Image sizes
With aspect_ratio, the sizes are the same as GPT Image 2.5's, see GPT Image 2.5 → Image sizes; quality, variant and output_format don't change them, and the size of auto depends on the reference images. With size, the image is exactly that size (for gif, each frame).
Fewer images than requested
Each image is generated on its own. If some can't be made (for example because moderation blocked them), the task still succeeded: outputs only has the images that were generated, fewer than num_outputs. Only those are charged and the rest of the frozen amount is returned (billing.refunded). The task fails only when no image could be generated, and then everything frozen is returned: if at least one of them was blocked by moderation, the reason is content_policy (not every image has to be blocked), otherwise usually generation_failed. outputs[].index numbers the generated images from 0 without gaps, so when there are fewer it doesn't match the position in your request: don't use it to pair images with anything.
Media
Reference images are passed in image_urls as public http(s) URLs. There's no upload endpoint: host the files yourself. URLs are at most 4096 characters, must download directly and can't point to localhost or private, loopback or reserved addresses.
Reference images (image_urls) | |
|---|---|
| Count | 0–16 (limits.max_reference_images in GET /v1/products); none with output_format: "svg" |
| Formats | JPEG, PNG, WebP, AVIF, GIF (the first frame), BMP and TIFF. HEIC / HEIF aren't supported: iPhone photos are HEIC by default, so convert them to JPEG first. |
| Transparency | A transparent PNG is flattened onto white before it's used. |
| If there's a problem | Read only when generation runs, after the cost was frozen: if an image can't be downloaded or its format isn't supported, the task fails with invalid_media and the frozen amount is returned in full. |
Keep every link reachable until the task finishes, including links that expire.
Referring to images in the prompt
In prompt | Refers to |
|---|---|
@Image1, @Image2, … | The images in image_urls, in order. |
- A reference beyond the images you sent (for example
@Image2with one image, or any@Imagewithoutimage_urls) returns400 invalid_requestwithparam"prompt", and no task is created. - An
@right after a letter, digit or dot isn't a reference, so an email address such asbob@image2go.comin the prompt is fine.
Pricing
frozen = price per image of the quality and resolution × num_outputs
charged = price per image of the quality and resolution × images generatedLoading the current prices…
- The same prices as GPT Image 2.5: both models are in product
gpt_imageand share its price rows. - Only
qualityandresolutionchange the price.variant,output_format,size,aspect_ratio, the frame count and duration,backgroundand reference images don't. sizedoesn't lower the price: a size smaller than theresolutiontier is billed at the tier, see Size rules.- The cost of all
num_outputsimages is frozen within a few seconds of creating the task. When it succeeds, each generated image is charged and the rest is returned, see Fewer images than requested; when it fails, all of it is returned.
Example: the WebP request above (high, 2k, num_outputs 2) freezes 2 × the high 2k price per image and is charged the same when both images are generated; the GIF request freezes 1 × the low 1k price, whatever the number of frames. How freezing and charging work in general: Billing.
The price is known from the request, so you can show it before submitting: read the current prices from GET /v1/products (product gpt_image, one prices row per quality and resolution). Prices change, so don't hard-code them; billing.frozen on the retrieved task is what counts.
Errors
Errors and failure reasons specific to this model. Every error of the create endpoint: Create a task → Errors; every failure reason: Failure reasons.
Create request errors: the request fails with an HTTP error and no task is created. param names the parameter; message explains it in English and can be shown to your users as is.
| Status | error.type | When | What to do |
|---|---|---|---|
400 | invalid_request | A required parameter is missing (Field required, param names it) or prompt is empty (prompt is required). | Send every required parameter, see Create a task. |
400 | invalid_request | The prompt refers to an image you didn't send, with param "prompt" (for example prompt references @Image2, but image_urls has 1 image: use @Image1). | Fix the reference, or add the image to image_urls. |
400 | invalid_request | variant, quality, resolution, output_format, aspect_ratio or background isn't one of the values above, frame_count isn't 2–64, frame_duration_ms isn't 20–2000, num_outputs isn't 1–4, or image_urls has more than 16 images. | Use an allowed value. |
400 | invalid_request | Both aspect_ratio and size (Provide either aspect_ratio or size, not both), or neither. | Send one of them; with gif, only size. |
400 | invalid_request | size breaks the size rules, with param "size" (for example size 1024x1536 has 1572864 pixels, more than resolution 1k allows (1075200): use a higher resolution or a smaller size). | Raise resolution or use a smaller size. |
400 | invalid_request | The format doesn't allow it: gif or svg above 1k (Input should be '1k' for output_format gif), gif with aspect_ratio or without size, frame_count or frame_duration_ms, frame parameters without gif, svg with image_urls (image_urls is not allowed for output_format svg), jpeg with a transparent background (background transparent is not supported for output_format jpeg). | Follow Output formats. |
400 | invalid_request | A parameter this model doesn't take: another image model's (thinking_level, enable_web_search, enable_image_search, seed, remove_bg) or a video model's (Extra inputs are not permitted). | Remove it. |
Other errors of the create endpoint (401, 402, 429 and so on): Create a task → Errors.
Task failures: the create request succeeded (200) and the task later turned failed. There's no HTTP status: the reason is the task's error.type, from retrieving the task or the webhook.
error.type | When | What to do |
|---|---|---|
insufficient_balance | Your available balance can't cover num_outputs × the price per image. Within a few seconds of creating the task, nothing frozen. | Top up, or ask for fewer images or a lower quality, then create the task again. |
spend_limit_exceeded | This task's cost would go over one of the key's spend limits. Within a few seconds of creating the task, nothing frozen. | Raise the limit in Console → API keys, or wait for it to reset, then create the task again. |
invalid_media | A reference image can't be downloaded or read (for example a HEIC photo, or a corrupt file). Found when generation runs, after the cost was frozen: all of it is returned. | Replace the image error.message points to (convert HEIC to JPEG) and create the task again. |
content_policy | No image could be generated, and at least one was blocked because the prompt or a reference image breaks the content policy (not necessarily every one). If only some images are blocked, the task succeeds with the others instead, see Fewer images than requested. | Resubmitting it as is fails again: change the prompt or the images. |
generation_failed | No image could be generated. | Create it again later, or change the prompt or images. |
queue_timeout / internal_error | Not started within 30 minutes / an error on our side. | Create it again later. |
Every failed task has its frozen amount returned in full and billing.charged "0.00".