Messages API
Use POST /v1/messages when your application already uses the Messages request and content-block format. Keiro accepts that wire shape, routes it through the same public eb1 service as the other completion endpoints, and returns a Messages-style response.
On this page 1 of 5
Send a message#
printf 'Keiro API key: '
IFS= read -rs KEIRO_BEARER
printf '\n'
curl -sS https://api.keirolabs.ai/v1/messages \
-H "Content-Type: application/json" \
-d '{
"model": "eb1-preview",
"max_tokens": 256,
"system": "Answer in one concise sentence.",
"messages": [
{
"role": "user",
"content": "Why are idempotency keys useful?"
}
]
}' \
-H @- <<<"Authorization: Bearer $KEIRO_BEARER"
Read generated text from the text blocks in content. A buffered response has this customer-visible shape:
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Idempotency keys let a safe retry reuse the original result instead of running twice."
}
],
"model": "eb1-preview",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 18,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"output_tokens": 19
}
}
IDs, text, and token counts vary by request. Depend on the field layout, not the sample values.
The three input-side fields are disjoint, matching Anthropic's native Messages usage semantics: input_tokens counts the portion of the prompt served from neither cache, cache_read_input_tokens counts prompt tokens served from a prompt cache, and cache_creation_input_tokens counts prompt tokens written to one. input_tokens + cache_read_input_tokens + cache_creation_input_tokens equals the full prompt, so a client that sums the three fields — Claude Code's context gauge does — reads the real context size. All three fields are always present. On a stream, the message_start usage carries zero for both cache fields — cache counts, like output_tokens, are only known at the terminal message_delta.
Deprecated (2026-08-08): additive-subset usage shape. Messages usage previously rendered input_tokens as the full inclusive prompt count with the two cache fields as subsets of it. That shape is retired for all Messages consumers; the disjoint semantics above are the contract and take effect with the next deployment. If your integration read input_tokens as the inclusive prompt total, sum input_tokens + cache_read_input_tokens + cache_creation_input_tokens to recover the old value. Responses with zero cache activity are byte-identical under both shapes.
Supported request fields#
The public Messages surface supports these top-level fields:
Unknown fields fail closed. Do not assume that a field from another Messages implementation is available until it is listed here.
model,messages, and optional top-levelsystemmax_tokens,temperature,top_p, andstop_sequencesstreamtools,tool_choice, andparallel_tool_callsthinkingwithtypeenabledordisabled; enabled thinking requires a positivebudget_tokensmetadataidempotency_key, with the request-header form preferred for HTTP clients
Content blocks#
User and assistant messages accept strings or non-empty content-block arrays. Supported customer workflows include text, top-level user image blocks, and the tool_use / tool_result history used for function calling.
Images are not supported inside tool_result content because tool results are textual on the shared continuation contract. See Images and vision for supported image placement and Tool calling for tool history.
Stream a response#
Set stream to true to receive Messages-style server-sent events. A normal text stream follows this lifecycle:
When extended thinking is enabled, one or more thinking content blocks arrive before the text block: a content_block_start with block type thinking, thinking_delta deltas carrying the thinking text, then content_block_stop, all closing before the text block opens. These blocks carry summary text constructed by the API and are unsigned; do not round-trip them to a provider as signed thinking blocks.
Streams are governed by documented idle and wall-clock time entitlements, not a flat timeout. Messages requests carry no effort field; thinking.budget_tokens selects the entitlement row — see Streaming.
A failure after streaming begins arrives as an in-band error event with a sanitized error.type, error.code, and error.message. Retriable failures also include error.retry_after_seconds.
message_startcontent_block_start- one or more
content_block_deltaevents content_block_stopmessage_delta, including the terminal stop reason and final usagemessage_stop