Almost every 401 has one of four causes, and only one is “the key is wrong.” The other three leave the key perfectly valid — which is why recreating the key is usually wasted effort.
The error
{
"type": "error",
"error": { "type": "authentication_error",
"message": "invalid x-api-key" }
}Causes and fixes at a glance
| Cause | Fix |
|---|---|
| Wrong header for the host | Anthropic reads x-api-key; most OpenAI-compatible gateways read Authorization: Bearer. The same value in the wrong header arrives as absent. |
| Stale environment variable left behind | A forgotten ANTHROPIC_API_KEY in your shell profile may override the one you just exported. |
| Base URL changed without changing the credential | Pointing to another host does not make the previous provider's key valid there. Host and credential must change together. |
| A space, line break, or quotation mark in the key | Copying from a PDF or chat often brings invisible characters. Check the string length. |
Check what the environment actually contains
Before changing anything, inspect the variables in the same shell that runs the application. A surprising number of cases have two credentials defined at the same time, from different providers.
for v in ANTHROPIC_API_KEY ANTHROPIC_AUTH_TOKEN ANTHROPIC_BASE_URL; do
printf '%-22s [%s] tamanho=%s\n' \
"$v" "$(printenv "$v" | cut -c1-10)" "$(printenv "$v" | wc -c)"
doneTest the credential outside the application
A direct request distinguishes "the host rejects the key" from "the application does not send the key." If curl works and the code does not, the problem is not the credential.
curl -s -o /dev/null -w 'status=%{http_code}\n' \
"$ANTHROPIC_BASE_URL/v1/models" \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN"
# 200 -> credencial boa; investigue a aplicação
# 401 -> credencial ou cabeçalho errados para este hostDistinguish 401 from 403 and 402
401 means "I don't know who you are": the credential was not accepted. 403 means "I know who you are and you may not": authenticated, without permission. 402 means "I know who you are and you are out of balance." Only 401 is fixed by changing the credential.
If you’re calling through Kunavo
Kunavo accepts the sk-kn- key in both Authorization: Bearer and x-api-key, and the base URL is the site's origin with no path afterward. With Claude Code, use ANTHROPIC_AUTH_TOKEN together with ANTHROPIC_BASE_URL, because the token does not depend on the one-time approval required by ANTHROPIC_API_KEY, and explicitly remove ANTHROPIC_API_KEY — an old value in that variable is the most common cause of a session that appears configured but still rejects requests. The authentication walkthrough is in the authentication documentation.
Frequently asked questions
Will recreating the key fix it?
Only if the key was actually revoked. For the other three common causes — wrong header, stale variable, changed base URL — the new key fails exactly the same way.
Can 401 mean insufficient balance?
No. Insufficient balance is 402, with a message mentioning credits. 401 is always about identity.
It works with curl and fails in my code. Why?
Almost always, the code reads a different environment variable or runs in another shell/container where the export did not arrive. Print the masked credential inside the process to confirm.
Related guides
- Claude API 429 rate_limit_error — what it means and how to fix it
- 529 overloaded_error in the Claude API — what it means and how to handle it
- Claude API 401 authentication_error / invalid x-api-key — every cause
More error semantics live in the error reference; getting a key takes a minute via signing up and the authentication guide.