Image Generation
RouterHub supports image generation through two API interfaces on this page:
| Interface | Endpoint | Request Shape |
|---|---|---|
| Gemini Native | POST /v1beta/models/{model}:generateContent |
Google contents / parts format |
| OpenAI Images | POST /v1/images/generations |
OpenAI-style model / prompt / size JSON |
Gemini Native Interface
Generate images using Google's Gemini image generation models. This endpoint uses the native Gemini generateContent API format—not the OpenAI Images format.
This endpoint is non-streaming only. The response is returned as a single JSON object once generation is complete.
For text-only Gemini requests (:generateContent on any text model, plus :streamGenerateContent) see Generate Content. The same URL pattern serves both flows — RouterHub selects the handler based on the resolved model class.
Available Gemini 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
}
}Gemini 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.
OpenAI Images Interface
Generate images using OpenAI-compatible request and response shapes. This interface is different from Gemini native :generateContent and should be called via /v1/images/generations.
Available OpenAI Image Models
| Model ID | Description |
|---|---|
| openai/gpt-image-1 | OpenAI-compatible image generation model |
| openai/gpt-image-1.5 | OpenAI-compatible image generation model (v1.5) |
| openai/gpt-image-2 | OpenAI-compatible image generation model (v2) |
Request Body
| Field | Type | Description | |
|---|---|---|---|
| model | string | Required | One of openai/gpt-image-1, openai/gpt-image-1.5, or openai/gpt-image-2. |
| prompt | string | Required | Text prompt describing the image to generate. |
| size | string | Optional | Output resolution, such as 1024x1024. |
| quality | string | Optional | Quality tier, such as medium. |
| output_compression | number | Optional | Output compression level (for supported formats). |
| output_format | string | Optional | Output image format, such as png or jpeg. |
| n | number | Optional | Number of images to generate. Commonly 1. |
Examples
This example uses openai/gpt-image-2 and returns base64 image data at data[0].b64_json.
curl -v https://api.routerhub.ai/v1/images/generations \
-H "Authorization: Bearer $ROUTERHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-image-2",
"prompt" : "A cute baby otter wearing a tiny top hat, watercolor style",
"size" : "1024x1024",
"quality" : "medium",
"output_compression" : 100,
"output_format" : "png",
"n" : 1
}' | jq -r '.data[0].b64_json' | base64 --decode > generated_image_gpt_image_2.pngimport base64
import requests
response = requests.post(
"https://api.routerhub.ai/v1/images/generations",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"model": "openai/gpt-image-2",
"prompt": "A cute baby otter wearing a tiny top hat, watercolor style",
"size": "1024x1024",
"quality": "medium",
"output_compression": 100,
"output_format": "png",
"n": 1,
},
)
response.raise_for_status()
payload = response.json()
img_b64 = payload["data"][0]["b64_json"]
img_bytes = base64.b64decode(img_b64)
with open("generated_image_gpt_image_2.png", "wb") as f:
f.write(img_bytes)
print("Saved generated_image_gpt_image_2.png")Sample Response
{
"created": 1735689600,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAA..."
}
]
}OpenAI Images Error Format
This interface returns OpenAI-style errors:
{
"error": {
"message": "Invalid value for 'model'",
"type": "invalid_request_error",
"param": "model",
"code": "invalid_model"
}
}