Building with the Claude API · lesson 2 of 17
Messages API
The single primary surface for the Claude API. Almost everything (chat, tools, vision, thinking, caching) flows through POST /v1/messages.
Minimal request
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system="You are a concise assistant.",
messages=[
{"role": "user", "content": "Explain prompt caching in two sentences."}
],
)
print(resp.content[0].text)
Anatomy of a request
| Field | Purpose |
|---|---|
model | Pinned model ID. Always pin. |
max_tokens | Hard cap on completion length. Required. |
system | System prompt (string or array of content blocks). Sets persona/rules. |
messages | Alternating user / assistant turns. First must be user. |
tools | Tool schemas Claude may call. |
tool_choice | auto (default), any, {type: "tool", name: "..."}, or none. |
temperature | 0–1. Lower = deterministic. |
top_p | Nucleus sampling. Usually leave default. |
stop_sequences | Strings that end generation. |
metadata.user_id | Per-user abuse tracking. |
thinking | {type: "enabled", budget_tokens: N} for extended thinking. |
stream | true for SSE streaming. |
The response
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"model": "claude-sonnet-4-6",
"content": [
{"type": "text", "text": "..."}
],
"stop_reason": "end_turn" | "max_tokens" | "stop_sequence" | "tool_use" | "pause_turn",
"usage": {"input_tokens": 123, "output_tokens": 45, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0}
}
stop_reason is the single most important field for agent loops — tool_use means you must run a tool and call back; end_turn means done.
Statelessness
The API is stateless. Every request must include the full conversation. The server has no memory of prior turns. This is why:
- Conversation state lives in your application.
- Prompt caching exists — to make replaying long histories cheap.
- Conversation compaction is your responsibility.
Content block types
Inside content you can see:
text— the obvious.tool_use—{type: "tool_use", id, name, input}. Claude is asking you to run a tool.thinking— extended-thinking output (visible when enabled).redacted_thinking— when the thinking content has been filtered.image— only in user turns.document— PDFs and other docs as input.