Dokumentation

Dokumentation

Bildgenerierung

Zwei Endpunkte: Text-zu-Bild und Bildbearbeitung bzw. Bild-zu-Bild. Beide geben dauerhafte Ergebnis-URLs zurück: Kunavo archiviert jedes Bild auf seinem eigenen CDN.

Kunavo stellt /v1/images/generations (Text-zu-Bild) und /v1/images/edits (Bild-zu-Bild/Bearbeitung) bereit. Beide sind standardmäßig synchron — der Aufruf wartet, bis der Upstream fertig ist, und gibt dann Ergebnis-URLs zurück — oder nutzen Sie asynchron mit "async": true oder einem webhook_url.

Text-zu-Bild

Endpunkt: POST /v1/images/generations. Verwenden Sie die Methode images.generate des OpenAI SDK oder direkt 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)

Gängige Parameter

ParameterTypHinweise
modelstringBeliebiger Bildmodell-Slug aus /v1/models.
promptstringText-Prompt. Immer erforderlich.
sizestringOpenAI-Format „1024x1024“. Wird dem Upstream-Seitenverhältnis zugeordnet.
qualitystandard|hdSofern unterstützt (gpt-image).
resolution1K|2K|4KAuflösungsstufe für Modelle mit Stufen — siehe unten Resolution tiers. Abrechnung nach Stufe.
nintAnzahl der Bilder. Die meisten Modelle geben unabhängig davon 1 zurück.
inputobjectAusweichmöglichkeit — siehe unten Raw input.
Ergebnis-URLs sind dauerhafte files.kunavo.com-Links: Kunavo archiviert jedes Bild auf seinem eigenen CDN, sodass sie im Gegensatz zu rohen Upstream-URLs nie ablaufen. Kann ein Bild nicht archiviert werden, ist seine URL die temporäre URL des Upstream-Anbieters auf einem anderen Host: Laden Sie dieses Bild herunter und hosten Sie es selbst.

Auflösungsstufen

Bei mehreren Bildmodellen richtet sich der Preis nach der Ausgabeauflösung und steigt stufenweise. Übergeben Sie resolution, um eine Stufe auszuwählen; lassen Sie den Parameter weg, wird die Standardstufe verwendet. Abgerechnet wird die tatsächlich erzeugte Stufe.

Modell (sowie dessen -edit-Variante)Stufen — Preis pro StufeStandard
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 (Pauschalpreis)1K

Auch für die veo-3-Familie gelten Auflösungsstufen — die Preise pro Stufe finden Sie auf der Seite /models des jeweiligen Modells.

GPT-Image-2 kann bei einem Seitenverhältnis von 1:1 (quadratisch) keine 4K-Auflösung erzeugen. Wenn Sie resolution = 4K mit quadratischer Größe anfordern, wird der Aufruf automatisch auf 2K heruntergestuft und zum 2K-Preis abgerechnet.

Bildbearbeitung / Bild-zu-Bild

Endpunkt: POST /v1/images/edits. Übergeben Sie das Quellbild als URL (HTTPS oder data:-Base64) über image für die Bearbeitung eines einzelnen Bildes oder über image_urls für mehrere Referenzbilder.

# 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"])

Mehrere Referenzbilder

Einige Modelle (Nano Banana Edit, GPT-Image-2 Edit) akzeptieren mehrere Referenzbilder.

# 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",
        ],
    },
)

Unterstützte Bearbeitungsmodelle

  • nano-banana-edit — Google Nano Banana-Bearbeitung
  • gpt-image-2-edit — OpenAI-Bild-zu-Bild

Ein Quellbild bereitstellen

Bildbearbeitung und Bild-zu-Video benötigen beide ein Quellbild, das das Modell abrufen kann. Sie haben drei Möglichkeiten — wählen Sie die passende für Ihre Anwendung:

  • Sie haben bereits eine öffentliche URL — übergeben Sie sie direkt als image (oder als image_url für Video). Fertig.
  • Sie haben eine lokale Datei — laden Sie sie einmal über POST /v1/files hoch und verwenden Sie dann die zurückgegebene dauerhafte URL erneut.
  • Sie haben Rohdaten im Code — fügen Sie sie als data:-Base64-URI direkt ein; Kunavo stellt sie transparent bereit.

Option A — über POST /v1/files hochladen

Senden Sie multipart/form-data mit einem file-Feld (oder als JSON-{ "file": "data:..." }). Sie erhalten eine dauerhafte files.kunavo.com-URL zurück — für Dateien bis zu 25 MB.

# 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"])

Option B — Base64 direkt einbetten

Überspringen Sie den separaten Upload vollständig: Fügen Sie im Feld image / image_url eine data:-URI ein. Kunavo dekodiert sie, hostet sie auf seinem CDN und übergibt dem Modell die gehostete 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}",
    },
)
Dasselbe gilt für POST /v1/video/generations — image_url akzeptiert für Bild-zu-Video-Modelle wie Veo eine HTTPS-URL oder eine data:-Base64-URI.

Antwortformat

Beide Endpunkte geben die standardmäßige Images-Antwort von OpenAI zurück:

{
  "created": 1779360636,
  "data": [
    { "url": "https://files.kunavo.com/image/.../result.png" }
  ]
}

Latenz & Zeitüberschreitungen

Die Bildgenerierung dauert je nach Modell üblicherweise 5–60 Sekunden. Im standardmäßigen synchronen Modus hält Kunavo die Verbindung offen und fragt den Upstream bis zu 540 Sekunden lang ab, bevor eine 504 zurückgegeben wird. Legen Sie das clientseitige Timeout entsprechend fest — oder verwenden Sie die asynchrone API, um innerhalb von Sekunden einen Auftrag einzureichen und nach Ihrem eigenen Zeitplan abzufragen:

  • Nano Banana / Nano Banana 2: normalerweise unter 10 Sekunden.
  • Nano Banana Pro / GPT-Image-2: 15–60 Sekunden.
  • Mehrere Referenzen und Premium-Stufe: bis zu etwa 2 Minuten.

Asynchrone API (Einreichung + Abruf / Webhook)

Beide Bildendpunkte sind standardmäßig synchron — der Aufruf hält die Verbindung offen, bis der Upstream das Bild erstellt hat, und gibt dann die standardmäßige OpenAI-Images-Antwort zurück. Für Batch-Aufträge, langsame Premium-Stufen oder serverlose Aufrufer, die keine lange Anfrage offen halten können, fügen Sie "async": true (oder eine webhook_url) zu /v1/images/generations oder /v1/images/edits hinzu.

Die Einreichung gibt sofort eine img_*-ID zurück; fragen Sie GET /v1/images/{id} so lange ab, bis status den Wert completed oder failed hat — oder registrieren Sie einen Webhook und überspringen Sie die Abfrage vollständig.

# 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"])

Aufgabenobjekt

FeldTypHinweise
idstringimg_* Aufgaben-ID — an GET /v1/images/{id} übergeben.
statusstringqueued | in_progress | completed | failed.
outputobject|nullNach Abschluss: { url, urls, archived }. archived ist false, wenn ein Bild nicht archiviert werden konnte und seine URL die temporäre URL des Upstream-Anbieters ist.
errorobject|nullBei Fehler: { code, message }.
expires_atint|nullUnix-Sekunden, 30 Tage nach dem Absenden: Mindestens bis dahin lässt sich die Aufgabe abfragen. Die Ergebnis-URLs der Aufgabe laufen nicht ab.
GET /v1/images/{id} ist auf den jeweiligen Eigentümer beschränkt: Wird eine ID abgefragt, die Ihnen nicht gehört, wird 404 zurückgegeben; die Antwort ist nicht von einer nie vergebenen ID zu unterscheiden. Empfohlener Abfrageabstand: 3 Sekunden, mit exponentiellem Backoff bis auf etwa 30 Sekunden.

Webhooks

Übergeben Sie beim Einreichen webhook_url (https), und Kunavo sendet beim Abschluss der Aufgabe ein signiertes image.completed-/image.failed-Ereignis per POST — mit derselben Hülle und Signatur wie bei Video- und Musik-Webhooks:

  • X-Kunavo-Webhook-Id — stabile Ereignis-ID, bei Wiederholungen identisch (zur Deduplizierung verwenden).
  • X-Kunavo-Webhook-Timestamp — Unix-Zeit in Sekunden, zu der die Signatur berechnet wurde.
  • X-Kunavo-Webhook-Signature — sha256= HMAC-SHA256 über {timestamp}.{rawBody}, mit Ihrem Webhook-Geheimnis als Schlüssel.
Zustellversuche werden über etwa 9 Stunden mit Backoff wiederholt. Die asynchrone Zeile kann die ganze Zeit abgefragt werden; ein verpasster Webhook lässt sich daher immer über GET wiederherstellen.

Direkte Übergabe von Rohparametern

Für modellspezifische Parameter, die Kunavo nicht zuordnet (Seed, negativer Prompt, Ausgabeformat), übergeben Sie input. Es wird unverändert an den Upstream gesendet und ersetzt die Eingabe, die unser Adapter erstellen würde.

Eine Ausnahme ist das Feld, das die Preisstufe eines Modells auswählt: resolution oder bei Ideogram rendering_speed. Bei einem Modell mit Stufen wird es stets als eine der Stufen des Modells gesendet, und diese Stufe wird Ihnen berechnet. Wenn input das Feld nicht enthält oder einen Wert angibt, der keiner der Stufen des Modells entspricht, wird die Standardstufe gesendet und berechnet. Dasselbe Feld auf der obersten Ebene der Anfrage wird nicht ausgelesen, wenn input gesetzt ist.

# 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",
    }},
)
Wenn Sie input übergeben, umgehen Sie die Validierung von Kunavo. Lehnt der Upstream Ihre Felder ab, erhalten Sie von uns einen 422-Fehler — lesen Sie die Fehlerdokumentation und die Upstream-Dokumentation des Modells.

Nächste Schritte