Anthropic Claude API — Getting Started Guide 2026

Sanjeev SharmaSanjeev Sharma
5 min read

Advertisement

Introduction

Why This Matters

The Anthropic Claude API provides programmatic access to Claude 3.5 Sonnet, Haiku, and Opus — enabling you to build AI features into your applications without managing model infrastructure. Understanding the API's specific design choices — the system parameter structure, content blocks, tool use flow, and prompt caching — is essential to build correct and cost-efficient applications from day one.

Account Setup

  1. Go to console.anthropic.com and create an account
  2. Navigate to API Keys and generate a key
  3. New accounts receive free trial credits (~$5 USD)
  4. Set up billing for production usage
# Store securely — never commit to source control
export ANTHROPIC_API_KEY="sk-ant-api03-..."
 
# Install the Python SDK
pip install anthropic
 
# Install the Node.js SDK
npm install @anthropic-ai/sdk

First API Call — Python

import anthropic
 
client = anthropic.Anthropic()
# Reads ANTHROPIC_API_KEY from environment automatically
 
message = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    system="You are a concise technical assistant. Answer in 2-3 sentences.",
    messages=[
        {
            "role": "user",
            "content": "What is the difference between a process and a thread?",
        }
    ],
)
 
print(message.content[0].text)
print(f"\nInput tokens: {message.usage.input_tokens}")
print(f"Output tokens: {message.usage.output_tokens}")

Key structural differences from the OpenAI API:

  • system is a top-level parameter, not a message with role: "system"
  • content returns a list of content blocks — access text with .content[0].text
  • stop_reason instead of finish_reason
  • Usage is in message.usage.input_tokens / message.usage.output_tokens

First API Call — JavaScript/TypeScript

import Anthropic from '@anthropic-ai/sdk';
 
const client = new Anthropic();
 
async function askClaude(question: string): Promise<string> {
  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 1024,
    system: 'You are a helpful coding assistant.',
    messages: [{ role: 'user', content: question }],
  });
 
  const block = message.content[0];
  if (block.type !== 'text') throw new Error('Unexpected content type');
  return block.text;
}
 
const answer = await askClaude('Explain async/await in JavaScript.');
console.log(answer);

Multi-Turn Conversations

import anthropic
 
client = anthropic.Anthropic()
 
messages = []
 
def send(user_message: str, system: str = "") -> str:
    messages.append({"role": "user", "content": user_message})
 
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=2048,
        system=system,
        messages=messages,
    )
 
    reply = response.content[0].text
    messages.append({"role": "assistant", "content": reply})
    return reply
 
system = "You are a Python code reviewer. Be specific and provide corrected code."
 
print(send("Review this login function: def login(u, p): return db.get(u).password == p", system))
print(send("Now add JWT token generation to the fixed version."))
print(send("What's the best way to test this with pytest?"))

Streaming

import anthropic
 
client = anthropic.Anthropic()
 
def stream_response(prompt: str) -> str:
    full_text = ""
 
    with client.messages.stream(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}],
    ) as stream:
        for text_chunk in stream.text_stream:
            print(text_chunk, end="", flush=True)
            full_text += text_chunk
 
    print()  # New line after streaming completes
    return full_text
 
stream_response("Explain how TCP/IP handshake works step by step.")

Vision — Analyzing Images

import anthropic
import base64
 
client = anthropic.Anthropic()
 
def analyze_image(image_path: str, question: str) -> str:
    with open(image_path, "rb") as f:
        image_data = base64.standard_b64encode(f.read()).decode("utf-8")
 
    ext = image_path.rsplit(".", 1)[-1].lower()
    media_types = {"png": "image/png", "jpg": "image/jpeg", "jpeg": "image/jpeg", "gif": "image/gif"}
    media_type = media_types.get(ext, "image/png")
 
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "media_type": media_type,
                            "data": image_data,
                        },
                    },
                    {"type": "text", "text": question},
                ],
            }
        ],
    )
 
    return response.content[0].text
 
result = analyze_image(
    "architecture_diagram.png",
    "Describe this system architecture and identify any potential bottlenecks."
)

Prompt Caching

Prompt caching reduces costs by caching frequently reused prompt prefixes (system prompts, document context). Cached tokens cost 90% less on subsequent requests.

import anthropic
 
client = anthropic.Anthropic()
 
LARGE_SYSTEM_PROMPT = """
You are a code review assistant for a large Python codebase.
Coding standards: [... very long standards document ...]
Security requirements: [... detailed security policies ...]
"""  # Imagine this is 5,000+ tokens
 
def review_with_cache(code: str) -> str:
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        system=[
            {
                "type": "text",
                "text": LARGE_SYSTEM_PROMPT,
                "cache_control": {"type": "ephemeral"},  # Cache this prefix
            }
        ],
        messages=[{"role": "user", "content": f"Review:\n\n{code}"}],
    )
 
    # Check cache performance
    usage = response.usage
    print(f"Cache read tokens: {usage.cache_read_input_tokens}")
    print(f"Cache write tokens: {usage.cache_creation_input_tokens}")
 
    return response.content[0].text

Cache hits on a 5,000-token system prompt reduce cost from 0.015to0.015 to 0.0015 per review — 10x cheaper after the first call.

Common Mistakes

  • Using role: "system" as a message role — Claude's API puts system in a top-level parameter, not in messages
  • Not accessing .content[0].text — returning the raw content list instead of the text
  • Ignoring stop_reason — not checking for "max_tokens" means truncated responses go undetected
  • Sending images as URLs without checking if the model can reach them — use base64 encoding for reliability
  • Skipping prompt caching on applications with large repeated system prompts — leaves 90% cost reduction on the table

Best Practices

  • Always log input_tokens and output_tokens from message.usage for cost tracking
  • Use Haiku for real-time, high-volume tasks; Sonnet for most production tasks; Opus for maximum reasoning
  • Enable prompt caching for any system prompt longer than 1,024 tokens to reduce repeated-request costs
  • Set max_tokens on every request — unexpected long responses inflate cost without limit
  • Handle stop_reason == "max_tokens" — detect and handle truncated responses before using them

Key Takeaways

  • The system parameter is top-level in Claude's API — not a role: "system" message like in OpenAI's API
  • Response text is in message.content[0].text — content is a list of typed blocks
  • Streaming uses client.messages.stream() context manager and yields via .text_stream
  • Vision requests pass images as base64-encoded content blocks with type: "image" and source.type: "base64"
  • Prompt caching reduces cost of cached tokens by 90% — essential for applications with large repeated system prompts
  • All three model tiers (Sonnet, Haiku, Opus) share the 200K-token context window
  • stop_reason == "max_tokens" indicates a truncated response — always check this in production
  • New API accounts receive free trial credits; billing setup is required for production-scale usage

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro

Related reading