# Images

> Generate an image from a prompt and up to eight reference pictures, then poll until it is ready and fetch it from your library.

`POST /v1/images` takes a prompt and answers at once with a `gen_…` id. The image is made in the background: poll `GET /v1/images/{id}` until `status` is terminal, then download it from `image.url`. Every finished image is also saved in your [asset library](https://docs.lumavox.ai/library/assets.md).

```bash title="curl"
curl https://api.lumavox.ai/v1/images \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A weathered brass diving helmet on wet slate, low winter light",
    "aspect_ratio": "16:9"
  }'
```

```json title="Response — 202 Accepted"
{
  "id": "gen_a1B2c3D4e5F6g7H8",
  "status": "queued",
  "capability": "image",
  "model": "flux-2-max",
  "prompt": "A weathered brass diving helmet on wet slate, low winter light",
  "aspect_ratio": "16:9",
  "width": 1328,
  "height": 752,
  "output_format": "jpeg",
  "seed": null,
  "megapixels": 1,
  "folder_id": null,
  "safety_tolerance": 2,
  "enhance_prompt": true,
  "duration": null,
  "resolution": null,
  "generate_audio": null,
  "start_frame": null,
  "end_frame": null,
  "voice_id": null,
  "speech": null,
  "negative_text": null,
  "style_id": null,
  "init_image": null,
  "init_strength": null,
  "credits_micros": 4000000,
  "template_id": null,
  "image": null,
  "video": null,
  "audio": null,
  "transcript": null,
  "skybox": null,
  "error": null,
  "created_at": "2026-10-24T09:14:03.120Z",
  "finished_at": null
}
```

Every generation has these fields, whatever made it: the ones another capability uses — a video's `duration`, a skybox's `style_id` — are `null` on an image. `credits_micros` is what was charged, in micro-credits ([Conventions](https://docs.lumavox.ai/conventions.md#credits)).

The key needs the `image` scope. See [Authentication](https://docs.lumavox.ai/authentication.md).

## Poll until it finishes

Poll every couple of seconds. `queued`, `submitted` and `running` mean keep going; `succeeded`, `failed` and `moderated` are final. [Queued jobs](https://docs.lumavox.ai/jobs.md) covers the pattern for every capability.

```bash title="curl"
curl https://api.lumavox.ai/v1/images/gen_a1B2c3D4e5F6g7H8 \
  -H "Authorization: Bearer $API_KEY"
```

```json title="Response — succeeded (abridged)"
{
  "id": "gen_a1B2c3D4e5F6g7H8",
  "status": "succeeded",
  "capability": "image",
  "width": 1328,
  "height": 752,
  "image": {
    "asset_id": "ast_Q9r8S7t6U5v4W3x2",
    "url": "https://…",
    "width": 1328,
    "height": 752,
    "content_type": "image/jpeg",
    "size_bytes": 412377
  },
  "error": null,
  "created_at": "2026-10-24T09:14:03.120Z",
  "finished_at": "2026-10-24T09:14:21.904Z"
}
```

- **`image.url` is a short-lived link** — about fifteen minutes. It is made fresh on every response and never stored, so poll again (or read the asset with `GET /v1/assets/{asset_id}`) for a new one. Download the file if you need to keep it outside the library.
- **`image.asset_id`** is the library entry. It stays after the link expires.
- **`error`** says why, when the status is `failed` or `moderated`.

An id from another capability, or another organisation, is a 404 here. [`GET /v1/generations/{id}`](https://docs.lumavox.ai/library/generations.md) reads any capability's generation by id.

## What you can set

Only `prompt` is required.

| Field | Default | What it does |
|---|---|---|
| `prompt` | — | What to generate. 1–4,000 characters. |
| `aspect_ratio` | `1:1` | One of `21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`. |
| `megapixels` | `1` | Output size, from `0.25` to `4`. **This and your references are what you are charged on.** |
| `output_format` | `jpeg` | `jpeg`, `png` or `webp`. |
| `seed` | random | Reuse a seed with the same prompt to get the same image again. |
| `safety_tolerance` | `2` | `0` (strictest) to `5`. Content refused at every setting is still refused. |
| `enhance_prompt` | `true` | Lets the model rewrite your prompt before rendering. Set `false` to send your words exactly. |
| `references` | `[]` | Up to eight images from your library to work from — see below. |
| `folder_id` | root | The `fld_…` folder in your library the finished file goes in. |

### Size

The pixels come from `aspect_ratio` and `megapixels` together: the API picks the width and height closest to that area at that ratio, each a multiple of 16. At the defaults that is 992 × 992; `16:9` at one megapixel is 1328 × 752. The 202 response already carries the `width` and `height` you will get.

The price is per megapixel, with a **one-megapixel minimum** — a 0.25 MP image costs the same as a 1 MP one. **Each reference image is charged at the same rate**, on its own megapixels and with no minimum — see [Reference images](#reference-images). Because the sizes are fixed before the work starts, so is the price: `credits_micros` on the 202 is what was charged.

### Reference images

Give the model pictures to work from — a product, a face, a style — as assets from your library. Upload them first with the [upload flow](https://docs.lumavox.ai/library/assets.md#upload-a-file), or reuse anything the API has made for you.

```json title="Request body"
{
  "prompt": "The same mug on a marble counter, morning light",
  "references": [
    { "asset_id": "ast_a1B2c3D4e5F6g7H8" },
    { "asset_id": "ast_Z9y8X7w6V5u4T3s2", "variant": "50" }
  ]
}
```

- Each reference must be an **image** in your library whose `status` is `ready`. One that is still processing, failed, or is not an image is a 422, and nothing is charged.
- Order matters: references are sent to the model in the order you list them. The same asset cannot appear twice.
- **Input and output share a 9-megapixel budget.** At a 1 MP output that is room for eight 1 MP references; at 2 MP, seven. Going over is a 422 at `references` that names the numbers — never a silent drop.
- **`variant`** picks which copy of a reference to send: `original` (the default), or `50`, `25` or `12.5` — the smaller copies made when the image was stored. Smaller copies spend less of the budget. If the copy you name was never made, the original is sent instead.
- **Each reference is charged** at the output's per-megapixel rate, on the megapixels of the copy sent, with no minimum. A 1 MP image from two 1 MP references costs three megapixels; the same with both references at `50` (a quarter of the pixels) costs one and a half.

## Charges and refunds

- **Charged when accepted.** The 202 means the credits are already spent, and `credits_micros` on the response says how many.
- **Refunded in full** if the generation ends `failed` or `moderated`.
- **Nothing is charged** for a request refused with a 4xx.

[Credits and usage](https://docs.lumavox.ai/usage.md) explains balances and plans.

## Errors

| Status | When |
|---|---|
| 400 | The body is not valid JSON. |
| 422 | A reference or `folder_id` that is missing, is not yours, is not a ready image, or the references go over the 9-megapixel budget. |
| 402 | Your organisation has run out of credits, or this job's estimate would take its balance past the grace buffer. Nothing is charged. |
| 403 | The key does not hold the `image` scope. |
| 404 | (Poll) No image generation with that id in your organisation. |
| 422 | The body failed validation: an `aspect_ratio`, `output_format` or `variant` outside its set, an empty prompt, a number out of range, an unknown field. `issues` names each. |
| 429 | Too many requests, or too many of your images are still generating at once. Wait for one to finish; nothing was charged. |
| 503 | Image generation is not available on this deployment. |

Every error has the same JSON shape — see [Errors and limits](https://docs.lumavox.ai/errors.md).

## See also

- [Videos](https://docs.lumavox.ai/media/videos.md) — animate an image from your library.
- [Templates](https://docs.lumavox.ai/media/templates.md) — generations someone has already designed.
- [The images reference](https://docs.lumavox.ai/reference/images.md) — every field.
