# Edit Image

`POST https://api.vultrinference.com/v1/images/edits`

Edits or recombines images with a prompt, in OpenAI's shape (`images.edit()` in OpenAI's SDKs): multipart `image[]` files and an optional `mask`, or JSON `images: [{image_url}]` and `mask: {image_url}`; OpenRouter's `input_references` works too. The same implementation as `/v1/images/generations`, and the same fields and answer.

Only a model with reference editing takes this route. `z-image-turbo` has none: the request is a 400 naming `image` (or `images`, `input_references`, `mask`, whichever was sent). Each image is an upload, a base64 data URI or an https URL the gateway fetches itself (public addresses only); the engine only receives bytes. An image's type is read from its bytes and checked against the model's accepted formats.

Billing is the output megapixels only, so an edit with any number of references bills the same as a generation of the same size. `size` `auto` is the model's default size, not the first image's.

## Body (multipart/form-data)

- `prompt` (string, required)
- `model` (string)
- `image` (array of string (binary)s, required): One or more image files. Send them as `image[]` (what the OpenAI SDKs do); PHP keeps only the last of several parts named plainly `image`.
- `mask` (string (binary)): A PNG mask; it needs at least one image.
- `n` (integer)
- `size` (string)
- `response_format` (string) [url, b64_json]
- `output_format` (string)
- `output_compression` (integer)
- `background` (string)
- `seed` (integer)
- `stream` (boolean)

## Body (application/json)

- `prompt` (string, required): A text description of the desired image(s). The maximum length is the model's (4000 characters for `z-image-turbo`), counted as Unicode characters rather than bytes. [at most 4000 characters]
- `model` (string): The model to use for image generation. Defaults to `z-image-turbo`. `GET /v1/images/models` lists the image models currently served. An unknown model returns 404. [default z-image-turbo]
- `n` (integer): The number of images to generate. The images in one request are generated together, so changing `n` can change every image, including the first, for the same `seed`. [default 1, range 1–10]
- `response_format` (string): How the image comes back. `url` is a presigned link that expires after one hour; `b64_json` is the image inline as base64. The default is `b64_json` on `POST /v1/images` (OpenRouter's SDKs require it) and `url` on `/v1/images/generations` and `/v1/images/edits`. [url, b64_json]
- `size` (string): `WIDTHxHEIGHT` in pixels, or a resolution label (`1K`, `2K`, ...). For `z-image-turbo` any sides that are multiples of 16, an area from 65,536 to 4,194,304 pixels and a longer side at most 4 times the shorter (so `768x768` works and `1000x1000` is a 400). `auto` is the same as leaving it out. An `aspect_ratio` or `resolution` beside an explicit size must agree with it. [default 1024x1024]
- `width` (integer): Legacy spelling of `size`, kept because this API once documented it as ignored. Needs `height` and means `size` `"{width}x{height}"` under the same rules; a 400 if it disagrees with a `size` sent beside it. Use `size`.
- `height` (integer): See `width`.
- `aspect_ratio` (string): One of the model's aspect ratios (`GET /v1/images/models`). With `resolution`, or alone at the model's default resolution, it picks the size.
- `resolution` (string): One of the model's resolutions (`512`, `768`, `1K`, `1.5K`, `2K` for `z-image-turbo`; `4K` is a 400).
- `seed` (integer (int64)): Random seed. Must be an integer; fractional values are rejected rather than rounded. When omitted, each request uses a random seed. Repeating a request with the same seed and the same value for every other field, including `n` and `size`, returns the same images from the same model version on the same hardware. A model or engine update can change the images a seed produces, and replicas on different GPUs can differ in the last bits.
- `output_format` (string) [default png, png, jpeg, webp]
- `output_compression` (integer): The encoder quality for `jpeg` and `webp`, the compression level for `png`. The engine's own default applies when omitted. [range 0–100]
- `background` (string): `auto` and `opaque` give an opaque image. `transparent` only works on a model whose spec supports it (it also needs `output_format` `png` or `webp`); on `z-image-turbo` it is a 400. [default auto, auto, opaque, transparent]
- `input_references` (array of objects): OpenRouter's reference images, for a model with reference editing (`z-image-turbo` has none, so it is a 400 naming this field). Each is `{"type": "image_url", "image_url": {"url": "<https URL or base64 data URI>"}}`. The gateway fetches an https URL itself.
  - `type` (string, required) [image_url]
  - `image_url` (object, required)
    - `url` (string, required)
- `steps` (integer): The number of denoising steps (`z-image-turbo`: 1 to 50, default 8). Generation time grows roughly linearly with steps. Also accepted as `num_inference_steps`, and under `provider.options` (see `provider`). For `z-image-turbo` the last step of the schedule lands at zero noise and does not change the image, so `N` steps apply `N - 1` denoising updates. The default of 8 applies 7; 9 matches the 8 updates in the upstream Z-Image-Turbo reference. [range 1–50]
- `num_inference_steps` (integer): Alias of `steps`. [range 1–50]
- `guidance_scale` (number (float)): Classifier-free guidance strength. When omitted, the model's default is used: 0 for `z-image-turbo`, which is also the upstream recommendation for Turbo models. `0` turns guidance off. Values above 0 turn it on, which enables `negative_prompt` and roughly doubles the model work per step. Higher values are not a quality setting for `z-image-turbo`. [range 0–20]
- `negative_prompt` (string): Text describing what to steer the image away from. It only takes effect when `guidance_scale` is above 0; at the `z-image-turbo` default of 0 it is ignored. It changes the output, but does not guarantee that the described content is absent.
- `provider` (object): OpenRouter's provider preferences. The routing fields (`order`, `only`, `ignore`, `sort`, `allow_fallbacks`, ...) are accepted and ignored. `options` carries the model's own settings (`steps`, `guidance_scale`, `negative_prompt`) for clients that cannot add top-level fields. From OpenRouter's SDKs use `options.stealth`: they keep only the slugs on their closed list and drop any other, `vultr` included, without an error. The first form present wins, the top level before any option; a key the model does not declare is a 400 naming its path.
- `stream` (boolean): `true` answers `text/event-stream`: one `image_generation.completed` event (see the response), then `[DONE]`. Always base64. Not with `n` above 1.
- `partial_images` (integer): OpenAI's partial image count. Only 0 is accepted; a stream carries the finished image only. [range 0–0]
- `user` (string): Accepted and ignored.
- `session_id` (string): Accepted and ignored.
- `trace` (object): Accepted and ignored.
- `images` (array of objects): The images to edit, at most the model's maximum (10 for `qwen-image-2.1`), 20 MB each. A `file_id` is not supported.
  - `image_url` (string, required): An https URL (public addresses only; the gateway fetches it) or a base64 data URI.
- `mask` (object): A PNG mask for the edit; it needs at least one image.
  - `image_url` (string)

## Responses

- `200`: OK (create-image-response-payload)
- `400`: A field the model does not accept, no image, or a malformed input. The message names the field. (error-payload)
- `401`: The API key is missing, unknown or not active. Send it as Authorization: Bearer <key>. (error-payload)
- `404`: The model does not exist (error-payload)
- `413`: An image over 20 MB, or the images over 64 MB together (error-payload)
- `429`: Too many requests for this model from your subscription in the last minute, or too many running at once. Wait for Retry-After, then retry. (error-payload)
- `503`: The model is temporarily unavailable (error-payload)

## Example

```bash
curl https://api.vultrinference.com/v1/images/edits \
  -H "Authorization: Bearer $VULTR_INFERENCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "string"
  }'
```

```python
import os
import requests

response = requests.post(
    "https://api.vultrinference.com/v1/images/edits",
    headers={"Authorization": f"Bearer {os.environ['VULTR_INFERENCE_API_KEY']}"},
    json={
        "prompt": "string",
    },
)
print(response.json())
```

```javascript
const response = await fetch("https://api.vultrinference.com/v1/images/edits", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.VULTR_INFERENCE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "prompt": "string"
  }),
});
console.log(await response.json());
```
