Gemini Image Generation

Overview

AIone supports the Gemini family of image generation models through two endpoints:

Endpoint Use it for Capabilities
POST /v1/chat/completions Quick integration with your existing OpenAI SDK Generation, image-to-image, streaming; size control for Nano 2.1
POST /v1beta/models/{model}:generateContent When you need a specific resolution or aspect ratio Everything above + resolution / aspect ratio control

Nano Banana 2.1 supports resolution and aspect ratio control on both endpoints: use image_size / aspect_ratio in Chat, or generationConfig.imageConfig on the native endpoint.

Available models

Model Notes
gemini-nano-banana-2.1 Nano Banana 2.1, with 1K / 2K / 4K output
gemini-3.1-flash-image Primary model, balanced speed and quality
gemini-3-pro-image More consistent output, suited to final artwork
gemini-2.5-flash-image Previous-gen Flash, default size only

For the full model list, refer to GET /v1/models and the Portal model list page.


1. Quick generation: /v1/chat/completions

Minimal request:

curl https://api.aiin1.ai/v1/chat/completions \
  -H "Authorization: Bearer sk-nex-your-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.1-flash-image",
    "messages": [
      {"role": "user", "content": "Draw a cute cat"}
    ]
  }'

Response shape

The image is returned inside message.content as a Markdown-embedded data URI:

{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "model": "gemini-3.1-flash-image",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "![image](data:image/png;base64,iVBORw0KGgoAAA...)"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 6,
    "completion_tokens": 1120,
    "total_tokens": 1126
  }
}

Extracting the image: message.content is a string — pull the data URI out with a regex.

import re, base64
content = response.choices[0].message.content
images = re.findall(r"data:(image/[\w.+-]+);base64,([A-Za-z0-9+/=]+)", content)
extensions = {"image/png": "png", "image/jpeg": "jpg", "image/webp": "webp"}
for index, (mime_type, encoded) in enumerate(images):
    image_bytes = base64.b64decode(encoded)
    extension = extensions.get(mime_type, "img")
    open(f"out-{index}.{extension}", "wb").write(image_bytes)

Images may be returned as PNG, JPEG or another format. Select the filename extension from the returned MIME type.

Python SDK

from openai import OpenAI
 
client = OpenAI(
    api_key="sk-nex-your-key-here",
    base_url="https://api.aiin1.ai/v1",
)
 
resp = client.chat.completions.create(
    model="gemini-3.1-flash-image",
    messages=[{"role": "user", "content": "Draw a cute cat"}],
)
print(resp.choices[0].message.content[:80])

Nano Banana 2.1: choose a resolution

Use the recommended model ID gemini-nano-banana-2.1, or the compatibility alias nano-banana-2.1. Pass the resolution as a parameter; do not add a -2k or -4k suffix to the model name.

curl --max-time 600 https://api.aiin1.ai/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "gemini-nano-banana-2.1",
  "messages": [
    {
      "role": "user",
      "content": "Draw a cute cat"
    }
  ],
  "image_size": "2K",
  "aspect_ratio": "1:1"
}'

With the OpenAI Python SDK, pass image parameters through extra_body:

resp = client.chat.completions.create(
    model="gemini-nano-banana-2.1",
    messages=[{"role": "user", "content": "Draw a cute cat"}],
    extra_body={"image_size": "2K", "aspect_ratio": "1:1"},
    timeout=600,
)

For native Gemini requests, use the same model ID and put the size in generationConfig.imageConfig:

curl --max-time 600 https://api.aiin1.ai/v1beta/models/gemini-nano-banana-2.1:generateContent \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "Draw a cute cat"
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": [
      "IMAGE"
    ],
    "imageConfig": {
      "imageSize": "2K",
      "aspectRatio": "1:1"
    }
  }
}'

A response may contain both a preview and the original image. Extract all images and check their dimensions; saving only the first data URI may save a lower-resolution preview. Set a timeout of at least 600 seconds for high-resolution or queued requests. The gateway waits for the result; clients do not need a separate polling step.

Image-to-image

Pass the reference image with the standard OpenAI multimodal content array:

{
  "model": "gemini-3.1-flash-image",
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "Replace the apple in this picture with an orange"},
        {
          "type": "image_url",
          "image_url": {"url": "data:image/png;base64,iVBORw0KGgoAAA..."}
        }
      ]
    }
  ]
}

Reference images may be a data: URI (base64) or a public https:// URL. base64 is recommended: some CDNs apply hotlink protection or format conversion, so a direct link may not be retrievable.

Streaming

"stream": true is supported. This is pseudo-streaming — the finished image is delivered in one SSE event once generation completes, not token by token. The benefit is that data keeps flowing on the connection, so intermediate network devices are less likely to drop it as idle.

curl https://api.aiin1.ai/v1/chat/completions \
  -H "Authorization: Bearer sk-nex-your-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.1-flash-image",
    "messages": [{"role": "user", "content": "Draw a cute cat"}],
    "stream": true
  }'

Image size on this endpoint

For Nano Banana 2.1, set the top-level image_size to 1K (default), 2K, or 4K, and set aspect_ratio to a ratio such as 1:1. Size controls for other image models depend on their capabilities; native parameters are described below. Use the returned image to determine the actual pixel dimensions.


2. Controlling resolution and aspect ratio: the /v1beta native endpoint

POST https://api.aiin1.ai/v1beta/models/{model}:generateContent

The model name goes in the URL path; size parameters go in generationConfig.imageConfig:

curl https://api.aiin1.ai/v1beta/models/gemini-3.1-flash-image:generateContent \
  -H "Authorization: Bearer sk-nex-your-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {"role": "user", "parts": [{"text": "Draw a cute cat"}]}
    ],
    "generationConfig": {
      "responseModalities": ["IMAGE"],
      "imageConfig": {
        "imageSize": "4K",
        "aspectRatio": "16:9"
      }
    }
  }'

imageSize — resolution tier

Nano Banana 2.1 supports only 1K / 2K / 4K, not 512. The pixel examples below are for Gemini 3.1 Flash Image; determine Nano 2.1 dimensions from the returned image.

Values: 512 / 1K (default) / 2K / 4K. Actual pixel dimensions at 16:9:

imageSize Pixels (16:9) Area
omitted (default 1K) 1376×768 1.06 MP
"2K" 2752×1536 4.23 MP
"4K" 5504×3072 16.9 MP
"512" 688×384 0.26 MP

gemini-2.5-flash-image outputs the default size only (1024×1024) and ignores imageSize.

aspectRatio — aspect ratio

14 values are supported. Actual pixels at the default tier (1K):

Ratio Pixels Ratio Pixels
1:1 1024×1024 9:16 768×1376
3:2 1264×848 16:9 1376×768
2:3 848×1264 21:9 1584×672
4:3 1200×896 1:4 512×2064
3:4 896×1200 4:1 2064×512
5:4 1152×928 1:8 352×2928
4:5 928×1152 8:1 2928×352

imageSize and aspectRatio combine freely — e.g. 4K + 21:9 gives an ultra-wide high-resolution image.

The model renders at the native resolution of the chosen tier and ratio; take the actual pixel size from the returned image.

Response shape

The image is in candidates[0].content.parts[] under inlineData; data is raw base64 with no prefix:

{
  "candidates": [
    {
      "content": {
        "parts": [
          {
            "inlineData": {
              "mimeType": "image/png",
              "data": "iVBORw0KGgoAAA..."
            }
          }
        ]
      },
      "finishReason": "STOP"
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 6,
    "candidatesTokenCount": 1120,
    "totalTokenCount": 1126,
    "candidatesTokensDetails": [{"modality": "IMAGE", "tokenCount": 1120}]
  }
}
import base64, json, requests
 
resp = requests.post(
    "https://api.aiin1.ai/v1beta/models/gemini-3.1-flash-image:generateContent",
    headers={"Authorization": "Bearer sk-nex-your-key-here"},
    json={
        "contents": [{"role": "user", "parts": [{"text": "Draw a cute cat"}]}],
        "generationConfig": {
            "responseModalities": ["IMAGE"],
            "imageConfig": {"imageSize": "2K", "aspectRatio": "16:9"},
        },
    },
    timeout=600,
)
for index, part in enumerate(resp.json()["candidates"][0]["content"]["parts"]):
    if "inlineData" in part:
        inline = part["inlineData"]
        extension = {"image/png": "png", "image/jpeg": "jpg", "image/webp": "webp"}.get(
            inline.get("mimeType"), "img"
        )
        open(f"out-{index}.{extension}", "wb").write(base64.b64decode(inline["data"]))

parts may also contain non-image entries such as thoughtSignature; when iterating, check for the presence of inlineData.

Native streaming generation and editing

Use the same request body with /v1beta/models/{model}:streamGenerateContent?alt=sse. The response is SSE; images in each JSON event are still under candidates[].content.parts[].inlineData.

4K generation may take several minutes. Allow a 600-second client timeout; native SSE or the Chat streaming mode described above keeps the connection active while waiting.

Image-to-image (native endpoint)

Put the reference image in parts as inlineData, alongside the text. data is raw base64 without the data:image/png;base64, prefix:

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {"inlineData": {"mimeType": "image/png", "data": "iVBORw0KGgoAAA..."}},
        {"text": "Replace the apple in this picture with an orange"}
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": ["IMAGE"],
    "imageConfig": {"aspectRatio": "1:1"}
  }
}

Add several inlineData parts to blend multiple images.


Billing

Image output is billed per image output token. The token count is determined by the resolution tier, independent of prompt length:

Tier gemini-3.1-flash-image gemini-3-pro-image gemini-nano-banana-2.1
512 747 — —
default / 1K 1,120 1,120 1,120
2K 1,680 1,120 1,680
4K 2,520 2,000 3,780

gemini-2.5-flash-image is 1,290 tokens per image.

The image portion follows the table above. usage.completion_tokens (chat endpoint) and usageMetadata.candidatesTokenCount (native endpoint) are the total output tokens for the request and may include a small number of text tokens besides the image; each portion is priced at its own rate. See "Pricing" for unit prices.

Nano 2.1 uses its own image output tiers above. Text and thinking tokens use the text output rate. When both a preview and an original are returned, do not multiply image tokens solely by the number of image entries; use the bill for the exact charge.

Request parameters

/v1/chat/completions

Parameter Type Required Description
model string Yes Image model ID
messages array Yes Standard OpenAI Chat message array; pass reference images as image_url parts
stream boolean No Pseudo-streaming; the image is delivered in one SSE event after generation
image_size string No Nano 2.1: 1K (default) / 2K / 4K
aspect_ratio string No Nano 2.1 aspect ratio, e.g. 1:1
temperature number No Sampling temperature

/v1beta/models/{model}:generateContent

Parameter Type Required Description
contents array Yes Conversation content; parts holds text and inlineData
generationConfig.responseModalities array No Recommended: ["IMAGE"]
generationConfig.imageConfig.imageSize string No 512 / 1K / 2K / 4K
generationConfig.imageConfig.aspectRatio string No One of the 14 values above

Notes

  1. Timeouts: high-resolution generation takes longer; set your client HTTP timeout to ≥ 600 seconds.
  2. Image extraction differs by endpoint: on the chat endpoint, extract the Markdown data URI from message.content; on the native endpoint, read parts[].inlineData.data (raw base64, no prefix).
  3. Reference image format: the chat endpoint takes a full data URI with the data: prefix; the native endpoint takes raw base64 without it. The two rules are opposite — do not mix them up.
  4. No Anthropic format: Gemini image models are not available on /v1/messages.
  5. Model access: make sure your API key is allowed to use the image model.