Claude API Authentication Header Setup Guide
Setting up authentication for the Claude API comes down to sending one HTTP header correctly: x-api-key, along with an anthropic-version header that tells the API which API version to interpret your request against. Get these two headers wrong — missing, misnamed, or malformed — and every request fails with a 401 or 400 error before your prompt is even processed.
This guide walks through the exact header format Anthropic's API expects, the most common mistakes that cause authentication failures, and how to structure your setup so keys don't leak into logs or client-side code. It also covers how authentication differs if you're using a gateway like SubToAPI instead of calling Anthropic directly.
The required headers for Claude API authentication
A valid request to the Claude Messages API needs three headers:
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-opus-4-20250514",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello, Claude"}]
}'
Note what's not here: there is no Authorization: Bearer header for direct Anthropic API calls. This trips up a lot of developers coming from OpenAI's API, which does use the Bearer scheme. Anthropic uses a custom header name instead:
x-api-key— your raw API key, noBearerprefix, no quotesanthropic-version— a date string pinning the API schema version (e.g.2023-06-01)content-type: application/json— required for any request with a JSON body
If you copy-paste a Bearer-style header from another integration, you'll get a 401 even with a perfectly valid key, because the API never looks for an Authorization header on that endpoint.
Common authentication header mistakes
Using Authorization: Bearer instead of x-api-key. This is the single most frequent cause of "invalid authentication" errors when developers switch providers or copy code from ChatGPT-style examples.
Forgetting anthropic-version. Without it, some SDKs and raw HTTP clients will reject the request outright or default to behavior you didn't intend. Always pin it explicitly rather than relying on defaults that might change.
Including the key with extra whitespace or quotes. If you're loading the key from an environment variable in a shell script and it gets wrapped in quotes from a .env file, the header value ends up malformed. Always echo $ANTHROPIC_API_KEY to verify it's clean before debugging further.
Mixing up test and live keys across environments. Keys scoped to a workspace or project will fail silently against resources in a different workspace — the error looks identical to a bad key, which makes debugging slower than it needs to be.
Setting headers in JavaScript
If you're calling the API directly with fetch instead of the official SDK, the header setup looks like this:
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-opus-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello, Claude" }],
}),
});
Never hardcode the key string in this object. Pull it from process.env on the server side only — never from a browser-exposed config, since any key placed in client-side JavaScript is visible to anyone who opens dev tools.
Why your auth header setup matters for security
The header itself is simple, but how you manage the value behind it is where most real incidents happen. A few practices worth adopting from day one:
- Never commit keys to source control. Use
.envfiles with.gitignore, or a secrets manager in production. - Scope keys per environment. Separate keys for staging and production limit the blast radius if one leaks.
- Rotate on suspicion, not just on schedule. If a key appears in a log file, browser bundle, or error report, rotate it immediately rather than waiting.
- Avoid routing client requests directly to the API. Any mobile app or browser-based client that embeds a raw API key can have that key extracted. Route through your own backend, or through a gateway that issues scoped keys per application.
An alternative: application-level keys through SubToAPI
If you're building a product on top of Claude rather than a single internal script, raw Anthropic keys create a problem: you likely want different keys per application, per customer, or per environment, with their own usage visibility — not one shared key passed around your codebase.
SubToAPI sits between your app and Claude, issuing its own sub_live_... application keys that you authenticate with using a standard Authorization: Bearer $SUBTOAPI_KEY header:
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-4-20250514",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello, Claude"}]
}'
This gives you the familiar Bearer token pattern most HTTP tooling expects, while each key stays tied to usage metadata, streaming support, and tool-use configuration in one dashboard. You can issue separate keys per app or per team member without rotating a single shared Anthropic credential every time someone leaves. See the quickstart for the full setup, or the Messages API reference for request and response formats. Plans start with a free trial at signup, with details on pricing.
questions
Why do I get a 401 error even though my API key looks correct? Almost always it's the header format, not the key. Confirm you're sending x-api-key rather than Authorization: Bearer, that there's no extra whitespace or quoting around the value, and that anthropic-version is present on the request.
Can I use the same authentication header format across different Claude API endpoints? Yes. Every endpoint on api.anthropic.com uses the same x-api-key plus anthropic-version pattern. If you're using a gateway like SubToAPI instead, it's a standard Authorization: Bearer header across all its endpoints, including streaming and tool use.
Should I ever put my API key directly in frontend JavaScript? No. Any key embedded in client-side code is visible to end users via browser dev tools. Keep authentication headers set on server-side requests only, or issue scoped, revocable keys per application through a gateway layer.