Anthropic Messages API
/ API docs← API quickstartView as Markdown
POST https://api.opencheese.dev/v1/messages is the Anthropic Messages API, the one Claude
Code, Claude Desktop and the Anthropic SDKs speak. Its base URL is
https://api.opencheese.dev, without /v1: the SDKs append /v1/messages themselves.
A first request
curl https://api.opencheese.dev/v1/messages \
-H "x-api-key: $OPENCHEESE_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model": "MODEL_ID", "max_tokens": 1024, "system": "Answer in one sentence.", "messages": [{"role": "user", "content": "What is a gateway?"}]}'
Authorization: Bearer works as well as x-api-key. The answer has the Anthropic shape:
{
"id": "msg_01AbCdEf",
"type": "message",
"role": "assistant",
"model": "MODEL_ID",
"content": [{ "type": "text", "text": "A gateway passes your requests on to the models behind it." }],
"stop_reason": "end_turn",
"usage": { "input_tokens": 24, "output_tokens": 13, "cache_read_input_tokens": 0, "cache_creation_input_tokens": 0 }
}
Parameters
| Field | Notes |
|---|---|
model |
Required. An id from /v1/models; dated Claude IDs such as ...-20251001 resolve to the undated model. |
messages |
Required. user and assistant turns with text, image, tool_use and tool_result blocks. |
system |
A string or text blocks. |
stream |
true for server-sent events. |
tools, tool_choice |
Tool use, where the model supports tools. |
output_config.effort |
A level from the model's supported_reasoning_levels. |
max_tokens, temperature, top_p, thinking |
Optional. If you don't set them, the model's defaults are used. |
Reasoning effort
Choose how hard the model thinks with Anthropic's output_config.effort (or reasoning_effort,
which is read too). If you don't set one, the model's default is used.
curl https://api.opencheese.dev/v1/messages \
-H "x-api-key: $OPENCHEESE_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model": "MODEL_ID", "max_tokens": 4096, "output_config": {"effort": "high"}, "messages": [{"role": "user", "content": "Plan a three-day trip to Lyon."}]}'
A level the model doesn't offer is refused with unsupported_reasoning_effort, and the error's
supported_reasoning_levels lists the levels it does offer. Thinking, where the model returns
it, arrives as thinking content blocks.
Streaming
With "stream": true the answer arrives as the Anthropic events: message_start,
content_block_start, content_block_delta (text in delta.text), content_block_stop,
message_delta with the stop_reason and usage, and message_stop. A failure after the
stream has started is an error event.
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"One, two"}}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":6}}
Images and tools
Images go in as image blocks with a base64 source or a url source, for models whose
modalities.input includes image. Tools follow the Anthropic format: tools with an
input_schema, a tool_use block in the answer, and your tool_result block in the next user
turn.
{
"model": "MODEL_ID",
"max_tokens": 1024,
"tools": [
{
"name": "get_weather",
"description": "Current weather for a city",
"input_schema": { "type": "object", "properties": { "city": { "type": "string" } }, "required": ["city"] }
}
],
"messages": [{ "role": "user", "content": "What is the weather in Paris?" }]
}
Count tokens
POST /v1/messages/count_tokens takes the same body and returns an estimate of its input
tokens. It is free: nothing is charged and no transaction is recorded.
curl https://api.opencheese.dev/v1/messages/count_tokens \
-H "x-api-key: $OPENCHEESE_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model": "MODEL_ID", "messages": [{"role": "user", "content": "How many tokens is this?"}]}'
{ "input_tokens": 9 }
SDKs
Python:
import anthropic
client = anthropic.Anthropic(base_url="https://api.opencheese.dev", api_key="YOUR_OPENCHEESE_API_KEY")
message = client.messages.create(
model="MODEL_ID",
max_tokens=1024,
messages=[{"role": "user", "content": "Write a haiku about cheese."}],
)
print(message.content[0].text)
JavaScript:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ baseURL: "https://api.opencheese.dev", apiKey: process.env.OPENCHEESE_API_KEY });
const message = await client.messages.create({
model: "MODEL_ID",
max_tokens: 1024,
messages: [{ role: "user", content: "Write a haiku about cheese." }]
});
console.log(message.content[0].text);
Errors use the Anthropic envelope, {"type": "error", "error": {...}}; see
Errors and rate limits. Add the
opencheese-session-uuid header to keep a conversation together.