Claude Code talks to an Anthropic-compatible Messages API. Pointing it at a custom gateway is two environment variables — plus one detail that trips up almost everyone: the base URL must be the origin, not /api/v1. Claude Code appends /v1/messages itself.
Written 2026-10-26. This is an independent setup guide for using Claude Code with JZS Token; it is not an Anthropic product page.
Why use Claude Code with a custom API
There are three practical reasons: you want one prepaid balance across Claude models instead of a separate Anthropic subscription; you want to see per-request token usage and prices in the same place as your other models; or you want a second path that does not depend on a single provider account.
The trade-off is that you own the configuration. Claude Code is a client, not a billing layer; the gateway is responsible for routing, limits, and the price. If you do not need that, the first-party Anthropic account is simpler.
How Claude Code talks to the API
Claude Code is a client for the Anthropic Messages API, not a model runtime. Each turn it sends aPOST /v1/messages request with the conversation, the system prompt, and the list of tools it is allowed to call. The response comes back as a server-sent event stream: text deltas first, then a stop reason and token usage.
When the model wants to use a tool — read a file, run a command — the response contains a tool-use block. Claude Code executes it locally and sends the result back as the next message. That loop is why a single user prompt can produce several billed requests: the conversation is resent with the tool output each time.
Authentication differs by variable. With ANTHROPIC_AUTH_TOKEN, the client sends the key as a bearer token. With ANTHROPIC_API_KEY, it uses the first-party header path. Use the auth-token variable for a custom gateway and the request will carry the header our endpoint expects.
This also explains the base-URL rule. The client appends /v1/messages to whatever you give it. If you give it https://jzstoken.com/api/v1, the actual request goes to /api/v1/v1/messages, which does not exist. Give it the origin and the path is correct.
What you need
| Item | Value | Notes |
|---|---|---|
| ANTHROPIC_BASE_URL | https://jzstoken.com | Origin only. No /api/v1 — Claude Code adds /v1/messages. |
| ANTHROPIC_AUTH_TOKEN | sk-… | The JZS key from Dashboard → API Keys. Not ANTHROPIC_API_KEY. |
| Node.js | 18 or newer | Only needed for the npm install. |
| Claude Code | current | npm install -g @anthropic-ai/claude-code. |
Step 1: install Claude Code
npm install -g @anthropic-ai/claude-code claude --version
If the command is not found, check that the npm global bin directory is on your PATH. On macOS and Linux this is usually ~/.npm-global/bin or the output of npm bin -g. Restart the shell after changing PATH.
Step 2: create a JZS key
Sign in, open Dashboard → API Keys, and create a comprehensive key. It starts with sk- and is shown once. Add a small amount of credit on the Buy Credits page if the signup credit is not active.
Step 3: set the environment variables
Set both variables in the shell that launches Claude Code. Use ANTHROPIC_AUTH_TOKEN, not ANTHROPIC_API_KEY: the latter is the first-party Anthropic key and will produce a 401 against a custom gateway.
macOS / Linux (zsh or bash)
export ANTHROPIC_BASE_URL="https://jzstoken.com" export ANTHROPIC_AUTH_TOKEN="sk-your-key-here" # Optional: pin the model for this shell export ANTHROPIC_MODEL="claude-sonnet-5.5"
To make it persistent, append the two exports to ~/.zshrc or ~/.bashrc. Do not put the key in a project file or commit it.
Windows PowerShell
$env:ANTHROPIC_BASE_URL = "https://jzstoken.com" $env:ANTHROPIC_AUTH_TOKEN = "sk-your-key-here" claude
For a persistent user-level variable, use [Environment]::SetEnvironmentVariable("ANTHROPIC_AUTH_TOKEN", "sk-...", "User") and the same for the base URL, then open a new terminal.
The most common failure is copying the base URL from another tutorial and keeping /api/v1. Claude Code will then call https://jzstoken.com/api/v1/v1/messages and get a 404. Remove the suffix.
Step 4: run Claude Code and verify
Start a session in a project directory and ask a small question:
cd ~/projects/your-app claude # inside Claude Code: /status > explain what this repository does in one paragraph
/status shows the active model and account. If the answer streams back, the base URL, key, and model are correct. The first request may be slower while the upstream connection is established; subsequent turns should be faster.
A first real session
A useful first task is one with a clear stopping point. From the project root, start Claude Code and ask for a read-only summary, then a single-file change, then a test run. That sequence exercises text generation, tool use, and multi-turn context without burning a large budget.
claude > give me a one-paragraph overview of this repo and list the test command > add a --dry-run flag to scripts/import.ts, do not change other files > run the test suite and summarize any failures
Use /cost after the session to see the token usage for the conversation, and /context to see what is occupying the context window. If the numbers look higher than expected, the cause is usually a long tool loop rather than a single large prompt.
When the task changes, start a new session. Claude Code resends the conversation on every turn, so a session that has drifted to an unrelated file keeps paying for the old context.
Step 5: choose a model
Claude Code is designed around Claude models. Use the in-app /model selector, or set ANTHROPIC_MODEL for the shell. The model ID must match our catalog exactly; there is no vendor prefix.
| Model | OpenRouter in / out | JZS in / out | 3:1 blended (OR → JZS) | JZS saves |
|---|---|---|---|---|
| Claude Sonnet 5.5claude-sonnet-5.5 | $2.00 / $10.00 | $0.78 / $3.89 | $4.000 → $1.557 | 61.1% |
| Claude Opus 5.5claude-opus-5.5 | $4.00 / $20.00 | $1.17 / $5.84 | $8.000 → $2.335 | 70.8% |
USD per 1M tokens, standard (non-batch) routes, captured 2026-10-26. Blended assumes 3 input tokens per output token. OpenRouter batch routes are often half price and are not compared here.
Sources: JZS public pricing API and OpenRouter public model list, both read on 2026-10-26. Prices move; check both pages before you commit to a provider.
Sonnet 5.5 is the practical default for coding: strong tool use, fast enough for interactive edits, and roughly 61% below OpenRouter's standard rate on the same model. Opus 5.5 is for the hard cases where a wrong edit costs more than the tokens; do not use it for every file read.
If you are also using the official Anthropic API elsewhere, keep your model IDs and prompts consistent during the comparison. A different model or prompt version will make the cost and quality comparison meaningless.
What a session costs
Claude Code sessions are input-heavy because the conversation is resent each turn. The table below uses list prices for input plus output, with no cache hits and no retries. Treat it as a floor, not a forecast.
| Tokens (input + output) | Sonnet 5.5 on JZS | Sonnet on OpenRouter | Opus 5.5 on JZS | Opus on OpenRouter |
|---|---|---|---|---|
| 1M + 200K | $1.56 | $4.00 | $2.34 | $8.00 |
| 5M + 1M | $7.78 | $20.00 | $11.68 | $40.00 |
| 20M + 4M | $31.14 | $80.00 | $46.71 | $160.00 |
The 20M + 4M row is roughly a heavy week for one developer. At that volume the gateway choice is a few hundred dollars a month, which is why teams that use Claude Code all day care about the per-token rate even when individual requests look cheap.
Step 6: keep an eye on cost
- Claude Code resends context as the conversation grows. Long sessions cost more per turn; start a new session when the task changes.
- Cap output where it makes sense. A model that writes a long explanation for every edit costs more than the edit.
- Use Sonnet for routine work and escalate to Opus for specific hard tasks.
- Check the usage page after the first day; the per-request token counts are the real number, not the estimate.
- If a request fails, retry once; a retry storm is more expensive than the original request.
Using Claude Code with a team
Give each developer their own API key, named after the person or the machine. A shared key makes the usage page useless: you can see that the team spent money, but not who spent it or which project caused it. Per-person keys also make rotation a one-line change instead of a coordinated event.
Set the environment variables in each developer's shell profile or in a local secrets manager, not in the repository. A committed .env is the most common way a key leaks, and Claude Code has no way to tell a leaked key from a real one. When someone leaves the project, delete their key and confirm in the usage log that requests stop.
If you need a shared budget, use one key per environment (laptop, CI, staging) rather than one key for the whole company. CI should use a separate key with its own balance; a runaway test suite should not be able to drain the balance the team uses for interactive work.
Troubleshooting
| Symptom | Fix |
|---|---|
| 404 Not Found | ANTHROPIC_BASE_URL ends with /api/v1. Use https://jzstoken.com only. |
| 401 Unauthorized | Use ANTHROPIC_AUTH_TOKEN, not ANTHROPIC_API_KEY. Check for whitespace in the key. |
| 403 model_not_supported | The model ID is not in the catalog, or the key type does not cover it. |
| 402 insufficient balance | Add credit; the request estimate exceeds the balance. |
| Streaming hangs | Check firewall/proxy buffering; SSE needs an unbuffered connection. |
If none of these fit, send us the time of the request and the model ID via the contact page or WhatsApp. We can look up the exact request instead of guessing.
Security notes
- Treat the key like a password. Do not commit it, paste it into a shared terminal, or put it in a project .env that ships to a server.
- Use a shell profile or a secrets manager; rotate the key if it appears in a log or a screenshot.
- Claude Code can run shell commands. Review the permissions it asks for; the gateway cannot undo a local command.
FAQ
Why does Claude Code need ANTHROPIC_AUTH_TOKEN instead of ANTHROPIC_API_KEY?
The two variables take different authentication paths. ANTHROPIC_API_KEY is the first-party Anthropic key and is sent in the vendor-specific header; a custom gateway is not that endpoint. ANTHROPIC_AUTH_TOKEN sends the key as a bearer token, which is the path this gateway accepts. If you see a 401 with a key you just created, check the variable name first.
Why is the base URL just the domain?
Because Claude Code appends /v1/messages. The gateway's Anthropic-compatible endpoint is at the origin, so the base URL is https://jzstoken.com. Adding /api/v1 produces a doubled path and a 404, which is the most common setup error.
Can I use one key for the whole team?
It works, but it costs you attribution. A shared key cannot tell you which developer or project caused a spike. Use one key per person or per environment; the usage page is only useful when each key maps to a known owner.
Is my source code sent through the gateway?
Yes — Claude Code sends the prompt, context, and tool results to the base URL you configure, and the gateway forwards them to the upstream provider to generate the response. If your repository contains regulated data, review the privacy policy and terms before pointing Claude Code at any third-party endpoint.
Does streaming work?
Yes. Claude Code uses server-sent events, and the gateway passes the stream through. If output hangs after the connection opens, the usual causes are a corporate proxy that buffers responses or a firewall that closes long-lived connections; test from a different network before changing your configuration.
Try Claude Code with JZS
Create a key, set the two environment variables above, and run /status. The full Claude Code setup guide has screenshots for macOS, Windows, and Linux.
Get an API keyFull Claude Code setup guide