Google Gemini API
Google Gemini API is Google’s native generative AI protocol. If your client is already developed according to Google GenAI SDK specifications, simply switch the Base URL and API Key to RouteAPI for direct use without rewriting request structures.
Protocol Overview
Section titled “Protocol Overview”Gemini API uses a unique design where the model name is embedded in the URL path. Request bodies use a contents array to express conversations, with each message having a role of user or model (note: not assistant). Response structures use a candidates array wrapper, supporting safety filtering and multiple candidate generation.
Use cases:
| Scenario | Description |
|---|---|
| Google GenAI SDK | google-generativeai Python / Node.js SDK, change base_url only |
| Gemini REST Client | Applications already developed for Gemini REST API |
| Multimodal Applications | Scenarios requiring native support for image, video, audio input |
| Google AI Studio Export | Code exported from AI Studio can be migrated directly |
If your client only supports OpenAI protocol, use Chat Completions instead. RouteAPI will perform necessary format adaptation internally, but prioritizing the protocol natively supported by your client ensures the best compatibility.
Endpoint Format
Section titled “Endpoint Format”Gemini API endpoint design is distinctive: the model name is directly embedded in the URL path.
POST /v1beta/models/{model}:generateContentFull address example:
https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:generateContentStreaming endpoint:
https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:streamGenerateContentReplace the {model} portion with the actual model name, such as gemini-1.5-pro, gemini-1.5-flash, gemini-2.0-flash-exp, etc. Note there is no space between the model name before the colon and the method name after it.
Request headers:
Authorization: Bearer sk-your-routeapi-tokenContent-Type: application/jsonAll protocols use the same RouteAPI Token. Please save the Token on the server side and do not expose it to browsers, mobile devices, or public repositories.
Request Format
Section titled “Request Format”| Field | Type | Required | Description |
|---|---|---|---|
contents | array | Yes | Conversation content list, at least one entry |
generationConfig | object | No | Generation configuration parameters |
safetySettings | array | No | Safety filtering settings |
systemInstruction | object | No | System instruction, independent field |
tools | array | No | Function calling tool definitions |
toolConfig | object | No | Tool calling configuration |
Basic request example:
{ "contents": [ { "role": "user", "parts": [ { "text": "Please introduce RouteAPI in one sentence" } ] } ], "generationConfig": { "temperature": 0.7, "maxOutputTokens": 1024 }}Unique Structure of contents
Section titled “Unique Structure of contents”Gemini API uses a three-layer nested structure:
contentsarray contains multiple messages- Each message has
roleandpartsfields partsarray contains actual content blocks
Key Differences:
rolecan only beuserormodel(notassistant)- Content must be placed in the
partsarray, with each element being a part object - Supports multimodal parts: text, image, video, audio can be mixed in the
partsof the same message
{ "contents": [ { "role": "user", "parts": [ { "text": "Analyze this image" }, { "inlineData": { "mimeType": "image/jpeg", "data": "base64 encoded image data..." } } ] }, { "role": "model", "parts": [ { "text": "This is an image showing..." } ] } ]}generationConfig Parameters
Section titled “generationConfig Parameters”| Parameter | Type | Description |
|---|---|---|
temperature | number | Sampling temperature, range 0 to 2, default 1.0 |
topP | number | Nucleus sampling parameter, default 0.95 |
topK | integer | Sample only from the top K tokens by probability |
maxOutputTokens | integer | Maximum output tokens |
stopSequences | array | Custom stop sequences, up to 5 |
candidateCount | integer | Number of candidates to generate, default 1 |
responseMimeType | string | Response format, e.g., "application/json" |
responseSchema | object | JSON Schema to constrain output structure |
Example:
{ "generationConfig": { "temperature": 0.9, "topP": 0.95, "topK": 40, "maxOutputTokens": 2048, "stopSequences": ["END", "STOP"] }}systemInstruction
Section titled “systemInstruction”System instruction is an independent field, not placed in contents:
{ "systemInstruction": { "parts": [ { "text": "You are a rigorous technical assistant who keeps answers concise." } ] }, "contents": [ { "role": "user", "parts": [{ "text": "Explain what an API gateway is" }] } ]}safetySettings
Section titled “safetySettings”Controls content safety filtering levels:
{ "safetySettings": [ { "category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE" }, { "category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_MEDIUM_AND_ABOVE" } ]}Common categories: HARM_CATEGORY_HARASSMENT, HARM_CATEGORY_HATE_SPEECH, HARM_CATEGORY_SEXUALLY_EXPLICIT, HARM_CATEGORY_DANGEROUS_CONTENT.
Threshold options: BLOCK_NONE, BLOCK_LOW_AND_ABOVE, BLOCK_MEDIUM_AND_ABOVE, BLOCK_ONLY_HIGH.
Multimodal Content
Section titled “Multimodal Content”Gemini API natively supports multimodal input through different types in the parts array.
{ "text": "This is text content" }Inline Image (base64)
Section titled “Inline Image (base64)”{ "inlineData": { "mimeType": "image/jpeg", "data": "/9j/4AAQSkZJRgABAQAAAQ..." }}Supported image formats: image/jpeg, image/png, image/webp, image/heic, image/heif.
Image URL (fileData)
Section titled “Image URL (fileData)”{ "fileData": { "mimeType": "image/jpeg", "fileUri": "https://example.com/image.jpg" }}Video and Audio
Section titled “Video and Audio”{ "fileData": { "mimeType": "video/mp4", "fileUri": "gs://bucket-name/video.mp4" }}Video support: video/mp4, video/mpeg, video/mov, etc.
Audio support: audio/wav, audio/mp3, audio/aac, etc.
Mixed Multimodal Example
Section titled “Mixed Multimodal Example”{ "contents": [ { "role": "user", "parts": [ { "text": "Analyze the relationship between this video and this image" }, { "fileData": { "mimeType": "video/mp4", "fileUri": "gs://my-bucket/video.mp4" } }, { "inlineData": { "mimeType": "image/jpeg", "data": "base64..." } } ] } ]}Response Format
Section titled “Response Format”Standard Response
Section titled “Standard Response”{ "candidates": [ { "content": { "parts": [ { "text": "RouteAPI is an API gateway that unifies management of multiple AI model providers." } ], "role": "model" }, "finishReason": "STOP", "safetyRatings": [ { "category": "HARM_CATEGORY_HARASSMENT", "probability": "NEGLIGIBLE" } ] } ], "usageMetadata": { "promptTokenCount": 12, "candidatesTokenCount": 18, "totalTokenCount": 30 }}Response Field Descriptions
Section titled “Response Field Descriptions”| Field | Description |
|---|---|
candidates | Array of candidate responses, default is one |
candidates[].content | Generated content, same structure as contents element in request |
candidates[].content.role | Always "model" |
candidates[].finishReason | Reason for completion |
candidates[].safetyRatings | Safety rating details |
usageMetadata | Token usage statistics |
finishReason Values
Section titled “finishReason Values”| Value | Meaning |
|---|---|
STOP | Model finished naturally |
MAX_TOKENS | Reached maxOutputTokens limit |
SAFETY | Blocked due to safety filter trigger |
RECITATION | Blocked due to detected content repetition |
OTHER | Other reasons |
usageMetadata Fields
Section titled “usageMetadata Fields”| Field | Description |
|---|---|
promptTokenCount | Input token count |
candidatesTokenCount | Output token count (sum of all candidates) |
totalTokenCount | Total token count |
cachedContentTokenCount | Cached token count (if context caching is used) |
Streaming Output
Section titled “Streaming Output”Use the streamGenerateContent endpoint for streaming responses:
POST /v1beta/models/{model}:streamGenerateContentStreaming responses use SSE (Server-Sent Events) format, with each event being a JSON object:
data: {"candidates":[{"content":{"parts":[{"text":"RouteAPI"}],"role":"model"},"finishReason":""}],"usageMetadata":{"promptTokenCount":12,"candidatesTokenCount":1,"totalTokenCount":13}}
data: {"candidates":[{"content":{"parts":[{"text":" is an"}],"role":"model"},"finishReason":""}],"usageMetadata":{"promptTokenCount":12,"candidatesTokenCount":3,"totalTokenCount":15}}
data: {"candidates":[{"content":{"parts":[{"text":" API gateway"}],"role":"model"},"finishReason":""}],"usageMetadata":{"promptTokenCount":12,"candidatesTokenCount":5,"totalTokenCount":17}}
data: {"candidates":[{"content":{"parts":[{"text":""}],"role":"model"},"finishReason":"STOP","safetyRatings":[{"category":"HARM_CATEGORY_HARASSMENT","probability":"NEGLIGIBLE"}]}],"usageMetadata":{"promptTokenCount":12,"candidatesTokenCount":18,"totalTokenCount":30}}Streaming Characteristics:
- Each chunk is a complete JSON object containing the full
candidatesstructure finishReasonis an empty string to continue, has a value to indicate completion- The last chunk contains complete
safetyRatingsand finalusageMetadata - Streaming responses have no explicit
[DONE]marker, rely onfinishReasonto determine completion
Function Calling
Section titled “Function Calling”Gemini API supports function calling to enable the model to call external tools.
Tool Definition
Section titled “Tool Definition”{ "tools": [ { "functionDeclarations": [ { "name": "get_weather", "description": "Query current weather for a specified city. Use full city name in Chinese.", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "City name, e.g., Beijing" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] } }, "required": ["city"] } } ] } ]}Function Call Response
Section titled “Function Call Response”Model returns a function call request:
{ "candidates": [ { "content": { "parts": [ { "functionCall": { "name": "get_weather", "args": { "city": "Beijing", "unit": "celsius" } } } ], "role": "model" }, "finishReason": "STOP" } ]}Return Function Results
Section titled “Return Function Results”Return function execution results as a new user message:
{ "contents": [ { "role": "user", "parts": [{ "text": "What's the weather in Beijing now?" }] }, { "role": "model", "parts": [ { "functionCall": { "name": "get_weather", "args": { "city": "Beijing", "unit": "celsius" } } } ] }, { "role": "user", "parts": [ { "functionResponse": { "name": "get_weather", "response": { "content": "Beijing, sunny, temperature 23 celsius, humidity 45%." } } } ] } ]}Comparison with OpenAI Format
Section titled “Comparison with OpenAI Format”Structure Comparison Table
Section titled “Structure Comparison Table”| Item | Gemini API | OpenAI Chat Completions |
|---|---|---|
| Endpoint format | /v1beta/models/{model}:generateContent | /v1/chat/completions |
| Model specification | In URL path | Request body model field |
| Conversation array field | contents | messages |
| Message structure | role + parts array | role + content string/array |
| Role names | user / model | user / assistant / system |
| System instruction | systemInstruction object | role: "system" in messages |
| Response wrapper | candidates array | choices array |
| Response content location | candidates[0].content.parts[0].text | choices[0].message.content |
| Completion reason field | finishReason | finish_reason |
| Usage statistics field | usageMetadata | usage |
Parameter Mapping Table
Section titled “Parameter Mapping Table”| Gemini API | OpenAI Chat Completions | Notes |
|---|---|---|
generationConfig.temperature | temperature | Gemini max 2, OpenAI also 2 |
generationConfig.topP | top_p | Different naming style |
generationConfig.topK | No equivalent | OpenAI doesn’t support |
generationConfig.maxOutputTokens | max_tokens / max_completion_tokens | Different field name |
generationConfig.stopSequences | stop | Different name |
generationConfig.candidateCount | n | Same semantics |
generationConfig.responseMimeType | response_format.type | Different control method |
generationConfig.responseSchema | response_format.json_schema | Different hierarchy |
safetySettings | No equivalent | OpenAI uses content moderation API |
tools[].functionDeclarations | tools[].function | Different wrapper level |
toolConfig | tool_choice | Different field name and structure |
Migration Considerations
Section titled “Migration Considerations”When migrating from OpenAI to Gemini API, check in the following order:
- Move model name to URL path:
/v1beta/models/gemini-1.5-pro:generateContent - Rename
messagestocontents, change each message structure torole+partsarray - Change all
assistantroles tomodel - Change
contentfield topartsarray, wrap text content as{ "text": "..." } - System prompt moves from
messagesarray tosystemInstructionobject - Generation parameters wrap into
generationConfigobject and adjust field names (e.g.,maxOutputTokens,stopSequences) - Response parsing changes to extract content from
candidates[0].content.parts[0].text - Streaming endpoint changes to
streamGenerateContent, each chunk is complete JSON - Tool definition changes to
functionDeclarationswrapper, parameter field changes toparameters
Role Name Mapping
Section titled “Role Name Mapping”| Gemini | OpenAI | Claude |
|---|---|---|
user | user | user |
model | assistant | assistant |
| No independent role | system | No independent role |
| No independent role | tool | No independent role |
Both Gemini and Claude elevate system instructions to top-level fields, not as message roles.
Complete Examples
Section titled “Complete Examples”Basic Conversation (curl)
Section titled “Basic Conversation (curl)”curl https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:generateContent \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "contents": [ { "role": "user", "parts": [ { "text": "Please introduce RouteAPI in one sentence" } ] } ], "generationConfig": { "temperature": 0.7, "maxOutputTokens": 1024 } }'Basic Conversation (Python SDK)
Section titled “Basic Conversation (Python SDK)”Using Google GenAI Python SDK, only change client_options:
import osimport google.generativeai as genaifrom google.api_core.client_options import ClientOptions
# Configure RouteAPI endpointgenai.configure( api_key=os.environ["ROUTEAPI_KEY"], transport="rest", client_options=ClientOptions( api_endpoint="https://api.routeapi.ai/v1beta" ))
model = genai.GenerativeModel("gemini-1.5-pro")
response = model.generate_content( "Please introduce RouteAPI in one sentence", generation_config={ "temperature": 0.7, "max_output_tokens": 1024 })
print(response.text)print(f"Input tokens: {response.usage_metadata.prompt_token_count}")print(f"Output tokens: {response.usage_metadata.candidates_token_count}")Image Input Example (curl)
Section titled “Image Input Example (curl)”# Convert image to base64IMAGE_BASE64=$(base64 -w 0 screenshot.jpg)
curl https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:generateContent \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "contents": [ { "role": "user", "parts": [ { "text": "What UI controls are in this image?" }, { "inlineData": { "mimeType": "image/jpeg", "data": "'"$IMAGE_BASE64"'" } } ] } ], "generationConfig": { "maxOutputTokens": 2048 } }'Image Input Example (Python SDK)
Section titled “Image Input Example (Python SDK)”import osimport google.generativeai as genaifrom google.api_core.client_options import ClientOptionsfrom PIL import Image
genai.configure( api_key=os.environ["ROUTEAPI_KEY"], transport="rest", client_options=ClientOptions( api_endpoint="https://api.routeapi.ai/v1beta" ))
model = genai.GenerativeModel("gemini-1.5-pro")
image = Image.open("screenshot.jpg")
response = model.generate_content( ["What UI controls are in this image?", image], generation_config={"max_output_tokens": 2048})
print(response.text)Streaming Output Example (curl)
Section titled “Streaming Output Example (curl)”curl https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:streamGenerateContent \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "contents": [ { "role": "user", "parts": [ { "text": "Explain step by step what an API gateway is" } ] } ] }'Streaming Output Example (Python SDK)
Section titled “Streaming Output Example (Python SDK)”import osimport google.generativeai as genaifrom google.api_core.client_options import ClientOptions
genai.configure( api_key=os.environ["ROUTEAPI_KEY"], transport="rest", client_options=ClientOptions( api_endpoint="https://api.routeapi.ai/v1beta" ))
model = genai.GenerativeModel("gemini-1.5-pro")
response = model.generate_content( "Explain step by step what an API gateway is", stream=True)
for chunk in response: print(chunk.text, end="", flush=True)
print()Complete Function Calling Example (Python SDK)
Section titled “Complete Function Calling Example (Python SDK)”import osimport google.generativeai as genaifrom google.api_core.client_options import ClientOptions
genai.configure( api_key=os.environ["ROUTEAPI_KEY"], transport="rest", client_options=ClientOptions( api_endpoint="https://api.routeapi.ai/v1beta" ))
# Define toolget_weather_declaration = { "name": "get_weather", "description": "Query current weather for a specified city. Use full city name.", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "City name, e.g., Beijing" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] } }, "required": ["city"] }}
model = genai.GenerativeModel( "gemini-1.5-pro", tools=[get_weather_declaration])
chat = model.start_chat()
# First round: user questionresponse = chat.send_message("What's the weather in Beijing now?")
# Check for function callif response.candidates[0].content.parts[0].function_call: function_call = response.candidates[0].content.parts[0].function_call
# Simulate function execution if function_call.name == "get_weather": city = function_call.args["city"] weather_result = f"{city}, sunny, temperature 23 celsius, humidity 45%."
# Second round: return function result response = chat.send_message( genai.protos.Content( parts=[ genai.protos.Part( function_response=genai.protos.FunctionResponse( name="get_weather", response={"content": weather_result} ) ) ] ) )
print(response.text)Compatibility Notes
Section titled “Compatibility Notes”- Actual parameter support depends on the selected model and upstream service capabilities. Some advanced features (such as context caching, code execution) should be verified in a test environment first.
- Optional parameters explicitly passed as
0orfalseare treated as user-set values, not default values to be discarded. - Production environments should fix model IDs and not rely on temporary aliases or display names.
- Log model ID, status code, and token usage for each request to facilitate troubleshooting of latency and cost anomalies.
- When using
fileUriwith thegs://protocol, ensure the file is accessible to upstream, or useinlineDatafor direct transmission. - Error response format may differ from OpenAI/Claude, see Error Handling.