Anthropic API
Upthos Relay exposes a drop-in compatible Anthropic Messages API. Any Anthropic client that lets you set a custom base URL (official SDKs, Claude Code, third-party apps) works directly against this endpoint.
Basics
| Field | Value |
|---|---|
| Base URL | https://relay.upthos.com |
| Protocol | Anthropic Messages API |
anthropic-version |
2023-06-01 (stable) |
| Content type | application/json for request/response; text/event-stream for streaming |
Authentication
Pass your API key via one of the following headers (in priority order):
Authorization: Bearer sk-...
x-api-key: sk-...
x-goog-api-key: sk-...
Create keys at Console → API Keys. The key must belong to an Anthropic-protocol group to call the endpoints below.
Security: treat API keys like passwords. Never commit them or share them publicly.
Endpoints
POST /v1/messages
Send a chat request. Request body, response body, and SSE event stream match the upstream Anthropic spec exactly.
Required: model, max_tokens, messages
Common optional: system, temperature, top_p, stop_sequences, tools, tool_choice, stream, thinking
Non-streaming:
curl https://relay.upthos.com/v1/messages \
-H "Authorization: Bearer $UPTHOS_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [
{ "role": "user", "content": "Hello" }
]
}'
Streaming (SSE):
curl -N https://relay.upthos.com/v1/messages \
-H "Authorization: Bearer $UPTHOS_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"stream": true,
"messages": [{ "role": "user", "content": "Introduce yourself in one sentence" }]
}'
Official SDKs:
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic({
baseURL: 'https://relay.upthos.com',
apiKey: process.env.UPTHOS_API_KEY,
})
const msg = await client.messages.create({
model: 'claude-sonnet-4-5',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello' }],
})
from anthropic import Anthropic
client = Anthropic(
base_url="https://relay.upthos.com",
api_key=os.environ["UPTHOS_API_KEY"],
)
msg = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
)
POST /v1/messages/count_tokens
Estimate input token count. Same request body shape as /v1/messages. Does not invoke the model and is not billed.
GET /v1/models
Lists models available to the current key's group:
{
"object": "list",
"data": [
{ "id": "claude-sonnet-4-5", "type": "model", "display_name": "claude-sonnet-4-5", "created_at": "2024-01-01T00:00:00Z" }
]
}
GET /v1/usage
Returns balance and aggregate usage for the current key. Primarily used by clients like CC Switch to show remaining quota.
Error format
Errors follow the upstream Anthropic shape:
{
"type": "error",
"error": {
"type": "authentication_error",
"message": "API key is required in Authorization header (Bearer scheme), x-api-key header, or x-goog-api-key header"
}
}
Common error.type values:
| type | HTTP | Meaning |
|---|---|---|
authentication_error |
401 | Missing or invalid API key |
permission_error |
403 | Key has no group assigned, or insufficient permission |
not_found_error |
404 | Path or resource does not exist |
rate_limit_error |
429 | Rate / concurrency limit exceeded |
overloaded_error |
503 | Upstream overloaded or no account available |
api_error |
5xx | Gateway or upstream internal error |
Limits & differences
- Request body size is bounded by the gateway's
Gateway.MaxBodySizesetting — relevant for image and long-context payloads. - Rate and concurrency limits are stacked between the group and the key. Excess requests return
rate_limit_error. modelIDs follow the group's model_mapping and may differ from upstream names. TrustGET /v1/modelsas the source of truth.- When the key's balance is exhausted,
/v1/messagesreturnspermission_error. Top up in advance or handle the error in your client.