API Reference
This gateway exposes Gemini-style REST routes and an optional OpenAI-compatible Chat Completions route. Requests use JSON bodies, JSON responses, standard HTTP methods, and API-key authentication.
The upstream is the cookie-authenticated Gemini Web application. The Gemini REST surface is a compatibility layer, not Google AI Studio or the official Gemini Developer API.
Authentication
The API uses API keys to authenticate requests. You can view and manage your API keys in the Admin Dashboard. Your API keys carry many privileges, so be sure to keep them secure!
Bearer Token
All API requests should include your API key in an Authorization HTTP header as follows:
Authorization: Bearer YOUR_API_KEY
Gemini-compatible authentication
Gemini REST clients may use any one of these forms:
x-goog-api-key: YOUR_API_KEY
Authorization: Bearer YOUR_API_KEY
GET /v1beta/models?key=YOUR_API_KEY
Supported Models
Select one of the current Gemini models below and pass its exact ID in the model parameter.
gemini-3.5-flash-lite
The fastest model for short answers and lightweight tasks.
gemini-3.6-flash
The balanced Gemini model for comprehensive everyday assistance.
gemini-3.1-pro
Advanced mathematics, programming, and complex reasoning.
Gemini REST API
These paths match Gemini REST naming. Both v1beta and v1 variants are available.
GET /v1beta/models
GET /v1beta/models/{model}
POST /v1beta/models/{model}:generateContent
POST /v1beta/models/{model}:streamGenerateContent
POST /v1beta/models/{model}:countTokens
GET /models accepts pageSize and pageToken, and returns nextPageToken when another page is available.
Generate Content
/v1beta/models/{model}:generateContent
Send Gemini contents, parts, and optional systemInstruction.
curl "https://aggeee.io.vn/v1beta/models/gemini-3.6-flash:generateContent" \
-H "x-goog-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"systemInstruction": {"parts": [{"text": "Answer concisely."}]},
"contents": [{"role": "user", "parts": [{"text": "Hello!"}]}]
}'
Response
{
"candidates": [{
"content": {"role": "model", "parts": [{"text": "Hello!"}]},
"finishReason": "STOP",
"index": 0
}],
"usageMetadata": {
"promptTokenCount": 4,
"candidatesTokenCount": 2,
"totalTokenCount": 6
},
"modelVersion": "gemini-3.6-flash",
"responseId": "gateway-generated-response-id"
}
Function Calling
Declare functions using functionDeclarations. The gateway validates the selected name and arguments. Your application executes the function; the gateway never executes arbitrary terminal commands.
{
"contents": [{"role": "user", "parts": [{"text": "Weather in Hue?"}]}],
"tools": [{"functionDeclarations": [{
"name": "get_weather",
"description": "Get current weather for a city",
"parametersJsonSchema": {
"type": "OBJECT",
"properties": {"city": {"type": "STRING"}},
"required": ["city"]
}
}]}],
"toolConfig": {"functionCallingConfig": {"mode": "AUTO"}}
}
A requested function is returned as a Gemini part:
{
"candidates": [{"content": {"role": "model", "parts": [{
"functionCall": {"name": "get_weather", "args": {"city": "Hue"}}
}]}}]
}
Execute the approved function and send its result in the next request:
{
"contents": [
{"role": "user", "parts": [{"text": "Weather in Hue?"}]},
{"role": "model", "parts": [{"functionCall": {
"name": "get_weather", "args": {"city": "Hue"}
}}]},
{"role": "function", "parts": [{"functionResponse": {
"name": "get_weather",
"response": {"temperature": 31, "condition": "Sunny"}
}}]}
]
}
AUTO: the model may answer normally or request a function.
VALIDATED: same choice behavior as AUTO, with gateway validation of any returned call.
ANY: at least one valid function call is required.
NONE: function calls are disabled.
allowedFunctionNames restricts selection to a declared subset.
parameters and parametersJsonSchema are both accepted but are mutually exclusive. Function selection is prompt-based emulation because Gemini Web does not expose Google's native Function Calling protocol.
Images and Files
Use Gemini-style inlineData. Each inline part is base64 encoded and limited to 20 MiB by this gateway.
import base64
import requests
with open("image.jpg", "rb") as image_file:
encoded = base64.b64encode(image_file.read()).decode("ascii")
response = requests.post(
"https://aggeee.io.vn/v1beta/models/gemini-3.6-flash:generateContent",
headers={"x-goog-api-key": "YOUR_API_KEY"},
json={"contents": [{"parts": [
{"text": "Describe this image."},
{"inlineData": {"mimeType": "image/jpeg", "data": encoded}}
]}]},
timeout=500,
)
response.raise_for_status()
Persistent fileData.fileUri and resumable Files API uploads are unavailable. Use inlineData.
Streaming and Token Counting
POST /v1beta/models/gemini-3.6-flash:streamGenerateContent?alt=sse
POST /v1beta/models/gemini-3.6-flash:countTokens
The streaming route uses Server-Sent Events. The Gemini Web response is collected first, so this compatibility route currently emits one final event instead of token-level deltas.
With ?alt=sse, the response is text/event-stream. Without it, the endpoint returns the final streamed JSON object with application/json.
countTokens and usageMetadata are estimates, not output from Google's tokenizer.
Supported compatibility generation options are candidateCount: 1, stopSequences, responseMimeType: "application/json", responseSchema, and responseJsonSchema. Parameters that cannot be honored by Gemini Web—such as temperature, topP, topK, seed, and maxOutputTokens—return INVALID_ARGUMENT instead of being silently ignored.
Chat Completions
/v1/chat/completions
Creates a model response for the given chat conversation.
Request Body
ID of the model to use (e.g., gemini-3.1-pro).
A list of messages comprising the conversation so far. Each object must have a role (system, user, assistant) and content.
stream: true is rejected on this route. Use Gemini's :streamGenerateContent endpoint for SSE.
Example Request
import requests
response = requests.post(
"https://aggeee.io.vn/v1/chat/completions",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"model": "gemini-3.1-pro",
"messages": [{"role": "user", "content": "Hello!"}],
},
timeout=500,
)
response.raise_for_status()
print(response.json()["choices"][0]["message"]["content"])
Response Format
{
"id": "chatcmpl_a1b2c3d4",
"object": "chat.completion",
"created": 1718291039,
"model": "gemini-3.1-pro",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hi there! How can I help you today?"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}
Conversation API
Use conversations when you want Gemini to continue the same underlying chat instead of creating a fresh Gemini chat for every request.
/v1/chats
Create an empty conversation and receive a conversation_id.
/v1/chats
List conversations owned by the current API key.
/v1/chats/{conversation_id}
Inspect a conversation and its stored Gemini metadata.
/v1/chats/{conversation_id}
Delete gateway metadata for a conversation.
Recommended Flow
# First request: no conversation_id, gateway creates a new Gemini chat.
curl https://aggeee.io.vn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"model": "gemini-3.1-pro",
"messages": [
{"role": "user", "content": "My name is Hung."}
]
}'
# Use conversation_id from the first response to continue the same Gemini chat.
curl https://aggeee.io.vn/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"model": "gemini-3.1-pro",
"conversation_id": "conv_xxx",
"messages": [
{"role": "user", "content": "What is my name?"}
]
}'
Conversation Response Fields
{
"id": "chatcmpl_a1b2c3d4",
"object": "chat.completion",
"model": "gemini-3.1-pro",
"conversation_id": "conv_xxx",
"gemini_metadata": ["gemini_chat_id", "reply_id", "candidate_id"],
"choices": [
{
"message": {
"role": "assistant",
"content": "Your name is Hung."
}
}
]
}
Compatibility Matrix
| Capability | Status | Notes |
|---|---|---|
| Text generation | Supported | Gemini Web output in a Gemini REST envelope. |
| Inline images, PDF, audio, video | Supported | Temporarily uploaded from inlineData. |
| Function calling | Emulated | Allowlist and JSON Schema validated. |
| Streaming | Final event only | SSE without upstream token deltas. |
| Token counts | Estimated | Approximately one token per four characters. |
| Safety settings, cached content, service tiers | Unavailable | Rejected explicitly instead of being silently ignored. |
| Built-in tools (code execution, Google Search, URL context) | Unavailable through this contract | Only custom function declarations use the validated compatibility layer. |
| Persistent Files API, embeddings, caches, tuning | Unavailable | Not exposed by Gemini Web. |
Error Codes
Our API uses conventional HTTP response codes to indicate the success or failure of an API request. Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, or you ran out of credits).
| HTTP Code | Description | Meaning / Resolution |
|---|---|---|
| 400 | Bad Request | The request was unacceptable, often due to missing a required parameter (like empty messages). |
| 401 / 403 | Unauthorized | No valid API key provided, or your API key is deactivated. Check your Authorization header. |
| 500 | Server Error | Something went wrong on our end (e.g. all backend Gemini accounts are overloaded). The system will Auto-Retry before throwing this error. |
| 503 | Service Unavailable | No active Gemini accounts are currently available in the system pool. |
Example Error Response
{
"detail": "Unauthorized"
}
Gemini REST error response
{
"error": {
"code": 400,
"message": "contents must be a non-empty array",
"status": "INVALID_ARGUMENT"
}
}