> For the complete documentation index, see [llms.txt](https://bountyv.gitbook.io/vdocs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bountyv.gitbook.io/vdocs/image-api/images-i2i.md).

# Image-to-Image / Inpaint

Re-render an input image on the selected architecture, per a prompt, at a chosen denoise strength. Supply an optional `mask` (white = repaint) to inpaint only part of the frame.

```
POST /api/v1/images/i2i
```

Synchronous — the re-rendered image is returned directly in the response body.

## Authentication

```
Authorization: Bearer sk_live_...
```

See [Authentication](/vdocs/authentication.md).

## Request

**Content-Type:** `multipart/form-data` — see [Uploading files](/vdocs/uploading-files.md).

| Field             | Type    | Required | Default  | Description                                                                                                                                                                                                                                                                                                                                 |
| ----------------- | ------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image`           | file    | ✅        | —        | The source image. **Repeatable** — send the field more than once (or as `image[]`) to compose from several references. See [Multiple reference images](#multiple-reference-images)                                                                                                                                                          |
| `mask`            | file    | —        | —        | Optional inpaint mask (white = repaint). Applies to the first image                                                                                                                                                                                                                                                                         |
| `prompt`          | string  | ✅        | —        | Re-render instruction                                                                                                                                                                                                                                                                                                                       |
| `engine`          | string  | —        | `"sdxl"` | One of `sdxl`, `zimage`, `qwen`, `flux2`, `seedream`, `nanobanana`, `gptimage`. The external engines — `seedream` (BytePlus ModelArk), `nanobanana` (Google Gemini 3 Pro Image / Nano Banana Pro), `gptimage` (OpenAI gpt-image-2 / ChatGPT Image) — are SFW-only and do whole-image i2i, ignoring `mask`/`denoise`/`upscale`/`face_detail` |
| `foundation`      | string  | —        | —        | Engine-specific foundation key                                                                                                                                                                                                                                                                                                              |
| `preset`          | string  | —        | —        | Engine LoRA preset (`sdxl` / `zimage` / `qwen` only)                                                                                                                                                                                                                                                                                        |
| `denoise`         | number  | —        | `0.55`   | `0.2`–`0.95`. Lower = closer to the source                                                                                                                                                                                                                                                                                                  |
| `upscale`         | boolean | —        | —        | `"true"` runs the ESRGAN upscale pass                                                                                                                                                                                                                                                                                                       |
| `upscale_factor`  | integer | —        | `2`      | `2` \| `3` \| `4`                                                                                                                                                                                                                                                                                                                           |
| `face_detail`     | boolean | —        | —        | `"true"` runs FaceDetailer                                                                                                                                                                                                                                                                                                                  |
| `negative_prompt` | string  | —        | —        | Extra negatives                                                                                                                                                                                                                                                                                                                             |
| `seed`            | integer | —        | —        | Reproducibility                                                                                                                                                                                                                                                                                                                             |

### Multiple reference images

The external engines compose from several references at once — combine two people, hold a product across shots, transfer an outfit, or lock a location. Repeat the `image` field (or use `image[]`); order is preserved, and your prompt can address them as "image 1", "image 2", and so on.

| Engine                            | Max `image` files |
| --------------------------------- | ----------------- |
| `gptimage` (OpenAI gpt-image-2)   | 16                |
| `nanobanana` (Gemini 3 Pro Image) | 14                |
| `seedream` (BytePlus ModelArk)    | 10                |
| `sdxl`, `zimage`, `qwen`, `flux2` | 1                 |

Sending more than the engine accepts returns `400` with a `max_reference_images` field rather than failing at the provider.

The self-hosted engines are limited by our deployed graph rather than the model: FLUX.2 itself references up to 10 images, but the worker we run builds a single reference latent. For multi-reference editing on a self-hosted engine today, use [Image Edit](/vdocs/image-api/images-edit.md) with `engine=qwen`, which takes 2.

Nano Banana Pro's 14 slots are a hard API ceiling; Google's own guidance is to spend at most 6 on object references and 5 on character references for the cleanest composition.

### Pricing

The price depends on the engine — the external frontier engines cost us more per render, so they bill higher than the self-hosted lanes:

| Engine                            | Price |
| --------------------------------- | ----- |
| `sdxl`, `zimage`, `qwen`, `flux2` | $0.25 |
| `seedream`                        | $0.29 |
| `gptimage`                        | $0.39 |
| `nanobanana`                      | $0.49 |

The exact amount deducted is always returned as `charged_cents`. If your balance can't cover the selected engine the call returns `402` with `required_cents` and the `engine` that was priced, before any generation runs.

### Masking

`sdxl`, `zimage`, and `qwen` honor the inpaint mask; `flux2` performs whole-image i2i and ignores it. The external engines (`seedream`, `nanobanana`, `gptimage`) also ignore it — they always do whole-image i2i.

## Response

```json
{
  "image": "https://.../generations/<id>.png?token=...",
  "generation_id": "gJ8nP3kQ2m",
  "engine": "sdxl",
  "reference_images": 1,
  "max_reference_images": 1,
  "charged_cents": 25,
  "balance_cents": 4775,
  "elapsed_ms": 11200
}
```

| Field                  | Type            | Description                                                                                                           |
| ---------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------- |
| `image`                | string          | Re-rendered image. A time-limited signed URL when the generation persists to storage, otherwise an inline `data:` URL |
| `generation_id`        | string \| null  | Generation record ID, or `null` if persistence failed                                                                 |
| `engine`               | string          | The engine that ran                                                                                                   |
| `reference_images`     | integer         | How many `image` files were used                                                                                      |
| `max_reference_images` | integer         | The engine's ceiling, so a client can size its picker                                                                 |
| `charged_cents`        | integer         | Amount deducted from your balance for this call                                                                       |
| `balance_cents`        | integer         | Remaining balance                                                                                                     |
| `elapsed_ms`           | integer \| null | Generation time in milliseconds                                                                                       |

## Example

```bash
curl -X POST https://substance-api.com/api/v1/images/i2i \
  -H "Authorization: Bearer sk_live_..." \
  -F "image=@input.png" \
  -F "engine=sdxl" \
  -F "prompt=..." \
  -F "denoise=0.6"
```

Composing from several references (Nano Banana Pro, up to 14):

```bash
curl -X POST https://substance-api.com/api/v1/images/i2i \
  -H "Authorization: Bearer sk_live_..." \
  -F "engine=nanobanana" \
  -F "image=@model.png" \
  -F "image=@jacket.png" \
  -F "image=@street-at-night.png" \
  -F "prompt=The woman from image 1 wearing the jacket from image 2, standing on the street from image 3"
```

With a mask (inpaint just the masked region):

```bash
curl -X POST https://substance-api.com/api/v1/images/i2i \
  -H "Authorization: Bearer sk_live_..." \
  -F "image=@input.png" \
  -F "mask=@mask.png" \
  -F "engine=zimage" \
  -F "prompt=..." \
  -F "denoise=0.55"
```

## Errors

| Status | When                                                                                                                    |
| ------ | ----------------------------------------------------------------------------------------------------------------------- |
| `400`  | Missing `image` or `prompt`, more `image` files than the engine accepts, or the prompt is rejected by the safety filter |
| `401`  | Missing/invalid API key                                                                                                 |
| `402`  | Insufficient credits                                                                                                    |
| `403`  | `nsfw` entitlement not enabled on your account                                                                          |
| `503`  | The base pipeline, or the selected external engine specifically, is temporarily disabled                                |
| `502`  | Generation failed upstream. Balance is refunded automatically                                                           |

See [Errors](/vdocs/errors.md) for the general error format.

## Pricing

Billed per call — see [Credits & pricing](/vdocs/account/credits.md) for current rates. Rate varies by `engine` and by whether a `mask` is supplied.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://bountyv.gitbook.io/vdocs/image-api/images-i2i.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
