Gemini Native (Image)
curl --request POST \
--url https://api.mixroute.ai/v1/models/{model}:generateContentimport requests
url = "https://api.mixroute.ai/v1/models/{model}:generateContent"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/v1/models/{model}:generateContent', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.mixroute.ai/v1/models/{model}:generateContent",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixroute.ai/v1/models/{model}:generateContent"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mixroute.ai/v1/models/{model}:generateContent")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/v1/models/{model}:generateContent")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyImage Series
Gemini Native (Image)
Native Gemini image generation/editing fields and model-specific limits.
Gemini Native (Image)
curl --request POST \
--url https://api.mixroute.ai/v1/models/{model}:generateContentimport requests
url = "https://api.mixroute.ai/v1/models/{model}:generateContent"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/v1/models/{model}:generateContent', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.mixroute.ai/v1/models/{model}:generateContent",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixroute.ai/v1/models/{model}:generateContent"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mixroute.ai/v1/models/{model}:generateContent")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/v1/models/{model}:generateContent")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyGenerate and edit images with Gemini using native Content parts and generationConfig settings.
POST https://api.mixroute.ai/v1/models/{model}:generateContent
Models
| Model ID | Capabilities and Limits |
|---|---|
gemini-nano-banana-2.1 | Nano Banana 2.1; 1K/2K/4K output; MINIMAL/MEDIUM/HIGH thinking, default MEDIUM. |
gemini-3.1-flash-image | Nano Banana 2; 512, 1K, 2K, 4K output; MINIMAL/HIGH thinking. |
gemini-3.1-flash-image-preview | Nano Banana 2; 512, 1K, 2K, 4K output; MINIMAL/HIGH thinking. |
gemini-3-pro-image | Nano Banana Pro; 1K, 2K, 4K output and image/text reasoning. |
gemini-3-pro-image-preview | Nano Banana Pro; 1K, 2K, 4K output and image/text reasoning. |
gemini-3.1-flash-lite-image | Nano Banana 2 Lite; 1K output only; no Google Search grounding. |
gemini-2.5-flash-image | Original Nano Banana; approximately 1K output. Omit imageSize. |
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
model (URL path) | string | Yes | Model ID in the endpoint path, not an extra JSON body field. |
contents | object[] | Yes | Conversation turns containing text and optional image inputs. |
contents[].role | string | No | user or model. Use the model role when preserving previous model output in a conversation. |
contents[].parts | object[] | Yes | Content parts. Text instructions and image parts can be combined for editing. |
contents[].parts[].text | string | Conditional | Text prompt or edit instruction. |
contents[].parts[].inlineData | object | Conditional | Inline image bytes: mimeType plus raw Base64 data. Do not include a data-URI prefix in data. |
contents[].parts[].inlineData.mimeType | string | Conditional | Image MIME type, such as image/png, image/jpeg, or image/webp. |
contents[].parts[].inlineData.data | string | Conditional | Base64-encoded image bytes. |
contents[].parts[].fileData | object | No | Native file reference with fileUri and mimeType. The file must be accessible to the route’s upstream account. |
contents[].parts[].thoughtSignature | string | No | Opaque signature returned by the model. Preserve it exactly when returning previous model content in a later turn; never invent or modify it. |
systemInstruction | object | No | Native Content object for system instructions, typically using parts[].text. |
generationConfig | object | No | Native generation settings. |
generationConfig.responseModalities | string[] | No | Include IMAGE to request image output, optionally with TEXT. Example: [“TEXT”, “IMAGE”]. |
generationConfig.imageConfig.aspectRatio | string | No | Output aspect ratio. If omitted, the model selects a ratio based on the input; a square is not guaranteed. See the supported ratios below. |
generationConfig.imageConfig.imageSize | string | No | Default 1K. Nano Banana 2.1 and Pro: 1K/2K/4K. Nano Banana 2 (3.1 Flash Image): 512/1K/2K/4K. Lite: 1K only. Omit for 2.5 Flash Image. |
generationConfig.thinkingConfig.thinkingLevel | string | No | Nano Banana 2.1: MINIMAL, MEDIUM (default), HIGH. 3.1 Flash Image and Lite: MINIMAL (default) or HIGH. Do not apply one model’s levels to another. |
generationConfig.thinkingConfig.includeThoughts | boolean | No | Whether to include supported thought summaries/parts in the response. Final-image handling should skip parts marked thought=true. |
generationConfig.maxOutputTokens | integer | No | Output budget shared by text and image output. A very small budget can prevent a complete image response; respect the model limit. |
tools | object[] | No | Native tools. Nano Banana 2.1, 3.1 Flash Image, and Pro support Google Search grounding where enabled by the route. Lite and 2.5 Flash Image do not support this workflow. |
safetySettings | object[] | No | Native safety settings with category and threshold, subject to model and account policy. Do not repeat the same category. |
Model Constraints
Nano Banana 2.1 uses the same native Content/Part request envelope. Configure image output undergenerationConfig.imageConfig, without metadata or asset wrappers. Its supported output tiers are 1K, 2K, and 4K, not 512. Omit unsupported temperature, topP, topK, seed, and logprobs fields. See Nano Banana 2.1 for the model-specific limits.
1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9
Nano Banana 2.1 and Gemini 3.1 Flash Image additionally support 1:4, 4:1, 1:8, and 8:1. Only use sizes/aspect ratios supported by the selected model. Gemini 3 image models support up to 14 reference images with model-specific subject limits; Lite is optimized for lightweight workflows. The image API is not controlled by an OpenAI n or size field.
Examples
Use your MixRoute key in theMIXROUTE_API_KEY environment variable. Requests use Authorization: Bearer .... Replace source-image placeholders with accessible images or local files before editing.
curl --request POST "https://api.mixroute.ai/v1/models/gemini-nano-banana-2.1:generateContent" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "A clean product photograph of a red ceramic mug on a white background."
}
]
}
],
"generationConfig": {
"responseModalities": [
"TEXT",
"IMAGE"
],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}'
Python
import json
import os
import requests
payload = json.loads(r'''
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "A clean product photograph of a red ceramic mug on a white background."
}
]
}
],
"generationConfig": {
"responseModalities": [
"TEXT",
"IMAGE"
],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}
''')
response = requests.post(
"https://api.mixroute.ai/v1/models/gemini-nano-banana-2.1:generateContent",
headers={"Authorization": "Bearer " + os.environ["MIXROUTE_API_KEY"]},
json=payload,
timeout=180,
)
response.raise_for_status()
result = response.json()
import base64
from pathlib import Path
image_index = 0
for candidate in result.get("candidates", []):
for part in candidate.get("content", {}).get("parts", []):
if part.get("thought"):
continue
inline = part.get("inlineData")
if inline and inline.get("data"):
extension = {"image/png": "png", "image/jpeg": "jpg", "image/webp": "webp"}.get(inline.get("mimeType"), "bin")
Path(f"image_{image_index}.{extension}").write_bytes(base64.b64decode(inline["data"]))
image_index += 1
elif "text" in part:
print(part["text"])
Image Editing and Conversation
For editing, add an inlineData image part to the user turn alongside the text instruction. For a subsequent edit, append the complete prior candidate.content object to contents and then add the next user turn; this retains native image data and thought signatures. Do not replace the model history with text alone.{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Make the mug blue while preserving its shape, lighting, and background."
},
{
"inlineData": {
"mimeType": "image/png",
"data": "BASE64_IMAGE_DATA"
}
}
]
}
],
"generationConfig": {
"responseModalities": [
"TEXT",
"IMAGE"
],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}