The Claude API becomes remarkably easy to work with once you've made that very first call. From wiring up my own services as an indie developer, I've found the hard part isn't grasping the concepts — it's knowing the right order to get a minimal setup running. This guide lays out that path, from getting your API key to your first Python and TypeScript request, so you can reach a working call in five minutes. Toward the end, I've added the two things you hit right after that first success: error handling and a sense of what it costs.
What is the Claude API?
The Claude API lets you integrate Claude's capabilities into your own applications. Through Anthropic's developer platform, you can programmatically access text generation, code generation, analysis, summarization, and more.
Getting Your API Key
- Visit console.anthropic.com
- Create an account or log in
- Navigate to the "API Keys" section and create a new key
- Save the key securely (it's only shown once)
# Set as environment variable
export ANTHROPIC_API_KEY="YOUR_API_KEY"Make one rule non-negotiable from the start: never hardcode the key in source. Reading it from an environment variable keeps it out of accidental commits.
Python SDK
Installation
pip install anthropicYour First Request
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from the environment
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "Write a prime number checker in Python"}
]
)
print(message.content[0].text)The model string has to match a name from the official model list exactly. A single wrong character returns an error, so this is where most first attempts stall.
Streaming Responses
For real-time output:
with client.messages.stream(
model="claude-sonnet-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "Explain the basics of machine learning"}
]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)TypeScript SDK
Installation
npm install @anthropic-ai/sdkYour First Request
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic(); // reads ANTHROPIC_API_KEY from the environment
const message = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [
{ role: "user", content: "Implement FizzBuzz in TypeScript" }
],
});
console.log(message.content[0].text);Key Parameters
| Parameter | Description | Example |
|---|---|---|
model | Model to use | claude-opus-4-8, claude-sonnet-5 |
max_tokens | Maximum output tokens | 1024, 4096 |
temperature | Randomness (0–1) | 0 = deterministic, 1 = creative |
system | System prompt | "You are a Python expert" |
stop_sequences | Stop strings (generation halts on a match) | ["<END>"] |
Using System Prompts
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
system="You are a senior software engineer. Always include code examples and comment on performance.",
messages=[
{"role": "user", "content": "What are effective caching strategies?"}
]
)Minimal Error Handling
Once the first sample works, the next thing you meet is errors. In real use, you only feel safe firing off requests after you've decided how the code behaves when a call fails. The SDK separates exceptions by type, so at minimum, catching rate limits, input errors, and other transport errors separately makes root-cause triage much faster.
import anthropic
client = anthropic.Anthropic()
try:
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
)
print(message.content[0].text)
except anthropic.RateLimitError:
# 429: wait and retry. Exponential backoff is the standard move
print("Rate limit hit. Wait a moment and retry.")
except anthropic.BadRequestError as e:
# 400: wrong model name, max_tokens exceeded — a mistake on your side
print(f"Bad request: {e}")
except anthropic.APIStatusError as e:
# Other server-side errors. Branch on status_code
print(f"API error ({e.status_code}): {e.message}")The mistake that burned me in my own projects was swallowing RateLimitError and retrying instantly, which only made the throttling worse. When you get a 429, always insert a wait before retrying. That one habit is what keeps an overnight batch stable.
Tool Use (Function Calling)
The Claude API supports calling external functions:
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get weather for a given city",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name (e.g., Tokyo)"
}
},
"required": ["city"]
}
}
],
messages=[
{"role": "user", "content": "What's the weather in Tokyo?"}
]
)Choosing the Right Model
| Model | Strengths | Best For |
|---|---|---|
| Claude Opus 4.8 | Highest capability, deep reasoning | Complex analysis, high-quality code |
| Claude Sonnet 5 | Balanced speed and quality | Everyday tasks, chatbots |
| Claude Haiku 4.5 | Fastest, lowest cost | High-volume processing, classification |
For a first build, starting with Sonnet 5 is the natural choice: the balance of speed and quality lets you get a feel for it while iterating. If accuracy falls short, move up to Opus 4.8; if you're running high-volume classification or summarization, drop down to Haiku 4.5. Ship on something, then tune to the workload — in my experience that's the fastest path.
Get a Sense of Cost Early
The API bills per token. Free credits cover your first experiments, but before you put anything into production, it helps to have a feel for the unit price so the bill doesn't surprise you later.
Sonnet 5 carries introductory pricing of $2 per million input tokens and $10 per million output tokens, in effect through August 31, 2026 (after which it returns to $3 / $15). So a request with 50K input and 10K output tokens lands around $0.1 + $0.1 = roughly $0.2 — that's the order of magnitude to keep in mind.
Pitfalls Right After Your First Call
The most common one is the model-name issue above. Version strings change, so rather than pasting a name from an article or an old sample, confirm the current string in the official docs before you pass it.
Next is max_tokens. It caps the output, not the input length. If a response feels cut off, suspect max_tokens first. Set it too high, though, and you pay for output you didn't need.
Missing environment variables are another classic. Anthropic() auto-discovers ANTHROPIC_API_KEY, but reopening a terminal can wipe the export. When you hit an auth error, the quickest check is echo $ANTHROPIC_API_KEY to confirm the value is actually set.
Next Steps
- Vision (Image Input) — Analyze and describe images via the API
- Advanced Tool Use — Automate complex multi-step workflows
- Batch Processing — Handle large volumes of requests efficiently
- MCP Integration — Connect services with Model Context Protocol
Run the official minimal sample untouched, then rewrite it into the smallest version of your own use case. Add one piece of error handling, and get a feel for the cost. Follow that order, and the call you got working in five minutes becomes a foundation you can actually ship on.