curl --request POST \
--url https://api.apiyi.com/v1/images/edits \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form model=grok-imagine-image \
--form 'prompt=Change the scarf color to bright RED. Keep everything else exactly the same.' \
--form image='@example-file'import requests
url = "https://api.apiyi.com/v1/images/edits"
files = { "image": ("example-file", open("example-file", "rb")) }
payload = {
"model": "grok-imagine-image",
"prompt": "Change the scarf color to bright RED. Keep everything else exactly the same."
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('model', 'grok-imagine-image');
form.append('prompt', 'Change the scarf color to bright RED. Keep everything else exactly the same.');
form.append('image', '<string>');
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\ngrok-imagine-image\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nChange the scarf color to bright RED. Keep everything else exactly the same.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\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\ngrok-imagine-image\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nChange the scarf color to bright RED. Keep everything else exactly the same.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\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\ngrok-imagine-image\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nChange the scarf color to bright RED. Keep everything else exactly the same.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\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\ngrok-imagine-image\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nChange the scarf color to bright RED. Keep everything else exactly the same.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"created": 0,
"data": [
{
"url": "https://apac.ossforai.com/2026/08/12/09b026d5-3492-4678-907c-e25972e6c914.jpg",
"b64_json": "<string>"
}
],
"usage": {
"prompt_tokens": 1000,
"total_tokens": 1000
}
}이미지 편집 API 레퍼런스
Grok Imagine 2 이미지 편집 API 레퍼런스 및 실시간 테스트 — 편집 또는 융합을 위한 지시문과 함께 참조 이미지 1-4장을 업로드합니다; multipart/form-data가 필요합니다
curl --request POST \
--url https://api.apiyi.com/v1/images/edits \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form model=grok-imagine-image \
--form 'prompt=Change the scarf color to bright RED. Keep everything else exactly the same.' \
--form image='@example-file'import requests
url = "https://api.apiyi.com/v1/images/edits"
files = { "image": ("example-file", open("example-file", "rb")) }
payload = {
"model": "grok-imagine-image",
"prompt": "Change the scarf color to bright RED. Keep everything else exactly the same."
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('model', 'grok-imagine-image');
form.append('prompt', 'Change the scarf color to bright RED. Keep everything else exactly the same.');
form.append('image', '<string>');
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\ngrok-imagine-image\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nChange the scarf color to bright RED. Keep everything else exactly the same.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\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\ngrok-imagine-image\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nChange the scarf color to bright RED. Keep everything else exactly the same.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\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\ngrok-imagine-image\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nChange the scarf color to bright RED. Keep everything else exactly the same.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\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\ngrok-imagine-image\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nChange the scarf color to bright RED. Keep everything else exactly the same.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"created": 0,
"data": [
{
"url": "https://apac.ossforai.com/2026/08/12/09b026d5-3492-4678-907c-e25972e6c914.jpg",
"b64_json": "<string>"
}
],
"usage": {
"prompt_tokens": 1000,
"total_tokens": 1000
}
}Bearer sk-xxx), image 파일을 선택한 다음 prompt와 model를 입력하고 전송하십시오.multipart/form-data 파일 업로드가 필요합니다/v1/images/edits에 JSON을 보내면 항상 400을 반환합니다:request Content-Type isn't multipart/form-data
{"image": {"type": "image_url", "url": "..."}})이 포함된 JSON 본문을 설명하지만, 그 형식은 APIYI 게이트웨이를 통해서는 작동하지 않습니다. 대신 이 페이지를 따르십시오.장점은 파일 업로드를 사용하면 이미지 호스팅이 필요 없다는 점입니다 — 로컬 파일만 전송하면 되므로, 공용 URL을 준비하는 것보다 더 간단합니다.파일 필드 이름은 반드시 image 또는 **image[]**여야 합니다; images / image_file는 415를 반환합니다. prompt가 필요하며 — 생략하면 400을 반환합니다.resolution와 aspect_ratio는 여기서 오류 없이 허용되지만 아무 영향도 없습니다 — 편집된 출력은 항상 첫 번째 참조 이미지의 크기와 일치합니다(1280x720을 넣으면 1280x720이 출력되고, 1024x1024를 넣으면 1024x1024가 출력됩니다).합성에도 동일하게 적용됩니다: 4개의 참조 이미지 순서를 뒤집자 출력이 1280x720에서 1024x1024로 바뀌었으며, 새 첫 번째 이미지를 따랐습니다.출력 크기를 변경하려면 업로드하기 전에 첫 번째 참조 이미지를 자르거나 크기를 조정하십시오.image[]은 1-4개의 참조 이미지를 허용하며(실측 상한은 4이고, 다섯 번째는 400을 반환합니다), 업로드 순서가 prompt에서 말하는 “image 1 / image 2 / image 3”의 기준입니다. 예를 들어, “image 1의 피사체를 image 2의 장면에 넣고, image 2의 아트 스타일을 유지하십시오”처럼 명시적으로 적으십시오.2 / 3 / 4개의 참조 이미지를 기준으로 측정한 결과: 추가 이미지마다 출력에 대응하는 피사체가 하나씩 더해지며, 각 이미지의 고유한 특징이 유지됩니다 — 합성이 실제로 작동합니다.코드 예시
Python (OpenAI SDK, 단일 이미지)
from openai import OpenAI
import urllib.request
client = OpenAI(
api_key="sk-your-api-key",
base_url="https://api.apiyi.com/v1",
timeout=360.0
)
# The SDK's images.edit already performs a multipart upload — pass the file object directly
resp = client.images.edit(
model="grok-imagine-image",
image=open("fox.jpg", "rb"),
prompt="Change the scarf color to bright RED. Keep everything else exactly the same.",
n=1
)
urllib.request.urlretrieve(resp.data[0].url, "edited.jpg")
Python (원시 requests, 단일 이미지)
import requests
import urllib.request
API_KEY = "sk-your-api-key"
# Key point: use files= so requests sets multipart/form-data and the boundary for you.
# Never use json= — that sends application/json and the gateway rejects it with 400.
with open("fox.jpg", "rb") as fp:
response = requests.post(
"https://api.apiyi.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"}, # do NOT set Content-Type manually
data={
"model": "grok-imagine-image",
"prompt": "Change the scarf to red, keep everything else exactly the same",
"n": 1,
"response_format": "url"
},
files={"image": ("fox.jpg", fp, "image/jpeg")},
timeout=360
).json()
urllib.request.urlretrieve(response["data"][0]["url"], "edited.jpg")
Python (멀티 이미지 융합, 파일 1-4개)
import requests
API_KEY = "sk-your-api-key"
# Repeat the image[] field for multiple references — order is "image 1 / image 2"
files = [
("image[]", ("character.jpg", open("character.jpg", "rb"), "image/jpeg")),
("image[]", ("scene.jpg", open("scene.jpg", "rb"), "image/jpeg")),
]
response = requests.post(
"https://api.apiyi.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
data={
"model": "grok-imagine-image",
"prompt": "Put the character from image 1 into the scene from image 2, "
"keeping image 2's art style and palette",
"response_format": "url"
},
files=files,
timeout=360
).json()
print(response["data"][0]["url"])
cURL
# 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=grok-imagine-image" \
-F "prompt=Change the scarf to red, keep everything else exactly the same" \
-F "n=1" \
-F "response_format=url" \
-F "[email protected]"
# Multi-image fusion: repeat image[], order is "image 1 / image 2"
curl -X POST "https://api.apiyi.com/v1/images/edits" \
-H "Authorization: Bearer sk-your-api-key" \
-F "model=grok-imagine-image-quality" \
-F "prompt=Put the character from image 1 into the scene from image 2, keep image 2's style" \
-F "image[][email protected]" \
-F "image[][email protected]"
Node.js (네이티브 fetch + FormData)
import fs from 'node:fs';
const form = new FormData();
form.append('model', 'grok-imagine-image');
form.append('prompt', 'Change the scarf to red, keep everything else exactly the same');
form.append('n', '1');
form.append('response_format', 'url');
// Single image uses `image`; for fusion append `image[]` repeatedly (max 3)
form.append('image', new Blob([fs.readFileSync('./fox.jpg')]), 'fox.jpg');
const resp = await fetch('https://api.apiyi.com/v1/images/edits', {
method: 'POST',
// Do not set Content-Type manually — let FormData supply the boundary
headers: { 'Authorization': 'Bearer sk-your-api-key' },
body: form,
signal: AbortSignal.timeout(360000)
});
const data = await resp.json();
const img = await fetch(data.data[0].url);
fs.writeFileSync('edited.jpg', Buffer.from(await img.arrayBuffer()));
브라우저 JavaScript
// ⚠️ Demo only: a front-end key is exposed — use a backend proxy in production
const fileInput = document.querySelector('#file'); // an <input type="file"> element
const form = new FormData();
form.append('model', 'grok-imagine-image');
form.append('prompt', 'Replace the background with a snowy pine forest at night, keep the subject');
form.append('response_format', 'url');
form.append('image', fileInput.files[0]);
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();
document.querySelector('#preview').src = data.data[0].url;
파라미터 레퍼런스
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
model | string | ✅ | — | grok-imagine-image ($0.02/image) 또는 grok-imagine-image-quality ($0.045/image) |
prompt | string | ✅ | — | 편집 지시입니다. 무엇을 변경할지와 나머지는 모두 그대로 유지한다고 적습니다 |
image | file | ✅ | — | 참조 이미지 파일입니다. 융합의 경우 image[]를 반복 사용하며, 1-4개 파일(다섯 번째는 400을 반환합니다). 첫 번째 파일이 출력 차원을 설정합니다 |
n | integer | ❌ | 1 | 출력 이미지, 1-10, 이미지당 과금되며 참조 개수와 무관합니다 |
response_format | string | ❌ | url | url는 직접 링크를 반환합니다; b64_json는 원시 base64를 반환합니다(없음 data: 접두사) |
resolution | string | ❌ | — | 여기서는 영향이 없습니다 — 출력은 입력 이미지를 따릅니다 |
aspect_ratio | string | ❌ | — | 여기서는 영향이 없습니다 — 출력은 입력 이미지를 따릅니다 |
편집 동작 및 prompt 스타일
편집 엔드포인트는 입력 이미지의 아트 스타일, 구도, 팔레트 및 주체 정체성을 유지하고, prompt가 지정한 내용만 변경합니다. 안정적인 결과를 얻으려면:| prompt 스타일 | 결과 |
|---|---|
✅ Change the scarf to red, keep everything else exactly the same | 스카프만 변경되며, 스타일, 구도 및 배경은 유지됩니다 |
✅ Add round black sunglasses to the cat, keep everything else unchanged | 선글라스만 추가되며, 윤곽선 스타일과 배경색은 그대로 유지됩니다 |
✅ Put the character from image 1 into the scene from image 2, keep image 2's style | 두 입력의 특성을 모두 유지하는 융합입니다 |
⚠️ Make it look better | 너무 모호함 — 변경 범위가 예측 불가능해집니다 |
image[] 업로드 순서에 맞춰 “image 1 / image 2”를 지칭하십시오.또한 가장 중요한 주체를 먼저 배치하십시오: 첫 번째 이미지는 출력 크기만 설정하는 것이 아니라, 테스트에서는 순서를 반대로 하면 보조 주체의 정체성이 다른 대상과 섞이는 문제가 발생했습니다.응답 형식
{
"created": 0,
"data": [
{
"url": "https://apac.ossforai.com/2026/08/12/09b026d5-3492-4678-907c-e25972e6c914.jpg"
}
],
"usage": {
"prompt_tokens": 1000,
"total_tokens": 1000
}
}
- 각
data[]항목에는response_format에 따라url또는b64_json중 하나만 포함됩니다 — 둘 다는 아닙니다. revised_prompt은 반환되지 않습니다 — 존재한다고 가정하지 마십시오.b64_json은data:image/...;base64,접두사가 없는 원시 base64입니다 — 바로 디코드하십시오.created는 항상0이며 타임스탬프로 사용할 수 없습니다.- 출력 차원은 입력 이미지에 의해 결정되므로 요청 파라미터로 너비/높이를 예측하지 마십시오.
usage은 정산에 사용할 수 없습니다: prompt_tokens는 항상 1000 x n인 플레이스홀더입니다. 편집 비용은 이미지당 정액 요율로 텍스트-투-이미지와 동일하며, 실제 과금은 APIYI 콘솔 과금 기록을 사용하십시오.인증
API Key created in the APIYI Console
본문
Model ID
grok-imagine-image, grok-imagine-image-quality Editing instruction. State what to change and explicitly ask for everything else to stay put,
e.g. Change the scarf color to bright RED. Keep everything else exactly the same.
"Change the scarf color to bright RED. Keep everything else exactly the same."
Reference image file. For multi-image fusion repeat the image[] field (1-4 files);
upload order is what "image 1 / image 2 / image 3" refers to in the prompt, and
the first file also determines output dimensions. Each added image contributes
a subject in testing. Accepted formats: png / jpg / webp.
Number of output images, 1-10. Independent of the number of reference images
1 <= x <= 101
Response format. url returns a direct link; b64_json returns raw base64 (no data: prefix)
url, b64_json "url"
응답
Image generated successfully
Creation timestamp. Always 0 for this model — do not use it for timing
0
Array of image results, length equals the requested n
Show child attributes
Show child attributes
Placeholder values — do not use for billing reconciliation. prompt_tokens is always 1000 x n
Show child attributes
Show child attributes
이 페이지가 도움이 되었나요?