← Blog

Claude API curl Request Example (Copy-Paste Ready)

2026-10-07 · 5 min read · SubToAPI Team

If you're looking for a Claude API curl request example that actually works on the first try, here it is:

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

That single request hits Anthropic's Messages endpoint, authenticates with your API key, and returns a JSON response containing Claude's reply. The rest of this article breaks down every part of that command, shows variations (streaming, system prompts, multi-turn conversations), and covers the most common errors people hit when testing the Claude API from the command line.

Why curl is the right first step

Before wiring Claude into a frontend, a backend service, or a CI pipeline, it's worth proving the request works with nothing but curl. It removes SDK version issues, framework quirks, and language-specific serialization bugs from the equation. If curl works, you know the problem is in your code, not your credentials or payload. If curl fails, you know it's a request or auth issue, not an app issue.

Breaking down the request

Endpoint: https://api.anthropic.com/v1/messages is the core endpoint for chat-style completions. There's no separate "completions" vs "chat" endpoint — Messages handles both single-turn and multi-turn conversations.

Headers: Three headers matter here:

Body fields:

Adding a system prompt

System prompts are a top-level field, not a message with role: "system":

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "system": "You are a terse technical writer. Answer in one short paragraph.",
    "messages": [
      {"role": "user", "content": "What is a REST API?"}
    ]
  }'

Multi-turn conversations

To continue a conversation, append the assistant's previous reply and the new user message to the messages array. Anthropic's API is stateless — it doesn't remember prior calls, so your client has to resend the full history each time:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "messages": [
      {"role": "user", "content": "What is the capital of France?"},
      {"role": "assistant", "content": "Paris."},
      {"role": "user", "content": "What is its population?"}
    ]
  }'

Streaming responses with curl

Add "stream": true and -N to disable curl's output buffering so you see tokens as they arrive:

curl -N https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "stream": true,
    "messages": [
      {"role": "user", "content": "Write a haiku about terminals."}
    ]
  }'

You'll get a stream of server-sent events (message_start, content_block_delta, message_stop, etc.) rather than one JSON blob.

Common curl errors and fixes

Turning your curl request into a production API

A raw curl command is fine for testing, but production apps usually need more: per-application API keys instead of one shared secret, usage tracking per key, team seat management, and a stable HTTPS surface you don't have to re-document every time Anthropic ships a new API version.

That's the gap SubToAPI fills. It takes your existing Claude access and exposes it as a clean HTTPS API with sub_live_... keys you can issue per app or per customer, full streaming support, tool use, and usage metadata in one dashboard — so the curl command above becomes:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "messages": [
      {"role": "user", "content": "Explain curl in one sentence."}
    ]
  }'

Same shape, same mental model, but with scoped keys and a dashboard instead of one shared secret buried in an environment variable. Start with a free trial at /signup, check the /docs/quickstart for the full setup, and see /docs/streaming and /docs/tools for the streaming and tool-use equivalents of the examples above.

FAQ

Do I need the Anthropic SDK to call the Claude API, or is curl enough? curl is enough for testing, scripting, and even production use if your stack doesn't need SDK conveniences like automatic retries or typed responses. Many teams use curl for quick checks and an SDK or a wrapper like SubToAPI for actual app code.

Why does my curl request return 401 even though I copied my key correctly? Check that you're using x-api-key, not Authorization: Bearer, for direct Anthropic API calls — mixing up auth schemes from other APIs is the most common cause. Also confirm the key hasn't been rotated or revoked in your account.

Can I test streaming with curl, or do I need a special tool? Plain curl works for streaming — just add "stream": true to the request body and pass -N to curl so it doesn't buffer the output before printing it.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →