Skip to content
Claudekit.ai

Claude API Tutorial: First Request in curl, Python and TS

Claude API tutorial for 2026: make your first Anthropic API request in curl, Python and TypeScript, then add streaming, multi-turn chat and tool use.

By Claudekit Team Published 8 min read

Quick answer: The Claude API (also called the Anthropic API) is the HTTP interface to Anthropic’s Claude models. You create an API key in the Claude Console, then send a POST request to https://api.anthropic.com/v1/messages with a model ID such as claude-opus-5-5 and a list of messages. Official SDKs for Python and TypeScript wrap the same endpoint.

This tutorial takes you from zero to a working request in curl, Python and TypeScript, then adds the three things every real app needs: conversation history, streaming and tool use. Every code shape below was checked against Anthropic’s official docs on October 24, 2026.

What you need before you start

RequirementWhere to get itNotes
Claude Console accountplatform.claude.comSeparate from a Claude.ai chat subscription
API creditsConsole, Settings, BillingMost organizations pay with prepaid credits
API keyConsole, API keys pageShown once, starts with sk-ant-
Python 3 or Node.jsYour machineOnly for the SDK examples

If you don’t have a key yet, follow our Claude API key guide. It covers creating, storing and rotating keys, plus the errors you’ll see when something is off.

Set the key once in your shell. Both SDKs read ANTHROPIC_API_KEY automatically, so you never paste it into code:

export ANTHROPIC_API_KEY="sk-ant-..."

Step 1: Your first request with curl

Every Claude API call goes through one endpoint: the Messages API.

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-5",
    "max_tokens": 1000,
    "messages": [
      {"role": "user", "content": "Explain what an API rate limit is in two sentences."}
    ]
  }'

Three headers matter:

  • x-api-key carries your key. Anthropic’s authentication docs also accept Authorization: Bearer with the key; x-api-key is the legacy form and still supported.
  • anthropic-version: 2023-06-01 pins the API version.
  • content-type: application/json.

The response is JSON. The text lives in a content array of blocks, and usage tells you how many input and output tokens you were billed for:

{
  "id": "msg_...",
  "type": "message",
  "role": "assistant",
  "model": "claude-opus-5-5",
  "content": [{ "type": "text", "text": "An API rate limit caps..." }],
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 21, "output_tokens": 48 }
}

To print only the text, pipe the output through jq -r '.content[] | select(.type == "text") | .text'.

Step 2: The same request in Python

Install the official SDK in a virtual environment:

python3 -m venv .venv && source .venv/bin/activate
pip install anthropic
import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY

message = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1000,
    messages=[
        {"role": "user", "content": "Explain what an API rate limit is in two sentences."}
    ],
)

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

Always check block.type before reading .text. Responses can contain other block types, such as thinking or tool_use, and current models think before answering.

Step 3: The same request in TypeScript

npm init -y
npm pkg set type=module
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-5",
  max_tokens: 1000,
  messages: [
    { role: "user", content: "Explain what an API rate limit is in two sentences." },
  ],
});

for (const block of message.content) {
  if (block.type === "text") {
    console.log(block.text);
  }
}

Run it with npx tsx quickstart.ts. Anthropic also publishes official SDKs for Go, Java, C#, PHP and Ruby, plus an ant command-line tool.

Choosing a model

The model field decides capability, speed and price. These are the current models listed on Anthropic’s models overview, with standard API prices as of October 24, 2026:

ModelAPI IDBest forInput / output per 1M tokens
Claude Fable 5.1claude-fable-5-1Demanding reasoning, long-horizon agents$10 / $50
Claude Opus 5.5claude-opus-5-5Recommended starting point for most work$4 / $20
Claude Sonnet 5.5claude-sonnet-5-5Balance of speed and intelligence$2 / $10
Claude Haiku 5.5claude-haiku-5-5High-volume classification, extraction, routingFrom $0.10 / from $0.50

All four have a 1M-token context window and up to 128K output tokens. Our Claude models explained guide covers how to pick, and the Claude API pricing guide works through real cost examples, including caching and batch discounts.

One API detail worth knowing: Opus 5.5 always uses adaptive thinking, and you steer depth with the effort parameter (its default is medium). You don’t need to set anything for a first request.

Step 4: System prompts and multi-turn conversations

The API is stateless. Claude does not remember earlier requests, so you send the whole conversation every time. Put stable instructions in system and alternate user and assistant turns in messages:

history = [
    {"role": "user", "content": "My name is Ana and I write Go."},
    {"role": "assistant", "content": "Nice to meet you, Ana. How can I help with Go?"},
    {"role": "user", "content": "Suggest a name for a CLI that renames photos."},
]

reply = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1000,
    system="You are a concise senior engineer. Answer in at most three bullet points.",
    messages=history,
)

To continue, append Claude’s reply as an assistant message, then add the next user message. Two rules save debugging time:

  • The last message must be from the user. Current models reject “prefilled” assistant turns with a 400 error.
  • Append the full content of each reply, not just the text, once you use tools or thinking.

For writing better system prompts, see our Claude prompting best practices.

Step 5: Stream the response

Long answers take time. Streaming sends text as it’s generated over server-sent events, so users see output immediately, and it avoids timeouts on large max_tokens values. Anthropic recommends streaming for long-running requests.

Python:

with client.messages.stream(
    model="claude-opus-5-5",
    max_tokens=64000,
    messages=[{"role": "user", "content": "Write a short story about a lighthouse."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

TypeScript:

const stream = client.messages.stream({
  model: "claude-opus-5-5",
  max_tokens: 64000,
  messages: [{ role: "user", content: "Write a short story about a lighthouse." }],
});

for await (const event of stream) {
  if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
    process.stdout.write(event.delta.text);
  }
}

If you only want the finished message without handling events, call stream.get_final_message() in Python or await stream.finalMessage() in TypeScript. With curl, add "stream": true to the body and you’ll get raw events.

Step 6: Tool use basics

Tool use (function calling) lets Claude ask your code to do something: look up an order, query a database, call another API. The round trip has four parts:

  1. You describe a tool with a name, description and JSON Schema input_schema.
  2. Claude replies with stop_reason: "tool_use" and a tool_use block containing arguments.
  3. Your code runs the function.
  4. You send the output back in a tool_result block that references the tool_use block’s id.
import anthropic

client = anthropic.Anthropic()

tools = [{
    "name": "get_weather",
    "description": "Get the current weather for a given location.",
    "input_schema": {
        "type": "object",
        "properties": {
            "location": {"type": "string", "description": "City and state, e.g. San Francisco, CA"}
        },
        "required": ["location"],
    },
}]
messages = [{"role": "user", "content": "What's the weather in San Francisco?"}]

response = client.messages.create(
    model="claude-opus-5-5", max_tokens=1024, tools=tools, messages=messages
)

if response.stop_reason == "tool_use":
    tool_use = next(b for b in response.content if b.type == "tool_use")
    weather = "15 degrees Celsius, partly cloudy"  # call your real weather service here

    messages += [
        {"role": "assistant", "content": response.content},
        {"role": "user", "content": [
            {"type": "tool_result", "tool_use_id": tool_use.id, "content": weather}
        ]},
    ]
    followup = client.messages.create(
        model="claude-opus-5-5", max_tokens=1024, tools=tools, messages=messages
    )
    print(next(b.text for b in followup.content if b.type == "text"))

A few things the docs call out:

  • These are client tools: your app runs them. Server tools such as web search, web fetch and code execution run on Anthropic’s infrastructure; you just declare them.
  • On Opus 5.5 and Sonnet 5.5, forcing a specific tool with tool_choice set to any or tool returns a 400. Leave the default auto and describe the tool clearly, or add strict: true to the tool definition for schema-valid inputs.
  • To skip writing the loop yourself, the SDKs include a tool runner helper that executes your functions and sends results back automatically.

Want Claude to reach tools that already exist as MCP servers? Read what is MCP, then build an MCP server in TypeScript.

Step 7: Errors, retries and rate limits

The API returns JSON errors with a type, a message and a request_id. The ones you’ll meet first:

StatusError typeUsual cause
400invalid_request_errorMalformed body, unsupported parameter, or a spend limit you set
401authentication_errorMissing, malformed, revoked or expired key
402billing_errorPayment or billing problem
403permission_errorKey lacks access to the resource or workspace
429rate_limit_errorRate limit or monthly spend cap reached
529overloaded_errorAPI temporarily overloaded

The official SDKs retry connection errors, 429s and 5xx errors twice by default with exponential backoff, honouring the retry-after header. Catch the SDK’s typed exceptions (for example anthropic.RateLimitError) rather than matching error strings.

Rate limits are set per organization by usage tier and measured in requests, input tokens and output tokens per minute. Cached input tokens don’t count toward the input limit on most models, which makes prompt caching a cheap way to raise throughput. Check your tier on the Console’s rate limits page.

Where to go next

GoalFeatureWhy it matters
Cut cost on repeated contextPrompt cachingCache reads cost a fraction of base input price
Process thousands of requestsMessage Batches API50% off, results arrive asynchronously
JSON you can parse safelyStructured outputsConstrains the response to your schema
An agent with file and shell toolsClaude Agent SDKThe Claude Code harness as a library
A hosted agentManaged AgentsAnthropic runs the loop and the sandbox

Our Claude agents guide explains when to move from plain API calls to the Agent SDK or Managed Agents. If you’d rather have Claude write the integration for you, the Claude API skill gives Claude Code up-to-date SDK patterns, and what is Claude Code explains the agent itself.

For the canonical reference, Anthropic’s get started guide and models overview are the sources we checked this page against.

Frequently asked questions

Is the Claude API the same as the Anthropic API?

Yes. Anthropic's docs call it the Claude API and note that its keys are also called Anthropic API keys. Requests go to api.anthropic.com, and the official SDKs are the anthropic package on PyPI and @anthropic-ai/sdk on npm.

Is the Claude API free?

No. The API is billed per token, separately from Claude.ai subscriptions. Most organizations buy prepaid credits in the Claude Console. As of October 24, 2026, Claude Opus 5.5 costs $4 per million input tokens and $20 per million output tokens.

Which model ID should I use?

Anthropic's models overview recommends starting with Claude Opus 5.5 (claude-opus-5-5) for most workloads. Use claude-sonnet-5-5 for a faster, cheaper balance, claude-haiku-5-5 for high-volume simple tasks, and claude-fable-5-1 for the hardest long-horizon work.

Do I need a Claude Pro subscription to use the API?

No. A Claude Pro plan covers the Claude apps and Claude Code, not API calls. The API needs a Claude Console account with credits and an API key, billed per token. Max and Team plans include a monthly allowance of API credits.

Get the weekly Claude digest

New skills, MCP servers, prompts and Claude updates — one short email a week. No spam, unsubscribe anytime.

The newsletter is launching soon. Follow the RSS feed in the meantime.