> ## 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：生成图片、参考图与连续编辑

> 通过 BetterToken 的 Gemini 原生接口接入 Nano Banana Pro、2 和 2.1。包含模型 ID、鉴权、分辨率、Python 示例、参考图、图片保存、连续编辑和参数限制。

用同一个 Gemini 原生接口完成文字生图、参考图编辑和连续编辑。下文示例使用 `nano-banana-2.1`；调用另外两款时，替换路径或 SDK 中的模型 ID。

* [Gemini 文生图 API](/zh/api-reference/gemini-images-generations)
* [Gemini 图片编辑 API](/zh/api-reference/gemini-images-edits)

<Warning>
  BetterToken API 不支持搜索生图，包括 Google 网页搜索和图片搜索增强。不要添加搜索工具。
</Warning>

## 接入信息

| 字段 | 填写内容 |
| - | - |
| Base URL | `https://bettertoken.ai` |
| 请求 | `POST /v1beta/models/{model}:generateContent` |
| 鉴权 | `x-goog-api-key: YOUR_API_KEY`；也支持 `Authorization: Bearer YOUR_API_KEY`，二选一。 |
| 请求体 | `application/json` |
| 模型 ID | `nano-banana-pro`, `nano-banana-2`, `nano-banana-2.1` |

<a href={"https://bettertoken.ai/register"}>创建 BetterToken API Key</a> · <a href={"https://bettertoken.ai/pricing"}>模型广场</a> · [Nano Banana 系列上线介绍](/zh/model-updates/nano-banana)

<Warning>
  三款 Nano Banana 模型不支持 `POST /v1/images/generations` 或 `POST /v1/images/edits`，调用会返回 `400 unsupported_endpoint`。不要套用 GPT Image 的 multipart、`image[]` 或 `data[].b64_json` 示例。
</Warning>

## 先生成一张图片

在终端设置 `BETTERTOKEN_API_KEY` 后执行。该请求会等待生成结束，将完整 JSON 响应保存为 `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": "白色桌面上蓝色陶瓷杯的影棚产品照片。"}]
        }],
        "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 = "白色桌面上蓝色陶瓷杯的影棚产品照片。" })
        })
        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>

将 `imageSize` 改为 `2K` 或 `4K` 可请求更高分辨率。先从 `1K`、`1:1` 和一张图片开始；不要加 `--retry` 自动重发生图。

## 常用参数

生成商品图时，描述主体、材质、光线和背景；制作海报时，明确画面中的文字和版式；编辑图片时，分别说明需要修改和需要保留的内容。

原生 HTTP 请求使用以下字段；Python SDK 对应使用 snake\_case 名称。将图片设置放在 `generationConfig.imageConfig` 内。

| 字段 | 填写内容 |
| - | - |
| `contents[].parts[].text` | 描述主体、背景、风格和要修改的内容。 |
| `contents[].parts[].inlineData` | 参考图片的 `mimeType` 和原始文件的 base64；不是图片 URL。 |
| `generationConfig.responseModalities` | 显式设置 `["IMAGE"]`。 |
| `generationConfig.imageConfig.imageSize` | `1K`、`2K` 或 `4K`，区分大小写；省略时为 `1K`。 |
| `generationConfig.imageConfig.aspectRatio` | 按模型选择下表中的比例；本页示例使用 `1:1`。 |
| `generationConfig.candidateCount` | 省略或设为整数 `1`；原生请求根级不要传 `n`。 |
| `X-BetterToken-Max-Images` | 可选请求头，整数 `1` 到 `4`，默认 `1`；允许返回并计费的图片数量上限。 |

<span id="aspect-ratios" />

### Google 官方支持的比例

Nano Banana 2 和 2.1 支持 14 种比例，Pro 支持 10 种。首次调用可先使用 `1:1`。

| 模型 | 分辨率 | 比例 |
| - | - | - |
| `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 比例与尺寸说明](https://ai.google.dev/gemini-api/docs/image-generation#aspect-ratios-and-image-size)

图片数量上限不是生成数量承诺。即使提示词要求多张，也可能只返回一张；需要固定多张时，逐张发送独立请求。

## 读取响应并保存图片

图片位于 `candidates[].content.parts[].inlineData`。下面只展示结构，`BASE64_IMAGE_DATA` 不是实际图片。遍历所有最终图片 part，并跳过 `thought: true` 的中间内容。

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

使用下面的 Python 代码保存 curl 返回的结果。根据 `mimeType` 选择文件后缀；返回的图片可能是 JPEG，不要一律命名为 `.png`。

```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.")
```

## Python SDK 完整示例

使用 Python 3.10 或更新版本。以下示例按 `google-genai==2.30.1` 编写。请在项目虚拟环境中安装；旧版 SDK 可能不发送 `image_size`。

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

SDK Base URL 为域名根地址，不要附加 `/v1` 或 `/v1beta`。`timeout` 单位为毫秒；`attempts=1` 关闭自动重试。示例的 `save_images` 会保存全部最终图片。

```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="白色桌面上蓝色陶瓷杯的影棚产品照片。")],
)
response = client.models.generate_content(
    model=MODEL, contents=[first_turn], config=config,
)
save_images(response, "generated")
```

## 传入参考图片

在上方 Python 示例后运行以下代码，会发送一次新的编辑请求。把 `reference.jpg` 换成你的本地图片。PNG 请改为 `mime_type="image/png"`；多个参考图可依次加入同一条用户消息的 `parts`。

```python theme={null}
first_turn = types.Content(
    role="user",
    parts=[
        types.Part(text="将杯子改成红色，保留它的形状和背景。"),
        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")
```

原生 JSON 对应 `inlineData: {"mimeType": "image/jpeg", "data": "BASE64_IMAGE_DATA"}`。传入文件原始字节的 base64，不要带 `data:image/...;base64,` 前缀。本接入方式不使用 multipart、Files 上传或 `fileData`。

## 连续编辑同一张图片

在上一次成功生成或参考图编辑之后继续运行。保留完整的模型响应 `content`，包括 part 顺序和 `thoughtSignature`；不要只提取图片重新拼接，也不要手写或修改签名。

```python theme={null}
history = [first_turn, response.candidates[0].content]
edit_turn = types.Content(
    role="user",
    parts=[types.Part(text="加上一个小巧的金色把手，其他内容保持不变。")],
)
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])
```

每一轮都是新的生成请求。继续编辑时沿用完整 `history`，加入新的用户指令，再加入新返回的模型 `content`。不要把 Interactions 的 `previous_interaction_id` 用在这个接口中。

## 接口支持范围

* 本接入方式使用非流式 `generateContent`。不支持 Files / `fileData`、Batch、Interactions 或流式调用。
* 不支持 `responseMimeType`、`responseSchema` 和自定义图片压缩格式。`imageConfig` 仅使用上方列出的两个字段。
* 不要添加 `cachedContent`、函数调用、代码执行、文件搜索、Maps、URL context 或音频输入与生成配置。

## 已有 OpenAI Chat 客户端时

可以使用 `POST /v1/chat/completions`，Base URL 为 `https://bettertoken.ai/v1`。新接入、参考图和连续编辑推荐使用上面的 Gemini 原生接口。Chat 请求中的 `n` 省略或设为整数 `1`。

直接 HTTP 请求把 `google.image_config` 放在 JSON 根级。使用 Python OpenAI SDK 时，通过 `extra_body` 传入，SDK 会将其合并到根级；不要把它误写为 `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": "白色桌面上的蓝色陶瓷杯。"}],
    "n": 1,
    "stream": false,
    "google": {"image_config": {"image_size": "1K", "aspect_ratio": "1:1"}}
  }'
```

如需 Python OpenAI SDK 示例，可在同一虚拟环境安装 `openai==1.66.2` 后运行：

```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": "白色桌面上的蓝色陶瓷杯。"}],
    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 图片在 `choices[0].message.content` 的 Markdown Data URL 中，不在 Images API 的 `data[]` 内。不要从 Chat 的图片文本重建连续编辑的签名历史，连续编辑使用原生示例。

## 常见调用错误

| 现象 | 处理方法 |
| - | - |
| `401` / 无效 Key | 使用 BetterToken API Key；检查环境变量和请求头，不要填写 Google 官方 Key。 |
| `404` / 路径错误 | SDK Base URL 用域名根地址，`api_version="v1beta"`；模型使用三个公开 ID 之一。 |
| `400 unsupported_endpoint` | 移除 `/v1/images/*` 调用，改用本页 `:generateContent` 路径。 |
| `400` / 参数错误 | 检查字段层级、`1K/2K/4K` 大小写和所选模型的比例；`candidateCount` 省略或设为整数 `1`，不要添加搜索工具。 |
| 成功响应中没有最终图片 | 检查完整响应中的错误、安全提示、文本和 `finishReason`；不要把中间 thought 图片当成结果。 |
| 保存后打不开 | 按 `mimeType` 选择后缀并解码 base64；不要把整个 JSON 或 Markdown 保存成图片。 |
| 超时或断开连接 | 先检查消费记录并保留响应中的请求 ID，向支持人员确认结果后再决定是否重试，避免重复生成和收费。 |

生成结果随当前响应返回，不提供本页请求的后台取图或任务轮询。成功后及时保存图片。SDK 及代理都应预留足够等待时间，并关闭自动重试。

## 官方来源

* [Nano Banana Pro 模型文档](https://ai.google.dev/gemini-api/docs/models/gemini-3-pro-image)
* [Nano Banana 2 模型文档](https://ai.google.dev/gemini-api/docs/models/gemini-3.1-flash-image)
* [Nano Banana 2.1 模型文档](https://ai.google.dev/gemini-api/docs/models/gemini-nano-banana-2.1)
* [Google 图片生成指南](https://ai.google.dev/gemini-api/docs/generate-content/image-generation)
* [Google 发布记录](https://ai.google.dev/gemini-api/docs/changelog)


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