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 |
POST /v1beta/models/{model}:generateContent |
When you need a specific resolution or aspect ratio | Everything above + resolution / aspect ratio control |
In short: to just get an image, use /v1/chat/completions; to control the size, use the /v1beta native endpoint.
Available models
| Model | Notes |
|---|---|
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/modelsand 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": ""
},
"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
m = re.search(r"data:image/\w+;base64,([A-Za-z0-9+/=]+)", content)
if m:
image_bytes = base64.b64decode(m.group(1))
open("out.png", "wb").write(image_bytes)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])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
/v1/chat/completions renders at the model's default size, about 1408×768 (image-to-image follows the reference image — a square reference yields 1024×1024).
To choose a resolution or aspect ratio, use the native endpoint below.
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
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 part in resp.json()["candidates"][0]["content"]["parts"]:
if "inlineData" in part:
open("out.png", "wb").write(base64.b64decode(part["inlineData"]["data"]))
partsmay also contain non-image entries such asthoughtSignature; when iterating, check for the presence ofinlineData.
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 |
|---|---|---|
| 512 | 747 | — |
| default / 1K | 1,120 | 1,120 |
| 2K | 1,680 | 1,120 |
| 4K | 2,520 | 2,000 |
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.
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 |
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
- Timeouts: high-resolution generation takes longer; set your client HTTP timeout to ≥ 600 seconds.
- Image extraction differs by endpoint: on the chat endpoint, extract the Markdown data URI from
message.content; on the native endpoint, readparts[].inlineData.data(raw base64, no prefix). - 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. - No Anthropic format: Gemini image models are not available on
/v1/messages. - Model access: make sure your API key is allowed to use the image model.