← Back to Blog

Fix API Key 401 Unauthorized Errors: Step-by-Step Checklist

Zivv15 min read
API key401troubleshooting

A 401 Unauthorized response means one specific thing: the server could not verify the identity attached to the request. It is not a model problem, not a capacity problem, and usually not a platform outage. In practice, almost every 401 traces back to one of a handful of causes — an incomplete key, a malformed Authorization header, a client still holding an old key, or an account password pasted where an API key belongs.

This guide orders the checks by hit rate, so you can stop at the first one that finds the problem instead of reinstalling clients at random.

Symptom, Cause, Fix at a Glance

SymptomLikely causeFix
401 everywhere, including curlKey truncated or copied with whitespaceRe-copy via a plain-text editor; check both ends
curl works, one client returns 401Client cached an old key or profileRestart the client; delete stale provider entries
401 only after changing env varsTerminal still holds the old valueOpen a new terminal; check system vs shell variables
Worked yesterday, 401 todayKey deleted, disabled, or expiredCheck key status in the console
401 on a brand-new setupLogin password used instead of an API keyCreate a real sk- key on the API Keys page
401 plus mentions of quota or balanceKey limit or balance exhaustedCheck balance and per-key limits in the console

Step 1: Confirm You Actually Have an API Key

A Zivv API key is created on the console's API Keys page and starts with sk-. None of the following will ever authenticate a request:

  • Your website login password
  • A browser cookie or session token
  • A payment or order number
  • The display name you gave a key

If the key is fresh, paste it into a plain-text editor first and inspect both ends for spaces or line breaks. Chat apps and rich-text tools sometimes add invisible characters that survive copy-paste and are impossible to spot in a password field.

Step 2: Test the Key Without Your Client

Before touching Claude Code, Codex, or a desktop app, bypass all of them and hit the model list directly:

curl https://zivv.pro/v1/models \
  -H "Authorization: Bearer sk-your-key"

Interpret the result:

ResultMeaningNext step
Model list returnedThe key is validThe problem is client-side caching or config
Still 401Key or header is wrongRe-copy the key; check the Bearer format
Connection failsNot an auth problem at allCheck network, DNS, and proxy settings

The header format for OpenAI-compatible requests is exactly Authorization: Bearer <KEY> — the word Bearer, one space, then the key. Smart quotes, a missing space, or Bearer: with a colon all produce a 401.

In an SDK, the same test looks like this:

from openai import OpenAI

client = OpenAI(
    base_url="https://zivv.pro/v1",
    api_key="sk-your-key",
)
print([m.id for m in client.models.list().data])

Step 3: Check the Base URL for Your Protocol

Different tools use different Zivv endpoints, and mixing them up can surface as an auth failure in some clients:

  • OpenAI SDKs, Codex, Cherry Studio, and most desktop clients: https://zivv.pro/v1
  • Claude Code: ANTHROPIC_BASE_URL=https://zivv.pro — no /v1 suffix
  • Gemini-protocol tools: https://zivv.pro/v1beta

A wrong path more often yields a 404, but some clients assemble an invalid URL and report it as a generic "authentication failed." The endpoint reference lists every current path.

Step 4: Make Sure the Client Uses the New Key

The most stubborn 401s come from stale configuration, not bad keys:

  1. The terminal was never reopened after the environment variable changed — exports only apply to new shells
  2. A system-level variable and a shell-level variable disagree, and the old value wins
  3. The client has multiple provider profiles, and the selected model still points at an old one
  4. A Docker container or remote workspace never received the variable you set locally

Check what the shell actually holds:

echo $ANTHROPIC_BASE_URL
echo $OPENAI_API_KEY

If the output is not what you just set, the client never saw your new key either. Claude Code users can cross-check both variables against the Claude Code guide.

Step 5: Check Key Status and Limits

In the console, verify that:

  • The key has not been deleted or disabled
  • Its expiry date has not passed
  • Its group is allowed to reach the endpoint you are calling
  • The account balance and any per-key limit still have headroom

Some clients flatten several distinct server responses into one generic "authentication failed" message. The usage log settles the question: if requests appear there, they reached the platform and the failure is a permission or limit, not the key string itself.

If the Key May Be Exposed

If a key ever landed in a public repo, a screenshot, or a shared channel, stop testing it. The response sequence:

  1. Delete or disable the exposed key immediately
  2. Create a replacement
  3. Update every place the old key was configured
  4. Review recent usage for calls you do not recognize

Never send a complete key to support — the last four characters are enough to identify it. Going forward, issue one key per person, per project, and per automation; Teams manages exactly that, with independent keys and spending limits per member.

FAQ

Q: curl succeeds but my client still gets 401. Is the platform at fault? A: No — a passing curl proves the key, endpoint, and account are all fine. The client is using different credentials than you think. Restart it, then hunt for cached profiles and duplicate config sources.

Q: Does 401 mean my balance ran out? A: Usually not — exhausted balances normally return a different error. But some clients blur the two, so check both key status and balance in the console when in doubt.

Q: Can one key really work for Claude Code, Codex, and a desktop app at once? A: Yes. The same sk- key authenticates against all three protocol endpoints. Just match each tool to its correct base URL, per Step 3.

Q: I regenerated the key and it still fails. What now? A: Almost always stale config: the old key is cached somewhere in the chain (shell, system variables, client profile, container). Work through Step 4, then verify with the curl test from Step 2.

Wrap-Up

Six checks in order: confirm it is an sk- key, curl /v1/models, verify the Bearer header, match the base URL to the protocol, restart to clear stale config, and review key status and balance. If it still fails, the error reference explains each response field. Setting up fresh instead of debugging? Create a key and start from a clean configuration — and if the next error you meet is a 404, the model not found guide is the companion checklist.