Call Gemini image models through Router Brain’s Google native /google endpoints.
Example model code: gemini-nano-banana-2.1-all — replace with a model enabled for your account in the model catalog. Authenticate with an API key created in the console. Replace every [BASE64_IMAGE_DATA] placeholder with real image data before calling in production.
1. Entry points
| Endpoint | Use case | Request | Response |
|---|---|---|---|
/google/{version}/models/{model}:generateContent | Native Google calls, multi-turn edits, video input | Google native JSON | Google native JSON |
/google/{version}/models/{model}:streamGenerateContent | Native Google streaming | Google native JSON | Google native SSE |
All of the above use POST. Use https://routerbrain.ai as the gateway base URL and the platform’s public model code in the path. Responses follow Google’s native JSON or SSE format.
2. Google native API
2.1 URL, auth, and headers
Synchronous:
POST https://routerbrain.ai/google/v1beta/models/{model_code}:generateContent
Streaming:
POST https://routerbrain.ai/google/v1beta/models/{model_code}:streamGenerateContent?alt=sse
| Parameter / header | Required | Description |
|---|---|---|
| Path version | Yes | Use v1, v1beta, or v1alpha in the path; supported versions depend on the model |
| Path model code | Yes | Public model code, e.g. gemini-nano-banana-2.1-all |
| Path operation | Yes | generateContent (sync) or streamGenerateContent (stream) |
Content-Type | Yes | application/json |
x-goog-api-key | One of two | Console API key; may be used instead of query key |
Query key | One of two | Console API key; Google alias $key is also accepted. URL-encode special characters |
Query alt=sse | Recommended for streaming | Standard SSE form; streaming is selected by :streamGenerateContent in the URL |
x-trace-id | No | Custom trace id for correlating requests |
x-user-id | No | End-user identifier |
x-agent-name | No | Calling app or agent name |
If both header and query key are sent, they must match. Duplicate or conflicting keys are rejected. This entry point requires x-goog-api-key or key; Authorization: Bearer ... alone is not sufficient.
See Google’s system parameters for key, $key, and X-Goog-Api-Key.
2.2 Text-to-image (sync)
Set local variables:
GATEWAY_URL='https://routerbrain.ai'
API_KEY='sk-REPLACE-WITH-YOUR-KEY'
MODEL_CODE='gemini-nano-banana-2.1-all'
curl --silent --show-error --fail-with-body --max-time 300 \
"${GATEWAY_URL}/google/v1beta/models/${MODEL_CODE}:generateContent" \
-H "x-goog-api-key: ${API_KEY}" \
-H 'Content-Type: application/json' \
--data-binary @- <<'JSON'
{
"contents": [
{
"role": "user",
"parts": [
{ "text": "Generate an image of an orange cat sitting by a window in the sun" }
]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "16:9",
"imageSize": "2K"
}
}
}
JSON
--max-time 300 is a client-side curl timeout, not a request body field; adjust as needed.
For query-parameter auth, save the JSON above as request.json:
curl --silent --show-error --fail-with-body --max-time 300 \
"${GATEWAY_URL}/google/v1beta/models/${MODEL_CODE}:generateContent" \
--url-query "key=${API_KEY}" \
-H 'Content-Type: application/json' \
--data-binary @request.json
--url-query requires a recent curl and handles URL encoding; the header example works on older curl versions.
2.3 Request body (main fields)
The request body matches the Google GenerateContent API. The table below lists common image-generation fields; capabilities vary by model.
| Field | Type | Required | Description |
|---|---|---|---|
contents | array<object> | Yes | Current turn or ordered conversation history |
contents[].role | string | Recommended | user for user turns; model for prior model replies |
contents[].parts | array<object> | Yes | Parts: text, inline media, file references, etc. |
parts[].text | string | When using text | Prompt, edit instruction, or history text |
parts[].inlineData | object | Inline media | mimeType + data |
inlineData.mimeType | string | With inline media | e.g. image/png, image/jpeg |
inlineData.data | string | With inline media | Raw base64 without a data:image/...;base64, prefix |
parts[].fileData | object | File reference | fileUri, optional mimeType; must be reachable by the model service |
fileData.fileUri | string | With file reference | URI the model service can read; see Google docs for supported schemes |
fileData.mimeType | string | Recommended | MIME of referenced file (image or video/mp4) |
parts[].thoughtSignature | string | Multi-turn when returned | Signature from the previous model part; do not invent or modify |
systemInstruction | object | No | Often { "parts": [{ "text": "..." }] } |
generationConfig | object | Recommended for images | Modalities, image size, sampling options |
cachedContent | string | No | Existing cached content name; this API does not create cache |
safetySettings | array<object> | No | e.g. category, threshold |
tools / toolConfig | No | Tool configuration when supported |
Use one content type per Part per Google’s spec. For multi-turn edits, keep the full previous content to preserve images, signatures, and context.
2.4 generationConfig
| Field | Type | Description |
|---|---|---|
responseModalities | array<string> | For images, prefer ["TEXT", "IMAGE"]; ["IMAGE"] when the model allows |
imageConfig.aspectRatio | string | e.g. 1:1, 16:9, 9:16, 4:3, 3:2; model-specific |
imageConfig.imageSize | string | 512, 1K, 2K, 4K — mind letter case; support varies by model |
temperature, topP, topK | Sampling; defaults apply when omitted | |
maxOutputTokens | integer | Output token cap; too low may truncate; not pixel or image count |
seed | integer | When supported; not a strict reproducibility guarantee |
candidateCount | integer | Prefer 1 for image calls |
stopSequences | array<string> | When supported |
thinkingConfig.* | Thinking level/budget/thoughts when the model supports them |
Do not use responseMimeType instead of inlineData.mimeType to force PNG/JPEG. Image calls use imageConfig; see GenerationConfig.
2.5 Image-to-image / edit
Replace placeholders and send as in §2.2:
{
"contents": [
{
"role": "user",
"parts": [
{ "text": "Keep the cat’s appearance; change the background to a beach sunset" },
{
"inlineData": {
"mimeType": "image/png",
"data": "[BASE64_IMAGE_DATA]"
}
}
]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": { "aspectRatio": "16:9", "imageSize": "2K" }
}
}
File reference part:
{
"fileData": {
"mimeType": "image/jpeg",
"fileUri": "https://example.com/reference.jpg"
}
}
Place inside contents[].parts. The URL must be directly reachable by the model service; Router Brain does not download remote images for you. HTTPS and Google file URIs depend on the model and Google’s documentation.
For video input, use inlineData or fileData with the appropriate video MIME; support depends on the model.
2.6 Multi-turn image editing
Keep candidates[0].content from the last response as a model turn, then append the new user message:
{
"contents": [
{
"role": "user",
"parts": [{ "text": "Generate an orange cat by the window" }]
},
{
"role": "model",
"parts": [
{
"inlineData": {
"mimeType": "image/png",
"data": "[BASE64_IMAGE_DATA]"
},
"thoughtSignature": "[ORIGINAL_THOUGHT_SIGNATURE]"
}
]
},
{
"role": "user",
"parts": [{ "text": "Same pose; change the view outside to snow" }]
}
],
"generationConfig": { "responseModalities": ["TEXT", "IMAGE"] }
}
Include thoughtSignature only when the prior response returned one. See Google image generation.
2.7 Native SSE
Save the §2.2 body as request.json:
curl -N --silent --show-error --fail-with-body --max-time 300 \
"${GATEWAY_URL}/google/v1beta/models/${MODEL_CODE}:streamGenerateContent?alt=sse" \
-H "x-goog-api-key: ${API_KEY}" \
-H 'Content-Type: application/json' \
--data-binary @request.json
Each data: line is typically one Google response object. Parse on SSE event boundaries; do not assume one read equals one JSON object or that [DONE] always appears.
Example event shapes:
data: {"candidates":[{"index":0,"content":{"role":"model","parts":[{"inlineData":{"mimeType":"image/png","data":"[BASE64_IMAGE_DATA]"}}]}}]}
data: {"candidates":[{"index":0,"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":11,"candidatesTokenCount":1120,"totalTokenCount":1131,"promptTokensDetails":[{"modality":"TEXT","tokenCount":11}],"candidatesTokensDetails":[{"modality":"IMAGE","tokenCount":1120}]}}
Events are separated by blank lines; multiple data: lines may belong to one event.
2.8 Response and reading images
Example response:
{
"candidates": [
{
"index": 0,
"finishReason": "STOP",
"content": {
"role": "model",
"parts": [
{
"inlineData": {
"mimeType": "image/png",
"data": "[BASE64_IMAGE_DATA]"
}
}
]
}
}
],
"usageMetadata": {
"promptTokenCount": 11,
"candidatesTokenCount": 1120,
"totalTokenCount": 1131,
"promptTokensDetails": [{ "modality": "TEXT", "tokenCount": 11 }],
"candidatesTokensDetails": [{ "modality": "IMAGE", "tokenCount": 1120 }]
}
}
Walk candidates[].content.parts[]:
| Field | Meaning |
|---|---|
part.text | Text output |
part.inlineData.data | Raw image base64 |
part.inlineData.mimeType | Actual image MIME for file extension |
part.thought | When true, thought content — not the final image |
part.thoughtSignature | Keep for the next multi-turn request |
candidate.finishReason | Completion reason for that candidate |
promptFeedback | Input blocking feedback |
usageMetadata | Token usage in the response; not a request field |
You may get text without an image. Check for image parts; HTTP 200 alone does not prove an image was generated.
3. Errors and limits
3.1 Error shape
Authentication error example:
{
"error": {
"code": 401,
"message": "API key not valid. Please pass a valid API key.",
"status": "UNAUTHENTICATED"
}
}
Responses may include Google-native error bodies. Check HTTP status, error, promptFeedback, each candidate’s finishReason, and whether image parts are present.
| Symptom | What to check |
|---|---|
401 / UNAUTHENTICATED | Valid API key via x-goog-api-key or key |
400 / INVALID_ARGUMENT | Valid JSON, non-conflicting keys, supported options |
404 / NOT_FOUND | Model code, API version, operation name |
| 403 or permission errors | Model enabled for your account; key valid and account has balance |
| Text but no image | IMAGE modality, model capability, safety/finish reason |
| Reference image fails | URI reachable by the model service, correct MIME; try inlineData base64 |
| Image size errors | imageSize casing, aspectRatio, model support |
| SSE errors | Treat as failed stream; keep x-request-id |
| Long wait | Increase client timeout; curl -N only disables buffering |
3.2 Boundaries
- Only
generateContentandstreamGenerateContenton this native entry; not Google Interactions API. - Model code and streaming operation are in the URL; do not use body
stream: trueinstead ofstreamGenerateContent. - Image size via
generationConfig.imageConfig, not OpenAIsize/response_format/n. - This API does not upload files or create caches;
fileData.fileUriandcachedContentmust reference existing resources the model service can use. - Capabilities and latency are model-specific; a valid body does not guarantee support.
- For SSE, read until final candidate state and errors; partial success is not enough.
- Image MIME comes from the response; do not assume PNG.
- When contacting support: include
x-request-id, model code, operation name, and error text — never full API keys or image base64.