문서
이미지 생성
두 가지 엔드포인트를 제공합니다. 텍스트에서 이미지 생성과 이미지 편집/이미지 변환입니다. 두 엔드포인트 모두 영구적인 결과 URL을 반환합니다. Kunavo는 모든 이미지를 자체 CDN에 보관합니다.
Kunavo는 /v1/images/generations(텍스트에서 이미지 생성) 및 /v1/images/edits(이미지 변환/편집)을 제공합니다. 둘 다 기본적으로 동기식입니다. 호출은 업스트림 작업이 끝날 때까지 대기한 후 결과 URL을 반환합니다. 또는 "async": true 또는 webhook_url를 사용해 비동기로 처리할 수 있습니다.
텍스트에서 이미지 생성
엔드포인트: POST /v1/images/generations. OpenAI SDK의 images.generate 메서드를 사용하거나 curl로 직접 호출하세요.
img = client.images.generate(
model="nano-banana-pro",
prompt="a red origami crane on a white desk, soft window light",
size="1024x1024",
)
print(img.data[0].url)일반 매개변수
| 매개변수 | 유형 | 참고 |
|---|---|---|
model | string | 모든 이미지 모델 슬러그를 /v1/ |
prompt | string | 텍스트 프롬프트입니다. 항상 필수입니다. |
size | string | OpenAI 형식의 "1024x1024"입니다. 업스트림 종횡비로 변환됩니다. |
quality | standard|hd | 지원되는 경우(gpt-image). |
resolution | 1K|2K|4K | 단계별 요금이 적용되는 모델의 해상도 등급입니다. 아래 Resolution tiers를 참조하세요. 선택한 등급에 따라 요금이 청구됩니다. |
n | int | 이미지 수입니다. 대부분의 모델은 요청과 관계없이 1개를 반환합니다. |
input | object | 예외적인 사용자 지정 설정입니다. 아래 Raw input를 참조하세요. |
files.kunavo.com 링크입니다. Kunavo가 모든 이미지를 자체 CDN에 보관하므로, 이 URL은 원본 업스트림 URL과 달리 만료되지 않습니다. 이미지를 보관하지 못한 경우에는 해당 URL이 다른 호스트에 있는 업스트림의 임시 URL이므로, 그 이미지를 다운로드해 다시 호스팅하세요.해상도 등급
일부 이미지 모델은 출력 해상도에 따라 단계별 요금을 부과합니다. resolution를 전달해 등급을 선택하세요. 생략하면 기본 등급이 사용됩니다. 실제 생성된 등급을 기준으로 요금이 청구됩니다.
| 모델(+ 해당 모델의 -edit 변형) | 등급별 가격 | 기본값 |
|---|---|---|
| nano-banana-2 | 1K $0.0469 · 2K $0.0707 · 4K $0.1057 | 1K |
| nano-banana-pro | 1K / 2K $0.067 · 4K $0.12 | 2K |
| gpt-image-2 | 1K / 2K / 4K — $0.0633 (고정) | 1K |
veo-3 계열에도 해상도별 등급이 적용됩니다. 등급별 가격은 각 모델의 /models 페이지에서 확인할 수 있습니다.
resolution = 4K를 요청하면 호출은 자동으로 2K로 낮춰 처리되며 2K 요금이 청구됩니다.이미지 편집/이미지 변환
엔드포인트: POST /v1/images/edits. 단일 이미지 편집에는 image를 통해 소스 이미지를 URL(HTTPS 또는 data: base64)로 전달하고, 여러 이미지 참조에는 image_urls를 사용하세요.
# Image edit / image-to-image: pass the source image URL
import requests
resp = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "gpt-image-2-edit",
"prompt": "recolor the crane to bright blue, keep composition",
"image": "https://your-cdn.com/source.png",
},
)
print(resp.json()["data"][0]["url"])여러 이미지 참조
일부 모델(Nano Banana Edit, GPT-Image-2 Edit)은 여러 참조 이미지를 받을 수 있습니다.
# nano-banana-edit accepts multiple reference images
resp = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "nano-banana-edit",
"prompt": "merge subject from img1 with background from img2",
"image_urls": [
"https://your-cdn.com/subject.png",
"https://your-cdn.com/background.png",
],
},
)지원되는 편집 모델
nano-banana-edit— Google Nano Banana 편집gpt-image-2-edit— OpenAI 이미지 변환
소스 이미지 제공
이미지 편집과 이미지를 동영상으로 변환하는 작업에는 모델이 가져올 수 있는 소스 이미지가 필요합니다. 앱에 맞는 방법을 선택하세요.
- 공개 URL이 이미 있는 경우 — 해당 URL을
image(또는 동영상의 경우image_url)로 그대로 전달하면 됩니다. 완료입니다. - 로컬 파일이 있는 경우 —
POST /v1/files를 통해 한 번 업로드한 다음 반환된 영구 URL을 재사용하세요. - 코드에 원시 바이트가 있는 경우 —
data:base64 URI로 인라인 전달하세요. Kunavo가 투명하게 호스팅합니다.
방법 A — POST /v1/files를 통해 업로드
multipart/form-data와 file 필드(또는 JSON { "file": "data:..." })를 전송하세요. 최대 25 MB 크기의 파일에 대해 영구 files.kunavo.com URL이 반환됩니다.
# Upload a local file → get a permanent Kunavo URL
import requests
with open("source.png", "rb") as f:
up = requests.post(
"https://api.kunavo.com/v1/files",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": f},
).json()
# up["url"] is now a permanent https://files.kunavo.com/... URL
edit = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "gpt-image-2-edit",
"prompt": "recolor the crane to bright blue",
"image": up["url"],
},
).json()
print(edit["data"][0]["url"])방법 B — base64 인라인 전달
별도 업로드를 생략하고 image 또는 image_url 필드에 data: URI를 넣으세요. Kunavo가 이를 디코딩해 CDN에서 호스팅한 후 모델에 호스팅 URL을 전달합니다.
# Or skip the upload step — pass base64 inline, we host it for you.
import base64, requests
with open("source.png", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
resp = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "gpt-image-2-edit",
"prompt": "recolor the crane to bright blue",
"image": f"data:image/png;base64,{b64}",
},
)POST /v1/video/generations에도 동일하게 적용됩니다. Veo와 같은 이미지에서 동영상을 생성하는 모델의 경우 image_url에 https URL 또는 data: base64 URI를 전달할 수 있습니다.응답 형식
두 엔드포인트 모두 OpenAI의 표준 이미지 응답을 반환합니다.
{
"created": 1779360636,
"data": [
{ "url": "https://files.kunavo.com/image/.../result.png" }
]
}지연 시간 및 시간 초과
이미지 생성에는 모델에 따라 보통 5~60초가 걸립니다. 기본 동기식 모드에서 Kunavo는 연결을 유지하고 업스트림을 최대 540초 동안 폴링한 후 504를 반환합니다. 이에 맞춰 클라이언트 측 시간 제한을 설정하거나, 비동기 API를 사용해 몇 초 만에 작업을 제출하고 원하는 일정에 따라 폴링하세요.
- Nano Banana/Nano Banana 2: 보통 10초 미만입니다.
- Nano Banana Pro/GPT-Image-2: 15~60초입니다.
- 다중 참조 및 프리미엄 등급: 최대 약 2분입니다.
비동기 API(제출 + 폴링/웹훅)
두 이미지 엔드포인트 모두 기본적으로 동기식입니다. 호출은 업스트림에서 렌더링이 끝날 때까지 연결을 유지한 다음 표준 OpenAI 이미지 응답을 반환합니다. 배치 작업, 느린 프리미엄 등급, 또는 장시간 요청을 유지할 수 없는 서버리스 호출자의 경우 "async": true(또는 webhook_url)를 /v1/images/generations 또는 /v1/images/edits에 추가하세요.
제출 즉시 img_* ID가 반환됩니다. status가 completed 또는 failed가 될 때까지 GET /v1/images/{id}을 폴링하세요. 또는 웹훅을 등록해 폴링을 완전히 생략할 수 있습니다.
# Async: add "async": true (or a webhook_url) to either image endpoint.
# The call returns instantly with an img_ id instead of holding the connection.
import requests, time
API = "https://api.kunavo.com/v1"
H = {"Authorization": f"Bearer {API_KEY}"}
submit = requests.post(
f"{API}/images/generations",
headers=H,
json={"model": "gpt-image-2", "prompt": "a red panda", "async": True},
).json()
task_id = submit["id"] # "img_abc..."
status = submit["status"] # "queued"
# Poll GET /v1/images/{id} until terminal — or skip polling and use a webhook.
while status not in ("completed", "failed"):
time.sleep(3)
r = requests.get(f"{API}/images/{task_id}", headers=H).json()
status = r["status"]
if status == "completed":
print(r["output"]["url"])
else:
print("failed:", r["error"])작업 객체
| 필드 | 유형 | 참고 |
|---|---|---|
id | string | img_* 작업 ID — GET /v1/ |
status | string | queued | in_progress | completed | failed. |
output | object|null | 완료 시: { url, urls, archived }. 이미지를 보관하지 못해 URL이 업스트림의 임시 URL인 경우 archived는 false입니다. |
error | object|null | 실패 시: { code, message }. |
expires_at | int|null | Unix 초 단위이며 제출 후 30일 시점입니다. 적어도 그때까지는 작업을 폴링할 수 있습니다. 결과 URL은 만료되지 않습니다. |
GET /v1/images/{id}는 소유자별로 범위가 지정됩니다. 본인 소유가 아닌 ID를 조회하면 404가 반환되며, 발급된 적 없는 ID와 구분되지 않습니다. 권장 폴링 간격은 3초이며, 지수 백오프를 적용해 최대 약 30초까지 늘리세요.웹훅
제출 요청에 webhook_url(https)를 전달하면 작업이 종료될 때 Kunavo가 서명된 image.completed / image.failed 이벤트를 POST합니다. 동영상 및 음악 웹훅과 동일한 봉투 형식과 서명을 사용합니다.
X-Kunavo-Webhook-Id— 재시도 간에 동일하게 유지되는 안정적인 이벤트 ID입니다(중복 제거에 사용).X-Kunavo-Webhook-Timestamp— 서명을 생성한 Unix 초 단위 시각입니다.X-Kunavo-Webhook-Signature—{timestamp}.{rawBody}를 대상으로 계산한 HMAC-SHA256이며, 키로 웹훅 비밀 키를 사용합니다.sha256=
원시 입력용 예외 처리
Kunavo가 변환하지 않는 모델별 설정(seed, 네거티브 프롬프트, 출력 형식)을 지정하려면 input을 전달하세요. 이 값은 Kunavo 어댑터가 구성했을 입력 대신 작성한 그대로 업스트림으로 전송됩니다.
모델의 가격 등급을 선택하는 필드는 예외입니다. resolution이며 Ideogram에서는 rendering_speed입니다. 등급이 있는 모델에서는 이 필드가 항상 해당 모델의 등급 중 하나로 전송되며, 해당 등급의 요금이 청구됩니다. input에서 이 필드를 생략하거나 모델의 등급에 해당하지 않는 값을 지정하면 기본 등급이 전송되고 그 등급의 요금이 청구됩니다. input이 설정된 경우 요청 최상위 수준의 동일한 필드는 읽지 않습니다.
# Raw upstream 'input': sent as written, in place of what our adapter builds.
# "resolution" sets the billed tier: 2K here, the default tier when left out.
resp = client.images.generate(
model="nano-banana-2",
prompt="", # ignored when input is set
extra_body={"input": {
"prompt": "a futuristic cyberpunk skyline at dusk",
"aspect_ratio": "16:9",
"resolution": "2K",
"output_format": "png",
}},
)input를 전달하면 Kunavo의 유효성 검사를 건너뜁니다. 업스트림에서 필드를 거부하면 Kunavo가 422를 반환합니다. 오류 문서와 해당 모델의 업스트림 문서를 확인하세요.