API Key Management Best Practices for Dev Teams
API key management best practices come down to five things: generate keys with enough entropy, store them somewhere secrets can't leak from, scope them to the minimum they need, rotate and revoke them on a schedule, and watch how they're actually used. Most breaches involving API keys aren't cryptographic failures — they're keys committed to git, keys with no expiry, or keys shared across ten services so nobody can revoke one without breaking nine others.
This article walks through each practice with concrete steps you can apply today, whether you're managing keys for your own infrastructure or issuing keys to customers of your own product.
Generate keys correctly from the start
A good API key is:
- Long enough to resist brute force — at least 32 bytes of randomness, base62 or hex encoded.
- Prefixed so it's identifiable in logs and scanners (
sub_live_...,sk_test_...). Prefixes let you grep for accidental exposure and let automated secret scanners (GitHub's included) flag leaks before you find out the hard way. - Generated server-side, never derived from user input or predictable counters.
Don't reuse the same key format for test and production. A distinct prefix (_test_ vs _live_) prevents someone from accidentally hitting production with a key copied from a staging .env file.
Store keys like secrets, not config
Keys belong in a secrets manager (Vault, AWS Secrets Manager, Doppler, or your platform's built-in equivalent), not in:
.envfiles committed to git, even in "private" repos- CI/CD YAML files
- Slack messages or shared docs
- Client-side JavaScript
If a key must live in an environment variable, make sure .env is in .gitignore before the first commit, not after. Use git-secrets or a pre-commit hook to catch accidental staging of files containing key-like strings.
# quick pre-commit check for common key prefixes
grep -rE "(sk_live_|sub_live_|AKIA)[A-Za-z0-9]{16,}" --include="*.{js,ts,env,yml}" .
For server-to-server calls, keep the key on the server only. Never ship it in a mobile app bundle or a frontend build — both are trivially extractable.
Scope keys to the minimum they need
A single key with full account access is a liability. If it leaks, the blast radius is everything. Instead:
- Issue separate keys per environment (dev, staging, production)
- Issue separate keys per service or integration, so a compromised key from your analytics pipeline can't touch billing
- Use read-only or restricted scopes where the provider supports them
- Set rate limits per key so a leaked key can't be used to exhaust your quota or run up your bill overnight
This is also why per-application keys matter when you're consuming a third-party API. If you're building multiple products on top of Claude, for example, SubToAPI lets you issue a separate sub_live_ key per application from one dashboard, so each app can be rotated or revoked independently without taking down the others. See /docs/quickstart for how key creation works.
Rotate keys on a schedule, not just after an incident
Rotation shouldn't be a reactive fire drill. Set a cadence:
- 90 days for keys with broad access
- 180 days for lower-risk, narrowly scoped keys
- Immediately for any key that touched a public repo, log file, or third-party tool, even briefly
The mechanics matter more than the interval. A rotation process that requires downtime will get skipped. Support dual-key overlap: issue the new key, deploy it, confirm traffic has shifted, then revoke the old one. Most well-designed APIs let you have two active keys simultaneously for exactly this reason.
// example: rotate a key with overlap, generic pattern
const newKey = await client.keys.create({ label: "prod-api-2025-q2" });
await deployToProduction(newKey);
await waitForTrafficShift(newKey, { minRequests: 1000 });
await client.keys.revoke(oldKey.id);
Revoke fast, and make revocation cheap
Revocation should take seconds, not a support ticket. If revoking a key requires redeploying an application or waiting on a vendor's support queue, that's a design flaw you should account for before you're in an incident. Look for providers that expose key revocation directly in a dashboard or API — this is a good signal of overall API key management maturity, not just a convenience feature.
When you revoke, log why: leaked, rotated, employee offboarding, service decommissioned. That history matters when you're doing a postmortem six months later and can't remember which of twelve keys was for what.
Monitor usage, not just existence
Knowing a key exists isn't the same as knowing what it's doing. Track, per key:
- Request volume and error rate over time
- Which endpoints or models it's hitting
- Token or usage cost attributed to it
- Geographic or IP origin of requests, if your provider surfaces it
A sudden spike in requests from a key that normally does 200 calls/day is worth an alert, not a shrug. This is one of the practical reasons to consolidate API access through a single gateway rather than scattering raw provider keys across every service: usage metadata becomes visible in one place instead of being buried in each individual integration's logs. SubToAPI surfaces this per key in the dashboard, alongside streaming and tool-use metadata — see /docs/messages and /docs/streaming for what's tracked on each request.
Handle team access without shared keys
The most common anti-pattern in small teams is one shared key pasted into a team wiki. It works until someone leaves, and then nobody knows whether to rotate it, what breaks if they do, or who else has a copy.
Instead:
- Give each team member or service their own key
- Use team/seat-based access control so revoking one person's access doesn't require touching everyone else's key
- Keep an audit trail of who created and revoked which key
If you're issuing Claude access to a team, this is exactly what seat-based plans are for — each person gets scoped API access without a shared secret floating around. See /pricing for how Team and Scale plans handle seats, or start with a free trial at /signup.
A minimal checklist
- [ ] Keys generated with sufficient entropy and identifiable prefixes
- [ ] Stored in a secrets manager, never in git or client-side code
- [ ] Scoped per environment, per service, per team member
- [ ] Rotated on a fixed schedule with overlap support
- [ ] Revocable in seconds, with a reason logged
- [ ] Usage monitored per key, with alerts on anomalies
FAQ
How often should API keys be rotated? 90 days is a reasonable default for high-privilege keys, 180 days for narrowly scoped ones. Any key exposed in a log, repo, or third-party tool should be rotated immediately, regardless of schedule.
Is it safe to store API keys in environment variables? Environment variables are fine at runtime, but the underlying file (.env) must never be committed to version control. For production systems, a dedicated secrets manager is safer than relying on .env files alone.
What's the difference between key scoping and key rotation? Scoping limits what a key can do (read-only, single service, rate-limited); rotation limits how long a key is valid. Both reduce blast radius, but scoping prevents damage while a key is active, and rotation limits the damage window if it leaks.