Die Nano Banana Pro API aufrufen: der komplette Durchgang
Das ist die vollständige Integration, von Anfang bis Ende, für Nano Banana Pro auf der E2X-API. Key holen, Job einreichen, Response lesen, richtig warten, die Arten des Scheiterns behandeln und die Bytes an einen Ort legen, an dem sie morgen noch liegen.
Der letzte Schritt ist der, der die Leute erwischt. Springen Sie dorthin, wenn Sie schon Bilder generieren und nur wissen wollen, warum Ihre verschwunden sind.

Ob Pro die richtige Stufe für Ihre Arbeit ist, ist eine andere Frage, und wir haben sie separat beantwortet, im Text zu Preis und Geschwindigkeit. Kurzfassung: $0.075 pro Request, rund 30 Sekunden, lohnend, wenn Ihre Bilder lesbaren Text tragen oder Referenzen kombinieren, die verschiedene Rollen spielen. Diese Seite setzt voraus, dass Sie sich entschieden haben.
Was Sie vor dem ersten Request brauchen
Vier Dinge, und drei davon sind je eine Zeile.
- Einen API-Key. Legen Sie einen in Ihrem E2X-Konto an. Alles unten schickt ihn als
Authorization: Bearer $E2X_API_KEY. Halten Sie ihn serverseitig. Ein Key in Browser-JavaScript ist ein Key, den jetzt jemand anders ausgibt. - Die Basis-URL, nämlich
https://api.e2x.ai/v1für jedes Modell in dem Katalog. - Den richtigen Slug. Generierung ist
google/nano-banana-pro/text-to-image. Editieren istgoogle/nano-banana-pro/edit-image. Diese Strings gehen wortgetreu in den Request Body, und es gibt darauf kein Fuzzy Matching. - Einen Prompt, der es wert ist. Pro belohnt Genauigkeit stärker als die Flash-Stufen, weil es mehr Raum hat, darauf zu reagieren. Wir haben einen eigenen Prompting-Guide, falls Sie tiefer wollen als „eine Katze, aber cineastisch“.
Der Vertrag ist asynchron. Sie reichen einen Job ein, bekommen eine ID, und das Bild kommt später. Es gibt keinen synchronen Endpoint, der blockiert, bis die Pixel fertig sind — und da Pro rund 30 Sekunden braucht, würden Sie einen auch nicht wollen.
Ihr erster text-to-image-Request
curl -X POST https://api.e2x.ai/v1/jobs/submit \
-H "Authorization: Bearer $E2X_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/nano-banana-pro/text-to-image",
"input": {
"prompt": "Eine handgeschriebene Kreidetafel-Karte hinter einer Marmor-Kaffeetheke, warmes Nachmittagslicht von einem Fenster links, geringe Schärfentiefe",
"aspect_ratio": "16:9",
"resolution": "2k"
}
}'
Dasselbe in Python:
import os
import requests
BASE = "https://api.e2x.ai/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['E2X_API_KEY']}"}
def submit(prompt, aspect_ratio="16:9", resolution="2k"):
r = requests.post(
f"{BASE}/jobs/submit",
headers=HEADERS,
json={
"model": "google/nano-banana-pro/text-to-image",
"input": {
"prompt": prompt,
"aspect_ratio": aspect_ratio,
"resolution": resolution,
},
},
timeout=30,
)
r.raise_for_status()
return r.json()["data"]["jobId"]
Beide Beispiele pinnen aspect_ratio und resolution mit Absicht, und beide Defaults sollte man verstanden haben, bevor man sie weglässt.
aspect_ratio steht per Default auf 9:16. Nicht auf 1:1. Lassen Sie es weg, ist jedes Bild, das Sie generieren, für immer hochkant, und Sie merken es erst, wenn ein breiter Platz in Ihrem Layout falsch aussieht. Über dieses Feld stolpern mehr Integrationen als über jedes andere auf unserer API. Pinnen Sie es.
Die Werte für resolution sind kleingeschrieben. 1k, 2k, 4k. Großgeschriebenes 2K ist nicht derselbe String, und die API sagt Ihnen das.
Behandeln Sie 1k auf diesem Slug als toten Wert. Die ersten beiden Einstellungen liegen auf einem einzigen Pauschalpreis — $0.075 für beide, geprüft am 26. August 2026 —, die kleinere gibt also einfach weniger Pixel für dieselbe Rechnungszeile zurück. Nur 4k bewegt die Zahl: $0.15, Decke 4096×4096.

Was zurückkommt
Der Submit-Call kehrt sofort mit einem Job-Umschlag zurück. Das Feld, das Sie brauchen, ist data.jobId:
{
"success": true,
"data": {
"jobId": "job_8Kd2mQvXpL",
"status": "pending"
}
}
Der Status wandert pending → processing → completed oder landet auf einem der beiden terminalen Fehlschläge, failed und cancelled. Ein fertiger Job trägt sein Ergebnis unter data.outputs[0].url, ein gescheiterter einen Grund unter data.error.message.
Ein Detail, das Sie verinnerlichen sollten, bevor Sie Abrechnungscode schreiben: Jeder Geldbetrag, den die API zurückgibt, ist in Mikro-Cent. Eine Million entspricht einem Dollar. Ein Nano-Banana-Pro-Request kommt also als 75000 zurück, nicht als 0.075. Teilen Sie in der Darstellungsschicht durch 1.000.000 und nirgends sonst, und speichern Sie den geteilten Wert nie.
Pollen, ohne zu hämmern
Die grobe Variante funktioniert:
curl https://api.e2x.ai/v1/jobs/job_8Kd2mQvXpL \
-H "Authorization: Bearer $E2X_API_KEY"
Packen Sie das in eine Schleife mit einem festen Sleep von zwei Sekunden, und Sie haben eine funktionierende Integration. Speziell für Nano Banana Pro ist ein festes Intervall wirklich akzeptabel — ein Request läuft rund 30 Sekunden, Sie machen also ungefähr fünfzehn Statusabfragen und hören auf. Das ist nicht genug Traffic, um irgendwen zu stören.
Ein Backoff ist trotzdem besser, aus einem Grund, der mit Höflichkeit nichts zu tun hat. Feste Intervalle verbergen Varianz. Braucht ein Job 90 statt 30 Sekunden, ruft eine feste Schleife weiter im selben Takt, und Ihre Logs sehen aus wie bei einem gesunden Lauf. Ein wachsender Backoff macht einen langsamen Job sichtbar langsam.
import time
TERMINAL = {"completed", "failed", "cancelled"}
def wait_for(job_id, timeout=300):
delay = 2.0
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
r = requests.get(f"{BASE}/jobs/{job_id}", headers=HEADERS, timeout=30)
r.raise_for_status()
data = r.json()["data"]
if data["status"] in TERMINAL:
return data
time.sleep(delay)
delay = min(delay * 1.4, 10.0)
raise TimeoutError(f"{job_id} still running after {timeout}s")
Zwei Dinge tut diese Schleife, die eine naive meist nicht tut. Sie hat eine harte Frist, ein festhängender Job wirft also einen Fehler, statt sich zu drehen, bis der Prozess getötet wird. Und sie behandelt alle drei terminalen Zustände auf der Transportebene gleich, gibt die Payload zurück und lässt den Aufrufer entscheiden, was ein Fehlschlag bedeutet. Retry-Logik gehört über diese Funktion, nicht hinein.

Webhooks, und warum Sie darauf umsteigen sollten
Übergeben Sie webhookUrl im Submit Body, und wir rufen Sie an, sobald der Job einen terminalen Zustand erreicht. Überhaupt keine Polling-Schleife.
curl -X POST https://api.e2x.ai/v1/jobs/submit \
-H "Authorization: Bearer $E2X_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/nano-banana-pro/text-to-image",
"input": {
"prompt": "Ein Architekturmodell einer Fußgängerbrücke auf einem Zeichentisch, Nordlicht",
"aspect_ratio": "3:2",
"resolution": "2k"
},
"webhookUrl": "https://your-app.example.com/hooks/e2x"
}'
Polling ist der richtige erste Schritt, weil Sie es in zehn Sekunden aus einem Terminal testen können. Es ist der falsche Dauerzustand, und der Grund ist Arithmetik. Bei einem Bild kostet Polling Sie eine Schleife. Bei zweihundert Bildern in einem Batch kostet Polling Sie zweihundert gleichzeitige Schleifen, jede mit einer offenen Verbindung für eine halbe Minute, in einem Prozess, der sich jetzt nicht neu starten lässt, ohne die Übersicht über jeden laufenden Job zu verlieren.
Webhooks machen die Arbeit neustartbar. Die Job-ID geht beim Einreichen in Ihre Datenbank, der Handler aktualisiert die Zeile, wenn wir anrufen, und ein Deployment dazwischen ändert nichts. Wenn Sie eine Generierungs-Pipeline bauen und kein Skript, ist das die Version zum Bauen, und sie passt zu den Mustern in unserem Text über Bildgenerierung von Anfang bis Ende automatisieren.
Zwei operative Hinweise. Ihr Endpoint muss aus dem öffentlichen Internet erreichbar sein, eine localhost-URL feuert in der Entwicklung also still nie — nehmen Sie einen Tunnel. Und behandeln Sie den Webhook als Benachrichtigung, nicht als Quelle der Wahrheit: Holen Sie den Job im Handler über seine ID, bevor Sie darauf reagieren.
Ein Bild editieren statt generieren
Derselbe Umschlag, anderer Slug, ein zusätzliches Feld. Der Edit-Endpoint nimmt image_urls neben dem Prompt und kostet dieselben $0.075.
curl -X POST https://api.e2x.ai/v1/jobs/submit \
-H "Authorization: Bearer $E2X_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/nano-banana-pro/edit-image",
"input": {
"prompt": "Ersetze den Hintergrund durch einen weichen grauen Studioverlauf, halte die Produktbeleuchtung exakt so, wie sie ist",
"image_urls": ["https://your-cdn.example.com/source/bottle.jpg"],
"aspect_ratio": "1:1",
"resolution": "2k"
}
}'
Die URLs, die Sie übergeben, müssen öffentlich abrufbar sein. Eine signierte URL aus Ihrem eigenen Speicher funktioniert; ein Pfad auf Ihrem Laptop nicht.
Nano Banana Pro nimmt bis zu vierzehn Referenzbilder und trennt sie, anders als die übrigen Stufen, nach Rollen — bis zu 5 für Charakteridentität, bis zu 6 für Objekttreue, bis zu 3 für Stil. Diese Rollentrennung ist überhaupt der Grund, auf dieser Stufe zu sein, und die genauen Feldnamen für rollengebundene Referenzen sind pro Modell in der maschinenlesbaren Spec-Datei dokumentiert, die maßgeblich ist, falls unsere Doku und dieser Text je auseinandergehen. Speziell zum Workflow für Charakterkonsistenz gehen wir im Leitfaden zur konsistenten Generierung tiefer.
Jeder Parameter, und sein Default
| Feld | Wohin es gehört | Erlaubte Werte | Default |
|---|---|---|---|
model | Body-Wurzel | google/nano-banana-pro/text-to-image oder google/nano-banana-pro/edit-image | erforderlich |
input.prompt | in input | String | erforderlich |
input.aspect_ratio | in input | 9:16, 16:9, 1:1, 2:3, 3:2, 21:9, 3:4, 4:3, 4:5, 5:4 | 9:16 |
input.resolution | in input | 1k, 2k, 4k | explizit pinnen |
input.image_urls | in input, nur Edit-Slug | Array öffentlich erreichbarer URLs | beim Edit erforderlich |
webhookUrl | Body-Wurzel | ein öffentlicher HTTPS-Endpoint | keiner, stattdessen pollen |
Die zwei Zeilen, die Leute Geld kosten, sind aspect_ratio und resolution. Alles andere verhält sich so, wie Sie es raten würden.
Wenn der Job nicht fertig wird
Drei Fehlerflächen, und sie brauchen unterschiedliche Behandlung.
Der Submit-Call selbst scheitert. Das ist ein HTTP-Fehler, bevor ein Job existiert — falscher Key, kaputter Body, unbekannter Modell-Slug. Nichts wurde eingereiht und nichts berechnet. Reparieren Sie den Request; ihn unverändert zu wiederholen scheitert identisch.
Der Job erreicht failed. Der Job existierte, und das Modell hat kein Bild produziert. Lesen Sie data.error.message für den Grund, meist eine Ablehnung durch die Content-Policy oder ein kaputter Input wie eine nicht erreichbare URL in image_urls. Ein blinder Retry auf eine Policy-Ablehnung scheitert genauso; ein Retry nach einem vorübergehenden Upstream-Fehler klappt meist. Protokollieren Sie die Nachricht, nicht nur den Status.
Der Job erreicht cancelled. Terminal, und kein Bug. Behandeln Sie ihn im Code genau wie failed — die Zeile ist geschlossen, es kommt keine Ausgabe mehr.
Ihre Warteschleife läuft in ein Timeout. Kein Job-Zustand. Es heißt, der Job läuft noch und Ihre Geduld war zu Ende. Die Job-ID ist weiter gültig, notieren Sie sie also und sehen Sie später nach, statt neu einzureichen — was Ihnen dasselbe Bild zweimal berechnen würde.
def generate(prompt, **kw):
job_id = submit(prompt, **kw)
job = wait_for(job_id)
if job["status"] != "completed":
reason = (job.get("error") or {}).get("message", "no reason given")
raise RuntimeError(f"{job_id} ended as {job['status']}: {reason}")
return job["outputs"][0]["url"]
Laden Sie den Output herunter, bevor er abläuft
Das ist der Teil, der eine Woche nach dem Launch kaputte Bilder ausliefert, deshalb bekommt er einen eigenen Abschnitt.
Die URL unter data.outputs[0].url ist temporär. Sie ist eine Auslieferungs-URL, kein Hosting. Wenn Sie diesen String in eine Datenbankspalte namens image_url schreiben und ihn auf einer Produktseite rendern, funktioniert die Seite in Staging, funktioniert im Review, funktioniert am Launch-Tag — und verwandelt sich dann still in kaputte Bildsymbole, sobald das Objekt zu alt wird.
Die Lösung ist ein Schritt, und sie ist nicht optional. Bytes holen, in den eigenen Speicher legen, Ihre URL speichern.
import pathlib
def download(url, dest):
with requests.get(url, stream=True, timeout=120) as r:
r.raise_for_status()
pathlib.Path(dest).parent.mkdir(parents=True, exist_ok=True)
with open(dest, "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 16):
f.write(chunk)
return dest
Oder aus der Shell:
curl -sL "$OUTPUT_URL" -o ./out/menu-board.jpg
Erledigen Sie den Download in derselben Arbeitseinheit, die den Abschluss behandelt hat. Nicht in einem Cron eine Stunde später, nicht faul beim ersten Seitenaufruf. Das Fenster ist großzügig genug, dass Sie im Test mit einer Verzögerung durchkommen, und schmal genug, dass Sie unter Last nicht durchkommen.

Das Ganze, als ein Skript
Alles von oben, zusammengesetzt. Setzen Sie E2X_API_KEY und führen Sie es aus.
#!/usr/bin/env python3
"""Ein Bild mit Nano Banana Pro erzeugen und lokal speichern."""
import os
import pathlib
import time
import requests
BASE = "https://api.e2x.ai/v1"
MODEL = "google/nano-banana-pro/text-to-image"
HEADERS = {"Authorization": f"Bearer {os.environ['E2X_API_KEY']}"}
TERMINAL = {"completed", "failed", "cancelled"}
def submit(prompt, aspect_ratio="16:9", resolution="2k"):
r = requests.post(
f"{BASE}/jobs/submit",
headers=HEADERS,
json={
"model": MODEL,
"input": {
"prompt": prompt,
"aspect_ratio": aspect_ratio,
"resolution": resolution,
},
},
timeout=30,
)
r.raise_for_status()
return r.json()["data"]["jobId"]
def wait_for(job_id, timeout=300):
delay = 2.0
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
r = requests.get(f"{BASE}/jobs/{job_id}", headers=HEADERS, timeout=30)
r.raise_for_status()
data = r.json()["data"]
if data["status"] in TERMINAL:
return data
time.sleep(delay)
delay = min(delay * 1.4, 10.0)
raise TimeoutError(f"{job_id} still running after {timeout}s")
def download(url, dest):
with requests.get(url, stream=True, timeout=120) as r:
r.raise_for_status()
pathlib.Path(dest).parent.mkdir(parents=True, exist_ok=True)
with open(dest, "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 16):
f.write(chunk)
return dest
def main():
job_id = submit(
"Eine handgeschriebene Kreidetafel-Karte hinter einer Marmor-Kaffeetheke, "
"warmes Nachmittagslicht von einem Fenster links, geringe Schärfentiefe"
)
print("submitted", job_id)
job = wait_for(job_id)
if job["status"] != "completed":
reason = (job.get("error") or {}).get("message", "no reason given")
raise SystemExit(f"{job_id} ended as {job['status']}: {reason}")
path = download(job["outputs"][0]["url"], "out/menu-board.jpg")
print("saved", path)
if __name__ == "__main__":
main()
Tauschen Sie den Slug gegen google/nano-banana-pro/edit-image und ergänzen Sie image_urls, und dasselbe Skript editiert statt zu generieren. Tauschen Sie ihn gegen Nano Banana 2 oder Nano Banana 2 Lite, und es läuft weiter, denn der Umschlag ist identisch über alles in der Kategorie text-to-image und alles in image-to-image. Nur die Felder in input unterscheiden sich, und der Modellvergleich behandelt, worauf Sie es richten sollten.
Eine letzte Sache, die kein Code ist. Jedes Bild aus jedem Google-Modell trägt ein SynthID-Watermark, und kein Anbieter kann es abschalten. Klären Sie das mit dem, der den Vertrag unterschreibt, bevor Sie darauf aufbauen.
Häufig gestellte Fragen
Wie rufe ich die Nano Banana Pro API auf?
Schicken Sie einen POST an https://api.e2x.ai/v1/jobs/submit mit einem Bearer Token, dem Modell-Slug google/nano-banana-pro/text-to-image und einem input-Objekt mit Ihrem Prompt. Die Response gibt data.jobId zurück. Pollen Sie https://api.e2x.ai/v1/jobs/{id} oder übergeben Sie eine webhookUrl im Submit Body und lesen Sie dann das fertige Bild aus data.outputs[0].url.
Welche Aspect Ratio ist der Default bei Nano Banana Pro?
9:16, also hochkant. Das überrascht fast jeden, denn die meisten Bild-APIs stehen per Default auf quadratisch. Wenn Sie aspect_ratio nicht explizit setzen, kommt jedes Bild senkrecht heraus. Das Modell nimmt 9:16, 16:9, 1:1, 2:3, 3:2, 21:9, 3:4, 4:3, 4:5 und 5:4.
Warum ist meine Nano-Banana-Pro-Bild-URL kaputt?
Weil die Output-URL, die wir zurückgeben, temporäre Auslieferung ist und kein dauerhaftes Hosting. Jede Pipeline, die unsere URL in eine Datenbank speichert und später rendert, zeigt kaputte Bilder, sobald das Objekt abläuft. Laden Sie die Bytes in demselben Schritt herunter, der den Job-Abschluss behandelt, und legen Sie sie in Ihren eigenen Bucket.
Soll ich mit der E2X-API pollen oder Webhooks nehmen?
Pollen Sie, solange Sie bauen, denn das lässt sich aus einem Terminal testen. Steigen Sie für alles, was produktiv läuft, auf Webhooks um. Ein Nano-Banana-Pro-Job braucht rund 30 Sekunden, ein Batch von zweihundert heißt also zweihundert gleichzeitige Polling-Schleifen, die beim nächsten Deployment alle ihren Zustand verlieren. Mit webhookUrl geht die Job-ID beim Einreichen in Ihre Datenbank, und der Handler nimmt sie später auf.
Wie editiere ich ein bestehendes Bild mit Nano Banana Pro?
Nehmen Sie den Slug google/nano-banana-pro/edit-image und ergänzen Sie im input-Objekt neben Ihrem Prompt ein Array image_urls. Die URLs müssen öffentlich abrufbar sein, eine signierte URL aus Ihrem Speicher funktioniert also, ein lokaler Pfad nicht. Editieren kostet dieselben $0.075 wie Generieren.
Welche Auflösung sollte ich bei Nano Banana Pro anfordern?
Schicken Sie 2k. Die ersten beiden Einstellungen teilen sich auf diesem Slug einen Pauschalpreis, 1k ist damit strikt unterlegen — weniger Pixel, identische Rechnungszeile. Greifen Sie nur zu 4k, wenn Sie die Decke von 4096×4096 wirklich brauchen, denn das verdoppelt die Abbuchung auf $0.15. Alle drei Werte sind kleingeschrieben.
Warum gibt die E2X-API Preise wie 75000 zurück?
Jeder Geldbetrag in der API ist in Mikro-Cent ausgedrückt, wobei 1.000.000 einem US-Dollar entspricht. Ein 75000 auf einem Nano-Banana-Pro-Job sind $0.075. Behalten Sie den Integer in der Speicherung und teilen Sie erst an der Stelle, an der ein Mensch liest, damit sich über eine Abrechnungsperiode keine Rundung aufsummiert.