Disclosure: independent site. Links to AgentRouter are referral links — we may earn a reward if you sign up, at no extra cost to you. We do not publish pricing or promo numbers we have not verified.

401 Unauthorized

Your key is probably fine. In most cases the process never saw the variable, or the gateway wants a different auth header than the one your tool sends. Work down this list in order — each step rules out one cause for good.

Prove where it breaks before you change anything

A 401 means you reached a server and it refused your credential. That is good news: DNS, routing and TLS all work. The problem is the credential or the header carrying it.

Send the same request two ways. The results tell you the cause.

# Bearer style (OpenAI-compatible gateways)
curl -s -o /dev/null -w 'bearer:    %{http_code}\n' \
  "$BASE_URL/v1/models" -H "Authorization: Bearer $TOKEN"

# x-api-key style (Anthropic native)
curl -s -o /dev/null -w 'x-api-key: %{http_code}\n' \
  "$BASE_URL/v1/models" -H "x-api-key: $TOKEN"
ResultCauseFix
200 on one, 401 on the otherRight credential, wrong header style. Your tool is sending the format this endpoint doesn't accept.Point the tool at the mode the endpoint accepts — for OpenAI-compatible gateways that means the OpenAI-style base URL and Bearer auth.
401 on bothThe credential itself is rejected: revoked, expired, from a different account, or truncated on copy.Regenerate it and paste it somewhere you can inspect before exporting.
200 on both, tool still 401sThe tool is not reading the environment you think it is.See the shell inheritance section below — this is the most common case.

Cause 1 — the process never saw your variable

This is the single most frequent cause, and it looks exactly like a bad key.

An editor launched from a dock icon does not inherit the environment from your shell profile. Nor does a tool started before you exported the variable.

  1. Check from the same process context the tool runs in: env | grep -i -E 'api_key|auth_token|base_url'
  2. If it prints nothing, the export never reached that process.
  3. Export it in the shell you will actually launch from, then start the tool from that same shell.
  4. For a GUI editor: quit it completely (not just close the window) and relaunch it from the terminal so it inherits the environment.
  5. Confirm the variable name character-for-character against the tool's documentation — a plausible-looking but wrong name fails silently as 'no credential'.
Silent killers in this category
  • A trailing newline or space captured by copy-paste. Verify length: echo -n "$TOKEN" | wc -c
  • Smart quotes from a docs page or PDF instead of plain ASCII quotes.
  • The variable set in ~/.bashrc while your shell is zsh (or the reverse) — non-interactive shells may read neither.
  • Two variables set, one stale: a shell export silently overriding a config file, or vice versa. Check both.

Cause 2 — base URL and auth style disagree

Gateways expose several compatibility surfaces. Mixing one endpoint's path with another's auth header produces a 401 with a perfectly valid key.

If a provider offers both an OpenAI-compatible and an Anthropic-compatible endpoint, they generally expect different auth headers and different paths. Pick one surface and configure it consistently: base URL, auth header, and model naming all come from the same side.

Watch for a doubled path segment. If your base URL already ends in /v1 and the client appends /v1 itself, you end up requesting /v1/v1/... — depending on the gateway that surfaces as 401, 403, or 404 rather than a helpful error.

Check what your base URL actually resolves to

echo "$BASE_URL"
# Then request the models list and read the effective URL back:
curl -s -o /dev/null -w '%{url_effective} -> %{http_code}\n' \
  "$BASE_URL/v1/models" -H "Authorization: Bearer $TOKEN"

Cause 3 — the credential is valid but not entitled

Some gateways return 401 rather than 403 when a key authenticates but lacks access to the requested resource — no credit balance, a model not enabled for the account, or a project-scoped key used outside its project.

Distinguish this cheaply: if /v1/models returns 200 but a completion request 401s, the credential is fine and the entitlement is not. That is an account state issue, not a configuration issue, and no amount of config editing will fix it.

Still stuck?

The 60-second version: a token and a base URL that are known to work together

If you have tried both header styles and the credential is genuinely dead, you need a working endpoint to test against — half of debugging a 401 is not knowing whether the fault is yours. AgentRouter issues a token from its console and documents the exact base URL for each surface: https://agentrouter.org for Anthropic-compatible clients like Claude Code, https://agentrouter.org/v1 for OpenAI-compatible ones. Set those two values, send the curl above, and you get a definitive answer about whether your tool config or your old credential was the problem.

Get a token and re-run the check →

Referral link — we may earn a reward if you sign up, at no extra cost to you. This is the same advice we would give with no link at all. Check their current pricing and model list on their own site; we deliberately do not restate numbers that change.

To be direct about the order of operations: if you have not yet run the two curl commands at the top of this page, do that first. Switching providers to fix an unexported environment variable moves the problem rather than solving it, and you will hit the same 401 on the new endpoint.

Error not on this page?

The Setup Doctor walks through your tool, symptom, and setup and points at the likely cause — no account needed.

Diagnose my error →