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

# GPT Image 2.5

> OpenAI GPT Image 2.5 on Upmore — text-to-image generation and image-to-image editing with masked edits, transparent backgrounds, up to 16 input images, and flexible resolution up to 4K. Available as gpt-image-2.5-flare and gpt-image-2.5-sunburst.

GPT Image 2.5 is OpenAI's image generation and editing model, available through Upmore API under two interchangeable model IDs: `gpt-image-2.5-flare` and `gpt-image-2.5-sunburst`. Both accept the same parameters, enforce the same limits, and return the same response shape. Use whichever you prefer.

Two endpoints cover it:

| Task                     | Endpoint                      | Content types                               |
| ------------------------ | ----------------------------- | ------------------------------------------- |
| Text-to-image            | `POST /v1/images/generations` | `application/json`                          |
| Image-to-image (editing) | `POST /v1/images/edits`       | `multipart/form-data` or `application/json` |

## How to pass parameters

Both endpoints take the **same parameter set** — only the endpoint and the request encoding change.

| What                                                                                                | Text-to-image                                | Image-to-image                                                                        |
| --------------------------------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------- |
| Endpoint                                                                                            | `POST /v1/images/generations`                | `POST /v1/images/edits`                                                               |
| Encoding                                                                                            | JSON body                                    | `multipart/form-data` **or** JSON body                                                |
| `prompt`, `size`, `quality`, `n`, `background`, `output_format`, `moderation`, `output_compression` | JSON fields, with real JSON types — `"n": 2` | Multipart: form fields, **all sent as strings** (`-F "n=2"`). JSON: normal JSON types |
| Input image                                                                                         | not used                                     | Multipart: file field `image`. JSON: `images[].image_url`                             |
| Mask                                                                                                | not used                                     | Multipart: file field `mask`. JSON: `mask.image_url`                                  |

The image-to-image endpoint has two interchangeable request shapes. Pick whichever fits what you already have:

* **You have the bytes** (a local file, or a file from another API) → `multipart/form-data` with a file upload.
* **You have a URL** (object storage such as TOS or R2, a CDN link, or an inline base64 payload) → `application/json` with `images[].image_url`.

## Key capabilities

* **Text-to-Image** — Generate images from a natural language prompt
* **Image-to-Image** — Edit an existing image with a prompt, by file upload or by URL
* **Multiple input images** — Up to 16 reference images per edit
* **Masked editing** — Restrict the edit to a region by supplying a mask
* **Flexible resolution** — Any size up to 4K, with the model choosing a resolution when you omit `size`
* **Transparent background** — `background: "transparent"` for cut-out assets
* **Batch generation** — Up to 10 images per request via `n`
* **Streaming previews** — Receive partial images as they render

## Output specifications

| Property                  | Value                                                                                               |
| ------------------------- | --------------------------------------------------------------------------------------------------- |
| Sizes                     | Flexible, e.g. `1024x1024`, `1536x1024`, `2048x2048`, `3840x2160`                                   |
| Size constraints          | Edges must be multiples of 16, aspect ratio ≤ 3:1, total pixels 655,360–8,294,400, max edge 3,840px |
| Default size              | Model-chosen (\~1.3M pixels) when `size` is omitted                                                 |
| Quality                   | `low` (default), `medium`, `high`, `auto`                                                           |
| Formats                   | `png` (default), `jpeg`                                                                             |
| Background                | `opaque` (default), `transparent`, `auto`                                                           |
| Output images per request | 1–10                                                                                                |
| Input images per edit     | 1–16                                                                                                |

## Text-to-image

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.upmore.net/v1/images/generations \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-image-2.5-flare",
      "prompt": "A red fox sitting in a snowy forest at dusk, photorealistic",
      "size": "1536x1024",
      "quality": "high"
    }'
  ```

  ```python Python theme={null}
  from openai import OpenAI
  import base64

  client = OpenAI(
      api_key="YOUR_API_KEY",
      base_url="https://api.upmore.net/v1"
  )

  response = client.images.generate(
      model="gpt-image-2.5-flare",
      prompt="A red fox sitting in a snowy forest at dusk, photorealistic",
      size="1536x1024",
      quality="high"
  )

  # The API always returns base64 data — decode it to a file.
  with open("fox.png", "wb") as f:
      f.write(base64.b64decode(response.data[0].b64_json))
  ```

  ```javascript Node.js theme={null}
  import OpenAI from "openai";
  import { writeFile } from "node:fs/promises";

  const client = new OpenAI({
    apiKey: process.env.UPMORE_API_KEY,
    baseURL: "https://api.upmore.net/v1",
  });

  const response = await client.images.generate({
    model: "gpt-image-2.5-flare",
    prompt: "A red fox sitting in a snowy forest at dusk, photorealistic",
    size: "1536x1024",
    quality: "high",
  });

  await writeFile("fox.png", Buffer.from(response.data[0].b64_json, "base64"));
  ```
</CodeGroup>

## Image-to-image

### Upload the image as a file

POST to `/v1/images/edits` as `multipart/form-data`: the source image goes in the `image` file field, the instruction in the `prompt` form field, and every other parameter (`size`, `quality`, `n`, …) as an ordinary form field with a string value.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.upmore.net/v1/images/edits \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -F "model=gpt-image-2.5-flare" \
    -F "prompt=Turn the fox's fur bright blue and add falling snowflakes" \
    -F "image=@fox.png;type=image/png" \
    -F "size=1024x1024" \
    -F "quality=high"
  ```

  ```python Python theme={null}
  from openai import OpenAI
  import base64

  client = OpenAI(
      api_key="YOUR_API_KEY",
      base_url="https://api.upmore.net/v1"
  )

  with open("fox.png", "rb") as source:
      response = client.images.edit(
          model="gpt-image-2.5-flare",
          image=source,
          prompt="Turn the fox's fur bright blue and add falling snowflakes",
          size="1024x1024",
          quality="high",
      )

  with open("fox-blue.png", "wb") as f:
      f.write(base64.b64decode(response.data[0].b64_json))
  ```
</CodeGroup>

<Warning>
  `image` in a multipart request must be an actual file. Sending a URL string there is rejected with `Invalid type for 'image': expected one of an array of files or file, but got a string instead.` To use a URL, send JSON instead (below).
</Warning>

### Reference the image by URL

Send `application/json` instead, and put the image in `images` — an array of objects, each with an `image_url`. This is the form to use when your image already lives somewhere reachable: TOS, R2, a CDN, or an inline `data:` URL.

<CodeGroup>
  ```bash cURL — public URL (TOS, R2, CDN) theme={null}
  curl https://api.upmore.net/v1/images/edits \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-image-2.5-flare",
      "prompt": "Turn the fox'"'"'s fur bright blue and add falling snowflakes",
      "images": [
        { "image_url": "https://your-bucket.tos-cn-beijing.volces.com/fox.png" }
      ],
      "size": "1024x1024",
      "quality": "high"
    }'
  ```

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

  with open("fox.png", "rb") as f:
      data_url = "data:image/png;base64," + base64.b64encode(f.read()).decode()

  response = requests.post(
      "https://api.upmore.net/v1/images/edits",
      headers={
          "Authorization": "Bearer YOUR_API_KEY",
          "Content-Type": "application/json",
      },
      json={
          "model": "gpt-image-2.5-flare",
          "prompt": "Turn the fox's fur bright blue and add falling snowflakes",
          "images": [{"image_url": data_url}],
          "size": "1024x1024",
          "quality": "high",
      },
  )

  print(response.json()["data"][0]["b64_json"][:100])
  ```
</CodeGroup>

What `image_url` accepts:

| Value                                                                          | Supported                                                                  |
| ------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| `https://…` public URL — TOS, R2, CDN, or any host reachable from the upstream | Yes                                                                        |
| `data:image/png;base64,…` inline payload                                       | Yes                                                                        |
| A time-limited presigned URL                                                   | Yes, as long as it is still valid when the request is processed            |
| `tos://bucket/key`                                                             | No — the scheme is rejected; pass an `https://` URL                        |
| A non-public URL (LAN, VPN-only, signed-out)                                   | No — the upstream fetches the URL itself, so it must be publicly reachable |

<Note>
  The upstream schema also accepts a `file_id` alternative to `image_url`, but Upmore does not expose the Files upload API, so only `image_url` is usable.
</Note>

### Edit from multiple reference images

Up to **16** input images per request. Repeat the file field as `image[]` in multipart, or add more objects to `images` in JSON.

<CodeGroup>
  ```bash cURL — multipart, two files theme={null}
  curl https://api.upmore.net/v1/images/edits \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -F "model=gpt-image-2.5-sunburst" \
    -F "prompt=Put the yellow circle from the second image into the first image" \
    -F "image[]=@fox.png;type=image/png" \
    -F "image[]=@logo.png;type=image/png"
  ```

  ```bash cURL — JSON, two URLs theme={null}
  curl https://api.upmore.net/v1/images/edits \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-image-2.5-sunburst",
      "prompt": "Put the yellow circle from the second image into the first image",
      "images": [
        { "image_url": "https://example.com/fox.png" },
        { "image_url": "https://example.com/logo.png" }
      ]
    }'
  ```
</CodeGroup>

Each input image adds its own image tokens to `usage.input_tokens_details.image_tokens`, proportional to its resolution — roughly 1,024 tokens for a 1024×1024 image. A 16-image request is billed for all 16.

## Masked editing

Supply a mask to confine the edit to one region. The mask must be a **PNG with an alpha channel**, the same pixel dimensions as the source image: transparent pixels mark the region the model may repaint, opaque pixels are preserved.

<CodeGroup>
  ```bash cURL — multipart theme={null}
  curl https://api.upmore.net/v1/images/edits \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -F "model=gpt-image-2.5-flare" \
    -F "prompt=a glowing golden orb" \
    -F "image=@fox.png;type=image/png" \
    -F "mask=@mask.png;type=image/png"
  ```

  ```bash cURL — JSON theme={null}
  curl https://api.upmore.net/v1/images/edits \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-image-2.5-flare",
      "prompt": "a glowing golden orb",
      "images": [{ "image_url": "https://example.com/fox.png" }],
      "mask": { "image_url": "https://example.com/mask.png" }
    }'
  ```
</CodeGroup>

A mask that does not match the source dimensions fails with `Invalid mask image format - mask size does not match image size`, and a mask without an alpha channel fails with `Invalid mask image format - mask image missing alpha channel`.

## Streaming

Set `stream: true` to receive server-sent events. The stream emits up to `partial_images` preview frames and always ends with a `completed` event carrying the final image. If you omit `partial_images`, or the image finishes before the previews are produced, you may receive only the `completed` event.

| Endpoint                 | Events                                                         |
| ------------------------ | -------------------------------------------------------------- |
| `/v1/images/generations` | `image_generation.partial_image`, `image_generation.completed` |
| `/v1/images/edits`       | `image_edit.partial_image`, `image_edit.completed`             |

<CodeGroup>
  ```bash cURL theme={null}
  curl -N https://api.upmore.net/v1/images/generations \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-image-2.5-flare",
      "prompt": "A blue ceramic teapot on a wooden table",
      "size": "1024x1024",
      "stream": true,
      "partial_images": 2
    }'
  ```

  ```text Response (truncated) theme={null}
  event: image_generation.partial_image
  data: {"type":"image_generation.partial_image","partial_image_index":0,"b64_json":"iVBORw0KGgo...","size":"1024x1024","quality":"low","output_format":"png"}

  event: image_generation.completed
  data: {"type":"image_generation.completed","b64_json":"iVBORw0KGgo...","size":"1024x1024","usage":{"input_tokens":11,"output_tokens":196,"total_tokens":207}}
  ```
</CodeGroup>

## Parameters

### Text-to-image (`/v1/images/generations`)

| Parameter            | Type    | Required | Description                                                                                                                                                           |
| -------------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`              | string  | Yes      | `gpt-image-2.5-flare` or `gpt-image-2.5-sunburst`                                                                                                                     |
| `prompt`             | string  | Yes      | Text description of the desired image                                                                                                                                 |
| `n`                  | integer | No       | Images to generate, 1–10. Default: `1`                                                                                                                                |
| `size`               | string  | No       | `{width}x{height}`. Edges must be multiples of 16, aspect ratio ≤ 3:1, total pixels 655,360–8,294,400, max edge 3,840px. Omit to let the model choose (\~1.3M pixels) |
| `quality`            | string  | No       | `low`, `medium`, `high`, `auto`. Default: `low`                                                                                                                       |
| `background`         | string  | No       | `opaque`, `transparent`, `auto`. Default: `opaque`. Use `png` output with `transparent`                                                                               |
| `output_format`      | string  | No       | `png`, `jpeg`. Default: `png`                                                                                                                                         |
| `output_compression` | integer | No       | Compression level for `jpeg` output (0–100)                                                                                                                           |
| `moderation`         | string  | No       | `auto` or `low`. Default: `auto`                                                                                                                                      |
| `stream`             | boolean | No       | Stream partial images as server-sent events. Default: `false`                                                                                                         |
| `partial_images`     | integer | No       | Number of preview frames to request when `stream` is `true`                                                                                                           |

### Image-to-image (`/v1/images/edits`)

All text-to-image parameters apply, plus:

| Parameter | Type             | Required                 | Description                                                                                                           |
| --------- | ---------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `image`   | file             | Multipart only, required | Source image. Repeat as `image[]` for multiple images                                                                 |
| `images`  | array of objects | JSON only, required      | Source images as `[{"image_url": "…"}]`, 1–16 entries                                                                 |
| `mask`    | file or object   | No                       | Editable region. Multipart: file field. JSON: `{"image_url": "…"}`. Must be a PNG with alpha, same size as the source |

<Warning>
  `response_format` and `input_fidelity` are not supported. Image data is always returned as base64 in `data[].b64_json`, and `webp` is not an accepted `output_format`.
</Warning>

## Response

```json theme={null}
{
  "created": 1789103440,
  "background": "opaque",
  "output_format": "png",
  "quality": "low",
  "size": "1024x1024",
  "data": [
    { "b64_json": "iVBORw0KGgo..." }
  ],
  "usage": {
    "input_tokens": 1053,
    "input_tokens_details": { "image_tokens": 1024, "text_tokens": 29 },
    "output_tokens": 439,
    "output_tokens_details": { "image_tokens": 439, "text_tokens": 0 },
    "total_tokens": 1492
  }
}
```

For image edits, `usage.input_tokens_details.image_tokens` counts the source images, so the same size and quality cost more than a text-to-image call.

## Limits and error codes

Requests that violate a constraint fail fast with HTTP 400 and a specific message:

| Condition                                        | Response                                                                                         |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| Edge not a multiple of 16                        | `Width and height must both be divisible by 16.`                                                 |
| Aspect ratio beyond 3:1                          | `The maximum supported aspect ratio is 3:1.`                                                     |
| Fewer than 655,360 pixels                        | `Requested resolution is below the current minimum pixel budget.`                                |
| More than 8,294,400 pixels                       | `Requested resolution exceeds the current pixel budget.`                                         |
| Edge above 3,840px                               | `The longest edge must be less than or equal to 3840.`                                           |
| `n` outside 1–10                                 | `Invalid 'n': integer above maximum value. Expected a value <= 10`                               |
| More than 16 input images                        | HTTP 500 from the upstream — cap requests at 16                                                  |
| Unknown `quality`                                | `Supported values are: 'low', 'medium', 'high', and 'auto'.`                                     |
| `output_format: "webp"`                          | `Supported values are: 'png' and 'jpeg'.`                                                        |
| URL string in a multipart `image` field          | `Invalid type for 'image': expected one of an array of files or file, but got a string instead.` |
| `image` / `images` with the wrong shape          | `Unknown parameter: 'image'. For application/json on /v1/images/edits, use 'images' (array).`    |
| `tos://` or other non-HTTP scheme in `image_url` | `Invalid 'images[0].image_url'. Expected a valid URL, but got a value with an invalid format.`   |
| Mask size differs from the source                | `Invalid mask image format - mask size does not match image size`                                |
| Mask has no alpha channel                        | `Invalid mask image format - mask image missing alpha channel`                                   |
| Missing prompt                                   | `Missing required parameter: 'prompt'.`                                                          |

<Note>
  The upstream also runs a safety system over the prompt/image combination. A rejected request returns `Your request was rejected by the safety system…` with an Azure request ID; retrying with different input usually resolves it, and the ID is what Azure support needs if it does not.
</Note>

<Card title="API Reference" icon="code" href="/api-reference/model-api/openai/gpt-image-2-5/generate">
  View the interactive API playground.
</Card>
