API Documentation
API Base URL
https://token.bitbeam.cn/v1Compatible with OpenAI SDK. Just replace base_url and api_key to use.
Chat Completions
POSThttps://token.bitbeam.cn/v1/chat/completionsRequest Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | Yes | Model ID |
| messages | array | Yes | Message list |
| stream | boolean | No | Stream output |
| temperature | number | No | Temperature 0-2 |
| max_tokens | integer | No | Max output tokens |
Response Format
{
"id": "chatcmpl-xxx",
"object": "chat.completion",
"model": "claude-haiku-4-5",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello!"
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 10,
"completion_tokens": 5,
"total_tokens": 15
}
}from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://token.bitbeam.cn/v1"
)
# Non-streaming
response = client.chat.completions.create(
model="claude-haiku-4-5",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
],
max_tokens=1000
)
print(response.choices[0].message.content)
# Streaming
stream = client.chat.completions.create(
model="claude-haiku-4-5",
messages=[{"role": "user", "content": "Hello!"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")Embeddings
POSThttps://token.bitbeam.cn/v1/embeddingsRequest Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | Yes | Embedding model ID |
| input | string | array | Yes | Input text |
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://token.bitbeam.cn/v1"
)
response = client.embeddings.create(
model="qwen3.7-text-embedding",
input="Hello world"
)
print(f"Dimensions: {len(response.data[0].embedding)}")
print(f"Vector: {response.data[0].embedding[:5]}...")Model List
GEThttps://token.bitbeam.cn/v1/modelsList all available models. Returns OpenAI-compatible format.
curl https://token.bitbeam.cn/v1/models \
-H "Authorization: Bearer YOUR_API_KEY"Anthropic Messages API
POSThttps://token.bitbeam.cn/v1/messagesCompatible with the official Anthropic Messages format — works with Claude Code and the Anthropic SDK. Note: these tools append /v1/messages themselves, so set base_url to the domain only.
# Claude Code / Anthropic SDK
export ANTHROPIC_BASE_URL="https://token.bitbeam.cn"
export ANTHROPIC_AUTH_TOKEN="YOUR_API_KEY"
# 直接调用
curl https://token.bitbeam.cn/v1/messages \
-H "x-api-key: YOUR_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-4-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello!"}]
}'OpenAI Responses API
POSThttps://token.bitbeam.cn/v1/responsesCompatible with the OpenAI Responses format, used by Codex CLI and the Codex IDE extension.
curl https://token.bitbeam.cn/v1/responses \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-4-5",
"input": "Hello!",
"max_output_tokens": 1024
}'Generation Cost Lookup
GEThttps://token.bitbeam.cn/v1/generationLook up the actual cost of a call by the id returned in the response (gen-xxx). Useful for cost tracking, e.g. the Claude Code statusline.
# 响应体里的 id 形如 gen-xxxxxxxx
curl "https://token.bitbeam.cn/v1/generation?id=gen-xxxxxxxx" \
-H "Authorization: Bearer YOUR_API_KEY"Error Response Format
Errors follow the official OpenAI structure, so SDK exception objects expose message / type / code directly. The Anthropic endpoint returns the official Anthropic structure.
# OpenAI 兼容端点(/chat/completions、/responses、/embeddings、/models)
{
"error": {
"message": "Model not found: xxx",
"type": "not_found_error",
"param": null,
"code": "BILLING_MODEL_NOT_FOUND"
}
}
# Anthropic 端点(/messages)
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "Model not found: xxx"
}
}Error Codes
| HTTP Status | Description | Handling |
|---|---|---|
| 200 | Success | - |
| 400 | Bad request (missing model/messages or other required fields) | Check request body format |
| 401 | Invalid, expired, or disabled API Key | Check Authorization header |
| 402 | Insufficient balance or wallet suspended | Recharge and retry |
| 403 | No access to this model (model allowlist restriction) | Contact admin to enable model access |
| 429 | Rate limit exceeded / Token quota exhausted / Daily limit reached | Reduce request frequency or contact admin to increase limit |
| 500 | Internal server error | Retry later |
| 502 | Upstream provider unavailable | Retry later or switch model |
Rate Limiting
API requests are protected by rate limiting. Limit info is returned via response headers:
| Response Header | Description |
|---|---|
| X-RateLimit-Limit | Max requests per minute |
| X-RateLimit-Remaining | Remaining requests in current window |
| X-RateLimit-Reset | Limit reset time (ISO 8601) |
When exceeded, returns 429 status code and Retry-After: 60 response header.
Frequently Asked Questions
What should I do if I get a 401 error?
A 401 means your API Key is invalid, expired, or disabled. Check: 1) Authorization header format is "Bearer YOUR_API_KEY"; 2) The key is active in your dashboard; 3) The key hasn't expired.
How do I handle a 402 (insufficient balance) error?
A 402 means your wallet balance is insufficient or suspended. Log in to the dashboard to top up your wallet, or contact your agent/admin for a recharge. Service resumes immediately after top-up.
How do I handle 429 rate limit errors?
A 429 means you've exceeded the rate limit. Solutions: 1) Add exponential backoff retry logic; 2) Check the X-RateLimit-Remaining response header to throttle requests; 3) Contact admin to increase your limits.
What's the difference between streaming and non-streaming? Which should I use?
Non-streaming (default) waits for the complete response before returning — good for batch processing. Streaming (stream: true) returns tokens as they're generated — ideal for chat UIs where users see real-time output. Both cost the same.
Can I use multiple models at the same time?
Yes. The same API Key can specify different model parameters in different requests. Switch freely between models without creating separate keys for each.