Gemini 3.1 Flash Image API

The image model gemini-3.1-flash-image (Nano Banana 2) uses the Gemini native protocol and does not use the OpenAI Images endpoints:

  • Base URL: https://api.teamorouter.com
  • Endpoint: POST https://api.teamorouter.com/v1beta/models/{model}:generateContent
  • Authentication: Authorization: Bearer sk-teamo-xxxxxx

Query GET /v1/models first to confirm the model is available. Treat the live response as the source of truth for available models and routing.


1. Generate an image

bash
curl https://api.teamorouter.com/v1beta/models/gemini-3.1-flash-image:generateContent \
  -H "Authorization: Bearer sk-teamo-xxxxxx" \
  -H "content-type: application/json" \
  -d '{
    "contents": [
      {"role": "user", "parts": [{"text": "A minimal tech poster, 16:9"}]}
    ],
    "generationConfig": {
      "responseModalities": ["IMAGE"],
      "imageConfig": {"aspectRatio": "16:9", "imageSize": "2K"}
    }
  }'

The image comes back as Base64 in candidates[0].content.parts[].inlineData:

json
{
  "candidates": [
    {
      "content": {
        "parts": [
          {
            "inlineData": {
              "mimeType": "image/png",
              "data": "iVBORw0KGgo..."
            }
          }
        ]
      }
    }
  ]
}

Iterate over every parts entry to find inlineData; never assume the image is the first part, and never log the full Base64 payload.


2. Request parameters

Field Common values Description
contents[].role user Message role
contents[].parts[].text Prompt string Subject, style, composition, text, and constraints
contents[].parts[].inlineData mimeType + Base64 data Source image when editing
generationConfig.responseModalities ["IMAGE"] or ["TEXT", "IMAGE"] Return image, text, or both
generationConfig.imageConfig.aspectRatio 1:1, 16:9, 9:16, and more Output aspect ratio
generationConfig.imageConfig.imageSize 512, 1K, 2K, 4K Output resolution, defaults to 1K

Resolution tiers

The sizes below use 1:1; other aspect ratios produce the corresponding non-square size:

imageSize 1:1 output Image output tokens (approx.) Recommended for
512 512 × 512 747 Previews, drafts, low-cost batch tests
1K 1024 × 1024 1120 Default tier, social posts, product shots
2K 2048 × 2048 1680 Posters, detail pages, text-heavy images
4K 4096 × 4096 2520 High-resolution delivery, print, later cropping

Supported aspect ratios: 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.

Use the uppercase 1K, 2K, 4K values in production code. The gateway accepts lowercase 2k in testing, but do not rely on it.


3. Python

bash
pip install requests
python
import base64
import os
from pathlib import Path

import requests

BASE_URL = "https://api.teamorouter.com"
API_KEY = os.environ["TEAMO_API_KEY"]
MODEL = "gemini-3.1-flash-image"

response = requests.post(
    f"{BASE_URL}/v1beta/models/{MODEL}:generateContent",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "contents": [
            {
                "role": "user",
                "parts": [{"text": "A minimal tech poster, 16:9"}],
            }
        ],
        "generationConfig": {
            "responseModalities": ["IMAGE"],
            "imageConfig": {"aspectRatio": "16:9", "imageSize": "2K"},
        },
    },
    timeout=300,
)
response.raise_for_status()
result = response.json()

parts = result["candidates"][0]["content"]["parts"]
image_part = next(part for part in parts if "inlineData" in part)
image_bytes = base64.b64decode(image_part["inlineData"]["data"])
Path("image.png").write_bytes(image_bytes)

4. JavaScript / TypeScript

Node.js 18+ can use fetch directly:

javascript
import fs from "node:fs";

const baseURL = "https://api.teamorouter.com";
const apiKey = process.env.TEAMO_API_KEY;
const model = "gemini-3.1-flash-image";

const response = await fetch(
  `${baseURL}/v1beta/models/${model}:generateContent`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "content-type": "application/json",
    },
    body: JSON.stringify({
      contents: [
        {
          role: "user",
          parts: [{ text: "A minimal tech poster, 16:9" }],
        },
      ],
      generationConfig: {
        responseModalities: ["IMAGE"],
        imageConfig: { aspectRatio: "16:9", imageSize: "2K" },
      },
    }),
    signal: AbortSignal.timeout(300_000),
  },
);

if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const result = await response.json();
const parts = result.candidates?.[0]?.content?.parts ?? [];
const image = parts.find((part) => part.inlineData?.data);
if (!image) throw new Error("No image part in the response");

fs.writeFileSync("image.png", Buffer.from(image.inlineData.data, "base64"));

5. Edit an image

Editing uses the same endpoint. Pass the instruction and the Base64 source image together in parts:

json
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {"text": "Keep the subject and composition, change the background to a sunset beach, add no text"},
        {
          "inlineData": {
            "mimeType": "image/png",
            "data": "<BASE64_IMAGE>"
          }
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": ["IMAGE"],
    "imageConfig": {"imageSize": "2K"}
  }
}

6. Production guidance

  • Call /v1/models at startup or on a schedule instead of relying on a static model table, and only surface models present in the live list.
  • Image generation is slow; set client timeouts to 300 seconds.
  • Only retry 429 and recoverable 5xx responses with exponential backoff. A 400 usually means a request or routing problem, so retrying will not help.
  • Keep API keys in server-side environment variables or a secrets manager. Never ship them to the browser, store them in a database, or write them to logs.
  • Validate the HTTP status, candidates, finishReason, inlineData.mimeType, and the Base64 decoding result.
  • Cap concurrency, output resolution, reference image count, and daily quota.

7. Common errors

401 / authentication failed

Confirm the header is Authorization: Bearer sk-teamo-xxxxxx, with a complete key and no extra whitespace. If you suspect a leak, delete the key in the console and create a new one immediately.

400 / invalid endpoint format

gemini-3.1-flash-image uses the Gemini native URL https://api.teamorouter.com/v1beta/models/{model}:generateContent. Do not add an extra /v1 prefix.

404 or model not found

Query /v1/models first. If the model is missing from the live list, treat it as not yet enabled on the gateway and stop retrying.

Request succeeds but returns no image

Confirm responseModalities includes IMAGE, iterate over every parts entry for inlineData, and check finishReason plus any safety blocking information.

Ready? Three steps to startLog in to the console · top up · create an API key
DiscordGet community help instantly
Gemini 3.1 Flash Image API · Docs