Building with the API

Your First Claude API Request: curl, Python, Node

3 min read

Everything in the Claude API goes through one endpoint: POST https://api.anthropic.com/v1/messages.

1. Key and environment variable

Create a key in the Claude Console under Settings → API keys, then export it. Never hardcode it in source or commit it:

export ANTHROPIC_API_KEY="your-api-key-here"

That puts the key where every Anthropic SDK looks by default — no api_key= argument needed anywhere below.

2. curl

curl https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-opus-5",
    "max_tokens": 1000,
    "messages": [{"role": "user", "content": "Explain HTTP 429 in one sentence."}]
  }'

Sends one user turn and returns a JSON message. anthropic-version and max_tokens are both required — omit either and you get a 400.

3. Python

pip install anthropic
import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY

message = client.messages.create(
    model="claude-opus-5",
    max_tokens=1000,
    messages=[{"role": "user", "content": "Explain HTTP 429 in one sentence."}],
)

for block in message.content:
    if block.type == "text":
        print(block.text)

The same call through the SDK, with retries and timeouts handled for you.

4. Node

npm install @anthropic-ai/sdk
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic(); // reads ANTHROPIC_API_KEY

const message = await client.messages.create({
  model: "claude-opus-5",
  max_tokens: 1000,
  messages: [{ role: "user", content: "Explain HTTP 429 in one sentence." }],
});

const text = message.content.find((b) => b.type === "text");
console.log(text.text);

Identical request shape — the SDKs are thin wrappers over the same JSON.

5. Read the response

{
  "id": "msg_013mHbppMPd2PrVJzGMZPt2D",
  "model": "claude-opus-5",
  "role": "assistant",
  "content": [{ "type": "text", "text": "..." }],
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 21, "output_tokens": 305 }
}

content is an array of blocks — check type before touching .text, because a reply can also contain thinking or tool_use blocks. stop_reason: "end_turn" means Claude finished; "max_tokens" means you truncated it.

Picking a model

claude-opus-5 is the current general recommendation; claude-sonnet-5 is cheaper and faster, claude-haiku-4-5 cheaper still. Model IDs change — take the exact string from the models page rather than copying an old one.


Next: tool use · streaming responses.

Open the full interactive version (with copy buttons) ↗

← All guides