Skip to content

Anthropic Messages

Alongside the OpenAI format, LLMTR serves the Anthropic Messages format. The same API key, quota and pricing apply; only the request and response shapes differ.

This endpoint lets the Anthropic SDKs and any agent tool that speaks the Anthropic format connect to LLMTR directly. Every chat model in the catalog can be called through it.

POST /v1/messages
x-api-key: llmtr-your_key
anthropic-version: 2023-06-01
Content-Type: application/json
{
"model": "qwen/qwen3.8-max",
"max_tokens": 1024,
"system": "Answer briefly and technically.",
"messages": [
{ "role": "user", "content": "What is cursor-based pagination?" }
]
}

Either x-api-key or Authorization: Bearer can be used for authentication; both accept the same key.

max_tokens is required. The Anthropic format has no default for it, and a request without it returns 400.

{
"id": "msg_...",
"type": "message",
"role": "assistant",
"model": "qwen/qwen3.8-max",
"content": [
{ "type": "text", "text": "Cursor-based pagination..." }
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": { "input_tokens": 24, "output_tokens": 180 }
}

stop_reason values: end_turn, max_tokens, tool_use.

With stream: true the response arrives as server-sent events. The event order matches Anthropic:

message_start
content_block_start
content_block_delta (text_delta or input_json_delta)
content_block_stop
message_delta (stop_reason and usage)
message_stop

Token counts arrive in the usage field of the message_delta event.

Terminal window
curl -N https://llmtr.com/v1/messages \
-H "x-api-key: llmtr-your_key" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "qwen/qwen3.8-max",
"max_tokens": 512,
"stream": true,
"messages": [{ "role": "user", "content": "Hello" }]
}'

Anthropic-format tool definitions are supported:

{
"model": "qwen/qwen3.8-max",
"max_tokens": 1024,
"tools": [
{
"name": "get_weather",
"description": "Returns the weather for a city",
"input_schema": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
],
"messages": [{ "role": "user", "content": "What is the weather in Ankara?" }]
}

When the model calls a tool, the response carries stop_reason: "tool_use" and a tool_use block. Send the result back on the next turn as a tool_result block:

{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "call_1", "content": "22 degrees" }
]
}

tool_choice values: auto, any, tool (named), none. anthropic/claude-sonnet-5.5 accepts only auto and none; any and tool return 400.

On models that accept images, use an image block:

{
"role": "user",
"content": [
{ "type": "image", "source": { "type": "base64", "media_type": "image/png", "data": "iVBOR..." } },
{ "type": "text", "text": "What is in this image?" }
]
}

source.type can be base64 or url.

import anthropic
client = anthropic.Anthropic(
base_url="https://llmtr.com",
api_key="llmtr-your_key",
)
message = client.messages.create(
model="qwen/qwen3.8-max",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
)
print(message.content[0].text)

Claude Code can be pointed at a gateway with ANTHROPIC_BASE_URL:

Terminal window
export ANTHROPIC_BASE_URL=https://llmtr.com
export ANTHROPIC_AUTH_TOKEN=llmtr-your_key
export ANTHROPIC_MODEL=anthropic/claude-sonnet-5

PowerShell:

Terminal window
$env:ANTHROPIC_BASE_URL = "https://llmtr.com"
$env:ANTHROPIC_AUTH_TOKEN = "llmtr-your_key"
$env:ANTHROPIC_MODEL = "anthropic/claude-sonnet-5"

To verify the connection:

Terminal window
curl https://llmtr.com/v1/messages \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model":"anthropic/claude-sonnet-5","max_tokens":16,"messages":[{"role":"user","content":"test"}]}'

Models are listed at the /v1/models endpoint. To see LLMTR models in the Claude Code model picker, set CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1; the picker only lists model ids containing claude or anthropic. Any other model can be selected directly with ANTHROPIC_MODEL. Claude Code uses a separate small model for background tasks, set by ANTHROPIC_DEFAULT_HAIKU_MODEL. Give both variables the same id and every request in the session goes to that model.

When Claude Code sees a model id that is not in its own list, it assumes a 200K context window and prints a warning. Requests still work. To declare the model's real window:

Terminal window
export CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000

cache_control markers are forwarded to Anthropic on Claude models whose model page publishes cache read and write prices. A marker can go on system, text and image blocks, on tool definitions, on tool_result blocks, or at the top level of the request:

{ "type": "ephemeral", "ttl": "1h" }

ttl can be "5m" or "1h"; without it the 5-minute lifetime applies. On other models the marker is ignored and does not affect pricing.

The response's usage field reports tokens written to cache as cache_creation_input_tokens and tokens read from cache as cache_read_input_tokens. input_tokens is the remainder outside those two.

The following fields currently have no effect on this endpoint. The request is not rejected; the field is ignored:

  • context_management

In the thinking field, {"type": "disabled"} or {"type": "between_tools"} has the same effect as choosing none on Claude models whose effort list on the model page includes none; an effort sent in the same request is then not applied. On other models, and for other thinking values, the field is ignored.

Responses contain only text and tool_use blocks.

Errors use the Anthropic envelope:

{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "max_tokens is required"
}
}

error.type is derived from the HTTP status: 400 invalid_request_error, 401 authentication_error, 403 permission_error, 404 not_found_error, 413 request_too_large, 429 rate_limit_error, 5xx api_error.

For the error format used by the other endpoints, see Errors.