API reference
Gemini generateContent API
Headers, path, parameters, request and response examples for Gemini's native generateContent endpoint. Same format as the Google Gemini API; the Google Gen AI SDK works after changing the base URL. Verified on this site.
The native Gemini endpoint uses the Google Gemini API format: the model name goes in the URL path, the conversation is built from contents and parts, and generation settings go in generationConfig. Code written with the Google Gen AI SDK works once you set the base URL to https://open.tutujin.com. We have verified this endpoint (generateContent) on this site.
https://open.tutujin.com/v1beta/models/gemini-3.8-flash:generateContentThe path pattern is /v1beta/models/MODEL:generateContent. Replace MODEL with the model you want; the request body does not need a model field.
Headers
| Header | Required | Description |
|---|---|---|
x-goog-api-key | One of the two | An API key from the console (sk-...). The Google Gen AI SDK uses this header by default |
Authorization | One of the two | Bearer sk-..., as an alternative to x-goog-api-key |
Content-Type | Yes | application/json |
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
contents | array | Yes | The conversation, oldest first. Each item has a role (user or model) and parts |
contents[].parts | array | Yes | Content parts. Text is {"text": "..."}; images, PDFs and other files use inlineData with a mimeType and base64 data |
systemInstruction | object | No | System prompt, shaped like a content item, e.g. {"parts": [{"text": "..."}]} |
generationConfig | object | No | Generation settings — see the next table |
safetySettings | array | No | Safety filter thresholds by category |
tools | array | No | Tools, e.g. functionDeclarations |
toolConfig | object | No | Function-calling mode, e.g. only allow specific functions |
generationConfig
| Field | Type | Description |
|---|---|---|
temperature | number | Sampling temperature; higher is more varied |
topP | number | Nucleus sampling |
topK | integer | Sample only from the K most likely tokens |
maxOutputTokens | integer | Most tokens to generate |
stopSequences | array | Stop generating when one of these strings appears |
responseMimeType | string | application/json asks for JSON output |
responseSchema | object | Schema to use with JSON output |
thinkingConfig | object | Thinking settings, e.g. {"thinkingBudget": 1024}; supported fields vary by model |
candidateCount | integer | Number of candidate answers |
Request example
curl "https://open.tutujin.com/v1beta/models/gemini-3.8-flash:generateContent" \
-H "x-goog-api-key: $TUTUJIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"systemInstruction": {"parts": [{"text": "You are an e-commerce copy assistant. Keep it short."}]},
"contents": [
{"role": "user", "parts": [{"text": "Write 3 selling points for a 500 ml insulated bottle"}]}
],
"generationConfig": {"temperature": 0.7, "maxOutputTokens": 512}
}'import os
from google import genai
from google.genai import types
client = genai.Client(
api_key=os.environ["TUTUJIN_API_KEY"],
http_options=types.HttpOptions(base_url="https://open.tutujin.com"),
)
resp = client.models.generate_content(
model="gemini-3.8-flash",
contents="Write 3 selling points for a 500 ml insulated bottle",
config=types.GenerateContentConfig(
system_instruction="You are an e-commerce copy assistant. Keep it short.",
temperature=0.7,
max_output_tokens=512,
),
)
print(resp.text)
print(resp.usage_metadata)import { GoogleGenAI } from '@google/genai'
const ai = new GoogleGenAI({
apiKey: process.env.TUTUJIN_API_KEY,
httpOptions: { baseUrl: 'https://open.tutujin.com' },
})
const resp = await ai.models.generateContent({
model: 'gemini-3.8-flash',
contents: 'Write 3 selling points for a 500 ml insulated bottle',
config: {
systemInstruction: 'You are an e-commerce copy assistant. Keep it short.',
temperature: 0.7,
maxOutputTokens: 512,
},
})
console.log(resp.text)
console.log(resp.usageMetadata)The SDKs append /v1beta/models/... to the base URL, so the base URL is just the site root.
Response example
{
"candidates": [
{
"content": {
"role": "model",
"parts": [{ "text": "1. Double-wall vacuum keeps drinks hot for hours..." }]
},
"finishReason": "STOP",
"index": 0
}
],
"usageMetadata": {
"promptTokenCount": 28,
"candidatesTokenCount": 96,
"totalTokenCount": 124
},
"modelVersion": "gemini-3.8-flash"
}| Field | Description |
|---|---|
candidates[].content.parts[].text | The model's answer, possibly split across several parts |
candidates[].finishReason | STOP finished normally; MAX_TOKENS hit the limit; SAFETY blocked by the safety filter |
usageMetadata.promptTokenCount | Input tokens, billed at the input price |
usageMetadata.candidatesTokenCount | Output tokens, billed at the output price |
usageMetadata.thoughtsTokenCount | Thinking tokens, on models with thinking enabled; counted as output |
usageMetadata.cachedContentTokenCount | Input tokens served from cache; when present, billed at the cache-read price |
Streaming
Gemini's streaming path is /v1beta/models/MODEL:streamGenerateContent?alt=sse; in the SDKs it is generate_content_stream (Python) and generateContentStream (Node.js).
Streaming requests are relayed as-is, but native-format Gemini streaming has not been verified separately on this site, so test it with a little traffic before going live. You can also call Gemini models that the catalog lists for Chat Completions in that format and use "stream": true.
Notes
- The model name goes in the URL path and must match the model hub exactly, including case.
- The model's side of the conversation uses
rolemodel, notassistant. - Images, PDFs and other files go in the body as base64
inlineData; bigger files mean bigger requests, so keep sizes in check. - On models with thinking, thinking tokens count as output; set a budget with
thinkingConfig. - Gemini groups differ in line and price — see Choosing a group. The same Gemini model can usually be called through Chat Completions too, which keeps one code path across vendors.
Models that support this endpoint
| Model | Vendor | Cheapest group | Input ¥/1M | Output ¥/1M | Per request ¥ |
|---|---|---|---|---|---|
| gemini-3.8-flash | Standard | ¥1.5 | ¥7.5 | — | |
| gemini-3.1-pro-preview | Standard | ¥4 | ¥24 | — | |
| gemini-2.5-flash-image | Gemini Plus | — | — | ¥0.16 | |
| Nano-banana | Gemini Plus | — | — | ¥0.16 | |
| gemini-nano-banana-2.1 | Standard | — | — | ¥0.2 | |
| gemini-nano-banana-2.1-2k | Standard | — | — | ¥0.2 | |
| gemini-nano-banana-2.1-4k | Standard | — | — | ¥0.2 | |
| gemini-3.1-flash-lite-image | Gemini Plus | — | — | ¥0.2 |
Prices in CNY, cheapest group for each model; updated Nov 12, 2026, 8:17 PM.
63 models support this endpoint; the table shows some of them. See them all in the model hub
Still stuck? Add our WeChat support JsnonoChat and send the request id from the error message, and we will look into it.