API Key Management Best Practices: A Working Checklist
If you're searching for best practice API key management, you're probably past the "what is an API key" stage and need a concrete answer: how do you generate, store, rotate, and revoke keys without either leaking credentials or breaking production. The short version is this — treat every key as a liability the moment it's created, scope it to the minimum it needs, never commit it to source control, rotate it on a schedule, and make revocation a one-click operation, not a support ticket.
This article walks through the concrete practices that matter, in the order they usually bite teams: generation, storage, scoping, rotation, revocation, and monitoring. None of this is theoretical — it's the same checklist you'd use auditing a production system before a launch.
Generate keys with structure, not randomness alone
A good API key isn't just a random string — it should be identifiable at a glance. Prefixed keys (sub_live_..., sk_live_...) let you:
- Tell environment apart instantly (
livevstest) - Grep logs and error trackers for accidental leaks
- Build automated secret scanners that catch a specific pattern
If you're issuing keys to your own users (say, for an internal tool or a wrapper API), don't reuse the same secret across environments. A test key and a production key should be structurally distinguishable, not just "the other one."
Never store keys in code or config files
This is the most common mistake and the most preventable one. Keys end up in:
- Git history (even if removed later, they're still in old commits)
- CI/CD YAML files committed alongside the pipeline
- Shared
.envfiles checked into a repo "temporarily"
The fix is boring but effective:
# .env (never committed — check your .gitignore)
SUBTOAPI_KEY=sub_live_xxxxxxxxxxxxxxxx
const apiKey = process.env.SUBTOAPI_KEY;
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "claude-3-5-sonnet-20241022",
max_tokens: 1024,
messages: [{ role: "user", content: "Summarize this ticket." }]
})
});
For production, use a secrets manager (Vault, AWS Secrets Manager, or your platform's built-in equivalent) rather than plain environment files on disk. Environment variables are fine for local dev; they're not a substitute for a real secrets store at scale.
Scope keys to what they actually need
A key that can do everything is a key that can break everything. If your API surface supports scoping — read-only vs write, specific endpoints, rate limits per key — use it. Practical scoping rules:
- One key per application or service, not one key shared across your whole stack. If your mobile app, backend, and internal dashboard all use the same key, you can't tell which one leaked when something goes wrong.
- One key per environment. Staging and production should never share credentials.
- One key per team member during development, if your provider supports it, so you can revoke access when someone leaves without rotating everyone else's key too.
This is one of the reasons application-level API keys matter even when you're building on top of another provider. If you're giving your Claude access an HTTPS API layer through something like SubToAPI, each application key (sub_live_...) is scoped independently — you can issue one key per app, track usage per key in the dashboard, and revoke a single one without touching the others. See /docs/quickstart for how key issuance works in practice.
Rotate keys on a schedule, not just after an incident
Rotation shouldn't be a reactive fire drill. A reasonable baseline:
- Rotate production keys every 90 days as a default policy
- Rotate immediately after any employee offboarding with key access
- Rotate immediately if a key appears in a log, error report, or public repository — even briefly
The practical challenge with rotation is downtime: if you swap a key and forget to update one service, that service breaks. The way around this is overlap — most good API systems let you issue a new key before revoking the old one, so you can update all consumers and confirm they're working before killing the old credential.
Make revocation instant and low-friction
If revoking a compromised key requires opening a support ticket and waiting, you have a security gap, not a security process. Look for (or build) systems where:
- Revocation takes effect immediately, not on the next billing cycle or deploy
- You can revoke one key without affecting others tied to the same account
- The dashboard shows you exactly which keys exist and when they were last used, so "unused for 8 months" keys don't linger indefinitely
This is a core reason to separate your application credentials from your underlying provider's own account credentials. When your app talks to Claude through a layer with its own key management — like SubToAPI's dashboard — you can kill a leaked application key in seconds without touching the account behind it. Details on request signing and auth headers are in /docs.
Monitor usage, not just existence
Key management doesn't stop once a key is issued. Watch for:
- Sudden spikes in request volume from a single key (possible leak or bot abuse)
- Requests from unexpected regions or IP ranges, if you track that
- Keys that are active but haven't rotated in a long time
Usage metadata — tokens consumed, request counts, error rates per key — is what turns "we have keys" into "we know how our keys are being used." If you're managing team access, per-seat visibility matters too: on SubToAPI's Team plan, each seat gets its own key and usage is broken out per key in the dashboard, so a spike is traceable to a person or service, not a mystery.
A short checklist
- [ ] Keys are prefixed and identifiable by environment
- [ ] No key exists in source control, ever
- [ ] Production secrets live in a secrets manager, not a flat file
- [ ] Every application/service has its own key
- [ ] Rotation happens on a schedule, not just after incidents
- [ ] Revocation is immediate and doesn't require a ticket
- [ ] Usage is monitored per key, not just per account
FAQ
How often should API keys be rotated? Every 90 days is a reasonable default for production systems. Rotate immediately, regardless of schedule, after an offboarding, a suspected leak, or any exposure in logs or public repos.
What's the difference between scoping and rotating keys? Scoping limits what a key can do (which endpoints, which environment, which rate limit). Rotation replaces the key's value over time. You need both — a well-scoped key that never rotates is still a long-term liability.
Should every application have its own API key? Yes. Shared keys across multiple apps or services make it impossible to tell which one leaked or misbehaved, and revoking one means breaking all of them. One key per application, one key per environment, is the baseline.