Use the Gemini native API format through CometAPI for text generation, multimodal input, thinking/reasoning, function calling, Google Search grounding, JSON mode, and streaming.
from google import genai
client = genai.Client(
api_key="<COMETAPI_KEY>",
http_options={"api_version": "v1beta", "base_url": "https://api.cometapi.com"},
)
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="Explain how AI works in a few words",
)
print(response.text){
"candidates": [
{
"content": {
"role": "<string>",
"parts": [
{
"text": "<string>",
"functionCall": {
"name": "<string>",
"args": {}
},
"inlineData": {
"mimeType": "<string>",
"data": "<string>"
},
"thought": true
}
]
},
"finishReason": "STOP",
"safetyRatings": [
{
"category": "<string>",
"probability": "<string>",
"blocked": true
}
],
"citationMetadata": {
"citationSources": [
{
"startIndex": 123,
"endIndex": 123,
"uri": "<string>",
"license": "<string>"
}
]
},
"tokenCount": 123,
"avgLogprobs": 123,
"groundingMetadata": {
"groundingChunks": [
{
"web": {
"uri": "<string>",
"title": "<string>"
}
}
],
"groundingSupports": [
{
"groundingChunkIndices": [
123
],
"confidenceScores": [
123
],
"segment": {
"startIndex": 123,
"endIndex": 123,
"text": "<string>"
}
}
],
"webSearchQueries": [
"<string>"
]
},
"index": 123
}
],
"promptFeedback": {
"blockReason": "SAFETY",
"safetyRatings": [
{
"category": "<string>",
"probability": "<string>",
"blocked": true
}
]
},
"usageMetadata": {
"promptTokenCount": 123,
"candidatesTokenCount": 123,
"totalTokenCount": 123,
"trafficType": "<string>",
"thoughtsTokenCount": 123,
"promptTokensDetails": [
{
"modality": "<string>",
"tokenCount": 123
}
],
"candidatesTokensDetails": [
{
"modality": "<string>",
"tokenCount": 123
}
]
},
"modelVersion": "<string>",
"createTime": "<string>",
"responseId": "<string>"
}| Setting | Google Default | CometAPI |
|---|---|---|
| Base URL | generativelanguage.googleapis.com | api.cometapi.com |
| API Key | $GEMINI_API_KEY | $COMETAPI_KEY |
x-goog-api-key and Authorization: Bearer headers are supported for authentication.thinkingLevel to control reasoning depth. Available levels: MINIMAL, LOW, MEDIUM, HIGH.curl "https://api.cometapi.com/v1beta/models/gemini-3.1-pro-preview:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $COMETAPI_KEY" \
-d '{
"contents": [{"parts": [{"text": "Explain quantum physics simply."}]}],
"generationConfig": {
"thinkingConfig": {"thinkingLevel": "LOW"}
}
}'
thinkingBudget for fine-grained token-level control:0 — disable thinking-1 — dynamic (model decides, default)> 0 — specific token budget (e.g., 1024, 2048)curl "https://api.cometapi.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $COMETAPI_KEY" \
-d '{
"contents": [{"parts": [{"text": "Solve this logic puzzle step by step."}]}],
"generationConfig": {
"thinkingConfig": {"thinkingBudget": 2048}
}
}'
thinkingLevel with Gemini 2.5 models (or thinkingBudget with Gemini 3 models) may cause errors. Use the correct parameter for your model version.streamGenerateContent?alt=sse as the operator to receive Server-Sent Events as the model generates content. Each SSE event contains a data: line with a JSON GenerateContentResponse object.
curl "https://api.cometapi.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $COMETAPI_KEY" \
--no-buffer \
-d '{
"contents": [{"parts": [{"text": "Write a short poem about the stars"}]}]
}'
systemInstruction:
curl "https://api.cometapi.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $COMETAPI_KEY" \
-d '{
"contents": [{"parts": [{"text": "What is 2+2?"}]}],
"systemInstruction": {
"parts": [{"text": "You are a math tutor. Always show your work."}]
}
}'
responseMimeType. Optionally provide a responseSchema for strict schema validation:
curl "https://api.cometapi.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $COMETAPI_KEY" \
-d '{
"contents": [{"parts": [{"text": "List 3 planets with their distances from the sun"}]}],
"generationConfig": {
"responseMimeType": "application/json"
}
}'
googleSearch tool:
curl "https://api.cometapi.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $COMETAPI_KEY" \
-d '{
"contents": [{"parts": [{"text": "Who won the euro 2024?"}]}],
"tools": [{"google_search": {}}]
}'
groundingMetadata with source URLs and confidence scores.
{
"candidates": [
{
"content": {
"role": "model",
"parts": [{"text": "Hello"}]
},
"finishReason": "STOP",
"avgLogprobs": -0.0023
}
],
"usageMetadata": {
"promptTokenCount": 5,
"candidatesTokenCount": 1,
"totalTokenCount": 30,
"trafficType": "ON_DEMAND",
"thoughtsTokenCount": 24,
"promptTokensDetails": [{"modality": "TEXT", "tokenCount": 5}],
"candidatesTokensDetails": [{"modality": "TEXT", "tokenCount": 1}]
},
"modelVersion": "gemini-2.5-flash",
"createTime": "2026-03-25T04:21:43.756483Z",
"responseId": "CeynaY3LDtvG4_UP0qaCuQY"
}
thoughtsTokenCount field in usageMetadata shows how many tokens the model spent on internal reasoning, even when thinking output is not included in the response.| Feature | Gemini Native (/v1beta/models/...) | OpenAI-Compatible (/v1/chat/completions) |
|---|---|---|
| Thinking control | thinkingConfig with thinkingLevel / thinkingBudget | Not available |
| Google Search grounding | tools: [\{"google_search": \{\}\}] | Not available |
| Google Maps grounding | tools: [\{"googleMaps": \{\}\}] | Not available |
| Image generation modality | responseModalities: ["IMAGE"] | Not available |
| Auth header | x-goog-api-key or Bearer | Bearer only |
| Response format | Gemini native (candidates, parts) | OpenAI format (choices, message) |
Your CometAPI key passed via the x-goog-api-key header. Bearer token authentication (Authorization: Bearer <key>) is also supported.
The Gemini model ID to use. See the Models page for current Gemini model IDs.
"gemini-2.5-flash"
The operation to perform. Use generateContent for synchronous responses, or streamGenerateContent?alt=sse for Server-Sent Events streaming.
generateContent, streamGenerateContent?alt=sse "generateContent"
The conversation history and current input. For single-turn queries, provide a single item. For multi-turn conversations, include all previous turns.
Show child attributes
System instructions that guide the model's behavior across the entire conversation. Text only.
Show child attributes
Tools the model may use to generate responses. Supports function declarations, Google Search, Google Maps, and code execution.
Show child attributes
Configuration for tool usage, such as function calling mode.
Show child attributes
Safety filter settings. Override default thresholds for specific harm categories.
Show child attributes
Configuration for model generation behavior including temperature, output length, and response format.
Show child attributes
The name of cached content to use as context. Format: cachedContents/{id}. See the Gemini context caching documentation for details.
Successful response. For streaming requests, the response is a stream of SSE events, each containing a GenerateContentResponse JSON object prefixed with data:.
The generated response candidates.
Show child attributes
Feedback on the prompt, including safety blocking information.
Show child attributes
Token usage statistics for the request.
Show child attributes
The model version that generated this response.
The timestamp when this response was created (ISO 8601 format).
Unique identifier for this response.
from google import genai
client = genai.Client(
api_key="<COMETAPI_KEY>",
http_options={"api_version": "v1beta", "base_url": "https://api.cometapi.com"},
)
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="Explain how AI works in a few words",
)
print(response.text){
"candidates": [
{
"content": {
"role": "<string>",
"parts": [
{
"text": "<string>",
"functionCall": {
"name": "<string>",
"args": {}
},
"inlineData": {
"mimeType": "<string>",
"data": "<string>"
},
"thought": true
}
]
},
"finishReason": "STOP",
"safetyRatings": [
{
"category": "<string>",
"probability": "<string>",
"blocked": true
}
],
"citationMetadata": {
"citationSources": [
{
"startIndex": 123,
"endIndex": 123,
"uri": "<string>",
"license": "<string>"
}
]
},
"tokenCount": 123,
"avgLogprobs": 123,
"groundingMetadata": {
"groundingChunks": [
{
"web": {
"uri": "<string>",
"title": "<string>"
}
}
],
"groundingSupports": [
{
"groundingChunkIndices": [
123
],
"confidenceScores": [
123
],
"segment": {
"startIndex": 123,
"endIndex": 123,
"text": "<string>"
}
}
],
"webSearchQueries": [
"<string>"
]
},
"index": 123
}
],
"promptFeedback": {
"blockReason": "SAFETY",
"safetyRatings": [
{
"category": "<string>",
"probability": "<string>",
"blocked": true
}
]
},
"usageMetadata": {
"promptTokenCount": 123,
"candidatesTokenCount": 123,
"totalTokenCount": 123,
"trafficType": "<string>",
"thoughtsTokenCount": 123,
"promptTokensDetails": [
{
"modality": "<string>",
"tokenCount": 123
}
],
"candidatesTokensDetails": [
{
"modality": "<string>",
"tokenCount": 123
}
]
},
"modelVersion": "<string>",
"createTime": "<string>",
"responseId": "<string>"
}