These are not aliases. One becomes `x-api-key`, the other becomes `Authorization: Bearer` — and when both are set, the one you did not mean to use can win. Most "my key is correct but auth fails" reports against a custom base URL are this.
The error
# Sent as: x-api-key: <value>
export ANTHROPIC_API_KEY="sk-ant-..."
# Sent as: Authorization: Bearer <value>
export ANTHROPIC_AUTH_TOKEN="sk-kn-..."
# Where those headers go:
export ANTHROPIC_BASE_URL="https://api.kunavo.com"Causes and fixes at a glance
| Cause | Fix |
|---|---|
| Gateway expects a bearer token; you set the API key variable | Most OpenAI-compatible gateways authenticate on `Authorization: Bearer`. Put the gateway key in ANTHROPIC_AUTH_TOKEN. |
| Both variables set, from different providers | A stale ANTHROPIC_API_KEY in your shell profile can be sent alongside the token. Unset the one you are not using. |
| Base URL set, credentials not changed | Pointing at a new host does not make an old provider's key valid there. The credential has to change with the host. |
| Variable set in a different shell than the one running the tool | An export in an interactive shell does not reach a GUI-launched process. Verify inside the same environment. |
See what your environment is actually holding
Check both, in the shell that launches the tool, before changing anything. A surprising share of these sessions have both set — often one from a months-old profile edit nobody remembers.
for v in ANTHROPIC_API_KEY ANTHROPIC_AUTH_TOKEN ANTHROPIC_BASE_URL; do
printf '%-22s %s\n' "$v" "$(printenv "$v" | cut -c1-12)"
done
# Prefixes tell you the provider at a glance:
# sk-ant- Anthropic direct
# sk-kn- KunavoSet the pair that matches your host, and unset the other
Treat host and credential as one unit. Against a third-party base URL, that is normally the bearer token plus the base URL, with the direct API key explicitly unset so it cannot be picked up.
unset ANTHROPIC_API_KEY
export ANTHROPIC_AUTH_TOKEN="sk-kn-..."
export ANTHROPIC_BASE_URL="https://api.kunavo.com"
claudeConfirm on the wire, not in your head
If auth still fails, take the environment out of the question: issue the request by hand with the header you believe is being sent. A 200 here with a failure in the tool means the tool is not reading the variable you set — most often a different shell, or a config file overriding it.
curl -s -o /dev/null -w '%{http_code}\n' \
"$ANTHROPIC_BASE_URL/v1/models" \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN"If you’re calling through Kunavo
Kunavo authenticates on `Authorization: Bearer`, so with Claude Code the working pair is ANTHROPIC_AUTH_TOKEN plus ANTHROPIC_BASE_URL — and ANTHROPIC_API_KEY should be unset rather than left over, because a stale value there is the single most common cause of a session that looks configured and still refuses. The same `sk-kn-` key works unchanged as an OpenAI-style bearer token against /v1/chat/completions, so one credential covers both shapes. The full setup, including the model names to use, is in our Claude Code 401 guide.
FAQ
If both are set, which wins?
Do not rely on the answer — it is a precedence rule that has changed between versions and differs across SDKs. Set exactly one and unset the other; that is the only configuration that behaves the same everywhere.
Can I use ANTHROPIC_AUTH_TOKEN with Anthropic directly?
Anthropic's own API authenticates on x-api-key, so a direct Anthropic key belongs in ANTHROPIC_API_KEY. The token variable exists for hosts that expect a bearer credential.
Does the SDK use the same variables?
The Python and TypeScript SDKs read ANTHROPIC_API_KEY and send x-api-key. If you point an SDK at a bearer-auth gateway, pass the credential explicitly rather than relying on the environment.
Related guides
- Claude Code “API Error: 401 authentication_error” with a custom base URL — every cause
- Claude API 401 authentication_error / invalid x-api-key — every cause
- OpenAI-compatible API returning 401/403 — base_url and header pitfalls
More error semantics live in the error reference; getting a key takes a minute via sign up and the authentication docs.