A script that worked all morning now fails on every call with 401 Unauthorized /
authentication_error. The provider console shows the key disabled, deleted, or
flagged. Sometimes there is an email: "we detected your API key in a public
repository and revoked it." Nothing in your code changed.
First weeks of API work. The key was pasted directly into a script or notebook — "temporarily, for the demo" — and the file was pushed to a public GitHub repo. Automated scanners read every public commit around the clock, and the providers run their own scans and auto-revoke what they find. Linked module: 3.2 (Working with LLM APIs properly). WR-006 covers scrubbing the secret out of git history; this entry covers the API side of the same incident.
A 401 means one thing: the credential did not pass. Four causes cover nearly every
case. (1) The key was revoked — by you, a teammate, or the provider's leak scanner.
(2) The key never loaded: the env var is unset in this shell, the .env file is
missing or in the wrong folder, or load_dotenv() runs after the variable is read.
(3) The wrong variable name — PROVIDER_API_KEY in .env, PROVIDER_KEY in code.
(4) The header is malformed — missing Bearer , stray quotes, trailing whitespace
from a copy-paste. Confirm in order: print len(os.environ.get("PROVIDER_API_KEY", ""))
(length, never the value) to see whether anything loaded; check the key's status in
the provider console; then search your pushed history for the key prefix. If the
provider auto-revoked it, the safety system worked — treat it as a confirmed leak,
not a false alarm.
Rotate first, investigate second. In the provider console: create a new key, revoke
the old one if it still exists, put the new value in .env, restart the process.
Never re-add the exposed key even if it still works — bots may already hold it.
Then open the usage dashboard and look for calls you do not recognise, and set a
monthly spending cap while you are there. Finally clean the repository itself per
WR-006 — deleting the file in a new commit is not enough, because the key lives on
in git history and in every scraper's cache.
The .env habit from minute one of every project: key in .env, .env in
.gitignore, a .env.example with fake values for teammates. Name every key for
its purpose (api-lab-learning) so revoking is fearless. Set a spending limit the
day you create an account. Memorise the leak drill — revoke, recreate, update
.env, check usage — it takes two minutes and it is always the correct response
to any exposure, however brief.
Q: "Your API calls started failing with 401 an hour after a git push. Walk me
through your response." Strong answer: connect push → scanner → auto-revoke in one
sentence, state rotate-first before any debugging, check the usage dashboard for
abuse, and name the .env + .gitignore + spending-cap prevention set. Bonus
signal: pointing out that a provider auto-revoking your key is the system working
as designed, and that deleting the file later changes nothing because history and
caches remember.