Skip to content

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.

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:

ScenarioDescription
Google GenAI SDKgoogle-generativeai Python / Node.js SDK, change base_url only
Gemini REST ClientApplications already developed for Gemini REST API
Multimodal ApplicationsScenarios requiring native support for image, video, audio input
Google AI Studio ExportCode 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.

Gemini API endpoint design is distinctive: the model name is directly embedded in the URL path.

POST /v1beta/models/{model}:generateContent

Full address example:

https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:generateContent

Streaming endpoint:

https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:streamGenerateContent

Replace 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-token
Content-Type: application/json

All 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.

FieldTypeRequiredDescription
contentsarrayYesConversation content list, at least one entry
generationConfigobjectNoGeneration configuration parameters
safetySettingsarrayNoSafety filtering settings
systemInstructionobjectNoSystem instruction, independent field
toolsarrayNoFunction calling tool definitions
toolConfigobjectNoTool calling configuration

Basic request example:

{
"contents": [
{
"role": "user",
"parts": [
{ "text": "Please introduce RouteAPI in one sentence" }
]
}
],
"generationConfig": {
"temperature": 0.7,
"maxOutputTokens": 1024
}
}

Gemini API uses a three-layer nested structure:

  1. contents array contains multiple messages
  2. Each message has role and parts fields
  3. parts array contains actual content blocks

Key Differences:

  • role can only be user or model (not assistant)
  • Content must be placed in the parts array, with each element being a part object
  • Supports multimodal parts: text, image, video, audio can be mixed in the parts of 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..." }
]
}
]
}
ParameterTypeDescription
temperaturenumberSampling temperature, range 0 to 2, default 1.0
topPnumberNucleus sampling parameter, default 0.95
topKintegerSample only from the top K tokens by probability
maxOutputTokensintegerMaximum output tokens
stopSequencesarrayCustom stop sequences, up to 5
candidateCountintegerNumber of candidates to generate, default 1
responseMimeTypestringResponse format, e.g., "application/json"
responseSchemaobjectJSON Schema to constrain output structure

Example:

{
"generationConfig": {
"temperature": 0.9,
"topP": 0.95,
"topK": 40,
"maxOutputTokens": 2048,
"stopSequences": ["END", "STOP"]
}
}

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" }]
}
]
}

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.

Gemini API natively supports multimodal input through different types in the parts array.

{ "text": "This is text content" }
{
"inlineData": {
"mimeType": "image/jpeg",
"data": "/9j/4AAQSkZJRgABAQAAAQ..."
}
}

Supported image formats: image/jpeg, image/png, image/webp, image/heic, image/heif.

{
"fileData": {
"mimeType": "image/jpeg",
"fileUri": "https://example.com/image.jpg"
}
}
{
"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.

{
"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..."
}
}
]
}
]
}
{
"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
}
}
FieldDescription
candidatesArray of candidate responses, default is one
candidates[].contentGenerated content, same structure as contents element in request
candidates[].content.roleAlways "model"
candidates[].finishReasonReason for completion
candidates[].safetyRatingsSafety rating details
usageMetadataToken usage statistics
ValueMeaning
STOPModel finished naturally
MAX_TOKENSReached maxOutputTokens limit
SAFETYBlocked due to safety filter trigger
RECITATIONBlocked due to detected content repetition
OTHEROther reasons
FieldDescription
promptTokenCountInput token count
candidatesTokenCountOutput token count (sum of all candidates)
totalTokenCountTotal token count
cachedContentTokenCountCached token count (if context caching is used)

Use the streamGenerateContent endpoint for streaming responses:

POST /v1beta/models/{model}:streamGenerateContent

Streaming 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 candidates structure
  • finishReason is an empty string to continue, has a value to indicate completion
  • The last chunk contains complete safetyRatings and final usageMetadata
  • Streaming responses have no explicit [DONE] marker, rely on finishReason to determine completion

Gemini API supports function calling to enable the model to call external tools.

{
"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"]
}
}
]
}
]
}

Model returns a function call request:

{
"candidates": [
{
"content": {
"parts": [
{
"functionCall": {
"name": "get_weather",
"args": {
"city": "Beijing",
"unit": "celsius"
}
}
}
],
"role": "model"
},
"finishReason": "STOP"
}
]
}

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%."
}
}
}
]
}
]
}
ItemGemini APIOpenAI Chat Completions
Endpoint format/v1beta/models/{model}:generateContent/v1/chat/completions
Model specificationIn URL pathRequest body model field
Conversation array fieldcontentsmessages
Message structurerole + parts arrayrole + content string/array
Role namesuser / modeluser / assistant / system
System instructionsystemInstruction objectrole: "system" in messages
Response wrappercandidates arraychoices array
Response content locationcandidates[0].content.parts[0].textchoices[0].message.content
Completion reason fieldfinishReasonfinish_reason
Usage statistics fieldusageMetadatausage
Gemini APIOpenAI Chat CompletionsNotes
generationConfig.temperaturetemperatureGemini max 2, OpenAI also 2
generationConfig.topPtop_pDifferent naming style
generationConfig.topKNo equivalentOpenAI doesn’t support
generationConfig.maxOutputTokensmax_tokens / max_completion_tokensDifferent field name
generationConfig.stopSequencesstopDifferent name
generationConfig.candidateCountnSame semantics
generationConfig.responseMimeTyperesponse_format.typeDifferent control method
generationConfig.responseSchemaresponse_format.json_schemaDifferent hierarchy
safetySettingsNo equivalentOpenAI uses content moderation API
tools[].functionDeclarationstools[].functionDifferent wrapper level
toolConfigtool_choiceDifferent field name and structure

When migrating from OpenAI to Gemini API, check in the following order:

  1. Move model name to URL path: /v1beta/models/gemini-1.5-pro:generateContent
  2. Rename messages to contents, change each message structure to role + parts array
  3. Change all assistant roles to model
  4. Change content field to parts array, wrap text content as { "text": "..." }
  5. System prompt moves from messages array to systemInstruction object
  6. Generation parameters wrap into generationConfig object and adjust field names (e.g., maxOutputTokens, stopSequences)
  7. Response parsing changes to extract content from candidates[0].content.parts[0].text
  8. Streaming endpoint changes to streamGenerateContent, each chunk is complete JSON
  9. Tool definition changes to functionDeclarations wrapper, parameter field changes to parameters
GeminiOpenAIClaude
useruseruser
modelassistantassistant
No independent rolesystemNo independent role
No independent roletoolNo independent role

Both Gemini and Claude elevate system instructions to top-level fields, not as message roles.

Terminal window
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
}
}'

Using Google GenAI Python SDK, only change client_options:

import os
import google.generativeai as genai
from google.api_core.client_options import ClientOptions
# Configure RouteAPI endpoint
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(
"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}")
Terminal window
# Convert image to base64
IMAGE_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
}
}'
import os
import google.generativeai as genai
from google.api_core.client_options import ClientOptions
from 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)
Terminal window
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" }
]
}
]
}'
import os
import google.generativeai as genai
from 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 os
import google.generativeai as genai
from 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 tool
get_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 question
response = chat.send_message("What's the weather in Beijing now?")
# Check for function call
if 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)
  • 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 0 or false are 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 fileUri with the gs:// protocol, ensure the file is accessible to upstream, or use inlineData for direct transmission.
  • Error response format may differ from OpenAI/Claude, see Error Handling.