Docs
ANTHROPIC_BASE_URL
The environment variable that points Claude Code and the Anthropic SDKs at an endpoint other than api.anthropic.com — the full variable reference, per-client setup, and the two traps that produce almost every failure.
ANTHROPIC_BASE_URL tells the Anthropic SDKs and Claude Code which host to send API requests to, replacing the default https://api.anthropic.com. Set it to an origin with no path — the client appends /v1/messages itself — and pair it with ANTHROPIC_AUTH_TOKEN, which becomes the Authorization: Bearer header.
# The origin only — no trailing /v1, no trailing slash.
export ANTHROPIC_BASE_URL=https://api.kunavo.com
export ANTHROPIC_AUTH_TOKEN=sk-kn-...Open a new terminal afterwards: Claude Code and the SDKs read these variables at process start, so a session that was already running keeps the old endpoint.
https://api.kunavo.com/v1 produces requests to /v1/v1/messages and every call returns 404. The OpenAI SDK uses the opposite convention and does want /v1 in its base_url — that difference is the single most common configuration mistake here.Every variable, and what it does
The full list Claude Code reads is in Anthropic's environment-variable reference. These are the ones that matter when you are redirecting the endpoint.
| Variable | Value | What it controls |
|---|---|---|
ANTHROPIC_ | https://api. | The origin every request goes to. No path, no trailing slash. |
ANTHROPIC_ | sk-kn-… | Credential sent as Authorization: Bearer. This is the one a gateway wants. |
ANTHROPIC_ | sk-ant-… | Credential sent as the x-api-key header, the form api. |
ANTHROPIC_ | claude-sonnet-5 | The main model Claude Code uses for the conversation. |
ANTHROPIC_ | claude-opus-5-5 | The model behind the opus alias (/model opus). Claude Code's own default is the newest Opus, so pin it to one the endpoint serves. Opus 5.5 needs Claude Code v2.1.280 or later. |
ANTHROPIC_ | claude-sonnet-5 | The model behind the sonnet alias (/model sonnet). The alias asks for Sonnet 5.5 by default, so pin it to a Sonnet the endpoint serves. |
ANTHROPIC_ | claude-haiku-4-5 | The model behind the haiku alias (/model haiku, subagents set to haiku), and the one Claude Code uses for its own background calls. The alias asks for Haiku 5.5 from v2.1.293, so pin it to a Haiku the endpoint serves. |
GET /v1/models.Per-client setup
Claude Code
Put the exports in the shell profile Claude Code starts from, then open a new terminal. Nothing about the install or the workflow changes.
# ~/.zshrc (or ~/.bashrc) — applies to every Claude Code session.
export ANTHROPIC_BASE_URL=https://api.kunavo.com
export ANTHROPIC_AUTH_TOKEN=sk-kn-...
# Pin models this endpoint serves. Claude Code's default and its opus/sonnet
# aliases follow Anthropic's newest models, which may not be served here —
# unpinned, those calls 404.
export ANTHROPIC_MODEL=claude-sonnet-5
export ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-5-5
export ANTHROPIC_DEFAULT_SONNET_MODEL=claude-sonnet-5
export ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-haiku-4-5Run /status inside Claude Code to confirm which endpoint the current session is using. Step-by-step, including where to generate the key: set an API key in Claude Code.
Anthropic SDK (Python / TypeScript)
The SDKs read the same environment variables, and both settings can also be passed to the constructor — useful when one process talks to more than one endpoint.
from anthropic import Anthropic
# The Anthropic SDK appends /v1/messages, so pass the origin — not .../v1.
client = Anthropic(
base_url="https://api.kunavo.com",
auth_token="sk-kn-...", # sets the Authorization: Bearer header
)
msg = client.messages.create(
model="claude-sonnet-5",
max_tokens=512,
messages=[{"role": "user", "content": "Say hi"}],
)
print(msg.content[0].text)OpenAI SDK — the other convention
If your code already speaks OpenAI, you do not need ANTHROPIC_BASE_URL at all. Point base_url at the OpenAI-compatible path — with the /v1 this time — and call the same Claude models through /v1/chat/completions.
from openai import OpenAI
# The OpenAI SDK is the other convention: it wants the /v1 in the base_url.
client = OpenAI(
api_key="sk-kn-...",
base_url="https://api.kunavo.com/v1",
)
r = client.chat.completions.create(
model="claude-sonnet-5",
messages=[{"role": "user", "content": "Say hi"}],
)
print(r.choices[0].message.content)Cline, Roo Code, Kilo Code, Cursor
Editor agents mostly expose the same two settings in their own UI rather than through the environment: a "base URL" or "custom endpoint" field and an API-key field. The rules do not change — origin without /v1 for an Anthropic-style provider, and the key in the API-key field. Per-client walkthroughs: Cline, Roo Code, Kilo Code.
Check that it worked
One curl proves the base URL and the credential at the same time. A 200 with a JSON body means both are right.
# 200 and a JSON body means the base URL and the token are both right.
curl -sS https://api.kunavo.com/v1/messages \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
-H "content-type: application/json" \
-d '{"model":"claude-haiku-4-5","max_tokens":16,
"messages":[{"role":"user","content":"ping"}]}'
# In Claude Code, /status shows the endpoint the session is actually using.When it does not work
| Symptom | Cause | Fix |
|---|---|---|
| 404 on every request | /v1 left on the end of ANTHROPIC_ | Set the origin only. The client appends /v1/ |
| 401 / invalid x-api-key | Credential set as ANTHROPIC_ when the endpoint authenticates with bearer tokens | Use ANTHROPIC_ instead — the difference in full |
| Still hitting api. | Variables exported after the session started, or set in a profile that shell does not read | Open a new terminal; confirm with echo $ANTHROPIC_ |
| 404 model_ | Model id the endpoint does not serve | Set ANTHROPIC_ to an id from GET /v1/models |
| Claude Code says the credit balance is too low | Requests are reaching the endpoint and being billed to the key, not the subscription | Expected — top up, or unset the token to return to the plan. See insufficient credit |
What this does to a Pro or Max subscription
While a credential variable is set, Claude Code bills the key rather than the logged-in subscription: plan limits stop applying and usage is charged to whoever owns the key. The subscription itself is untouched — remove the variable, open a new terminal, and Claude Code goes back to the plan. The two never combine, and the cost arithmetic between them is in Claude Code pricing.
Next
Frequently asked questions
What is ANTHROPIC_BASE_URL?
ANTHROPIC_BASE_URL is the environment variable that tells the Anthropic SDKs and Claude Code which host to send API requests to, instead of the default https://api.anthropic.com. Set it to an origin with no path — the client appends /v1/messages itself — and pair it with ANTHROPIC_AUTH_TOKEN, which becomes the Authorization: Bearer header. Any Anthropic-compatible endpoint works; on Kunavo the value is https://api.kunavo.com.
Should ANTHROPIC_BASE_URL include /v1?
No. ANTHROPIC_BASE_URL takes the origin only — https://api.kunavo.com, not https://api.kunavo.com/v1 — because the Anthropic SDKs and Claude Code append the /v1/messages path themselves. Including /v1 produces requests to /v1/v1/messages, which return 404. The OpenAI SDK follows the opposite convention and does want /v1 in its base_url, which is why the same gateway is written two different ways depending on which client is calling it.
What is the difference between ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY?
ANTHROPIC_AUTH_TOKEN sends the credential as an Authorization: Bearer header, while ANTHROPIC_API_KEY sends it as the x-api-key header that api.anthropic.com expects. A gateway that authenticates with bearer tokens needs ANTHROPIC_AUTH_TOKEN; setting ANTHROPIC_API_KEY instead is the most common cause of a 401 after changing ANTHROPIC_BASE_URL. Set one, not both — when both are present the behaviour depends on the client version.
How do I set a custom base URL in Claude Code?
Export ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN in the shell profile Claude Code starts from (~/.zshrc or ~/.bashrc), then open a new terminal so the variables are inherited. Claude Code reads them at startup, so a session that was already running keeps the old endpoint. Run /status inside Claude Code to confirm which endpoint the current session is using.
Does setting ANTHROPIC_BASE_URL disable my Claude Pro or Max subscription?
While a credential variable such as ANTHROPIC_AUTH_TOKEN is set, Claude Code bills the key rather than the logged-in subscription, so Pro and Max plan limits no longer apply and usage is charged to whoever owns the key. The subscription itself is unaffected and unset — remove the variable and open a new terminal, and Claude Code goes back to the plan.