Claude API basics: your first call, messages, max_tokens and stop_reason
The Claude API's core is one endpoint, the Messages API: you POST a model, a max_tokens limit and a list of messages, and get back a message with content blocks, token usage and a stop_reason. The API is stateless, so every request carries the whole conversation. The stop_reason tells your code what to do next: use the answer, run a tool, continue or treat it as truncated.
What is the Claude API?
The Claude API is Anthropic's HTTP API for Claude, and its center is the Messages API: POST https://api.anthropic.com/v1/messages. Everything else you hear about, tool use, structured outputs, vision, batches, builds on this one request. The official client SDKs (Python, TypeScript, Java, Go, C#, PHP, Ruby) wrap it, and higher-level options such as the Claude Agent SDK run their loops on top of it.
Your first Claude API call
A request needs three things: a model, a max_tokens limit and messages. Authentication is the x-api-key header, plus an anthropic-version header.
bash
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-5-5",
"max_tokens": 512,
"system": "You answer customer questions for a bike-rental shop. Be brief.",
"messages": [{"role": "user", "content": "Can I return an e-bike at a different location?"}]
}'
The same call in Python:
```python import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY message = client.messages.create( model="claude-opus-5-5", max_tokens=512, system="You answer customer questions for a bike-rental shop. Be brief.", messages=[{"role": "user", "content": "Can I return an e-bike at a different location?"}], ) print(message.content[0].text, message.stop_reason) ```
The response: content blocks, usage and stop_reason
json
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"content": [{"type": "text", "text": "..."}],
"model": "claude-opus-5-5",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {"input_tokens": 41, "output_tokens": 63}
}
content is a list of blocks, not a string. A reply can hold text, a tool_use block, or both, so read blocks by their type. usage counts input and output tokens, which is what you pay for.
System prompt, roles and the conversation history
The system prompt is a top-level system field, not a message. Messages alternate user and assistant. On the newest models you can also add a message with "role": "system" after a user turn to give a new instruction partway through a conversation.
The Messages API is stateless: it remembers nothing between calls. To continue a conversation you send the whole history again, user turns and Claude's earlier replies:
python
messages = [
{"role": "user", "content": "Can I return an e-bike at a different location?"},
{"role": "assistant", "content": "Yes, at any of our three pick-up points."},
{"role": "user", "content": "Is there a fee?"},
]
Earlier assistant turns do not have to come from Claude; you can write them yourself to set up a pattern. Longer histories cost more input tokens on every call, which is why long conversations need context management.
max_tokens: a cap, not a target
max_tokens is the most tokens Claude may generate in this response. It does not make answers longer. If the reply reaches it, the response stops mid-thought with stop_reason: "max_tokens". Set it for the longest answer you expect, and handle the truncated case instead of passing half an answer downstream.
What each stop_reason means
| stop_reason | What happened | What your code does |
|---|---|---|
end_turn |
Claude finished naturally | Use the response |
max_tokens |
The reply hit your max_tokens |
Raise the limit or continue the response |
stop_sequence |
Claude emitted one of your stop_sequences |
Read stop_sequence to see which |
tool_use |
Claude is calling a tool you defined | Run the tool, send a tool_result back |
pause_turn |
A server-tool loop hit its iteration limit | Send the assistant content back as-is to continue |
refusal |
Claude declined (arrives as HTTP 200) | Read stop_details, retry on a fallback model if appropriate |
model_context_window_exceeded |
The reply filled the context window | Treat it as truncated |
Write the check as a switch on stop_reason, with a safe default branch for values you don't handle yet. New values have been added over time.
The stop_reason drives the agent loop
When you give Claude tools, stop_reason becomes your loop condition. While it is tool_use, your code runs each requested tool, appends Claude's message and your tool_result blocks to the history, and calls the API again. When it is end_turn, the job is done. This is the loop the Claude Agent SDK runs for you, and it is why the API, the Agent SDK, Claude Code and MCP differ mainly in who runs that loop.
The classic mistake is to decide the loop is finished by reading Claude's text ("I'm done", "Here is the answer"). Natural language is not a reliable signal; stop_reason is. The Claude Certified Architect exam guide names this anti-pattern explicitly in task statement 1.1, together with arbitrary iteration caps used as the main stopping mechanism.
What changed on the newest Claude models
- Sampling parameters.
temperature,top_pandtop_kare not supported on Claude 4.7 and later models; a non-default value returns a 400 error. Leave them out and steer with the prompt. - Prefill. Pre-filling the start of Claude's reply in a final assistant message returns a 400 error on Claude 4.6 and later models. Use structured outputs or system prompt instructions instead.
- Forced tool use.
tool_choiceset toanyor a named tool returns a 400 on Claude Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1; useautowith strict tools or structured outputs.
Older tutorials still show all three, so check the model you target.
Messages API or Managed Agents?
The docs now present two ways to build: the Messages API for custom agent loops and fine-grained control, and Claude Managed Agents, a pre-built agent harness that runs in managed infrastructure for long-running and asynchronous work. Start with the Messages API to understand what every higher layer does for you.
Next: the CCAR-F study plan and all articles.
Sources: Using the Messages API; Handling stop reasons; Messages API reference; Define tools; Claude Certified Architect Foundations exam guide v1.0, task statement 1.1.
FAQ
What is the Claude API?
Anthropic's HTTP API for Claude. Its main endpoint, the Messages API (POST /v1/messages), takes a model, max_tokens and a list of user and assistant messages, and returns Claude's reply as content blocks with a stop_reason and token usage.
Does the Claude API remember previous messages?
No. The Messages API is stateless: you send the full conversation history with every request. Earlier assistant turns can even be written by you.
What does max_tokens do?
It caps how many tokens Claude may generate in that response. If the reply hits the cap, stop_reason is max_tokens and the answer is cut off, so raise the limit or continue the response.
What does stop_reason tool_use mean?
Claude wants to call a tool you defined. Your code runs the tool and sends the result back in a tool_result block in the next request; the loop continues until stop_reason is end_turn.
Can I still set temperature on Claude?
Not on Claude 4.7 and later models: a non-default temperature, top_p or top_k returns a 400 error. Leave them out and steer the output with your prompt.