> ## Documentation Index
> Fetch the complete documentation index at: https://docs.naga.ac/llms.txt
> Use this file to discover all available pages before exploring further.

# Image generation

> Create images from a prompt with POST /v1/images/generations, or change an existing image with POST /v1/images/edits.

Send a prompt to `POST /v1/images/generations` and NagaAI returns the finished images as links or as inline base64. To change a picture you already have, send it with a prompt to `POST /v1/images/edits`. Both endpoints follow the OpenAI Images format, so the OpenAI SDK works unchanged.

## Generate an image

```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.naga.ac/v1", api_key=os.environ["NAGA_API_KEY"])

result = client.images.generate(
    model="gpt-image-2",
    prompt="A red paper boat on a calm lake, flat illustration for a blog header",
    size="1536x1024",
    n=1,
)

print(result.data[0].url)
```

```javascript Node.js theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.naga.ac/v1", apiKey: process.env.NAGA_API_KEY });

const result = await client.images.generate({
  model: "gpt-image-2",
  prompt: "A red paper boat on a calm lake, flat illustration for a blog header",
  size: "1536x1024",
  n: 1,
});

console.log(result.data[0].url);
```

```bash cURL theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
curl https://api.naga.ac/v1/images/generations \
  -H "Authorization: Bearer $NAGA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-image-2", "prompt": "A red paper boat on a calm lake, flat illustration for a blog header", "size": "1536x1024", "n": 1}'
```

Pick any model whose `kinds` include `image` in [`GET /v1/models`](https://docs.naga.ac/get-started/models), or browse them at [naga.ac/models](https://naga.ac/models).

The response lists one entry in `data` per image, and `usage` reports what NagaAI counted for the bill:

```json theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
{
  "created": 1767225600,
  "data": [
    {"url": "https://media.naga.ac/outputs/c1f7a2d4-3b8e-4f60-9a15-7e2d0b6c8f31.png"}
  ],
  "usage": {"input_tokens": 18, "output_tokens": 2048, "total_tokens": 2066}
}
```

## Set the size and count

`size` is `WIDTHxHEIGHT`, such as `1536x1024`. There is no separate aspect ratio field, so you set the ratio through `size`. `n` asks for several images in one request. The limit is `limits.max_images` on the model's `image_generation` operation in `GET /v1/models`, usually 4.

| Field | Notes |
| - | - |
| `prompt` | Required, 1 to 8,192 characters |
| `size` | `WIDTHxHEIGHT`. Any other form fails with `400` |
| `n` | One image when omitted |
| `quality` | Sent to the provider as you wrote it. A model with no quality setting drops the field and the request still succeeds |
| `response_format` | `url` (default) or `b64_json` |

NagaAI ignores `style`, `output_format` and other fields, so setting them changes nothing.

## Choose a link or base64

With `url`, each entry of `data` holds a link on `media.naga.ac` to a copy that NagaAI hosts for 24 hours and then deletes. Download the file when you receive the response, or store it in your own bucket. With `b64_json`, the image bytes come inline as base64 and NagaAI stores nothing.

Vector models such as Ideogram Vector return SVG. A browser that opens the link downloads the file, and an `<img>` tag still shows it.

## Edit an image

`POST /v1/images/edits` takes a multipart form with the image, a prompt, and an optional mask. A transparent area of the mask marks what the model may repaint.

```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.naga.ac/v1", api_key=os.environ["NAGA_API_KEY"])

with open("boat.png", "rb") as image:
    result = client.images.edit(
        model="gpt-image-2",
        image=image,
        prompt="Make the boat blue and add a small flag",
        size="1024x1024",
    )

print(result.data[0].url)
```

```javascript Node.js theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import fs from "node:fs";
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.naga.ac/v1", apiKey: process.env.NAGA_API_KEY });

const result = await client.images.edit({
  model: "gpt-image-2",
  image: fs.createReadStream("boat.png"),
  prompt: "Make the boat blue and add a small flag",
  size: "1024x1024",
});

console.log(result.data[0].url);
```

```bash cURL theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
curl https://api.naga.ac/v1/images/edits \
  -H "Authorization: Bearer $NAGA_API_KEY" \
  -F model=gpt-image-2 \
  -F image=@boat.png \
  -F prompt="Make the boat blue and add a small flag" \
  -F size=1024x1024
```

The response has the same shape as a generation. The model must have an `image_edit` operation in `GET /v1/models`.

| Field | Notes |
| - | - |
| `image` | Required. Send the part once per image: models that combine pictures take several |
| `mask` | A single image whose transparent area marks what to change |
| `prompt` | Required, 1 to 32,000 characters |
| `background`, `quality`, `n`, `size`, `response_format` | Work as in generation. `background` exists only on edits |

## Billing

Images are priced per token. `usage.output_tokens` is what the provider reports for the images it made. When a provider reports nothing, NagaAI counts the model's published number for the picture's resolution, for example 1,290 for `gemini-2.5-flash-image`. A model with no published number counts 2,048 per image. The `output_image_token` row of `pricing` in `GET /v1/models` holds the price per token.

NagaAI checks every prompt with its own moderation before it picks a provider.

## Draw with a chat model

Some chat models draw inside a chat request instead. They return the pictures through the chat endpoints, see [Images in the answer](https://docs.naga.ac/guides/images-and-files.md#images-in-the-answer).

## Troubleshooting

### An image link stops working

NagaAI deletes hosted images 24 hours after it makes them. Download the image on arrival, or ask for `b64_json`.

### 400 with `size must be in format`

The message reads `body.size: Value error, size must be in format "{width}x{height}", for example "1024x1024"`. Write the size as two numbers joined by a lowercase `x`, with no spaces and no ratio such as `16:9`.

### 400 with `Too many images`

The message reads `Too many images. This model supports up to 4`, with the model's own limit. Lower `n`, or send several requests.

### 400 with `At least one image must be provided`

An edit needs at least one `image` part. Check that the form is `multipart/form-data` and that the part is named `image` or `image[]`.

### 400 `model_not_found`

The model does not exist or has no `image_generation` operation (`image_edit` for edits). Check its `operations` in `GET /v1/models`.

### 403 `inappropriate_content`

NagaAI's moderation blocked the prompt. Change the prompt and send it again.

### 413

The request body is over 32 MiB. Send a smaller image.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.