Why this page exists
The chat window is a product wrapped around an API. Once you call the API directly, Claude becomes a component: something you can put inside a pipeline, a notebook, a cron job, or a data quality check. This page covers the "Accessing Claude with the API" module that all three official engineering courses share, plus the API fundamentals from Claude Platform 101.
One call, fully understood 12 min
The whole API is one method: client.messages.create(). Learn its parameters properly once and every advanced feature is just another argument.
CoreSetup and your first request5 min▶
Three steps: install the SDK, set your key as an environment variable (never hardcode it - keys in notebooks end up in git), make the call.
Read the response object once, carefully: response.content is a LIST of blocks (later, tool calls appear here too), so the text lives at response.content[0].text. response.usage tells you input and output token counts - that is your bill. response.stop_reason tells you why generation ended; "max_tokens" there means you cut Claude off mid-answer.
CoreAnatomy of a request: model, max_tokens, temperature7 min▶
Three parameters do most of the work. Get the mental model right for each:
| Parameter | What it controls | How to set it |
|---|---|---|
model | Capability vs speed vs cost | Capable tier (Opus, Sonnet) for reasoning and hard extraction; fast tier (Haiku) for classification, routing, high-volume simple tasks |
max_tokens | Hard ceiling on OUTPUT length | A budget, not a target - Claude stops naturally before it. Set generously (1024-4096); a truncated answer is worse than a few unused tokens |
temperature | Sampling randomness, 0 to 1 | 0 for extraction, classification, anything you will parse (near-deterministic); around 1 for brainstorming and creative variety. Default is 1 |
Multi-turn and system prompts 10 min
The API has no memory. Every call is a blank slate - "conversation" is something YOU maintain by resending history. This surprises everyone once.
CoreMulti-turn: the messages list IS the conversation6 min▶
The messages parameter is not "the new message" - it is the WHOLE conversation so far, alternating user and assistant roles. To continue a chat, you append Claude's reply to your list and send everything again next call. The server stores nothing between calls.
Two rules the API enforces: roles must alternate (user, assistant, user, ...), and the last message is normally from user. Forget to append the assistant turn and Claude "forgets" its own previous answer - the #1 beginner bug.
A team built a support-ticket summarizer that "kept losing context" after the second question. The bug: they sent only the newest user message each call. One line - appending the assistant reply to history - fixed it. Cost implication too: since you resend history, long conversations grow in input tokens every turn. Production apps truncate or summarize old turns; 6.5 covers prompt caching, which makes resent history nearly free.
CoreSystem prompts: the standing instructions4 min▶
The system parameter is a separate top-level argument, not a message. It sets who Claude is for the whole conversation: role, rules, output format. The messages list then carries the actual work items.
Rule of thumb: if it should be true for EVERY turn (persona, rules, format, tone), it belongs in system. If it is this particular task's data or question, it belongs in a user message. Mixing them - stuffing documents into system, or repeating rules in every user turn - works, but degrades both steering and cost.
Streaming, JSON, and failure 13 min
Three patterns separate a demo from a tool people use: tokens that appear as they generate, output your code can parse, and calls that survive a bad network day.
CoreStreaming: tokens as they arrive4 min▶
A long answer can take 20+ seconds to finish. Without streaming your user stares at nothing; with it, text flows immediately - same total time, completely different experience. The SDK makes it a context manager:
Use streaming for anything a human watches (chat UIs, CLI tools, Streamlit apps). Skip it for batch pipelines - there, nobody is watching and the plain call is simpler code.
CoreStructured output: the JSON prefill trick5 min▶
Ask for JSON and Claude often adds a friendly preamble ("Here is the JSON you requested:") that breaks json.loads. The fix is prefilling: you supply the START of the assistant's answer as the last message, and Claude continues from it. Start it with { and there is nowhere for a preamble to go.
The pattern in one line: describe the exact schema in system, prefill {, glue it back on, json.loads before you trust anything. In 6.3 you will see tool use, which gives schema-enforced JSON - but this trick needs zero extra machinery and covers most extraction jobs.
AdvancedError handling and rate limits4 min▶
Two failures you WILL meet: 429 rate_limit_error when you send requests faster than your tier allows, and occasional 5xx or timeouts like any remote service. Both are retryable; the standard answer is exponential backoff.
Notes for real pipelines: the SDK already retries some errors by itself (tune with max_retries= on the client); rate limits are per model and measured in requests AND tokens per minute, so batch jobs should throttle on tokens; and a 400 means fix your request, not retry it. For huge offline jobs, the Batch API (half price, results within 24h) is usually the right tool - it comes up in 6.3.
Three builds ◐ 10 min in session, finish after
- 1 · CLI chat with memory. Take the chat loop from Part 2 and run it. Then break it on purpose: comment out the line that appends the assistant reply, ask a follow-up question, and watch Claude lose the thread. Put the line back. Now you understand multi-turn forever.
- 2 · The messy-email extractor. Use the prefill extractor from Part 3 on three real (anonymized) emails from your inbox - one clear, one rambling, one that is missing a field. Decide how your schema should represent "missing" (null? empty string?) and encode that in the system prompt.
- 3 · Stream a long answer. Ask for a 1000-word explanation of something from your actual domain with the streaming pattern, watching it render live. Then run the same request without streaming and feel the difference - that feeling is why every chat product streams.
Official courses covered
This page teaches the shared "Accessing Claude with the API" module from the three official 8-hour engineering courses at claude.com/resources/courses, plus the API fundamentals from Claude Platform 101.