Messages API Basics
7 examples to get you started with the Messages API - 5 basic and 2 intermediate.
Search across all documentation pages
7 examples to get you started with the Messages API - 5 basic and 2 intermediate.
pip install anthropic.export ANTHROPIC_API_KEY=sk-ant-... (or construct anthropic.Anthropic(api_key=...) directly).claude-opus-4-8; swap in claude-sonnet-5 or claude-haiku-4-5 if you want a different speed/cost tradeoff.The smallest possible call: one user message, no history.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=[
{"role": "user", "content": "What is the capital of France?"},
],
)
print(response.content[0].text)max_tokens is required on every request and caps the length of Claude's reply.response.content is a list of content blocks; for a plain text reply, the first block's .text holds the answer.system prompt is required - it's optional, not mandatory.The system parameter sits outside messages and shapes tone, persona, or constraints for the whole conversation.
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
system="You are a terse assistant. Answer in one sentence.",
messages=[
{"role": "user", "content": "Why is the sky blue?"},
],
)
print(response.content[0].text)system is a top-level request parameter, not a message with a role.Continue a conversation by including Claude's prior reply as an assistant turn before your next question.
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=[
{"role": "user", "content": "What is the capital of France?"},
{"role": "assistant", "content": "The capital of France is Paris."},
{"role": "user", "content": "What is its population?"},
],
)
print(response.content[0].text)user, assistant, user - the API rejects requests that break this pattern.The full Message object carries more than just the reply text - inspect it to build reliable applications.
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=[{"role": "user", "content": "Name three programming languages."}],
)
print(response.stop_reason) # why generation stopped, e.g. "end_turn"
print(response.usage.input_tokens, response.usage.output_tokens)
print(response.model) # the model that actually served the responsestop_reason tells you whether Claude finished naturally (end_turn), hit the token cap (max_tokens), or stopped for another reason.usage reports token counts for both the input and the generated output, which is what you're billed on.stop_reason before trusting response.content is complete - a max_tokens stop means the reply was cut off.Network issues, rate limits, and bad requests all raise typed exceptions - catch them explicitly rather than guessing from a bare Exception.
import anthropic
client = anthropic.Anthropic()
try:
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
)
except anthropic.RateLimitError:
print("Rate limited - back off and retry")
except anthropic.APIStatusError as e:
print(f"API error {e.status_code}: {e.message}")RateLimitError, NotFoundError, AuthenticationError, and so on).APIStatusError for anything else.429 and 5xx responses automatically with backoff, so a caught RateLimitError means retries were exhausted.Most real applications don't hardcode the conversation - they append to a list and resend it on every turn.
import anthropic
client = anthropic.Anthropic()
messages = []
def ask(user_text: str) -> str:
messages.append({"role": "user", "content": user_text})
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
system="You are a helpful assistant who remembers context within this chat.",
messages=messages,
)
reply_text = response.content[0].text
messages.append({"role": "assistant", "content": response.content})
return reply_text
print(ask("My favorite color is teal."))
print(ask("What's my favorite color?"))response.content (not just the extracted text) as the assistant turn, so any non-text blocks are preserved for later turns.messages grows by two entries per exchange: your new user turn and Claude's assistant reply.For longer replies, stream tokens as they're generated instead of waiting for the full response.
import anthropic
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=2048,
messages=[{"role": "user", "content": "Write a short poem about the ocean."}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
final_message = stream.get_final_message()
print("\n\nStop reason:", final_message.stop_reason)client.messages.stream() returns a context manager; stream.text_stream yields incremental text chunks as they arrive.stream.get_final_message() after the loop to get the complete Message object, including usage and stop_reason.max_tokens is large, since non-streaming requests risk hitting client-side HTTP timeouts.Related: Understanding Roles and Turns in the Messages API - the conceptual model behind these examples | Building Multi-Turn Conversations with the Messages Array - a deeper look at managing conversation state
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5 - and the official
anthropicPython SDK (latest 0.x release). Model names, SDK versions, and pricing move quickly - verify current specifics at platform.claude.com/docs before relying on them.
Reviewed by Chris St. John·Last updated Jul 18, 2026