Intermediate

Claude API Basics

Learn to integrate Claude into your applications using the Messages API. Make your first API call with curl, Python, and JavaScript.

What is the Claude API?

The Claude API gives you programmatic access to Claude's capabilities. Instead of chatting through a web interface, you send HTTP requests and receive responses — enabling you to build Claude into your own applications, tools, and workflows.

The API uses the Messages API format, where you send a list of messages (similar to a conversation) and receive Claude's response. This is the same interface whether you are building a chatbot, a content pipeline, or a code analysis tool.

💡
Prerequisites: This lesson assumes basic familiarity with REST APIs and at least one programming language. You will need an Anthropic API key to follow along.

Getting an API Key

  1. Create an Anthropic account

    Go to console.anthropic.com and sign up. This is separate from your claude.ai account.

  2. Navigate to API Keys

    In the console, go to "API Keys" in the left sidebar.

  3. Create a new key

    Click "Create Key," give it a name, and copy the key. Store it securely — you will not be able to see it again.

  4. Set up billing

    Add a payment method in "Billing." The API uses pay-as-you-go pricing based on token usage. New accounts typically receive a small amount of free credits.

Security: Never hardcode your API key in source code. Use environment variables instead. Never commit API keys to git repositories. If a key is exposed, revoke it immediately in the console.

Making Your First API Call

Here is how to call the Claude API in three different ways. Each example sends the same request and receives the same response.

curl

Bash (curl)
# Set your API key as an environment variable
export ANTHROPIC_API_KEY="sk-ant-your-key-here"

# Make a request to 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-sonnet-4-20250514",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "user",
        "content": "What is the capital of France? Reply in one sentence."
      }
    ]
  }'

Python

Python
# Install: pip install anthropic
import anthropic

# The client reads ANTHROPIC_API_KEY from environment
client = anthropic.Anthropic()

message = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "What is the capital of France? Reply in one sentence."
        }
    ]
)

print(message.content[0].text)
# Output: The capital of France is Paris.

JavaScript / TypeScript

JavaScript
// Install: npm install @anthropic-ai/sdk
import Anthropic from '@anthropic-ai/sdk';

// Reads ANTHROPIC_API_KEY from environment
const client = new Anthropic();

const message = await client.messages.create({
  model: 'claude-sonnet-4-20250514',
  max_tokens: 1024,
  messages: [
    {
      role: 'user',
      content: 'What is the capital of France? Reply in one sentence.',
    },
  ],
});

console.log(message.content[0].text);
// Output: The capital of France is Paris.

Understanding the Messages API

Every API call uses the same core structure. Here are the key parameters:

Parameter Required Description
model Yes Which Claude model to use (e.g., claude-sonnet-4-20250514)
max_tokens Yes Maximum number of tokens in Claude's response
messages Yes Array of message objects with role and content
system No System prompt that sets Claude's behavior
temperature No Randomness (0.0-1.0). Default: 1.0
stream No Enable streaming responses (true/false)

Request / Response Format

Full Request with System Prompt

Python
import anthropic

client = anthropic.Anthropic()

message = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    temperature=0.0,
    system="You are a helpful coding assistant. Respond only with code, no explanations.",
    messages=[
        {
            "role": "user",
            "content": "Write a Python function to reverse a string."
        }
    ]
)

# Access the response
print(message.content[0].text)
print(f"Tokens used: {message.usage.input_tokens} in, {message.usage.output_tokens} out")

Response Object Structure

JSON Response
{
  "id": "msg_01XFDUDYJgAACzvnptvVoYEL",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "def reverse_string(s: str) -> str:\n    return s[::-1]"
    }
  ],
  "model": "claude-sonnet-4-20250514",
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 25,
    "output_tokens": 14
  }
}

Multi-Turn Conversation

Python
# Conversations are built by alternating user/assistant messages
message = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "What is the largest planet?"
        },
        {
            "role": "assistant",
            "content": "Jupiter is the largest planet in our solar system."
        },
        {
            "role": "user",
            "content": "How many moons does it have?"
        }
    ]
)

# Claude knows "it" refers to Jupiter from the conversation
print(message.content[0].text)

Streaming Responses

Streaming lets you receive Claude's response token-by-token as it generates, rather than waiting for the complete response. This improves perceived latency in interactive applications.

Python - Streaming
import anthropic

client = anthropic.Anthropic()

# Use stream() for streaming responses
with client.messages.stream(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "Explain quantum computing in simple terms."
    }]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
JavaScript - Streaming
import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic();

const stream = client.messages.stream({
  model: 'claude-sonnet-4-20250514',
  max_tokens: 1024,
  messages: [{
    role: 'user',
    content: 'Explain quantum computing in simple terms.',
  }],
});

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

Error Handling

The API returns standard HTTP error codes. Here are the ones you should handle:

Status Code Meaning Action
400 Bad Request Fix your request format or parameters
401 Unauthorized Check your API key
403 Forbidden Your key lacks permission for this action
429 Rate Limited Wait and retry with exponential backoff
500 Server Error Retry after a brief delay
529 Overloaded API is busy; retry with backoff
Python - Error Handling
import anthropic
import time

client = anthropic.Anthropic()

def call_claude(prompt: str, retries: int = 3) -> str:
    """Call Claude with retry logic."""
    for attempt in range(retries):
        try:
            message = client.messages.create(
                model="claude-sonnet-4-20250514",
                max_tokens=1024,
                messages=[{
                    "role": "user",
                    "content": prompt
                }]
            )
            return message.content[0].text

        except anthropic.RateLimitError:
            wait = 2 ** attempt  # Exponential backoff
            print(f"Rate limited. Waiting {wait}s...")
            time.sleep(wait)

        except anthropic.APIStatusError as e:
            print(f"API error: {e.status_code} - {e.message}")
            if e.status_code >= 500:
                time.sleep(1)
                continue
            raise

    raise Exception("Max retries exceeded")

# Usage
result = call_claude("Explain REST APIs in 3 sentences.")
print(result)
Best practice: Always implement retry logic with exponential backoff for 429 (rate limit) and 5xx (server) errors. The official Python and TypeScript SDKs include automatic retry handling by default.