Integration guides
Using the Anthropic SDK
In the official Anthropic Python and TypeScript SDKs, set base_url to https://open.tutujin.com and use your Tutujin key to call the native Claude Messages API, streaming included. This endpoint is verified on this site.
The official Anthropic SDKs need two changes: set base_url to the site root https://open.tutujin.com (the SDK appends /v1/messages itself) and use your Tutujin key as api_key. Requests and responses stay in Anthropic's native format, so an existing Anthropic integration barely changes. The native Claude Messages endpoint is verified on this site.
Install
pip install anthropicnpm install @anthropic-ai/sdkCreate a client
import os
import anthropic
client = anthropic.Anthropic(
base_url="https://open.tutujin.com",
api_key=os.environ["TUTUJIN_API_KEY"],
)import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic({
baseURL: 'https://open.tutujin.com',
apiKey: process.env.TUTUJIN_API_KEY,
})Environment variables work too — the SDKs read ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY by default:
export ANTHROPIC_BASE_URL="https://open.tutujin.com"
export ANTHROPIC_API_KEY="sk-your-key"Leave /v1 off the base URL. The SDK requests the base URL plus /v1/messages; with https://open.tutujin.com/v1 you would get /v1/v1/messages and a 404.
Send a message
max_tokens is required by the Messages API. The system prompt goes in its own system parameter, not in messages:
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
system="You are a careful contract review assistant.",
messages=[
{"role": "user", "content": "List the 5 most common risky clauses in a purchase contract."},
],
)
print(message.content[0].text)
print(message.usage) # input_tokens / output_tokensconst message = await client.messages.create({
model: 'claude-sonnet-5-5',
max_tokens: 1024,
system: 'You are a careful contract review assistant.',
messages: [{ role: 'user', content: 'List the 5 most common risky clauses in a purchase contract.' }],
})
console.log(message.content[0].type === 'text' ? message.content[0].text : message.content[0])
console.log(message.usage) // input_tokens / output_tokensStreaming
with client.messages.stream(
model="claude-sonnet-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Write a 150-word company profile"}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
final = stream.get_final_message()
print("\n", final.usage)const stream = client.messages.stream({
model: 'claude-sonnet-5-5',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Write a 150-word company profile' }],
})
stream.on('text', (text) => process.stdout.write(text))
const final = await stream.finalMessage()
console.log('\n', final.usage)Plain cURL
Without an SDK, send an Anthropic-format request; authenticate with either x-api-key or Authorization: Bearer:
curl https://open.tutujin.com/v1/messages \
-H "x-api-key: $TUTUJIN_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello"}]
}'Parameters are covered in Claude Messages.
Models and prices
Set model to a Claude model name from the model hub. The same Claude model costs different amounts and runs on different lines in different groups, for example:
| Group | Input ¥/1M | Output ¥/1M | Cache read ¥/1M |
|---|---|---|---|
| Standard | ¥4 | ¥20 | ¥0.4 |
| Official · Enterprise | ¥21.9 | ¥109.5 | ¥2.19 |
| Claude Direct | ¥15 | ¥75 | ¥1.5 |
| Claude List Price | ¥24 | ¥120 | ¥2.4 |
| Claude Plus | ¥8 | ¥40 | ¥0.8 |
| Claude LiteLowest | ¥3.2 | ¥16 | ¥0.32 |
Claude Sonnet 5.5 · Prices in CNY, cheapest group for each model; updated Nov 12, 2026, 8:17 PM.
The API key decides the group — see Choosing a group. client.models.list() with that key lists the models it can use, in Anthropic's format.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| 404 | The base URL includes /v1; it should be https://open.tutujin.com |
| 401 | Wrong or invalid key. Errors from checks that run before relaying, such as authentication, come back in OpenAI's format, but the SDK still raises the matching exception from the status code |
| 400 about max_tokens | The Messages API requires max_tokens |
503 with model_not_found | The key's group lacks this model; switch groups or check the name |
To call Claude the OpenAI way, use the OpenAI SDK with Chat Completions; both approaches use the same key.
Still stuck? Add our WeChat support JsnonoChat and send the request id from the error message, and we will look into it.