API Documentation

API Base URL

https://token.bitbeam.cn/v1

Compatible with OpenAI SDK. Just replace base_url and api_key to use.

Chat Completions

POSThttps://token.bitbeam.cn/v1/chat/completions

Request Parameters

ParameterTypeRequiredDescription
modelstringYesModel ID
messagesarrayYesMessage list
streambooleanNoStream output
temperaturenumberNoTemperature 0-2
max_tokensintegerNoMax 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/embeddings

Request Parameters

ParameterTypeRequiredDescription
modelstringYesEmbedding model ID
inputstring | arrayYesInput 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/models

List 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/messages

Compatible 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/responses

Compatible 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/generation

Look 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 StatusDescriptionHandling
200Success-
400Bad request (missing model/messages or other required fields)Check request body format
401Invalid, expired, or disabled API KeyCheck Authorization header
402Insufficient balance or wallet suspendedRecharge and retry
403No access to this model (model allowlist restriction)Contact admin to enable model access
429Rate limit exceeded / Token quota exhausted / Daily limit reachedReduce request frequency or contact admin to increase limit
500Internal server errorRetry later
502Upstream provider unavailableRetry later or switch model

Rate Limiting

API requests are protected by rate limiting. Limit info is returned via response headers:

Response HeaderDescription
X-RateLimit-LimitMax requests per minute
X-RateLimit-RemainingRemaining requests in current window
X-RateLimit-ResetLimit 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.