문서

문서

이미지 생성

두 가지 엔드포인트를 제공합니다. 텍스트에서 이미지 생성과 이미지 편집/이미지 변환입니다. 두 엔드포인트 모두 영구적인 결과 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)

일반 매개변수

매개변수유형참고
modelstring모든 이미지 모델 슬러그를 /v1/models에서 확인할 수 있습니다.
promptstring텍스트 프롬프트입니다. 항상 필수입니다.
sizestringOpenAI 형식의 "1024x1024"입니다. 업스트림 종횡비로 변환됩니다.
qualitystandard|hd지원되는 경우(gpt-image).
resolution1K|2K|4K단계별 요금이 적용되는 모델의 해상도 등급입니다. 아래 Resolution tiers를 참조하세요. 선택한 등급에 따라 요금이 청구됩니다.
nint이미지 수입니다. 대부분의 모델은 요청과 관계없이 1개를 반환합니다.
inputobject예외적인 사용자 지정 설정입니다. 아래 Raw input를 참조하세요.
결과 URL은 영구적인 files.kunavo.com 링크입니다. Kunavo가 모든 이미지를 자체 CDN에 보관하므로, 이 URL은 원본 업스트림 URL과 달리 만료되지 않습니다. 이미지를 보관하지 못한 경우에는 해당 URL이 다른 호스트에 있는 업스트림의 임시 URL이므로, 그 이미지를 다운로드해 다시 호스팅하세요.

해상도 등급

일부 이미지 모델은 출력 해상도에 따라 단계별 요금을 부과합니다. resolution를 전달해 등급을 선택하세요. 생략하면 기본 등급이 사용됩니다. 실제 생성된 등급을 기준으로 요금이 청구됩니다.

모델(+ 해당 모델의 -edit 변형)등급별 가격기본값
nano-banana-21K $0.0469 · 2K $0.0707 · 4K $0.10571K
nano-banana-pro1K / 2K $0.067 · 4K $0.122K
gpt-image-21K / 2K / 4K — $0.0633 (고정)1K

veo-3 계열에도 해상도별 등급이 적용됩니다. 등급별 가격은 각 모델의 /models 페이지에서 확인할 수 있습니다.

GPT-Image-2는 1:1(정사각형) 종횡비에서 4K를 렌더링할 수 없습니다. 정사각형 크기와 함께 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"])

작업 객체

필드유형참고
idstringimg_* 작업 ID — GET /v1/images/{id}에 전달합니다.
statusstringqueued | in_progress | completed | failed.
outputobject|null완료 시: { url, urls, archived }. 이미지를 보관하지 못해 URL이 업스트림의 임시 URL인 경우 archived는 false입니다.
errorobject|null실패 시: { code, message }.
expires_atint|nullUnix 초 단위이며 제출 후 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=
약 9시간 동안 백오프를 적용해 전송을 재시도합니다. 이 기간 내내 비동기 항목을 폴링할 수 있으므로 웹훅을 받지 못해도 GET으로 언제든 결과를 복구할 수 있습니다.

원시 입력용 예외 처리

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를 반환합니다. 오류 문서와 해당 모델의 업스트림 문서를 확인하세요.

다음 단계