> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bettertoken.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Nano Banana API: Bilder, Referenzen und weitere Bearbeitung

> Nutze Nano Banana Pro, 2 und 2.1 mit BetterToken: Authentifizierung, Auflösungen, Python, Referenzbilder, Bildspeicherung, weitere Bearbeitung und API-Grenzen.

Nutze denselben nativen Gemini-Endpunkt für Textbilder, Referenzbearbeitung und weitere Änderungen. Die Beispiele verwenden `nano-banana-2.1`; ersetze das Modell in URL oder SDK für die anderen beiden.

* [Gemini Text-zu-Bild-API](/de/api-reference/gemini-images-generations)
* [Gemini API zur Bildbearbeitung](/de/api-reference/gemini-images-edits)

<Warning>
  Die BetterToken API unterstützt keine Bildgenerierung mit Suche, einschließlich Google Web Search und Image Search grounding. Füge keine Suchwerkzeuge hinzu.
</Warning>

## Verbindung

| Feld | Wert |
| - | - |
| Base URL | `https://bettertoken.ai` |
| Anfrage | `POST /v1beta/models/{model}:generateContent` |
| Authentifizierung | `x-goog-api-key: YOUR_API_KEY` oder `Authorization: Bearer YOUR_API_KEY`. Wähle eine Variante. |
| Anfragetext | `application/json` |
| Model IDs | `nano-banana-pro`, `nano-banana-2`, `nano-banana-2.1` |

<a href={"https://bettertoken.ai/register"}>BetterToken API Key erstellen</a> · <a href={"https://bettertoken.ai/pricing"}>Modellkatalog</a> · [Nano Banana Modellübersicht](/de/model-updates/nano-banana)

<Warning>
  Diese drei Modelle unterstützen weder `POST /v1/images/generations` noch `POST /v1/images/edits`: Antwort `400 unsupported_endpoint`. Übernimm keine GPT-Image-Beispiele mit multipart, `image[]` oder `data[].b64_json`.
</Warning>

## Erstes Bild erzeugen

Setze `BETTERTOKEN_API_KEY` im Terminal und führe die Anfrage aus. Sie wartet auf die Generierung und speichert die vollständige JSON-Antwort in `response.json`.

<Tabs>
  <Tab title="macOS / Linux">
    ```bash theme={null}
    export BETTERTOKEN_API_KEY="YOUR_API_KEY"

    curl --fail-with-body --max-time 650 \
      "https://bettertoken.ai/v1beta/models/nano-banana-2.1:generateContent" \
      -H "x-goog-api-key: $BETTERTOKEN_API_KEY" \
      -H "Content-Type: application/json" \
      -H "X-BetterToken-Max-Images: 1" \
      -d '{
        "contents": [{
          "role": "user",
          "parts": [{"text": "Ein Studiofoto einer blauen Keramiktasse auf einem weißen Tisch."}]
        }],
        "generationConfig": {
          "responseModalities": ["IMAGE"],
          "candidateCount": 1,
          "imageConfig": {"imageSize": "1K", "aspectRatio": "1:1"}
        }
      }' -o response.json
    ```
  </Tab>

  <Tab title="Windows PowerShell">
    ```powershell theme={null}
    $env:BETTERTOKEN_API_KEY = "YOUR_API_KEY"
    $headers = @{
        "x-goog-api-key" = $env:BETTERTOKEN_API_KEY
        "X-BetterToken-Max-Images" = "1"
    }
    $body = @{
        contents = @(@{
            role = "user"
            parts = @(@{ text = "Ein Studiofoto einer blauen Keramiktasse auf einem weißen Tisch." })
        })
        generationConfig = @{
            responseModalities = @("IMAGE")
            candidateCount = 1
            imageConfig = @{ imageSize = "1K"; aspectRatio = "1:1" }
        }
    } | ConvertTo-Json -Depth 10
    Invoke-WebRequest `
        -Uri "https://bettertoken.ai/v1beta/models/nano-banana-2.1:generateContent" `
        -Method Post `
        -Headers $headers `
        -ContentType "application/json" `
        -Body ([System.Text.Encoding]::UTF8.GetBytes($body)) `
        -TimeoutSec 650 `
        -OutFile "response.json"
    ```
  </Tab>
</Tabs>

Ändere `imageSize` für höhere Auflösung auf `2K` oder `4K`. Beginne mit `1K`, `1:1` und einem Bild. Keine automatischen Wiederholungen per `--retry`.

## Häufige Parameter

Beschreibe für Produktfotos Motiv, Material, Licht und Hintergrund. Gib für Poster den genauen Text und das Layout an. Sage bei Änderungen, was geändert und was beibehalten werden soll.

Natives HTTP verwendet diese Felder; das Python SDK nutzt snake\_case. Bildoptionen gehören in `generationConfig.imageConfig`.

| Feld | Wert |
| - | - |
| `contents[].parts[].text` | Beschreibe Motiv, Hintergrund, Stil und Änderungen. |
| `contents[].parts[].inlineData` | `mimeType` und Base64 der ursprünglichen Referenzdatei, keine Bild-URL. |
| `generationConfig.responseModalities` | Ausdrücklich `["IMAGE"]` setzen. |
| `generationConfig.imageConfig.imageSize` | Großgeschrieben `1K`, `2K` oder `4K`; Standard `1K`. |
| `generationConfig.imageConfig.aspectRatio` | Wähle ein Seitenverhältnis für dein Modell aus der Tabelle unten; die Beispiele nutzen `1:1`. |
| `generationConfig.candidateCount` | Weglassen oder Ganzzahl `1`; kein `n` auf nativer Wurzelebene. |
| `X-BetterToken-Max-Images` | Optionaler Header: Ganzzahl `1` bis `4`, Standard `1`. Maximale Anzahl für Ausgabe und Abrechnung. |

<span id="aspect-ratios" />

### Von Google unterstützte Seitenverhältnisse

Nano Banana 2 und 2.1 unterstützen 14 Seitenverhältnisse, Pro unterstützt 10. Beginne beim ersten Aufruf mit `1:1`.

| Modell | Auflösung | Seitenverhältnisse |
| - | - | - |
| `nano-banana-pro` | `1K`, `2K`, `4K` | `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, `21:9` |
| `nano-banana-2` | `1K`, `2K`, `4K` | `1:1`, `1:4`, `1:8`, `2:3`, `3:2`, `3:4`, `4:1`, `4:3`, `4:5`, `5:4`, `8:1`, `9:16`, `16:9`, `21:9` |
| `nano-banana-2.1` | `1K`, `2K`, `4K` | `1:1`, `1:4`, `1:8`, `2:3`, `3:2`, `3:4`, `4:1`, `4:3`, `4:5`, `5:4`, `8:1`, `9:16`, `16:9`, `21:9` |

[Google-Referenz für Seitenverhältnisse und Bildgrößen](https://ai.google.dev/gemini-api/docs/image-generation#aspect-ratios-and-image-size)

Das Maximum garantiert keine Anzahl. Trotz Mehrfachwunsch kann nur ein Bild zurückkommen. Sende für eine feste Anzahl separate Anfragen.

## Antwort lesen und Bilder speichern

Bilder stehen in `candidates[].content.parts[].inlineData`. Die Struktur unten verwendet den Platzhalter `BASE64_IMAGE_DATA`. Verarbeite alle endgültigen Bildteile und überspringe `thought: true`.

```json theme={null}
{
  "candidates": [{
    "content": {
      "role": "model",
      "parts": [{
        "inlineData": {
          "mimeType": "image/jpeg",
          "data": "BASE64_IMAGE_DATA"
        }
      }]
    },
    "finishReason": "STOP"
  }]
}
```

Dieses Python speichert das curl-Ergebnis. Wähle die Endung anhand von `mimeType`; es kann JPEG statt `.png` sein.

```python theme={null}
import base64
import json
from pathlib import Path

suffixes = {"image/png": ".png", "image/jpeg": ".jpg"}
result = json.loads(Path("response.json").read_text())
saved = 0
for candidate in result.get("candidates", []):
    for part in candidate.get("content", {}).get("parts", []):
        if part.get("thought"):
            continue
        blob = part.get("inlineData")
        if not blob:
            continue
        suffix = suffixes.get(blob["mimeType"])
        if suffix is None:
            raise ValueError("Unexpected image MIME type: " + blob["mimeType"])
        saved += 1
        Path(f"generated-{saved}{suffix}").write_bytes(
            base64.b64decode(blob["data"], validate=True)
        )
if saved == 0:
    raise RuntimeError("No final image returned; inspect response.json.")
```

## Vollständiges Python-SDK-Beispiel

Nutze Python ab 3.10 und `google-genai==2.30.1`. Installiere im virtuellen Projektumfeld; ältere SDK-Versionen können `image_size` weglassen.

```bash theme={null}
python -m pip install "google-genai==2.30.1"
```

Die SDK Base URL ist die Domainwurzel ohne `/v1` oder `/v1beta`. `timeout` gilt in Millisekunden; `attempts=1` deaktiviert automatische Wiederholungen. `save_images` speichert alle endgültigen Bilder.

```python theme={null}
import os
from pathlib import Path
from google import genai
from google.genai import types

MODEL = "nano-banana-2.1"
client = genai.Client(
    vertexai=False,
    api_key=os.environ["BETTERTOKEN_API_KEY"],
    http_options=types.HttpOptions(
        base_url="https://bettertoken.ai",
        api_version="v1beta",
        timeout=650_000,
        retry_options=types.HttpRetryOptions(attempts=1),
        headers={"X-BetterToken-Max-Images": "1"},
    ),
)
config = types.GenerateContentConfig(
    response_modalities=["IMAGE"],
    candidate_count=1,
    image_config=types.ImageConfig(image_size="1K", aspect_ratio="1:1"),
)

def save_images(response, prefix):
    if len(response.candidates or []) != 1 or not response.candidates[0].content:
        raise RuntimeError("No single image candidate returned.")
    saved = 0
    suffixes = {"image/png": ".png", "image/jpeg": ".jpg"}
    for part in response.candidates[0].content.parts or []:
        if part.thought or not part.inline_data:
            continue
        blob = part.inline_data
        suffix = suffixes.get(blob.mime_type)
        if suffix is None:
            raise ValueError("Unexpected image MIME type: " + str(blob.mime_type))
        saved += 1
        Path(f"{prefix}-{saved}{suffix}").write_bytes(blob.data)
    if saved == 0:
        raise RuntimeError("No final image returned; inspect the response.")

first_turn = types.Content(
    role="user",
    parts=[types.Part(text="Ein Studiofoto einer blauen Keramiktasse auf einem weißen Tisch.")],
)
response = client.models.generate_content(
    model=MODEL, contents=[first_turn], config=config,
)
save_images(response, "generated")
```

## Referenzbild senden

Führe dies nach dem Python-Beispiel aus, um eine neue Bearbeitung anzufragen. Ersetze `reference.jpg` durch deine lokale Datei. Für PNG nutze `mime_type="image/png"`. Weitere Referenzen kommen in `parts` derselben Nutzernachricht.

```python theme={null}
first_turn = types.Content(
    role="user",
    parts=[
        types.Part(text="Mache die Tasse rot. Behalte Form und Hintergrund bei."),
        types.Part.from_bytes(
            data=Path("reference.jpg").read_bytes(),
            mime_type="image/jpeg",
        ),
    ],
)
response = client.models.generate_content(
    model=MODEL, contents=[first_turn], config=config,
)
save_images(response, "reference-edit")
```

Natives JSON nutzt `inlineData: {"mimeType": "image/jpeg", "data": "BASE64_IMAGE_DATA"}`. Kodiere die Originalbytes ohne `data:image/...;base64,`-Präfix. Kein multipart, Files-Upload oder `fileData`.

## Weiter bearbeiten

Führe dies nach erfolgreicher Generierung oder Referenzbearbeitung aus. Behalte den gesamten Modell-`content`, die Reihenfolge und `thoughtSignature`. Baue den Verlauf nicht allein aus dem Bild auf; erfinde oder ändere keine Signaturen.

```python theme={null}
history = [first_turn, response.candidates[0].content]
edit_turn = types.Content(
    role="user",
    parts=[types.Part(text="Füge einen kleinen goldenen Henkel hinzu. Lasse alles andere unverändert.")],
)
edited = client.models.generate_content(
    model=MODEL, contents=[*history, edit_turn], config=config,
)
save_images(edited, "follow-up")
history.extend([edit_turn, edited.candidates[0].content])
```

Jeder Schritt ist eine neue Generierung. Behalte den gesamten `history`, ergänze die Anweisung und dann den Modell-`content`. `previous_interaction_id` aus Interactions wird hier nicht verwendet.

## API-Unterstützung

* Nutze `generateContent` ohne Streaming. Files / `fileData`, Batch, Interactions und Streaming werden hier nicht unterstützt.
* `responseMimeType`, `responseSchema` und eigene Bildkompressionsformate werden nicht unterstützt. Nutze in `imageConfig` nur die zwei oben aufgeführten Felder.
* Lasse `cachedContent`, Funktionsaufrufe, Codeausführung, Dateisuche, Maps, URL context sowie Audioeingaben und Einstellungen zur Audioerzeugung weg.

## Mit vorhandenem OpenAI-Chat-Client

Du kannst `POST /v1/chat/completions` mit Base URL `https://bettertoken.ai/v1` aufrufen. Nutze für neue Integrationen, Referenzbilder und mehrere Bearbeitungsschritte die native Gemini-API oben. Lasse in Chat `n` weg oder setze die Ganzzahl `1`.

In HTTP steht `google.image_config` an der JSON-Wurzel. Im Python OpenAI SDK kommt es in `extra_body`, das in die Wurzel eingefügt wird. Hier kein `generationConfig`.

```bash theme={null}
curl --fail-with-body --max-time 650 \
  "https://bettertoken.ai/v1/chat/completions" \
  -H "Authorization: Bearer $BETTERTOKEN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-BetterToken-Max-Images: 1" \
  -d '{
    "model": "nano-banana-2.1",
    "messages": [{"role": "user", "content": "Eine blaue Keramiktasse auf einem weißen Tisch."}],
    "n": 1,
    "stream": false,
    "google": {"image_config": {"image_size": "1K", "aspect_ratio": "1:1"}}
  }'
```

Installiere für das Python-OpenAI-SDK-Beispiel `openai==1.66.2` im selben virtuellen Umfeld:

```python theme={null}
import base64
import os
import re
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["BETTERTOKEN_API_KEY"],
    base_url="https://bettertoken.ai/v1",
    max_retries=0,
    timeout=650,
)
response = client.chat.completions.create(
    model="nano-banana-2.1",
    messages=[{"role": "user", "content": "Eine blaue Keramiktasse auf einem weißen Tisch."}],
    n=1,
    stream=False,
    extra_headers={"X-BetterToken-Max-Images": "1"},
    extra_body={
        "google": {"image_config": {"image_size": "1K", "aspect_ratio": "1:1"}}
    },
)
content = response.choices[0].message.content or ""
images = re.findall(r"data:(image/(?:png|jpeg));base64,([A-Za-z0-9+/=]+)", content)
if not images:
    raise RuntimeError("No inline image in Chat response.")
for index, (mime, data) in enumerate(images, 1):
    suffix = ".png" if mime == "image/png" else ".jpg"
    Path(f"chat-{index}{suffix}").write_bytes(base64.b64decode(data, validate=True))
```

Chat liefert Markdown Data URLs in `choices[0].message.content`, nicht `data[]` der Images API. Baue aus diesem Text keinen signierten Verlauf auf; verwende native Bearbeitung.

## Häufige Fehler

| Problem | Aktion |
| - | - |
| `401` / ungültiger Key | BetterToken API Key statt Google nutzen; Variable und Header prüfen. |
| `404` / URL | Domainwurzel als Base URL, `api_version="v1beta"` und eine der drei öffentlichen Model IDs. |
| `400 unsupported_endpoint` | `/v1/images/*` durch `:generateContent` ersetzen. |
| `400` / Parameter | Prüfe Verschachtelung, Großschreibung von `1K/2K/4K` und die Seitenverhältnisse des Modells. Lasse `candidateCount` weg oder setze Ganzzahl `1`; füge keine Suchwerkzeuge hinzu. |
| Kein endgültiges Bild | Fehler, Sicherheitsfeedback, Text und `finishReason` prüfen. Thought-Bilder sind keine Endergebnisse. |
| Datei lässt sich nicht öffnen | Base64 dekodieren und MIME-Endung wählen; nicht das gesamte JSON oder Markdown speichern. |
| Zeitüberschreitung oder Abbruch | Verbrauch prüfen und Anfrage-ID behalten. Vor Wiederholung Ergebnis mit Support klären, um doppelte Generierung und Kosten zu vermeiden. |

Die Bilder kommen mit der aktuellen Antwort. Dieser Ablauf bietet weder späteren Bildabruf noch Aufgabenabfrage. Ergebnisse sofort speichern, genug Wartezeit in SDK und Proxy zulassen und automatische Wiederholungen deaktivieren.

## Offizielle Quellen

* [Nano Banana Pro Modell](https://ai.google.dev/gemini-api/docs/models/gemini-3-pro-image)
* [Nano Banana 2 Modell](https://ai.google.dev/gemini-api/docs/models/gemini-3.1-flash-image)
* [Nano Banana 2.1 Modell](https://ai.google.dev/gemini-api/docs/models/gemini-nano-banana-2.1)
* [Google Bildanleitung](https://ai.google.dev/gemini-api/docs/generate-content/image-generation)
* [Google Versionshinweise](https://ai.google.dev/gemini-api/docs/changelog)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.