> This page is for Gateway.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.merge.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.merge.dev/_mcp/server.

# Image generation

> Generate images on Gateway with POST /v1/images/generations or inline on /v1/responses with image-capable chat models, and read per-token or per-image pricing.

Dedicated image models such as `openai/gpt-image-2` and `xai/grok-imagine-image` generate through `POST /v1/images/generations`. Chat models that also output images, such as `google/gemini-3.1-flash-image`, generate inline on `/v1/responses`. To change an existing image, use [image editing](/merge-gateway/capabilities/multimodal/image-editing).

## Dedicated endpoint

**`cURL`**

```bash title="cURL"
curl https://api-gateway.merge.dev/v1/images/generations \
  -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-image-2", "prompt": "a lighthouse at dawn, watercolor", "size": "1024x1024"}'
```

**`Python`**

```python title="Python"
import base64, os, requests

resp = requests.post(
    "https://api-gateway.merge.dev/v1/images/generations",
    headers={"Authorization": f"Bearer {os.environ['MERGE_GATEWAY_API_KEY']}"},
    json={"model": "openai/gpt-image-2", "prompt": "a lighthouse at dawn, watercolor", "size": "1024x1024"},
).json()

with open("image.png", "wb") as f:
    f.write(base64.b64decode(resp["data"][0]["b64_json"]))
```

Images come back as base64 in `data[].b64_json`, with `images_generated`, `cost` in USD, and `usage` on token-priced models. The `X-Merge-Vendor` header names the vendor. For xAI, Gateway requests base64 when you omit `response_format`, since xAI refuses URL output for zero data retention accounts; an explicit `"url"` is forwarded.

## Inline in chat

Set `modalities: ["text", "image"]` with a model that lists `image` in `capabilities.output` (other routes return `400 unsupported_params` with `param: modalities`). Images arrive in `output[].content[]` as `"type": "image"` blocks with base64 `data`.

**`cURL`**

```bash title="cURL"
curl https://api-gateway.merge.dev/v1/responses \
  -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemini-3.1-flash-image",
    "input": [{"type": "message", "role": "user", "content": [{"type": "text", "text": "draw a small blue star"}]}],
    "modalities": ["text", "image"]
  }'
```

## Reference

| Field                                       | Notes                                                                                 |
| ------------------------------------------- | ------------------------------------------------------------------------------------- |
| `model`                                     | Required. A canonical model ID, since `@alias/...` returns `400 alias_not_supported`. |
| `prompt`                                    | Required                                                                              |
| `n`                                         | 1 to 10                                                                               |
| `size`, `quality`, `style`, `output_format` | Model-specific                                                                        |
| `response_format`                           | `b64_json` or `url`                                                                   |
| `vendor`                                    | Pin the execution vendor                                                              |
| `customer`                                  | Customer UUID to scope the key, budget, and usage to                                  |
| `provider_options`                          | Vendor-specific options. Other top-level fields are also forwarded.                   |

`pricing.unit` on `GET /v1/models` says how a model bills: `per_token` meters image output tokens (`usage.image_output_tokens`), so cost scales with resolution, and `per_image` charges a flat rate per image, with optional tiers in `output_per_image_by_resolution`.

## Next steps

#### [Image editing](/merge-gateway/capabilities/multimodal/image-editing)

Edit or combine reference images

#### [Video generation](/merge-gateway/capabilities/multimodal/video-generation)

Video through an async job