# How to use the Nano Banana 2 API: key, request and result

By SeedRouter · Published 2026-09-25 · Updated 2026-09-25

To use the Nano Banana 2 API, create an API key, send Google's `generateContent` request body with a `model` field to one endpoint, and poll the task it returns until the image URL is ready. The same steps work for Nano Banana Pro and Nano Banana 2 Lite; only the `model` value changes.

This guide walks through each step with working code, then shows how to edit with reference images and how to hand the job to a coding agent.

## What do you need before the first request?

1. **An API key.** Create one on the [API keys](https://seedrouter.ai/apikeys) page and keep it on your server. Never put it in browser code.
2. **Credits.** Add a balance on the [billing page](https://seedrouter.ai/billing). Credits never expire, and failed requests are not charged.
3. **A model ID.** `gemini-3.1-flash-image` bills a flat price per image; `gemini-3.1-flash-image-official` bills tokens. See the [pricing guide](https://seedrouter.ai/blog/nano-banana-api-pricing) to choose.

```bash
export SEEDROUTER_API_KEY="your-key"
```

## How do you send a Nano Banana 2 request?

POST the request to `/v1/images/generations`. The body is Google's `generateContent` shape plus `model`:

```bash
curl https://api.seedrouter.ai/v1/images/generations \
  -H "Authorization: Bearer $SEEDROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.1-flash-image",
    "contents": [{"parts": [{"text": "A ceramic teapot on a linen tablecloth, soft window light"}]}],
    "generationConfig": {
      "responseModalities": ["IMAGE"],
      "imageConfig": {"aspectRatio": "16:9", "imageSize": "2K"}
    }
  }'
```

The response is a task, not an image:

```json
{
  "id": "task_...",
  "model": "gemini-3.1-flash-image",
  "status": "processing",
  "created_at": 1790310979
}
```

If you already call Google's API, the body you send is the same one you would send to `generateContent`. Calling `/v1beta/models/...:generateContent` on SeedRouter directly is not supported; use this endpoint.

## How do you get the image?

Poll the task every few seconds until `status` is `completed` or `failed`. In Python:

```python
import os
import time
import requests

API = "https://api.seedrouter.ai/v1"
headers = {"Authorization": f"Bearer {os.environ['SEEDROUTER_API_KEY']}"}

response = requests.post(
    f"{API}/images/generations",
    headers=headers,
    json={
        "model": "gemini-3.1-flash-image",
        "contents": [{"parts": [{"text": "A ceramic teapot on a linen tablecloth, soft window light"}]}],
        "generationConfig": {
            "responseModalities": ["IMAGE"],
            "imageConfig": {"aspectRatio": "16:9", "imageSize": "2K"},
        },
    },
    timeout=60,
)
response.raise_for_status()
task_id = response.json()["id"]

deadline = time.monotonic() + 600
while time.monotonic() < deadline:
    result = requests.get(f"{API}/tasks/{task_id}", headers=headers, timeout=30)
    result.raise_for_status()
    task = result.json()
    if task["status"] == "completed":
        for image in task["output"]["data"]:
            print(image["url"])
        break
    if task["status"] == "failed":
        raise RuntimeError(task["error"]["message"])
    time.sleep(3)
else:
    raise TimeoutError(f"Still waiting. Resume polling task {task_id}.")
```

A completed task has the image URL in `output.data[0].url`, plus token usage. With `"responseModalities": ["TEXT", "IMAGE"]`, any text the model writes comes back in `output.text`. Download the image to your own storage if you need it long term.

A timeout while polling does not mean the image failed. Keep the task ID and check it again; submitting a new request means paying for a second image.

## How do you edit an image or use references?

Add `fileData` parts next to the text. Each one is a public URL and its MIME type:

```bash
curl https://api.seedrouter.ai/v1/images/generations \
  -H "Authorization: Bearer $SEEDROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.1-flash-image",
    "contents": [{
      "role": "user",
      "parts": [
        {"text": "Turn this photo into a watercolor painting. Keep the composition."},
        {"fileData": {"mimeType": "image/jpeg", "fileUri": "https://example.com/photo.jpg"}}
      ]
    }]
  }'
```

Nano Banana 2 accepts up to 14 references per request: images, videos or PDFs, each under 50 MB. References must be URLs; base64 `inlineData` is not accepted. If a URL cannot be fetched, the task fails and is not charged. For a follow-up edit, send the earlier turns as `user` and `model` entries and end with a new `user` turn.

## Which settings matter most?

| Setting                   | What it does                                                          |
| ------------------------- | --------------------------------------------------------------------- |
| `imageConfig.imageSize`   | `512`, `1K`, `2K` or `4K`; `1K` by default                            |
| `imageConfig.aspectRatio` | 14 ratios from `1:8` to `8:1`; follows the first reference if omitted |
| `responseModalities`      | `["IMAGE"]` for the image only, `["TEXT", "IMAGE"]` to also get text  |
| `systemInstruction`       | Standing rules such as a house style                                  |
| `seed`                    | Reuse it to get closer to an earlier result                           |
| `mediaResolution`         | How many tokens each reference uses; lower is cheaper on Official     |

The [Nano Banana 2 API reference](https://seedrouter.ai/docs/gemini-3-1-flash-image) lists every field and limit. Unknown fields are rejected before anything is charged, and Google Search grounding (`tools`) is not available yet.

## How do you let a coding agent use the Nano Banana 2 API?

A coding agent such as Claude Code, Codex or Cursor can call the API with a shell command or a short script. SeedRouter does not ship an MCP server or a packaged skill; this prompt is the whole integration. Export the key first, then paste:

```text
Use the SeedRouter API to generate a Nano Banana 2 image for me.

Security: read SEEDROUTER_API_KEY from my local environment. Never ask me to paste it and never print it.

Goal: [subject, setting, style, what the image is for]
Size: [512 | 1K | 2K | 4K]    Aspect ratio: [e.g. 1:1, 16:9, 9:16]
References: [public image URLs, or none]

Send POST https://api.seedrouter.ai/v1/images/generations with
{"model": "gemini-3.1-flash-image",
 "contents": [{"parts": [{"text": "..."}, {"fileData": {"mimeType": "image/jpeg", "fileUri": "https://..."}}]}],
 "generationConfig": {"responseModalities": ["IMAGE"],
   "imageConfig": {"aspectRatio": "...", "imageSize": "..."}}}
Accepted top-level fields: model, contents, systemInstruction, safetySettings,
generationConfig. References must be fileData URLs (up to 14), never base64.
Do not add tools or any other field.

Before sending, show me the request body and wait for my approval: each
request is charged. Then poll GET https://api.seedrouter.ai/v1/tasks/{id}
every 3 seconds until status is completed or failed. If polling times out,
keep checking the same task; never resubmit. Save output.data[0].url into
./images/ and tell me the file path.
```

The approval step matters: the agent spends your balance, so it should never submit on its own.

## Frequently asked questions

### How do I get a Nano Banana 2 API key?

Sign in, open the [API keys](https://seedrouter.ai/apikeys) page and create a key. The same key works for Nano Banana 2, Nano Banana Pro, Nano Banana 2 Lite and the other models on SeedRouter.

### Does the Nano Banana 2 API support batch requests?

Send one request per image and poll the tasks in parallel. Each request returns one image, and each task is billed on its own.

### What errors should I handle?

A `400` means the body broke a rule, such as an unknown field or an unsupported size, and nothing is charged. A task that ends `failed` carries an error message and is not charged either. The [error guide](https://seedrouter.ai/docs/api/errors) lists every code and when to retry.

## Send your first request

Create a key, add a small balance, and run the Python example above, or try the same request with no code in the [Nano Banana 2 playground](https://seedrouter.ai/models/nano-banana-2#playground). For complex prompts, change the model to `gemini-3-pro-image` for [Nano Banana Pro](https://seedrouter.ai/models/nano-banana-pro).
