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

# 이미지 편집 API 레퍼런스

> 실시간 Playground를 지원하는 MAI-Image 2.6 이미지 편집 API 레퍼런스 — 참조 이미지 및 지시사항 업로드, image + image2를 통한 두 이미지 합성, multipart/form-data 파일 업로드만 지원

<Info>
  오른쪽의 대화형 Playground에서는 로컬 이미지 업로드를 지원합니다. **Authorization** 아래에 API 키(형식: `Bearer sk-xxx`)를 입력하고, `image` 파일을 선택한 후, `prompt` 및 `model` 항목을 입력하고 전송하십시오.
</Info>

<Warning>
  **🔴 이 엔드포인트는 `multipart/form-data` 파일 업로드만 허용합니다**

  `/v1/images/edits`에 JSON을 전송하면(`image`를 URL, 데이터 URI 또는 원시 base64로 지정) 400 오류가 반환됩니다:

  ```text theme={null}
  request Content-Type isn't multipart/form-data
  ```

  **이미지 URL은 입력으로 지원되지 않습니다.** URL만 보유하고 있는 경우, 먼저 서버에서 다운로드한 후 해당 파일을 업로드하십시오. 파일 업로드는 이미지 호스팅이 필요하지 않으며, 로컬 파일만 전송하면 됩니다.
</Warning>

<Tip>
  **사용 사례**: 이 페이지는 참조 이미지를 편집하거나 두 이미지를 합성하는 용도입니다. 텍스트로만 생성하려면 [텍스트-이미지 API](/ko/api-capabilities/mai-image/text-to-image)를 사용하십시오.
</Tip>

<Warning>
  **⚠️ 두 개의 이미지의 경우 필드 이름은 `image[]`이 아니라 `image` + `image2`입니다**

  두 개의 참조 이미지를 사용하는 경우, 첫 번째 필드 이름을 `image`, 두 번째 필드 이름을 `image2`(으)로 지정하십시오. `image[]`를 반복하거나, `image`를 반복하거나, `mask` 필드를 추가하면 모두 400 `File must be attached in a form field with a name starting with 'image'` 오류가 반환됩니다.

  즉, OpenAI SDK의 다중 이미지 형식 `client.images.edit(image=[f1, f2])`은 **작동하지 않습니다**(`image[]`을(를) 전송함). SDK를 통한 단일 이미지 편집은 정상 작동합니다.
</Warning>

<Info>
  **텍스트-이미지와 동일한 금지 파라미터**: `response_format`, `seed` 또는 `negative_prompt`를 전송하지 마십시오(400). 응답은 항상 `data[0].b64_json`(PNG)입니다.
</Info>

## 코드 예제

### Python (OpenAI SDK · 단일 이미지)

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

client = OpenAI(
    api_key="sk-your-api-key",
    base_url="https://api.apiyi.com/v1",
    timeout=180.0
)

# images.edit uses a multipart file upload under the hood; do not pass response_format
resp = client.images.edit(
    model="MAI-Image-2.6-Flash",
    image=open("teaset.jpg", "rb"),
    prompt="Change the teapot to a deep cobalt blue glaze, keep everything else identical"
)

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

### Python (requests · 단일 이미지)

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

# Pass the file via files=; requests sets multipart/form-data and the boundary for you
# Do not use json=, and do not set Content-Type by hand
with open("teaset.jpg", "rb") as fp:
    response = requests.post(
        "https://api.apiyi.com/v1/images/edits",
        headers={"Authorization": f"Bearer {os.environ['APIYI_API_KEY']}"},
        data={
            "model": "MAI-Image-2.6",
            "prompt": "Change the teapot to a deep cobalt blue glaze, keep everything else exactly the same"
        },
        files={"image": ("teaset.jpg", fp, "image/jpeg")},
        timeout=180
    )
response.raise_for_status()

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

### Python (두 이미지 합성 · image + image2)

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

files = {
    "image": ("scene.jpg", open("scene.jpg", "rb"), "image/jpeg"),     # image 1
    "image2": ("person.jpg", open("person.jpg", "rb"), "image/jpeg"),  # image 2: field name is image2
}

response = requests.post(
    "https://api.apiyi.com/v1/images/edits",
    headers={"Authorization": f"Bearer {os.environ['APIYI_API_KEY']}"},
    data={
        "model": "MAI-Image-2.6",
        "prompt": "Have the person from image 2 sit at the table in image 1, arranging the tea set, natural light, photorealistic"
    },
    files=files,
    timeout=180
)
response.raise_for_status()

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

### cURL

```bash theme={null}
# Single-image edit: -F means multipart/form-data, @ uploads a local file
curl -X POST "https://api.apiyi.com/v1/images/edits" \
  -H "Authorization: Bearer sk-your-api-key" \
  -F "model=MAI-Image-2.6-Flash" \
  -F "prompt=Change the teapot to a deep cobalt blue glaze, keep everything else identical" \
  -F "image=@teaset.jpg" \
  | python3 -c "import sys,json,base64; open('edited.png','wb').write(base64.b64decode(json.load(sys.stdin)['data'][0]['b64_json']))"
```

```bash theme={null}
# Two-image fusion with the canvas changed to 1536×1024
curl -X POST "https://api.apiyi.com/v1/images/edits" \
  -H "Authorization: Bearer sk-your-api-key" \
  -F "model=MAI-Image-2.6" \
  -F "prompt=Have the person from image 2 sit at the table in image 1, arranging the tea set" \
  -F "width=1536" \
  -F "height=1024" \
  -F "image=@scene.jpg" \
  -F "image2=@person.jpg"
```

### Node.js (fetch + FormData)

```javascript theme={null}
import fs from 'node:fs';

const form = new FormData();
form.append('model', 'MAI-Image-2.6-Flash');
form.append('prompt', 'Replace the background with a snowy pine forest at night, keep the person unchanged');
form.append('image', new Blob([fs.readFileSync('./photo.jpg')]), 'photo.jpg');
// Second reference image: form.append('image2', ...)

const resp = await fetch('https://api.apiyi.com/v1/images/edits', {
    method: 'POST',
    // Do not set Content-Type by hand; FormData adds the boundary
    headers: { 'Authorization': `Bearer ${process.env.APIYI_API_KEY}` },
    body: form,
    signal: AbortSignal.timeout(120000)
});

const data = await resp.json();
fs.writeFileSync('edited.png', Buffer.from(data.data[0].b64_json, 'base64'));
```

## 파라미터 레퍼런스

| 파라미터 | 타입 | 필수 여부 | 기본값 | 설명 |
| - | - | - | - | - |
| `model` | string | ✅ | — | `MAI-Image-2.6` (\$0.12/image) 또는 `MAI-Image-2.6-Flash` (\$0.06/image), **대소문자 구분** |
| `prompt` | string | ✅ | — | 편집 지시사항입니다. 변경할 내용과 그 외 나머지는 그대로 유지하도록 명시하십시오 |
| `image` | file | ✅ | — | 참조 이미지 파일(첫 번째) |
| `image2` | file | ❌ | — | 두 번째 참조 이미지(2개 이미지 합성용) |
| `width` / `height` | integer | ❌ | 원본 비율 따름 | 출력 크기, 텍스트-투-이미지와 동일한 규칙이 적용되며, 다른 가로세로 비율을 지정하면 이미지가 **재구성**됩니다 |
| `n` | integer | ❌ | `1` | 이미지 수입니다. **이 엔드포인트에서 지원**되며, 이미지당 과금됩니다 |
| ~~`mask`~~ | — | — | — | **지원되지 않음**, 400을 반환합니다 |
| ~~`response_format`~~ / ~~`seed`~~ / ~~`negative_prompt`~~ | — | — | — | **400 반환** |

<Info>
  **생략 시 출력 크기**: 출력은 16의 배수로 맞춰진 원본의 가로세로 비율을 따릅니다(예: 1344×756 입력 시 1360×768 출력). 구도를 유지해야 하는 부분 편집의 경우 `width` / `height`을 전송하지 마십시오.
</Info>

## 편집 결과 및 prompt 작성

편집 엔드포인트는 **원본의 구도, 색상 및 세부 사항을 유지**하며 prompt에서 요청한 부분만 변경합니다:

<Frame>
  <img src="https://mintcdn.com/apiyillc/_zXMTnA1u6gpoDyM/images/mai-image-edit-teaset.jpg?fit=max&auto=format&n=_zXMTnA1u6gpoDyM&q=85&s=c86dc86c5aadf0173e19102433c01f49" alt="MAI-Image-2.6-Flash 편집 예시: 크림색 티팟을 코발트 블루로 변경, 다른 모든 요소는 변경되지 않음" width="1048" height="532" data-path="images/mai-image-edit-teaset.jpg" />
</Frame>

| Prompt | 결과 |
| - | - |
| ✅ `Change the teapot to a deep cobalt blue glaze, keep everything else exactly the same` | 티팟의 색상만 변경되며, 라벨과 기타 객체는 픽셀 단위까지 동일하게 유지됩니다 |
| ✅ `Turn this photo into a watercolor painting, keep the composition` | 스타일이 다시 렌더링되며 구도는 유지됩니다 |
| ✅ `Have the person from image 2 sit at the table in image 1` | 두 이미지 합성: 이미지 1이 배경 장면을 제공하고 이미지 2가 인물을 제공합니다 |
| ⚠️ `Make it look better` | 너무 모호하여 변경 범위 예측이 불가능합니다 |

<Tip>
  두 이미지 합성의 경우, prompt 내에서 `image` / `image2`을 “image 1 / image 2”로 지칭하십시오. 테스트 결과 **인물에 대한 동일성 재현율은 보통 수준**(이목구비 특징이 달라질 수 있음)이므로, 인물 사진의 일관성이 중요하다면 먼저 소량 배치로 검증하십시오.
</Tip>

## 응답 형식

```json theme={null}
{
  "created": 1791000788,
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAIAAADwf7zU..."
    }
  ],
  "usage": {
    "prompt_tokens": 1000,
    "total_tokens": 1000,
    "input_tokens": 1000,
    "output_tokens": 0
  }
}
```

<Warning>
  **응답 필드**

  * `b64_json`은 **`data:` 접두사가 없는 일반 base64**이며 PNG로 디코딩됩니다.
  * `n > 1` 사용 시 `data` 배열에 여러 항목이 포함되므로 `data[0]`만 읽지 마십시오.
  * `url` 및 `revised_prompt`는 반환되지 않습니다.
</Warning>

<Info>
  **`usage`으로 과금을 대조하지 마십시오**: 해당 필드는 플레이스홀더 값을 담고 있습니다(`prompt_tokens`는 항상 이미지 수 × 1000입니다). 편집은 텍스트 기반 이미지 생성과 **비용이 동일하며**, 이미지당 과금됩니다. APIYI 콘솔의 과금 내역이 공식 기준입니다.
</Info>


## OpenAPI

````yaml api-reference/mai-image-edit-openapi-en.yaml POST /v1/images/edits
openapi: 3.1.0
info:
  title: MAI-Image 2.6 Image Editing API
  description: >
    Microsoft MAI-Image 2.6 image generation — image editing endpoint.


    - **The request must be `multipart/form-data` (file upload)**; JSON or image
    URLs return 400

    - Single-image editing and two-image fusion (field names `image` + `image2`)

    - No mask support; do not send `response_format` / `seed` /
    `negative_prompt`

    - Flat per-image pricing, same as text-to-image; `n` works on this endpoint
    and is billed per image


    **Authentication**: add `Authorization: Bearer YOUR_API_KEY` to the request
    headers


    **Get an API key**: create a token in the [APIYI
    console](https://api.apiyi.com/token)
  version: 1.0.0
servers:
  - url: https://api.apiyi.com
    description: Primary endpoint
security:
  - bearerAuth: []
paths:
  /v1/images/edits:
    post:
      tags:
        - Image Editing
      summary: 'Image editing: edit a reference image or fuse two images'
      description: >
        Edit an uploaded reference image, or fuse two images, from a text
        instruction with MAI-Image 2.6.


        - **Must use `multipart/form-data`**. Sending `application/json` returns
          400: `request Content-Type isn't multipart/form-data`
        - The second reference image's field is `image2`; repeated `image[]`,
        repeated `image`, or a `mask` field all return 400

        - Without `width` / `height` the output follows the original's ratio; a
        different aspect ratio recomposes the image
      operationId: editMaiImage
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/MaiImageEditRequest'
            encoding:
              image:
                contentType: image/png, image/jpeg, image/webp
              image2:
                contentType: image/png, image/jpeg, image/webp
      responses:
        '200':
          description: Image generated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ImageResponse'
        '400':
          description: >-
            Not multipart/form-data, invalid field names, invalid parameters, or
            blocked by moderation
        '401':
          description: Unauthorized - invalid API key
        '429':
          description: Rate limit exceeded or insufficient balance
        '500':
          description: No image file field in the request (`image is required`)
      security:
        - bearerAuth: []
components:
  schemas:
    MaiImageEditRequest:
      type: object
      required:
        - model
        - prompt
        - image
      properties:
        model:
          type: string
          description: Model ID (case-sensitive)
          enum:
            - MAI-Image-2.6-Flash
            - MAI-Image-2.6
          default: MAI-Image-2.6-Flash
        prompt:
          type: string
          description: >-
            Edit instruction. State what to change and that everything else
            stays the same
          example: >-
            Change the teapot to a deep cobalt blue glaze, keep everything else
            identical
        image:
          type: string
          format: binary
          description: >-
            Reference image file (the first one, "image 1" in the prompt). png /
            jpg / webp
        image2:
          type: string
          format: binary
          description: >-
            Optional second reference image ("image 2" in the prompt), for
            two-image fusion
        width:
          type: integer
          description: >-
            Optional output width. Same rules as text-to-image: each side ≥ 768,
            width × height ≤ 2,359,296, sent together with `height`
          minimum: 768
        height:
          type: integer
          description: Optional output height, same rules as `width`
          minimum: 768
        'n':
          type: integer
          description: Number of images. Works on this endpoint, billed per image
          minimum: 1
          default: 1
          example: 1
    ImageResponse:
      type: object
      properties:
        created:
          type: integer
          description: Creation timestamp
          example: 1791000788
        data:
          type: array
          description: Image results; length equals `n`
          items:
            type: object
            properties:
              b64_json:
                type: string
                description: 'Plain base64 image data (PNG, no data: prefix)'
        usage:
          type: object
          description: >-
            **Placeholder values, not for billing reconciliation.**
            `prompt_tokens` is always `1000 × images`
          properties:
            prompt_tokens:
              type: integer
              example: 1000
            total_tokens:
              type: integer
              example: 1000
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key from the APIYI console

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.