api.foo
api.foo / Docs / Claude Code with a custom API

Claude Code with a Custom API or Base URL (2026): ANTHROPIC_BASE_URL, Gateways, Claude Code Router and Model Mapping

Updated · Tested on: macOS (Apple silicon) · Claude Code 2.1.300
On this page

Short answer: put this in ~/.claude/settings.json (Windows: %USERPROFILE%\.claude\settings.json) and restart claude:

{
  "env": {
    "ANTHROPIC_BASE_URL": "https://your-endpoint.example.com",
    "ANTHROPIC_AUTH_TOKEN": "your-key"
  }
}

The endpoint has to speak Anthropic's Messages API. Write the base URL without /v1, since Claude Code adds /v1/messages itself. Run /status to confirm it took. If the API you want to use only speaks the OpenAI format, you need a translating proxy such as Claude Code Router in between.

Everything below was tested on Claude Code 2.1.300 on October 17, 2026. We pointed Claude Code at a local test server that logged every request, so the paths, headers and model names here are what Claude Code actually sent, not what we expected it to send.

Three ways to use Claude Code with another API

Your endpoint What to do Example
Speaks the Anthropic Messages API Set ANTHROPIC_BASE_URL and a key An LLM gateway, a multi-model API service, DeepSeek's or Kimi's Anthropic-compatible endpoint
Speaks only the OpenAI format, or you want to mix providers Run a translating proxy locally and point ANTHROPIC_BASE_URL at it Claude Code Router, LiteLLM
Is Amazon Bedrock, Google Cloud or Microsoft Foundry Use the provider's own CLAUDE_CODE_USE_* variables CLAUDE_CODE_USE_BEDROCK=1

This guide covers the first two.

What Claude Code actually sends

With a custom base URL, a plain claude -p "say hi" produced this request on our test server:

POST {ANTHROPIC_BASE_URL}/v1/messages?beta=true
Authorization: Bearer <your key>
anthropic-version: 2023-06-01
anthropic-beta: claude-code-20250219,interleaved-thinking-2025-05-14,context-management-2025-06-27,…
user-agent: claude-cli/2.1.300 (external, sdk-cli)

{"model": "claude-opus-5-5", "stream": true, "max_tokens": 128000, "thinking": {…}, "tools": […], …}

Three things follow from this:

  1. Don't put /v1 in the base URL. https://api.example.com/v1 becomes /v1/v1/messages, which most endpoints answer with 404.
  2. The endpoint must handle streaming, thinking and tools, plus several beta fields. An endpoint that only handles plain chat will fail on real coding sessions.
  3. The default model is claude-opus-5-5. If your endpoint calls its models something else, you need the model mapping below.

Step by step

1. Pick the right credential variable

Variable Header it sends Use when
ANTHROPIC_AUTH_TOKEN Authorization: Bearer <key> The endpoint expects a bearer token, or you weren't told
ANTHROPIC_API_KEY x-api-key: <key> The endpoint expects x-api-key
apiKeyHelper (in settings.json) Both The key rotates and comes from a command

We confirmed the headers on our test server. A key in the wrong variable reaches the endpoint in a header it doesn't read, and you get a 401.

2. Write it to settings.json, not just your shell

Use ~/.claude/settings.json for all projects, or .claude/settings.local.json for one project (add it to .gitignore). Never put a key in a project's .claude/settings.json, which is committed to the repository.

You can also export the variables in your shell to try them out. If both are set, settings.json wins: in our test, settings.json pointed at one URL, the shell exported another, and requests went to the settings.json URL.

A useful extra line for third-party endpoints:

"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"

It stops version checks, telemetry and error reporting to Anthropic. It also turns off auto-update, so run claude update now and then.

3. Verify

  1. Start claude. No login screen means it found your key.
  2. Run /status. The Anthropic base URL line should show your endpoint, and the Auth token or API key line should name the variable you set.
  3. Send a message.

To test the endpoint without Claude Code, send it a one-token request:

curl -sS -w '\n%{http_code}\n' -X POST "$ANTHROPIC_BASE_URL/v1/messages" \
  -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model": "claude-haiku-5-5", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'

A response starting with {"id":"msg_ means it works. An "unknown model" error also proves the URL and key are fine. A 401 means the key or the variable is wrong.

Map model names

Claude Code requests these exact model names. We captured each one:

You choose Claude Code requests
Nothing (default) or opus claude-opus-5-5
sonnet claude-sonnet-5-5
haiku (also used for background tasks such as session titles) claude-haiku-5-5
fable or best claude-fable-5-1

If your endpoint uses different names, map them in the same env block:

{
  "env": {
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "provider-opus-name",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "provider-sonnet-name",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "provider-small-model",
    "ANTHROPIC_DEFAULT_FABLE_MODEL": "provider-top-model"
  }
}

With ANTHROPIC_DEFAULT_SONNET_MODEL=my-sonnet, choosing sonnet sent my-sonnet, and Claude Code warned:

Claude Code doesn't recognize the model "my-sonnet", so it assumes a context window of 200k tokens.

That's harmless; it just compacts the conversation earlier. If the model really has a 1M window, append [1m] to the name, for example my-model[1m]. Claude Code strips the suffix before sending. Two more variables are worth knowing: CLAUDE_CODE_SUBAGENT_MODEL sets the model for subagents, and ANTHROPIC_DEFAULT_MODEL sets the default for new sessions.

Model discovery. Set CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 and Claude Code calls GET /v1/models?limit=1000 on your endpoint at startup and adds what it finds to the /model picker. In our test it kept only IDs containing claude (or anthropic) and dropped a GPT model from the list. The list is cached in ~/.claude/cache/gateway-models.json.

Providers with their own Anthropic-compatible endpoint

Some model providers accept Claude Code directly, with no proxy:

Provider Base URL Notes
DeepSeek https://api.deepseek.com/anthropic DeepSeek's Claude Code guide maps every alias to deepseek-flash (deepseek-flash[1m] for the main models). Prices: DeepSeek API pricing
Kimi (international) https://api.moonshot.ai/anthropic Kimi's guide maps Opus and Sonnet to kimi-k3[1m] and Haiku to kimi-k2.7-code. See Kimi API

These are still non-Claude models. Anthropic says it doesn't support routing Claude Code to them, so if something behaves oddly, check the provider's own Claude Code guide first.

Claude Code Router and other proxies

If your provider only speaks the OpenAI format, or you want one place to switch between providers, run a local proxy that accepts Anthropic requests and translates them.

Claude Code Router (CCR) is the most popular option. It's an independent open-source project (MIT license, about 37,700 GitHub stars in October 2026), not an Anthropic product. Version 3.1.3 (October 2026):

  • Runs a local gateway on http://127.0.0.1:3456 with a management UI on http://127.0.0.1:3458, as a desktop app for macOS, Windows and Linux or as an npm CLI (npm install -g @musistudio/claude-code-router, then ccr ui; needs Node.js 22+).
  • Works with Claude Code, Codex, OpenCode, Kimi CLI and other agents, not just Claude Code.
  • Talks to OpenAI Chat and Responses, Anthropic Messages, Gemini, OpenRouter, DeepSeek, Moonshot and custom endpoints, with routing rules, retries, fallbacks and request logs.

Many tutorials online describe an earlier version configured by hand-editing a JSON file. The current README sets it up through the UI: Providers → Server → Agent Profiles.

Other options:

  • LiteLLM: a widely used open-source gateway (about 61,000 GitHub stars) that calls 100+ model APIs and can be self-hosted for a team.
  • claude-code-proxy repositories: several small projects with this name translate Claude Code requests to OpenAI. Check the license and recent activity before relying on one. For example, 1rgs/claude-code-proxy has no license file, and luohy15/y-router is archived.

The trade-off with any translating proxy is fidelity. Claude Code relies on Anthropic-specific features such as interleaved thinking, prompt caching and its tool format, and a translation can drop or change them. Expect more rough edges than with a native Anthropic-format endpoint.

VS Code, the desktop app and remote servers

  • VS Code extension: the extension checks for a login before it starts, and that check doesn't read ~/.claude/settings.json. Put the variables in VS Code's user settings (Preferences: Open User Settings (JSON)) and turn off the login prompt:
{
  "claudeCode.environmentVariables": [
    { "name": "ANTHROPIC_BASE_URL", "value": "https://your-endpoint.example.com" },
    { "name": "ANTHROPIC_AUTH_TOKEN", "value": "your-key" }
  ],
  "claudeCode.disableLoginPrompt": true
}
  • Desktop app: it ignores ANTHROPIC_BASE_URL and settings.json. Use Help → Troubleshooting → Enable Developer Mode, then Developer → Configure Third-Party Inference.
  • A remote server over SSH: create ~/.claude/settings.json in your own home directory there. No root access is needed.

What changes when you switch

  • Your claude.ai subscription isn't used. With ANTHROPIC_AUTH_TOKEN set, requests carry that key, your plan's usage limits don't apply, and the endpoint's owner bills you. Your claude.ai login stays saved; remove the variable to go back to it.
  • Remote Control and voice dictation stop working, because both need a claude.ai identity.
  • Claude Code retries failures quietly. With a wrong key we watched it retry about ten times with growing gaps (1, 2, 3, 5, 10, 18, 35 seconds…) before it showed the error, so it looks frozen. Set CLAUDE_CODE_MAX_RETRIES=0 while you debug.
  • You may see a notice beginning "We're changing auto mode to no longer charge for classifier requests". It says auto mode keeps working; you can ignore it.

Troubleshooting

You see Cause Fix
Failed to authenticate. API Error: 401 … The endpoint rejected the key, or it's in the wrong variable Re-copy the key; swap ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY
The login screen still appears Claude Code didn't find a key at startup Put it in ~/.claude/settings.json, not a project file; check the JSON is valid
ANTHROPIC_API_KEY is set but ignored You once declined it at the approval prompt Enable Use custom API key in /config
A warning ending in auth may not work as expected A key and a saved claude.ai login are both active /logout, or remove the variable
404 on /v1/v1/messages /v1 in the base URL Use the root URL
API returned an empty or malformed response (HTTP 200) The URL points at a web page, not the API Use the provider's API URL
400 mentioning context_management or Extra inputs are not permitted The endpoint rejects Claude Code's beta fields Set CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1
400 mentioning thinking or adaptive The upstream model doesn't support adaptive thinking Ask the provider to update; on Opus 4.6 / Sonnet 4.6, CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1
Connection refused or ENOTFOUND Wrong URL or no network path Test with the curl command above
SSL certificate verification failed A corporate TLS-inspection proxy Set NODE_EXTRA_CA_CERTS to your company's CA bundle

Using a multi-model API service

A service that offers Claude models through Anthropic's own API format needs no proxy and no model mapping, as long as it uses Anthropic's model names. api.foo, the service that publishes these docs, is one example: set ANTHROPIC_BASE_URL to https://api.foo, and Claude Code's default names (claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5, claude-fable-5-1) work as they are. It accepts both credential variables, and offers https://dc.api.foo as a direct route without a 100-second proxy timeout for long tasks. Prices are on the api.foo pricing page.

Sources

Claude Code documentation, checked October 17, 2026: Connect to an LLM gateway, Gateway compatibility, Model configuration, Environment variables, Settings, VS Code. Claude Code Router README (v3.1.3). DeepSeek's Claude Code guide and Kimi's Claude Code guide for their Anthropic-compatible endpoints. Request captures from our own test server.

FAQ

How do I set a custom base URL in Claude Code?

Add ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN to the env block of ~/.claude/settings.json, then restart claude. The URL is the provider's root, such as https://api.example.com, without /v1, because Claude Code appends /v1/messages itself. Run /status to confirm the base URL is active.

What URL does Claude Code use by default?

Without ANTHROPIC_BASE_URL, Claude Code sends model requests to Anthropic's API at api.anthropic.com. When you set ANTHROPIC_BASE_URL, model requests go to that URL instead, at the path /v1/messages.

Can Claude Code use GPT, Gemini or other non-Claude models?

Only through a translating proxy such as Claude Code Router or LiteLLM, or through a provider that offers an Anthropic-compatible endpoint for its own models, such as DeepSeek or Kimi. Anthropic's documentation says it doesn't support routing Claude Code to non-Claude models, so features like tool use and thinking can behave differently.

Should I use ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY?

Use whichever header your endpoint reads. ANTHROPIC_AUTH_TOKEN sends the key as Authorization Bearer and ANTHROPIC_API_KEY sends it as x-api-key. If you aren't told, start with ANTHROPIC_AUTH_TOKEN and switch if you get a 401.

Does a custom base URL use my Claude Pro or Max subscription?

Not if you also set a credential. With ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY set, requests carry that key instead of your claude.ai login, so subscription limits don't apply and the endpoint's owner bills you. Setting only ANTHROPIC_BASE_URL keeps your saved login as the credential.

Is Claude Code Router official?

No. Claude Code Router is an independent open-source project (MIT license) by musistudio. Version 3 runs a local gateway on 127.0.0.1:3456 that Claude Code, Codex, OpenCode and other agents can point at, and routes their requests to the providers you configure.

Found a mistake? Email [email protected].