Home / Glossary / Secrets (API Keys & Tokens)
Tech & ITSecrets (API Keys & Tokens)
By Sitraka Forler · Lecturer, Durham Business SchoolUpdated 3 October 2026 About this site
Credentials such as API keys, passwords and tokens that grant access to a system.
Also known as: access token, access tokens.
A leaked API (application programming interface) key lets anyone act as you, so keep secrets out of code and Git: use environment variables, a secrets manager or your continuous integration (CI) secret store, and commit only a .env.example file with placeholder values. If one leaks, rotate it: revoke it and issue a new one. Deleting the commit is not enough: Git history and existing clones still hold the old value.
The intuition
A secret is a string that stands in for you. An API key lets a program call a data vendor on your account, a token lets it push to your repository, a database password lets it read every trade. Whoever holds the string holds the access; the service cannot tell you from a thief. That is why the question is never whether the secret is safe inside your code, but who can read the code, now and later, including every copy, every log and every backup.
The mental model is separation: code is shared, configuration is local. The program reads its secrets from the environment at start-up, through os.environ, and the environment is populated differently on each machine: a .env file on a laptop, a secret store in CI, a managed vault in production. The code itself contains only the name of the variable. A colleague can clone the repository and run it with their own key, and the repository never learns anyone's key.
The second habit is assuming leaks will happen and planning for them. A secret that has reached a commit, a chat message or a screenshot is gone, even if you delete the message, because Git history and other people's clones remember. The response is rotation: revoke the old value at the issuer, mint a new one, update the environments. Short-lived tokens and least-privilege scopes make each rotation cheap and each leak small.
Example
# local config, never committed echo 'API_KEY=YOUR_API_KEY' > .env # tell Git to ignore the file echo '.env' >> .gitignore # prints .env if it is ignored git check-ignore .env
Moving a market-data key out of a script and into the environment
- The starting point is a script with API_KEY = "sk_live_7f3a..." on line 2 and requests.get(url, headers={"Authorization": f"Bearer {API_KEY}"}) below. Anyone with read access to the repository, including a future public fork, can call the vendor as you.
- Create a local configuration file that Git will never see: a file named .env containing the single line MARKET_API_KEY=sk_live_7f3a..., then add .env to .gitignore. Running git check-ignore .env prints .env, which confirms the rule matches; running git status shows nothing about the file.
- Read it from the environment in the script: from dotenv import load_dotenv; import os; load_dotenv(); key = os.environ["MARKET_API_KEY"]. The python-dotenv package loads the file into the process environment; os.environ[...] raises KeyError if the variable is absent, which is the right behaviour, since running without a key should fail loudly rather than send unauthenticated requests.
- Commit a template instead: a file .env.example containing MARKET_API_KEY=YOUR_KEY_HERE, so a new collaborator knows which variables to set. In CI, the same name is defined as a repository secret and injected as an environment variable; in production, a secrets manager supplies it. The code is identical everywhere.
- Now suppose the original line had already been pushed. git rm --cached and a new commit remove it from the tip, but git log -p still shows it and every clone keeps it. The only fix is at the issuer: revoke sk_live_7f3a..., create a new key, put the new value in each environment, and treat the old value as public from that moment.
- Add a guard so it does not happen again: a pre-commit hook running a scanner such as gitleaks blocks commits containing strings that look like keys, and GitHub's push protection refuses pushes with recognised secret formats.
Code holds the variable name, the environment holds the value, and a leak is fixed by rotation at the issuer, never by deleting a commit.
Common pitfalls
- Committing the secret, then deleting the commit. Git history, reflogs, forks and CI caches still hold the value. Rotation is the only remedy; the delete is just tidying.
- Putting the .env file in the repository or in a Docker image. Both are copied freely. The file belongs on the machine, the image gets the value at run time through environment variables or a mounted secret.
- Printing the environment while debugging. A print(os.environ) or a logger that dumps request headers writes the key into a log file that is retained, searchable and often shared.
- Using one all-powerful key everywhere. A read-only market-data scope cannot be used to trade, and a key per environment means a leak from a laptop does not expose production. Scope narrowly and separate environments.
- Pasting keys into chat, tickets or notebooks. A Jupyter notebook saves outputs, so a cell that echoes a key stores it in the .ipynb file, which then gets committed.
Frequently asked questions
What is the difference between an API key and a token?
Both are secret strings presented to prove identity. An API key is usually long-lived, tied to an account or application, and identifies the caller for billing and rate limits. A token is often short-lived and scoped, issued after a login or an OAuth flow, and may expire or be refreshed. Both must be kept out of code and rotated when exposed.
Where should I store API keys in a Python project?
In environment variables, loaded from a local .env file that is listed in .gitignore, and read in code with os.environ["NAME"]. The python-dotenv package loads the file for you. Commit a .env.example with placeholder values so collaborators know which variables exist. In CI and production, set the same variables from the platform's secret store instead of a file.
What should I do if I accidentally committed an API key?
Assume it is compromised and rotate it at the issuer immediately: revoke the old key, generate a new one, and update every environment that uses it. Then remove it from the repository tip and, if the repository is public, consider rewriting history, but do not rely on that: clones, forks and scanners may already hold the value.
Is it safe to put secrets in a .env file?
On your own machine, yes, provided the file is ignored by Git, not copied into images or shared drives, and readable only by you. A .env file is a convenience for local development; it is not a vault. For shared or production systems use the platform's secret manager, which encrypts values at rest and records who read them.