Image Generation
Generate images using Google's Gemini image generation models. This endpoint uses the native Gemini generateContent API format—not the OpenAI chat completions format.
This endpoint is non-streaming only. The response is returned as a single JSON object once generation is complete.
Available Models
| Model ID | Description |
|---|---|
| google/gemini-2.5-flash-image | Gemini 2.5 Flash with image generation |
| google/gemini-3-pro-image-preview | Gemini 3 Pro image generation preview |
| google/gemini-3.1-flash-image-preview | Gemini 3.1 Flash image generation preview |
The google/ prefix is optional in the URL. For example, both /v1beta/models/gemini-2.5-flash-image:generateContent and /v1beta/models/google/gemini-2.5-flash-image:generateContent work.
Authentication
This endpoint supports two authentication methods:
| Method | Header | Example |
|---|---|---|
| Bearer token | Authorization |
Authorization: Bearer rh_your_api_key |
| Google-style API key | x-goog-api-key |
x-goog-api-key: rh_your_api_key |
Request Body
| Field | Type | Description | |
|---|---|---|---|
| contents | array | Required | Array of Content objects with role and parts. See Content Object. |
| generationConfig | object | Optional | Generation parameters (temperature, responseModalities, etc.). Defaults to responseModalities: ["TEXT", "IMAGE"] if omitted. |
| safetySettings | array | Optional | Safety filter thresholds for content categories. |
| systemInstruction | object | Optional | System-level instruction as a Content object. |
| cachedContent | string | Optional | Resource name of cached content (e.g., projects/my-project/cachedContents/abc123). |
Content Object
| Field | Type | Description | |
|---|---|---|---|
| role | string | Required | "user" or "model" |
| parts | array | Required | Array of parts. Each part contains one of: text (string) or inlineData (object with mimeType and base64-encoded data). |
Response Body
| Field | Type | Description |
|---|---|---|
| candidates | array | Array of candidate responses. Each has content (with parts), finishReason, and optional safetyRatings. |
| modelVersion | string | The model version used. |
| usageMetadata | object | Token usage: promptTokenCount, candidatesTokenCount, totalTokenCount. |
| promptFeedback | object | Present if the prompt was blocked. Contains blockReason and safetyRatings. |
Generated images appear as inlineData parts in the candidate's content, with mimeType (e.g., image/png) and base64-encoded data.
Examples
Text-to-Image
curl https://api.routerhub.ai/v1beta/models/gemini-2.5-flash-image:generateContent \
-H "Authorization: Bearer $ROUTERHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{
"role": "user",
"parts": [{"text": "A cute baby otter wearing a tiny top hat, watercolor style"}]
}
]
}'import requests
import base64
response = requests.post(
"https://api.routerhub.ai/v1beta/models/gemini-2.5-flash-image:generateContent",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"contents": [
{
"role": "user",
"parts": [{"text": "A cute baby otter wearing a tiny top hat, watercolor style"}],
}
],
},
)
data = response.json()
for part in data["candidates"][0]["content"]["parts"]:
if "inlineData" in part:
img_bytes = base64.b64decode(part["inlineData"]["data"])
with open("otter.png", "wb") as f:
f.write(img_bytes)
print("Saved otter.png")
elif "text" in part:
print(part["text"])Image Editing
Send an existing image along with an editing instruction:
# Base64-encode your image first
IMG_B64=$(base64 -w0 photo.png)
curl https://api.routerhub.ai/v1beta/models/gemini-3-pro-image-preview:generateContent \
-H "Authorization: Bearer $ROUTERHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{
"role": "user",
"parts": [
{"inlineData": {"mimeType": "image/png", "data": "'${IMG_B64}'"}},
{"text": "Remove the background and replace it with a beach scene"}
]
}
]
}'import requests
import base64
with open("photo.png", "rb") as f:
img_b64 = base64.b64encode(f.read()).decode()
response = requests.post(
"https://api.routerhub.ai/v1beta/models/gemini-3-pro-image-preview:generateContent",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"contents": [
{
"role": "user",
"parts": [
{"inlineData": {"mimeType": "image/png", "data": img_b64}},
{"text": "Remove the background and replace it with a beach scene"},
],
}
],
},
)
data = response.json()
for part in data["candidates"][0]["content"]["parts"]:
if "inlineData" in part:
img_bytes = base64.b64decode(part["inlineData"]["data"])
with open("edited.png", "wb") as f:
f.write(img_bytes)
print("Saved edited.png")With Generation Config
curl https://api.routerhub.ai/v1beta/models/gemini-3.1-flash-image-preview:generateContent \
-H "Authorization: Bearer $ROUTERHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{
"role": "user",
"parts": [{"text": "A serene mountain landscape at sunset"}]
}
],
"generationConfig": {
"temperature": 1.0,
"responseModalities": ["TEXT", "IMAGE"]
}
}'Sample Response
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"inlineData": {
"mimeType": "image/png",
"data": "iVBORw0KGgo..."
}
},
{
"text": "Here is your otter wearing a top hat!"
}
]
},
"finishReason": "STOP"
}
],
"modelVersion": "gemini-2.5-flash-image",
"usageMetadata": {
"promptTokenCount": 12,
"candidatesTokenCount": 1290,
"totalTokenCount": 1302
}
}Error Format
This endpoint returns errors in Google API format, different from the OpenAI and Anthropic error formats used by other endpoints.
{
"error": {
"code": 400,
"message": "body must be valid JSON",
"status": "INVALID_ARGUMENT"
}
}See Errors for the full list of HTTP status codes and retry guidance.