Messages

Generate a model response using the Anthropic Messages wire format. Use this endpoint with the Anthropic SDKs, Claude Code and any tool that has an "Anthropic base URL" setting; it serves the same Claud models and bills identically to Chat completions.

POST/v1/messages
Note:

Claud is an independent service. This endpoint implements a request format for interoperability; it is not affiliated with Anthropic and every request is served by a Claud model.

Authentication#

Send your key as x-api-key: sk-... (what the Anthropic SDKs do) or Authorization: Bearer sk-.... The anthropic-version header is accepted and ignored.

Request body#

modelstringrequired
A Claud model slug or alias, for example claud-5.1.
max_tokensintegerrequired
Upper bound on generated tokens, including thinking tokens.
messagesarrayrequired
Alternating user / assistant turns. content is a string or an array of blocks: text, image (source.type = base64 or url), tool_use (assistant), tool_result (user) and thinking. Unknown block types are ignored.
systemstring | array
System prompt, either a string or an array of text blocks. cache_control markers are accepted and ignored.
temperaturenumber
Between 0 and 1.
top_pnumber
Nucleus sampling threshold in (0, 1].
top_kinteger
Accepted for compatibility; not applied.
stop_sequencesstring[]
Up to 16 sequences at which generation halts.
streambooleandefault: false
Stream the response as server-sent events (see below).
toolsarray
Tool definitions: { name, description?, input_schema }. Up to 128.
tool_choiceobject
{ type: "auto" }, { type: "any" }, { type: "none" } or { type: "tool", name }.
thinkingobject
{ type: "enabled", budget_tokens? } turns on reasoning for reasoning-capable models; { type: "disabled" } turns it off. budget_tokens is accepted but the model's own limits apply.
metadataobject
{ user_id } is recorded on usage records for your own attribution.

Response#

JSON
{
  "id": "msg_01J9X3Q5K7M2N8P4R6T0V2W4Y6",
  "type": "message",
  "role": "assistant",
  "model": "claud-5.1",
  "content": [{ "type": "text", "text": "Rivers carve the stone..." }],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 18,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 0,
    "output_tokens": 42,
    "claud_tokens_debited": "102",
    "claud_cost_usd": "0.000204"
  }
}
contentarray
Ordered blocks: thinking (reasoning models with thinking enabled), text, and tool_use ({ id, name, input } with input already parsed as an object).
stop_reasonstring
end_turn, max_tokens or tool_use. Claud cannot distinguish a stop sequence from a natural end, so stop_sequence is always null and such stops report end_turn.
usage.input_tokensinteger
Prompt tokens that were not served from cache. cache_read_input_tokens holds the cached portion; the two sum to the total prompt size.
usage.output_tokensinteger
Generated tokens, including thinking tokens.
usage.claud_tokens_debitedstring
Claud tokens charged for this request.
usage.claud_cost_usdstring
The same charge in USD.

The response also carries the x-request-id, x-claud-model, x-claud-tokens-debited, x-claud-balance and x-ratelimit-* headers described under Chat completions.

Streaming#

With "stream": true the response is a text/event-stream in the Messages event sequence:

Text
event: message_start
data: {"type":"message_start","message":{"id":"msg_...","type":"message","role":"assistant","model":"claud-5.1","content":[],"stop_reason":null,"usage":{"input_tokens":0,"output_tokens":0}}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Rivers "}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":18,"cache_read_input_tokens":0,"output_tokens":42,"claud_tokens_debited":"102","claud_cost_usd":"0.000204","claud_balance_tokens":"1199400","claud_fallback_used":false}}

event: message_stop
data: {"type":"message_stop"}
  • Thinking arrives as a thinking block with thinking_delta deltas, before the text block.
  • Tool calls arrive as tool_use blocks: content_block_start carries id and name; input_json_delta deltas carry partial_json fragments that concatenate to the arguments object.
  • Final token counts and billing are on message_delta. claud_balance_tokens is your available balance after the request; claud_fallback_used is true if a fallback model served it.
  • Errors after the stream has started are sent as event: error with an Anthropic-style error body, followed by the end of the stream.

Count tokens#

POST/v1/messages/count_tokens

Accepts the same body as /v1/messages (max_tokens optional) and returns { "input_tokens": n } using the same estimator the gateway uses to reserve tokens before a request. Not billed and not rate limited against your token budget.

Examples#

curl https://api.claudkey.com/v1/messages \
  -H "x-api-key: $CLAUD_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claud-5.1",
    "max_tokens": 200,
    "system": "You are a concise assistant.",
    "messages": [{"role": "user", "content": "Write a haiku about rivers."}]
  }'

Tool use round trip#

JSON
{
  "model": "claud-5.1",
  "max_tokens": 400,
  "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?" },
    { "role": "assistant", "content": [
      { "type": "tool_use", "id": "toolu_01", "name": "get_weather", "input": { "city": "Paris" } }
    ]},
    { "role": "user", "content": [
      { "type": "tool_result", "tool_use_id": "toolu_01", "content": "18°C, cloudy" }
    ]}
  ]
}

Errors#

Errors use the Messages envelope { "type": "error", "error": { "type", "message", "code", "request_id" } }. Codes are the same as for Chat completions; error.type is one of invalid_request_error, authentication_error, permission_error, not_found_error, rate_limit_error, request_too_large, overloaded_error or api_error.