API reference
Chat Completions
Headers, parameters, request and response examples and the streaming format for POST /v1/chat/completions. OpenAI-compatible, so GPT, Claude, Gemini, DeepSeek and more run on one code path. Verified on this site, streaming included.
POST /v1/chat/completions is the endpoint you will use most: send a list of messages, get the model's reply. The format matches OpenAI Chat Completions, and every model the catalog lists for this endpoint — GPT, Claude, Gemini, DeepSeek, Qwen and others — works with the same code. We have verified this endpoint on this site, streaming included.
https://open.tutujin.com/v1/chat/completionsHeaders
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer sk-..., an API key from the console |
Content-Type | Yes | application/json |
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Model name, e.g. gpt-5.4-mini |
messages | array | Yes | The conversation so far, oldest first — structure below |
stream | boolean | No | true streams the reply as server-sent events; default false |
stream_options | object | No | With streaming, {"include_usage": true} adds usage to the last chunk |
max_tokens | integer | No | Most tokens to generate. Some newer models use max_completion_tokens instead |
max_completion_tokens | integer | No | Generation limit, including reasoning tokens on reasoning models |
temperature | number | No | Sampling temperature, usually 0 to 2; higher is more varied. Reasoning models usually ignore or reject it |
top_p | number | No | Nucleus sampling; tune this or temperature, not both |
n | integer | No | Number of candidate replies; each one is billed for the tokens it generates |
stop | string or array | No | Stop generating when one of these strings appears |
presence_penalty | number | No | -2 to 2; positive values push the model toward new topics |
frequency_penalty | number | No | -2 to 2; positive values reduce repeated wording |
response_format | object | No | {"type": "json_object"} asks for JSON; some models support json_schema for strict structured output |
tools | array | No | Function definitions the model may call (function calling) |
tool_choice | string or object | No | auto, none, required, or a specific function |
reasoning_effort | string | No | Reasoning depth such as low, medium, high; only some models support it |
seed | integer | No | Best-effort determinism for identical inputs; not guaranteed |
user | string | No | Your end-user identifier, useful when investigating abuse |
Vendors support optional parameters to different degrees. A parameter a model does not support may be ignored or may return a 400, so try new models with a little traffic first.
The messages array
Each message is an object whose role is one of:
| role | Use |
|---|---|
system | System prompt: role, rules and output format; usually the first message |
user | User input |
assistant | The model's earlier replies, sent back as-is in multi-turn chats |
tool | The result of a function call, with the matching tool_call_id |
content is a string or an array. Use the array form for mixed text and images on models that support vision:
{
"role": "user",
"content": [
{ "type": "text", "text": "What is the total on this invoice?" },
{ "type": "image_url", "image_url": { "url": "https://example.com/invoice.png" } }
]
}You can also inline an image in url as data:image/png;base64,....
Request example
curl https://open.tutujin.com/v1/chat/completions \
-H "Authorization: Bearer $TUTUJIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4-mini",
"messages": [
{"role": "system", "content": "You are a store support agent. Keep answers short and polite."},
{"role": "user", "content": "How soon do orders ship?"}
],
"temperature": 0.3
}'import os
from openai import OpenAI
client = OpenAI(base_url="https://open.tutujin.com/v1", api_key=os.environ["TUTUJIN_API_KEY"])
resp = client.chat.completions.create(
model="gpt-5.4-mini",
messages=[
{"role": "system", "content": "You are a store support agent. Keep answers short and polite."},
{"role": "user", "content": "How soon do orders ship?"},
],
temperature=0.3,
)
print(resp.choices[0].message.content)
print(resp.usage)import OpenAI from 'openai'
const client = new OpenAI({ baseURL: 'https://open.tutujin.com/v1', apiKey: process.env.TUTUJIN_API_KEY })
const resp = await client.chat.completions.create({
model: 'gpt-5.4-mini',
messages: [
{ role: 'system', content: 'You are a store support agent. Keep answers short and polite.' },
{ role: 'user', content: 'How soon do orders ship?' },
],
temperature: 0.3,
})
console.log(resp.choices[0].message.content)
console.log(resp.usage)Response example
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1794000000,
"model": "gpt-5.4-mini",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "In-stock orders usually ship within 48 hours of payment."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 31,
"completion_tokens": 22,
"total_tokens": 53
}
}| Field | Description |
|---|---|
choices[].message.content | The model's answer |
choices[].message.tool_calls | Present when the model decides to call a function: function name and JSON arguments |
choices[].finish_reason | stop finished normally; length hit the generation limit; tool_calls wants you to run a function; content_filter was blocked by a safety policy |
usage.prompt_tokens | Input tokens, billed at the input price |
usage.completion_tokens | Output tokens (including reasoning on reasoning models), billed at the output price |
usage.prompt_tokens_details.cached_tokens | Input tokens served from the context cache, when the model supports caching; billed at the cache-read price |
Streaming
With "stream": true the server sends server-sent events. Each chunk is one data: {...} line with new text in choices[0].delta.content, and the stream ends with data: [DONE]:
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"In-stock"}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]With an SDK, iterate over the stream:
stream = client.chat.completions.create(
model="gpt-5.4-mini",
messages=[{"role": "user", "content": "Write a 60-word product description"}],
stream=True,
stream_options={"include_usage": True},
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.usage:
print("\n", chunk.usage)const stream = await client.chat.completions.create({
model: 'gpt-5.4-mini',
messages: [{ role: 'user', content: 'Write a 60-word product description' }],
stream: true,
stream_options: { include_usage: true },
})
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content
if (text) process.stdout.write(text)
if (chunk.usage) console.log('\n', chunk.usage)
}Turn streaming on for long outputs: users see text sooner, and a single long wait is less likely to be cut off by a gateway or client timeout.
Notes
- Model names must match the model hub exactly; they are case-sensitive.
- A key only uses the lines of its own group. If a model returns 503 saying no channel is available, that group usually does not offer the model — try a key in another group. See Choosing a group.
- Reasoning tokens count as output tokens, so reasoning models can cost noticeably more. Cap them with
max_completion_tokens. - The server keeps no conversation state. Send the history with every request; longer history means more input tokens, so trim it when you can.
- Tokens and cost for every request are listed under Usage in the console.
Models that support this endpoint
| Model | Vendor | Cheapest group | Input ¥/1M | Output ¥/1M | Per request ¥ |
|---|---|---|---|---|---|
| gpt-image-2 | OpenAI | Standard | — | — | ¥0.12 |
| Claude Haiku 5.5 | Anthropic | Claude Plus | ¥0.4 | ¥2 | — |
| qwen3.5-plus | Qwen | China Models | ¥1.12 | ¥6.72 | — |
| gemini-3.8-flash | Standard | ¥1.5 | ¥7.5 | — | |
| gpt-5.4-mini | OpenAI | Standard | ¥1.5 | ¥9 | — |
| deepseek-v4.1-flash | DeepSeek | China Models | ¥2.8 | ¥11.2 | — |
| Claude Sonnet 5.5 | Anthropic | Claude Lite | ¥3.2 | ¥16 | — |
| GPT-6.1 Sol | OpenAI | Standard | ¥4 | ¥20 | — |
| gemini-3.1-pro-preview | Standard | ¥4 | ¥24 | — | |
| Claude Opus 5.5 | Anthropic | Claude Lite | ¥8 | ¥40 | — |
Prices in CNY, cheapest group for each model; updated Nov 12, 2026, 8:17 PM.
681 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.