curl --request POST \
--url https://api.apiyi.com/v1/images/edits \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form model=gpt-image-2.5-sunburst \
--form 'prompt=Place subject from image 1 into scene from image 2, using color style from image 3' \
--form 'image=<string>' \
--form image.items='@example-file' \
--form mask='@example-file'import requests
url = "https://api.apiyi.com/v1/images/edits"
files = {
"image.items": ("example-file", open("example-file", "rb")),
"mask": ("example-file", open("example-file", "rb"))
}
payload = {
"model": "gpt-image-2.5-sunburst",
"prompt": "Place subject from image 1 into scene from image 2, using color style from image 3",
"image": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('model', 'gpt-image-2.5-sunburst');
form.append('prompt', 'Place subject from image 1 into scene from image 2, using color style from image 3');
form.append('image', '<string>');
form.append('image.items', '{
"fileName": "example-file"
}');
form.append('mask', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.apiyi.com/v1/images/edits', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1/images/edits",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\ngpt-image-2.5-sunburst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nPlace subject from image 1 into scene from image 2, using color style from image 3\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mask\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1/images/edits"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\ngpt-image-2.5-sunburst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nPlace subject from image 1 into scene from image 2, using color style from image 3\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mask\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1/images/edits")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\ngpt-image-2.5-sunburst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nPlace subject from image 1 into scene from image 2, using color style from image 3\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mask\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1/images/edits")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\ngpt-image-2.5-sunburst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nPlace subject from image 1 into scene from image 2, using color style from image 3\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mask\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"created": 1776832476,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAA..."
}
],
"usage": {
"input_tokens": 1280,
"output_tokens": 6240,
"total_tokens": 7520
}
}Справочник API редактирования изображений
Справочник API редактирования изображений и интерактивное тестирование для gpt-image-2.5-sunburst / gpt-image-2.5-flare / gpt-image-2 — загрузка эталонных изображений (до 16) и инструкций для редактирования одного изображения, объединения нескольких изображений или заливки по маске
curl --request POST \
--url https://api.apiyi.com/v1/images/edits \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form model=gpt-image-2.5-sunburst \
--form 'prompt=Place subject from image 1 into scene from image 2, using color style from image 3' \
--form 'image=<string>' \
--form image.items='@example-file' \
--form mask='@example-file'import requests
url = "https://api.apiyi.com/v1/images/edits"
files = {
"image.items": ("example-file", open("example-file", "rb")),
"mask": ("example-file", open("example-file", "rb"))
}
payload = {
"model": "gpt-image-2.5-sunburst",
"prompt": "Place subject from image 1 into scene from image 2, using color style from image 3",
"image": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('model', 'gpt-image-2.5-sunburst');
form.append('prompt', 'Place subject from image 1 into scene from image 2, using color style from image 3');
form.append('image', '<string>');
form.append('image.items', '{
"fileName": "example-file"
}');
form.append('mask', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.apiyi.com/v1/images/edits', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1/images/edits",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\ngpt-image-2.5-sunburst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nPlace subject from image 1 into scene from image 2, using color style from image 3\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mask\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1/images/edits"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\ngpt-image-2.5-sunburst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nPlace subject from image 1 into scene from image 2, using color style from image 3\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mask\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1/images/edits")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\ngpt-image-2.5-sunburst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nPlace subject from image 1 into scene from image 2, using color style from image 3\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mask\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1/images/edits")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\ngpt-image-2.5-sunburst\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nPlace subject from image 1 into scene from image 2, using color style from image 3\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"mask\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"created": 1776832476,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAA..."
}
],
"usage": {
"input_tokens": 1280,
"output_tokens": 6240,
"total_tokens": 7520
}
}Bearer sk-xxx), выберите файлы изображения / маски, заполните prompt и model и отправьте запрос.multipart/form-data. Для обычной генерации изображений по тексту используйте эндпоинт генерации изображений по тексту.请求时发生错误: unable to complete request после получения ответа — запрос фактически выполнен успешно; браузер просто не может отобразить настолько длинную строку base64.Рекомендуемый рабочий процесс (подходит начинающим):- Скопируйте приведённый ниже пример на Python / Node.js / cURL и запустите его локально. Код автоматически выполняет
base64.b64decodeдля ответа и записывает изображение в файл. - Если необходимо использовать браузерную площадку Playground, используйте небольшое эталонное изображение (< 50 КБ), установите
sizeна минимальный уровень (например,1024x1024), аquality— наlow.
- Не передавайте
input_fidelity— все три модели принудительно используют высокую точность; его передача приводит к ошибке 400 (проверено на версии 2.5 2026-09-09) - Запросы на редактирование требуют заметно больше входных token — эталонные изображения преобразуются в большое количество token по тарифам Vision; учитывайте это при планировании бюджета
- Объединение нескольких изображений: максимум 16 — повторяйте поле
image[]; при превышении 16 запрос завершается ошибкой
image[] принимает несколько эталонных изображений. Порядок загрузки определяет соответствие эталонных изображений «изображение 1 / изображение 2 / изображение 3» в промпте. Явно ссылайтесь на них:Поместите объект с изображения 1 в сцену с изображения 2, используя цветовой стиль изображения 3Ограничение для каждого файла: менее 50 МБ (загрузка файлов multipart), форматы:
png / jpg / webp; на практике перед загрузкой сожмите файлы до размера не более 1,5 МБ (см. раздел «Ограничения размера загрузки» ниже).Примеры кода
Python (OpenAI SDK · редактирование одного изображения)
from openai import OpenAI
import base64
client = OpenAI(
api_key="sk-your-api-key",
base_url="https://api.apiyi.com/v1"
)
resp = client.images.edit(
model="gpt-image-2.5-sunburst",
image=open("photo.png", "rb"),
prompt="Replace the background with a seaside sunset, preserve subject details",
size="1536x1024",
quality="high"
)
# b64_json is raw base64 (no prefix) — decode manually
with open("edited.png", "wb") as f:
f.write(base64.b64decode(resp.data[0].b64_json))
Python (OpenAI SDK · объединение нескольких изображений)
resp = client.images.edit(
model="gpt-image-2.5-sunburst",
image=[
open("person.png", "rb"),
open("scene.png", "rb"),
open("style.png", "rb"),
],
prompt="Place subject from image 1 into scene from image 2, using color style from image 3, keep lighting consistent",
size="1536x1024",
quality="high"
)
with open("fused.png", "wb") as f:
f.write(base64.b64decode(resp.data[0].b64_json))
cURL (объединение нескольких изображений)
curl -X POST "https://api.apiyi.com/v1/images/edits" \
-H "Authorization: Bearer sk-your-api-key" \
-F "model=gpt-image-2.5-sunburst" \
-F "prompt=Place subject from image 1 into scene from image 2, using color style from image 3" \
-F "size=1536x1024" \
-F "quality=high" \
-F "image[][email protected]" \
-F "image[][email protected]" \
-F "image[][email protected]"
cURL (дорисовка по маске)
curl -X POST "https://api.apiyi.com/v1/images/edits" \
-H "Authorization: Bearer sk-your-api-key" \
-F "model=gpt-image-2.5-sunburst" \
-F "prompt=Replace the sky with pink sunset clouds" \
-F "size=1024x1024" \
-F "quality=high" \
-F "image[][email protected]" \
-F "[email protected]" \
| jq -r '.data[0].b64_json' | base64 -d > photo_edited.png
Node.js (нативные fetch + FormData · объединение нескольких изображений)
import fs from 'node:fs';
const form = new FormData();
form.append('model', 'gpt-image-2.5-sunburst');
form.append('prompt', 'Place subject from image 1 into scene from image 2');
form.append('size', '1536x1024');
form.append('quality', 'high');
form.append('image[]', new Blob([fs.readFileSync('./person.png')]), 'person.png');
form.append('image[]', new Blob([fs.readFileSync('./scene.png')]), 'scene.png');
const resp = await fetch('https://api.apiyi.com/v1/images/edits', {
method: 'POST',
headers: { 'Authorization': 'Bearer sk-your-api-key' },
body: form
});
const { data } = await resp.json();
fs.writeFileSync('fused.png', Buffer.from(data[0].b64_json, 'base64'));
Справочник параметров
| Поле | Тип | Обязательно | По умолчанию | Описание |
|---|---|---|---|---|
model | text | Да | — | gpt-image-2.5-sunburst (приоритет точности редактирования, выбор для правок) / gpt-image-2.5-flare (приоритет скорости) / gpt-image-2 (предыдущее поколение, всё ещё доступно); в production фиксируйте датированные снимки gpt-image-2.5-sunburst-2026-09-08 / gpt-image-2.5-flare-2026-09-08. Одинаковые цена и параметры для всех трёх |
prompt | text | Да | — | Инструкция по редактированию / объединению |
image[] | file | Да | — | Эталонные изображения, можно повторять (макс. 16) |
mask | file | Нет | — | Изображение маски (применяется только к первому изображению, требуется alpha-канал) |
size | text | Нет | auto | Размер выходного изображения, как для преобразования текста в изображение |
quality | text | Нет | auto | low / medium / high / xhigh / max / auto; xhigh / max появились в версии 2.5, gpt-image-2 поддерживается только до high |
output_format | text | Нет | png | png / jpeg / webp |
output_compression | text | Нет | — | 0–100, только для jpeg / webp |
background | text | Нет | auto | transparent / opaque / auto. При использовании transparent значение output_format должно быть png или webp. Обратите внимание: прозрачность в эндпоинте редактирования — это перерисовка, а не точное вырезание; см. раздел часто задаваемых вопросов о прозрачном фоне |
standard / hd для quality. Принимаются только шесть официальных значений перечисления low / medium / high / xhigh / max / auto (xhigh / max — только двумя моделями 2.5). Устаревшие значения ведут себя непоследовательно в разных backend-каналах: иногда они немедленно завершаются ошибкой 400 (invalid_value), а иногда молча игнорируются, и запрос выполняется с параметром auto (непредсказуемая стоимость). Всегда явно передавайте одно из официальных значений.Ограничения на размер загрузки
| Пункт | Лимит | Примечания |
|---|---|---|
| Количество reference image | До 16 | Повторите поле image[] |
| На одно изображение (загрузка файла multipart) | Менее 50MB каждое | Форматы: png / jpg / webp |
| На одно изображение (base64 data URL) | Длина поля ~20MiB | Это ограничение длины для URL/base64 строкового поля (схема maxLength: 20971520) — не то же самое, что и лимит 50MB для multipart; base64 увеличивает размер примерно на 1/3, поэтому исходные изображения держите в пределах 15MB |
| Файл mask | PNG до 4MB | Должен совпадать с размерами исходного изображения и содержать alpha-канал |
Требования к формату эталонного изображения и предварительная обработка
/v1/images/edits принимает только стандартные форматы png / jpg / webp. Если вы получаете эту ошибку 400:
{
"error": {
"message": "Invalid image file or mode for image 1, please check your image file. ...",
"type": "shell_api_error",
"code": "invalid_image_file"
}
}
.jpg, полученные прямо с телефонов серии Huawei Mate, содержат вложенный подкадр HDR gain-map и на самом деле являются MPO. Эти файлы начинаются с того же заголовка FFD8 — расширение и команда file оба сообщают JPEG — поэтому их невозможно распознать визуально; определить это может только разбор с учетом кадров (например, Pillow). «изображение 1» в сообщении об ошибке относится к N-му эталонному изображению (нумерация с 1), поэтому используйте индекс, чтобы найти проблемный файл.
Image.open(f).format возвращает "MPO", файл нужно конвертировать. Один шаг повторного кодирования в вашем пайплайне загрузки также покрывает HEIC и другие форматы смартфонов:
from PIL import Image
import io
def normalize_image(path: str) -> bytes:
"""Convert phone photos (MPO/HDR multi-frame etc.) to standard JPEG that passes edits validation"""
im = Image.open(path)
im.load() # for MPO, keeps only the first (full-size) frame
if im.mode not in ("RGB", "RGBA"):
im = im.convert("RGB")
out = io.BytesIO()
im.save(out, format="JPEG", quality=92) # or format="PNG"
return out.getvalue()
Требования к Mask Inpainting
- Тот же размер, что и у оригинала, формат PNG, меньше 4MB
- Обязательно наличие alpha channel: прозрачные области (alpha=0) = область inpaint, непрозрачные = сохранять
- Маска применяется только к первому изображению
- Маска — это «мягкая подсказка»: модель может расширять или сужать область вокруг замаскированного региона
image[] следующего вызова с новой инструкцией для постепенной доработки. Каждый раунд тарифицируется отдельно по tokens — следите за совокупной стоимостью.Формат ответа
{
"created": 1776832476,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAA..."
}
],
"usage": {
"input_tokens": 848,
"input_tokens_details": {
"image_tokens": 832,
"text_tokens": 16
},
"output_tokens": 196,
"output_tokens_details": {
"image_tokens": 196,
"text_tokens": 0
},
"total_tokens": 1044
}
}
b64_json — это необработанный base64, без префикса data:image/...;base64, — в отличие от gpt-image-2-all. Декодируйте его на стороне клиента, чтобы записать файл, или добавьте префикс для отображения в браузере.input_tokens у запросов на редактирование обычно значительно выше, чем у генерации изображений по тексту при том же размере, поскольку опорные изображения тарифицируются по правилам тарификации Vision — точная сумма доступна напрямую в usage.input_tokens_details.image_tokens и учитывается отдельно от текстовой части (text_tokens). Объединение нескольких изображений увеличивает image_tokens строго линейно с каждым дополнительным опорным изображением (проверено в июле 2026: 4 × 1024² изображений = 4 × 1024 tokens) — см. Как несколько входных изображений влияют на стоимость для таблицы измерений. См. Как проверить фактическое количество token для каждого вызова на странице обзора для полной справки по полям.Авторизации
API Key obtained from APIYI Console
Тело
Model name. gpt-image-2.5-flare (speed-first) / gpt-image-2.5-sunburst (quality- and editing-first) / gpt-image-2 (previous generation) share the same price and parameters; pin a dated snapshot in production
gpt-image-2.5-flare, gpt-image-2.5-sunburst, gpt-image-2, gpt-image-2.5-flare-2026-09-08, gpt-image-2.5-sunburst-2026-09-08 Edit/fusion instruction. For multi-image, use 'image 1 / image 2 / image 3' to reference upload order
"Place subject from image 1 into scene from image 2, using color style from image 3"
Reference images. For a single image, send the field once; for multiple images, repeat the same image field (e.g., -F [email protected] -F [email protected], max 16) — upload order maps to image 1 / image 2 / ... in the prompt. multipart file upload: each under 50MB, formats: png/jpg/webp; compress to within 1.5MB in practice
Mask image (optional, only applies to first image). Requirements:
- Same size as original
- PNG format, under 4MB
- Must have alpha channel (alpha=0 = inpaint area, opaque = preserve)
Output size (same as text-to-image). Preset or constraint-satisfying custom size
"1536x1024"
Quality tier. xhigh / max are new in 2.5 and rejected by gpt-image-2
auto, low, medium, high, xhigh, max Output format
png, jpeg, webp Output compression (0–100), only effective for jpeg/webp
0 <= x <= 100Background mode. auto or opaque. Not supported: transparent
auto, opaque Была ли эта страница полезной?