# Claude Code

URL: https://docs.router.ezat.io/tools/claude-code

> Run Claude Code on your EZAT Router balance with two environment variables, ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN.

## When to use this page

You use Claude Code and want its requests to go through EZAT Router and be paid from your EZAT balance. Two environment variables do it. Claude Code's own model names keep working, so nothing else changes.

## What you need

- An EZAT API key (`ezat_sk_…`). Create one on the dashboard's [API keys](https://router.ezat.io/keys) page; see [API keys](https://docs.router.ezat.io/api-keys.md).
- Credit on your balance ([Billing](https://docs.router.ezat.io/billing.md)).
- Claude Code, installed as usual.

## Set it up

<Steps>
<Step>

### Set the base URL and your key

In the terminal you'll start Claude Code from, with your key in `EZAT_API_KEY`:

```bash tab="macOS and Linux"
export ANTHROPIC_BASE_URL="https://api.router.ezat.io"
export ANTHROPIC_AUTH_TOKEN="$EZAT_API_KEY"
```

```powershell tab="Windows PowerShell"
$env:ANTHROPIC_BASE_URL = "https://api.router.ezat.io"
$env:ANTHROPIC_AUTH_TOKEN = $env:EZAT_API_KEY
```

The base URL has no `/v1`: Claude Code adds it.

</Step>
<Step>

### Start Claude Code

Run `claude` from the same terminal, so it inherits the variables.

</Step>
<Step>

### Check it

Inside Claude Code, run `/status`. On the Status tab:

- `Anthropic base URL` shows `https://api.router.ezat.io`;
- `Auth token` names `ANTHROPIC_AUTH_TOKEN`.

Then send any prompt. A normal answer means it works, and the request appears on the dashboard's Usage page within a few seconds.

</Step>
</Steps>

To test the key and URL without Claude Code, send one request with the same header Claude Code uses:

```bash tab="curl" test
curl --fail-with-body https://api.router.ezat.io/v1/messages \
  -H "Authorization: Bearer $EZAT_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model": "anthropic/claude-sonnet-5-5", "max_tokens": 16, "messages": [{"role": "user", "content": "Hi"}]}'
```

A JSON answer with `"type": "message"` means the key and URL are right. A `401` means the key is wrong.

## Make it permanent

Shell exports last for one terminal. To keep the setting, either add the two `export` lines to your shell profile (`~/.zshrc`, `~/.bashrc`, or PowerShell's `$PROFILE`), or put them in the `env` block of a Claude Code settings file:

```json title="~/.claude/settings.json"
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://api.router.ezat.io",
    "ANTHROPIC_AUTH_TOKEN": "ezat_sk_…"
  }
}
```

If the file already exists, add the `env` entries to it rather than replacing it. When a variable is set both in your shell and in a settings file, the settings file wins. A settings file also reaches Claude Code's background agents, which a shell export may not.

| File | Applies to | Put the key here? |
| --- | --- | --- |
| `~/.claude/settings.json` | You, in every project | Yes |
| `.claude/settings.local.json` in a project | You, in that project | Yes, if the file stays out of version control |
| `.claude/settings.json` in a project | Everyone who clones the project | **No.** It is committed and shared. Put only `ANTHROPIC_BASE_URL` here. |

Claude Code applies a project's `env` block only after you trust the folder. If it asks you to log in on first start, put the key in your shell or in `~/.claude/settings.json` instead.

## Why ANTHROPIC_AUTH_TOKEN

EZAT accepts the key either way, but `ANTHROPIC_AUTH_TOKEN` is the simpler choice:

| Variable | Sent as | Behaviour in Claude Code |
| --- | --- | --- |
| `ANTHROPIC_AUTH_TOKEN` | `Authorization: Bearer <key>` | Takes over from a saved claude.ai login or Console key at once. |
| `ANTHROPIC_API_KEY` | `x-api-key: <key>` | Asks once, in an interactive session, before it takes over. A key you declined earlier is ignored without asking again. |

While the token is set, Claude Code doesn't use your claude.ai subscription: requests are billed to your EZAT balance, and the subscription's limits don't apply. Your login stays saved; unset the variable to go back to it. Setting only `ANTHROPIC_BASE_URL` is not enough, because Claude Code would then send your claude.ai credential, which EZAT rejects.

## Choose a model

You don't need a model setting. Claude Code's aliases (`opus`, `sonnet`, `haiku`, `fable`) resolve to Anthropic model names such as `claude-opus-5-5`, and EZAT accepts those names as aliases of its own ids. Background tasks use the model the `haiku` alias points to.

- **Switch for the current session:** `/model` (opens the picker), or `/model opus`.
- **Start on a model:** `claude --model sonnet`, or set `ANTHROPIC_MODEL`.
- **Pin an exact version:** use Anthropic's full name, for example `claude-opus-5-5`, with `/model`, `ANTHROPIC_MODEL` or the `model` setting.

| Variable | Sets |
| --- | --- |
| `ANTHROPIC_MODEL` | The model for sessions started with it set |
| `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL`, `ANTHROPIC_DEFAULT_FABLE_MODEL` | What the `opus`, `sonnet`, `haiku` and `fable` aliases resolve to. The Haiku one also sets the model for background tasks. |
| `CLAUDE_CODE_SUBAGENT_MODEL` | The default model for subagents |

Use Anthropic's names (the aliases column on [Models](https://docs.router.ezat.io/models.md)), not EZAT's `anthropic/…` ids. Claude Code sets the context window and features from the model name, so it needs a name it recognizes.

## Prompt caching

Claude Code marks its own cache breakpoints, and EZAT keeps each conversation on one deployment so the cache is read back. There is nothing to set. Cache tokens show on the Usage page under Cache (write / read). See [Prompt caching and sessions](https://docs.router.ezat.io/guides/prompt-caching.md).

## See usage and cost

Every request appears on the dashboard's Usage page, with tokens and cost per model and per key. Give Claude Code its own key to see its usage on its own (By key), and set a spend limit on that key if you want a cap ([API keys](https://docs.router.ezat.io/api-keys.md)).

## Other ways to run Claude Code

**VS Code extension.** Set the variables in VS Code's user settings (Preferences: Open User Settings (JSON)). The extension checks credentials from this setting before it starts:

```json
{
  "claudeCode.environmentVariables": [
    { "name": "ANTHROPIC_BASE_URL", "value": "https://api.router.ezat.io" },
    { "name": "ANTHROPIC_AUTH_TOKEN", "value": "ezat_sk_…" }
  ]
}
```

**GitHub Actions.** Put the key in a repository secret and pass it as the action's `anthropic_api_key` input. The action sends it as `x-api-key`, which EZAT accepts:

```yaml
env:
  ANTHROPIC_BASE_URL: https://api.router.ezat.io

steps:
  - uses: anthropics/claude-code-action@v1
    with:
      anthropic_api_key: ${{ secrets.EZAT_API_KEY }}
```

**Not available through EZAT:** Claude Code on the web (cloud sessions) and Claude Code in Slack don't apply these variables, so they can't run on EZAT. Remote Control and voice dictation need a claude.ai login, and Claude Code turns them off while `ANTHROPIC_AUTH_TOKEN` is set.

## Common problems

| What you see | Cause | Fix |
| --- | --- | --- |
| Claude Code opens the login screen | No key reached it: not exported in this terminal, or only in a project file that isn't trusted yet | Export it in this terminal, or put it in `~/.claude/settings.json` |
| `/status` has no `Anthropic base URL` line | `ANTHROPIC_BASE_URL` didn't reach the session | Start `claude` from the terminal where you exported it, or use a settings file |
| A startup warning naming two credential sources | The token and a saved claude.ai login are both present | Run `/logout` to keep using EZAT, or unset the token to use the login |
| `401` `Invalid API key` | The key is mistyped or revoked, or `ANTHROPIC_API_KEY` is also set to another key: when a request has both headers, EZAT uses `x-api-key` | Check the key on the API keys page; run `unset ANTHROPIC_API_KEY` |
| `401` with an `apiKeyHelper` in your settings | The helper's output is sent in both headers and replaces your EZAT key | Remove `apiKeyHelper`, or make it print your EZAT key |
| `ANTHROPIC_API_KEY` is set but ignored | It needs approval, or you declined it before | Enable it in `/config` (Use custom API key), or use `ANTHROPIC_AUTH_TOKEN` |
| `402` `billing_error` | The balance is used up, or the key reached its spend limit | Add credits on the Billing page, or raise the key's limit |
| `404` with `model: …` | The model name isn't one EZAT knows | Use a name from [Models](https://docs.router.ezat.io/models.md); check `ANTHROPIC_MODEL` and the `ANTHROPIC_DEFAULT_*_MODEL` variables |
| `403` `This API key is not allowed to use …` | The key is limited to some models | Allow the model on the key. Claude Code also needs the model behind `haiku` for background tasks. |
| `400` mentioning `Extra inputs are not permitted`, or `Unexpected value(s)` for `anthropic-beta` | A pre-release feature Claude Code sends isn't accepted by the model provider | Set `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` |
| `This machine's managed settings require a first-party login` | Your organization's managed settings force a login method | Ask your administrator; managed logins and a custom key can't be combined |

More cases are on [Common issues](https://docs.router.ezat.io/troubleshooting.md).

## For AI agents

1. Never ask the user to paste the key into the chat. Read it from `EZAT_API_KEY`, or ask the user to set it themselves.
2. Set `ANTHROPIC_BASE_URL` to `https://api.router.ezat.io` (no `/v1`) and `ANTHROPIC_AUTH_TOKEN` to the key, in the `env` block of `~/.claude/settings.json` (merge into the existing file, don't overwrite it) or in the shell profile.
3. Never write the key into a project's `.claude/settings.json`: it is committed.
4. Don't also set `ANTHROPIC_API_KEY` or `apiKeyHelper`. If `ANTHROPIC_API_KEY` holds another key, unset it.
5. Don't set a model. To pin one, use an Anthropic model name from the aliases on [Models](https://docs.router.ezat.io/models.md), not an `anthropic/…` id.
6. Verify with the curl request above, then have the user run `/status` and check `Anthropic base URL` and `Auth token`.