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

# Images

> Generate and edit images with one synchronous endpoint across every image model.

`POST /v3/images` is a deterministic, provider-agnostic image endpoint. You pass a `model` and a `prompt`; Opper runs the job and returns the image inline. The same call works across every image model (OpenAI GPT Image, Google Imagen, xAI, Pruna, and more) — `model` and `prompt` are owned by Opper, a small set of high-level parameters is normalized for you, and anything model-specific goes in `parameters`.

<Info>
  Image generation is **synchronous**: the response comes back on the same request with the image as base64 (and, by default, a stored `file_id` + presigned `url`). For looking at images instead of making them, see [Vision & PDFs](/build/multimodal/vision-pdfs).
</Info>

## Generate an image

<CodeGroup>
  ```bash cURL theme={null}
  curl -sX POST https://api.opper.ai/v3/images \
    -H "Authorization: Bearer $OPPER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai/gpt-image-1",
      "prompt": "a wide-angle photo of a hot air balloon over green hills at dawn",
      "size": "1024x1024"
    }'
  ```

  ```python Python theme={null}
  import os, base64, requests

  r = requests.post(
      "https://api.opper.ai/v3/images",
      headers={"Authorization": f"Bearer {os.environ['OPPER_API_KEY']}"},
      json={
          "model": "openai/gpt-image-1",
          "prompt": "a wide-angle photo of a hot air balloon over green hills at dawn",
          "size": "1024x1024",
      },
  )
  r.raise_for_status()
  img = r.json()["data"][0]
  open("balloon.png", "wb").write(base64.b64decode(img["b64_json"]))
  print("saved balloon.png", "·", img.get("file_id"))
  ```
</CodeGroup>

The response mirrors OpenAI's `images/generations` shape, plus gateway extras:

```json theme={null}
{
  "id": "img_...",
  "model": "openai/gpt-image-1",
  "created": 1716124800,
  "data": [
    {
      "b64_json": "iVBORw0KGgo...",
      "mime_type": "image/png",
      "file_id": "file_...",
      "url": "https://...presigned...",
      "revised_prompt": "..."
    }
  ],
  "usage": { "cost": 0.011, "images": 1 }
}
```

By default each image is also stored so you get a reusable `file_id` and a presigned `url` alongside the base64. Pass `"store": false` to skip persistence and get base64 only, or `"response_format": "url"` to omit the base64 and return only the stored URL.

<Note>
  The `file_id` is a reusable handle — pass it as the `image` on a later edit or as the seed `image` on a [video](/build/multimodal/video) call, no re-upload. See [Files](/build/multimodal/files) for how files work, lifecycle, and storage quotas.
</Note>

## Parameters

`model` and `prompt` are required. The rest are optional; the high-level ones are normalized across providers, and `parameters` is forwarded verbatim to the provider, which validates it.

| Field             | What it does                                                                                                                                            |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `n`               | Number of images to generate (default 1, max 4).                                                                                                        |
| `size`            | Pixel size `WxH` for pixel-sized models (GPT Image, DALL·E). Validated against the model's sizes.                                                       |
| `aspect_ratio`    | `16:9`, `1:1`, etc. for aspect-ratio models (Imagen, Pruna, xAI). Bridged to/from `size` per model.                                                     |
| `quality`         | Normalized tier: `low` \| `medium` \| `high` (default `medium`), plus `4k` where a model declares it. Rejected on models that declare no quality tiers. |
| `response_format` | `b64_json` (default) or `url` (returns the stored URL only).                                                                                            |
| `store`           | Persist the output to storage and return a `file_id` + `url`. Defaults to true; respects retention rules.                                               |
| `parameters`      | Opaque per-provider passthrough for anything not normalized above.                                                                                      |

Model-specific knobs go in `parameters` — for example DALL·E 3's `style` (`vivid` | `natural`), or a diffusion model's `seed` / `negative_prompt`. They're forwarded verbatim and validated by the provider. See [Discover models](#discover-models) for how to list the keys a given model accepts.

## Edit and image-to-image

Pass a source image alongside the prompt. Each input accepts an http(s) URL, a data-URI, or a `file_id` from a previous generation or upload. Models that only do text-to-image reject these with a clear `400`.

| Field              | Use for                                                   |
| ------------------ | --------------------------------------------------------- |
| `image`            | The source image to edit or transform.                    |
| `mask`             | An inpaint mask (`image/*`) marking the region to change. |
| `reference_images` | Style or subject reference images.                        |

```bash theme={null}
curl -sX POST https://api.opper.ai/v3/images \
  -H "Authorization: Bearer $OPPER_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-image-1",
    "prompt": "put the balloon over a snowy mountain range",
    "image": "file_abc123"
  }'
```

## Discover models

`GET /v3/images/models` reports the models you can use and their capabilities. Each model's `params.image` block lists the normalized axes it accepts — `sizes`, `aspect_ratios`, `resolutions`, `qualities` — plus a `parameters` list of the native passthrough keys (e.g. `seed`, `negative_prompt`, `personGeneration`) you can put in `parameters`, so you can discover a model's knobs instead of guessing.

```bash theme={null}
curl -s "https://api.opper.ai/v3/images/models" \
  -H "Authorization: Bearer $OPPER_API_KEY"
```

## What's next

<CardGroup cols={2}>
  <Card title="Vision & PDFs" icon="image" href="/build/multimodal/vision-pdfs">
    Send images into a model instead of generating them.
  </Card>

  <Card title="Video" icon="film" href="/build/multimodal/video">
    Turn a generated image into video.
  </Card>

  <Card title="Models" icon="brain" href="/capabilities/models">
    Which models generate images, and at what sizes.
  </Card>

  <Card title="Control Plane" icon="shield-check" href="/control-plane/overview">
    Govern providers, regions, and spend on every generation.
  </Card>
</CardGroup>
