What You Need to Know
The Messages API is how an application talks to Claude. A request names the model, caps the reply length and carries the conversation so far. The response holds content, a list of typed content blocks: text, tool_use or thinking. It also holds stop_reason, which says why generation ended, and usage, the token counts.
Take a tile shop with a help chat on its website. Customers ask how many boxes of tiles a floor needs, send room photos and check stock. Each customer turn starts a Messages API request.
The Request and the Response
A request needs exactly three parameters: model, max_tokens and messages. Everything else is optional. system sits at the top level and is never a message role. The messages array alternates user and assistant turns, and consecutive same-role messages are merged.
The API is stateless: it holds no conversation. The application resends the transcript it wants the model to see, every turn. If the tile shop's chat sent only the newest question, Claude would answer without the history, missing the room described two turns earlier.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
system="You summarise fisheries observer reports for a compliance team.",
messages=[{"role": "user", "content": report_text}],
)
print(response.stop_reason)
print(response.usage.input_tokens, response.usage.output_tokens)
print(response.usage.cache_creation_input_tokens, response.usage.cache_read_input_tokens)The documented stop_reason values are:
end_turn: a natural finishmax_tokens: the cap was hitstop_sequence: a configured stop sequence firedtool_use: the model wants a tool runpause_turnrefusalmodel_context_window_exceeded
Read stop_reason before the content: it separates diagnosing a truncation from blaming the model for it. When a tile shop reply ends mid-sentence, the field shows whether it hit the max_tokens cap. In usage, total input is the sum of input_tokens, cache_creation_input_tokens and cache_read_input_tokens.
Data goes in as content blocks: text, image or document blocks. Files API references let a file be uploaded once and referenced many times. The tile shop could upload its fitting guide once and reference it from every chat.
Tools at the Wire Level
A tool definition carries name, description and a JSON Schema input_schema. Say the tile shop defines a stock-check tool. To call it, the model stops with stop_reason tool_use and emits a tool_use block holding an id, the tool name and the parsed input.
The caller, never Anthropic, executes a client tool. The tile shop's own code checks the stock. It then continues with a user turn holding a tool_result block whose tool_use_id matches that id. The matching id ties the result to the call. The handler below shows the same round trip for a different tool:
tools = [{
"name": "look_up_vessel",
"description": "Look up a vessel registration record by its IMO number.",
"input_schema": {
"type": "object",
"properties": {"imo_number": {"type": "string"}},
"required": ["imo_number"],
},
}]
response = client.messages.create(
model="claude-sonnet-5-5", max_tokens=1024, tools=tools, messages=messages,
)
if response.stop_reason == "tool_use":
block = next(b for b in response.content if b.type == "tool_use")
result = look_up_vessel(**block.input) # your code runs the tool
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": [
{"type": "tool_result", "tool_use_id": block.id, "content": result},
]})tool_choice steers the decision. Its values are auto, any, tool (forcing a named tool) and none. Forcing depends on the model. As of 29 September 2026, Claude Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1 reject any and tool with a 400 error. Manual extended thinking rejects both on any model. For those, the documented route is auto with strict tool use.
Server tools such as web search invert the execution side. Anthropic runs them, and the results arrive in the same response.
Streaming
With stream: true, the response arrives as server-sent events in a documented order:
message_start- for each content block, a
content_block_start, one or morecontent_block_deltaevents and acontent_block_stop message_delta, with top-level changes and cumulative usage- a final
message_stop
ping events can arrive throughout.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const stream = await client.messages.create({
model: "claude-sonnet-5-5",
max_tokens: 2048,
messages: [{ role: "user", content: "Summarise this observer report..." }],
stream: true,
});
for await (const event of stream) {
console.log(event.type);
// message_start, content_block_start, content_block_delta,
// content_block_stop, message_delta, message_stop, ping
}Each delta has a type:
text_deltafor textinput_json_deltafor tool-call arguments: accumulate the partial JSON, then parse it atcontent_block_stopthinking_delta, plus a closingsignature_delta, for thinking blocks
Errors can also arrive mid-stream, as error events after the 200. A stream consumer therefore handles failure in two places: at the request, and inside the event stream.
Streaming moves the time to the first token. It does not change total cost or total generation time. That makes it the fix when users watch a spinner, as the tile shop's chat customers do. For a slow batch job, it is irrelevant.
Vision
Images travel as image content blocks with three source types: base64 embedded bytes, a url reference, or a file id from the Files API. The Files API has left beta, so no beta header is needed. As of September 2026, the legacy files-api-2025-04-14 header still works but only keeps the old beta response shapes.
Supported media types are JPEG, PNG, GIF and WebP. As of August 2026, the per-image limits are 10 MB on the Claude API (5 MB on Bedrock and Google Cloud) and 8000x8000 pixels. The same August 2026 limits allow 100 images per request on 200k-context models and 600 on other models.
Claude reads the image in context, so the architecture needs no separate OCR service. A customer's photo of a cracked tile goes straight into the request as an image block.
Cost is patch-based: roughly one visual token per 28x28-pixel patch. Fewer pixels mean fewer patches, so pre-resizing images controls both cost and latency. The domain quick reference carries the dated tier figures for vision.
Thinking
Thinking parameters depend on the model generation. Current models use thinking.type adaptive, with depth steered by output_config.effort. The older extended-thinking shape, type enabled with budget_tokens, belongs to models that predate adaptive thinking. It is deprecated but still accepted on the 4.6 generation, and rejected with a 400 invalid_request_error from 4.7 onward. On the newest generation thinking is always on, and type disabled also returns a 400.
Thinking arrives as thinking content blocks ahead of the text, each carrying a signature. The display setting controls whether summarised thinking text comes back or the block arrives empty.
In multi-turn tool use, pass thinking and redacted_thinking blocks back exactly as received. Editing, reordering or dropping them is a 400. With thinking on, the tile shop's code appends the assistant turn unchanged before the tool_result turn.
Prompt Caching Mechanics
Prompt caching is prefix hashing. A cache_control marker of type ephemeral tells the API to cache everything up to that point. A request can set up to 4 explicit breakpoints, or use the newer automatic top-level marker. A later request hits only if its prefix is 100% identical, evaluated in a fixed hierarchy: tools, then system, then messages.
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
system=[{
"type": "text",
"text": OBSERVER_HANDBOOK, # large, stable prefix
"cache_control": {"type": "ephemeral"},
}],
messages=[{"role": "user", "content": todays_report}], # volatile, last
)The hash covers the exact prefix, so any changed byte before the breakpoint is a miss. The design rule follows: stable content first, volatile content last. The tile shop caches its product catalogue in the system prompt and puts each customer question after it.
Invalidation cascades down the hierarchy: a change at one level invalidates that level and every level after it. A tools change invalidates everything. A system change invalidates the system and message caches. Editing the stock tool's definition would cost the tile shop every cached prefix.
Entries live 5 minutes by default, refreshed on use, or an hour with ttl set to "1h". A prompt below the per-model minimum cacheable length is silently not cached. It shows up as zeroes in the usage cache fields.
Batch Versus Realtime
The Message Batches API processes requests asynchronously at a 50% discount on all usage. A batch holds up to 100,000 requests or 256 MB, whichever is reached first. Every batched request needs max_tokens of at least 1.
Results become available when every request finishes or at the 24-hour mark, whichever comes first. Requests unfinished at 24 hours expire unbilled. Each result is succeeded, errored, canceled or expired, streamed from a results_url that lives 29 days.
Most batches complete inside an hour, but that is typical behaviour, not a guarantee. So latency-tolerant, cost-dominated work belongs in batch. Anything interactive stays realtime, as does any job whose hard deadline sits inside the completion window. If throughput is the issue, use bounded client-side concurrency. The tile shop's rewrite of every product description suits a batch; its chat stays realtime.
Vendor Surfaces
One model family is reachable through several platforms. What changes for the developer is always the same short list:
- authentication
- endpoint
- model-ID format
- feature parity
- release timing
The request and response shape never changes: it is the Messages API everywhere.
Claude in Amazon Bedrock exposes the Messages API on a Bedrock endpoint, with SigV4 auth and anthropic.-prefixed model IDs. The legacy Bedrock path uses Converse/InvokeModel.
Claude Platform on AWS is different in kind. Anthropic operates the platform and the full Claude API surface (beta headers included, features typically same-day, first-party model IDs). AWS provides authentication and Marketplace billing.
Google Cloud uses @date-suffixed IDs for dated pre-4.6 snapshots, while its current-generation IDs match the first-party format. Microsoft Foundry follows the first-party model lifecycle.
Parity is the recurring caveat on the partner-operated platforms. Bedrock and Vertex carry the core Messages surface, caching, thinking and tool use. They do not carry the Batches API, the Files API or most of Anthropic's server tools. As of September 2026, Google Cloud carries web search and Bedrock carries none. On both, images arrive base64-only. A tile shop chat on Bedrock would send photos as base64 and lose the batch route.
The Error Surface
Each status maps to an exact error type:
| Status | Error type |
|---|---|
| 400 | invalid_request_error |
| 401 | authentication_error |
| 402 | billing_error |
| 403 | permission_error |
| 404 | not_found_error |
| 409 | conflict_error |
| 413 | request_too_large |
| 429 | rate_limit_error |
| 500 | api_error |
| 504 | timeout_error |
| 529 | overloaded_error |
Rate limits are token-bucket enforced across RPM, ITPM and OTPM. A rate-limit 429 names the exceeded limit and carries retry-after. The anthropic-ratelimit-* headers expose limit, remaining and reset continuously.
The official SDKs retry transient failures (connection errors, 429s, 5xx) twice by default, with exponential backoff, honouring retry-after. A 529 is overload: back away rather than hammer it. Every error body carries a request_id for support.
As of September 2026, four rows need more than the table:
- A 409 means resolve the conflict, then retry.
- A 504 on a long-running request points at streaming or the Message Batches API.
- The tier's monthly spend cap returns a 429 with no
retry-afteranderror.details.error_codeenforced_spend_limit_reached. No retry clears it until access resumes. - A spend limit you set returns a 400. Limits on the Claude Code workspace can return a 429 instead.
For the tile shop's chat, a 529 means the API is overloaded, so back off. A 429 carrying enforced_spend_limit_reached means the monthly spend cap, which no retry clears until access resumes.
In the exam
Items key on exact parameter names, exact stop_reason strings and exact error types. The distractors are invented-but-plausible near-misses, so knowing the documented values is how you spot the invention. Thinking is a favourite for distractors that mix vocabularies across generations. An item can key on recognising which surface a model string belongs to. Enterprise platform strategy is not tested; the integration point is.
Domain 2 owns these wire shapes. The loop that drives repeated calls is Domain 1, and describing tools well is Domain 8. Choosing when a task warrants thinking is Domain 5. So are caching's write premiums and read discounts, and when caching pays; here the tested skill is making the cache hit at all. Working out which layer of a failing system broke is Domain 4; the handling mechanics live here.
Current-State Notes
Current-state note (August 2026)
Two guide-era techniques fail on current models. Assistant-message prefill is rejected with a 400 on Claude 4.6 and later. Temperature, top_p and top_k return a 400 on non-default values on Claude 4.7 and later. Structured outputs and system-prompt instruction are the current routes to shaped output. Keyed answers follow the guide where it speaks. Runnable code stays current-correct, which is why none of the code on this page uses either mechanism.
Exam Traps
Accepting an invented-but-plausible parameter, value or limit because it sounds like the documented ones.
The required trio is model, max_tokens and messages; tool_choice takes auto, any, tool and none; cache_control takes type ephemeral. A fifth tool_choice value, an invented cache parameter or a plausible-sounding required field is the house distractor and always wrong.
Attributing client tool execution to Anthropic's servers.
The caller executes client tools and returns a tool_result block with the matching tool_use_id. Server tools such as web search are the documented exception, running on Anthropic infrastructure with results in the same response.
Treating the typical under-an-hour batch completion as a guarantee a deadline can lean on.
Results are available when all requests complete or at 24 hours, whichever comes first, and stragglers expire unbilled. A hard deadline inside the completion window keys realtime with bounded concurrency, not batch.
Inferring why generation stopped from the symptom instead of reading stop_reason.
max_tokens, stop_sequence and model_context_window_exceeded are distinct documented values with distinct fixes. Items reward reading the field; the distractors each pair a wrong value with a plausible remedy.
Practice Scenario
A fisheries compliance service summarises observer reports with the Messages API. Summaries intermittently arrive cut off mid-sentence. Inspecting a failing response shows usage.output_tokens exactly equal to the request's max_tokens value. What does the response's stop_reason read, and what fixes it?
Build Exercise
Touch Every Mechanism Once
What you'll learn
- How to read stop_reason and usage instead of guessing from symptoms
- How the documented SSE event sequence arrives in practice
- How a cache breakpoint turns creation tokens into read tokens
- How the tool_use / tool_result wire shape round-trips
- How batch results stream back with per-request result types
- Write a script (Python or TypeScript SDK) that sends a Messages request and prints stop_reason and the full usage object; run it once normally and once with max_tokens set absurdly low
Why: Producing the max_tokens stop on purpose means you meet the truncation signature on your own terms rather than during an incident.
You should see: end_turn on the first run; max_tokens on the second, with output_tokens equal to your cap.
- Re-run with streaming enabled and log every SSE event type in arrival order
Why: The documented event sequence is a keyed fact, and watching it arrive beats memorising it.
You should see: message_start, then content_block_start, deltas and content_block_stop per block, then message_delta and message_stop, possibly with ping events interspersed.
- Place a cache_control breakpoint after a large stable system prefix, call twice within five minutes, then change one early byte and call again
Why: Watching cache_creation_input_tokens become cache_read_input_tokens, then vanish on a one-byte change, makes the identical-prefix rule visceral.
You should see: Creation tokens on call one, read tokens on call two, and a full re-write on call three.
- Define one client tool with an input_schema, trigger it, execute the call yourself, and return a tool_result with the matching tool_use_id
Why: Round-tripping the wire shape once settles who executes what and which ids must line up.
You should see: stop_reason tool_use, your function running locally, and a final text response that uses the result.
- Submit a five-request Message Batch, poll its status, stream the results from results_url, then point one request at an invalid model name
Why: Batch result types and the error surface are both keyed facts, and one small batch exercises them together.
You should see: succeeded results matched by custom_id, one errored result, and a documented error shape with a request_id.
Sources
- Messages API reference — Claude Docs, required parameters, roles, system, tool_choice and stop_reason values
- Claude API errors — Claude Docs, the status table, the 409, 504 and spend-limit guidance, SDK retry defaults, request size limits and request_id
- Streaming messages — Claude Docs, the SSE event sequence, delta types and mid-stream error events
- Vision — Claude Docs, image source types, format and size limits, patch-based token cost
- Thinking — Claude Docs, adaptive thinking, effort control, signatures and pass-back rules
- Prompt caching — Claude Docs, cache_control, the prefix hierarchy, invalidation and TTLs
- Batch processing — Claude Docs, batch limits, the completion window, result types and results_url
- Rate limits — Claude Docs, token-bucket enforcement, retry-after, the ratelimit headers, the tier spend cap and self-set spend limits
- Tool use with Claude — Claude Docs, tool definitions, tool_use and tool_result blocks, client versus server tools
- Define tools — Claude Docs, tool_choice values and the models and settings that reject forced tool use
- Claude Platform on AWS — Claude Docs, the Anthropic-operated AWS surface and how it differs from Bedrock
- Models overview — Claude Docs, model identifiers across vendor surfaces
- Claude Certified Developer Foundations Exam Guide — Domain 2, Claude API Mechanics — Anthropic