A few years back, I watched a small startup’s cloud bill jump from $200 to $47,000 in a single weekend. The cause? A single API key, hardcoded in a mobile app, that someone extracted and used to spin up crypto-mining instances. That’s the kind of damage one exposed key can do, and it’s exactly why I treat API key security as a non-negotiable part of every project I build.
Why API Keys Are Such a High-Value Target
API keys are attractive to attackers because they’re often:
- Long-lived (some never expire)
- Broadly scoped (full account access instead of limited permissions)
- Easy to find (hardcoded in client-side code, mobile apps, or public repos)
- Directly tied to billing and infrastructure access
Unlike a password, there’s frequently no MFA layer sitting behind an API key. Whoever has it, has the access.
Best Practice 1: Never Embed Keys in Client-Side Code
This is the mistake I see most often — a key sitting in JavaScript that ships to the browser, or hardcoded in a mobile app binary. Both are trivially extractable.
// Never do this in frontend code
const apiKey = "sk_live_abcd1234";
fetch(`https://api.example.com/data?key=${apiKey}`);
Instead, I route all requests that need a secret key through my own backend, which holds the key server-side and proxies the request.
sequenceDiagram
participant Client
participant MyBackend
participant ThirdPartyAPI
Client->>MyBackend: Request data (no key exposed)
MyBackend->>ThirdPartyAPI: Request with API key
ThirdPartyAPI-->>MyBackend: Response
MyBackend-->>Client: Filtered response
Best Practice 2: Scope Keys to the Minimum Permissions Needed
Most providers let you create restricted keys — read-only, limited to specific endpoints, or scoped to a specific resource. I always create the narrowest key possible for each use case rather than reusing one master key everywhere.
For example, with AWS, I never use root account keys for applications. I create IAM users or roles with tightly scoped policies instead. I cover this in more depth in IAM Best Practices for DevSecOps.
Best Practice 3: Store Keys in a Secrets Manager, Not Config Files
Plaintext .env files are fine for local development, but for production I move keys into a dedicated secrets manager:
- AWS Secrets Manager or Parameter Store
- HashiCorp Vault
- Google Secret Manager
- Azure Key Vault
# Example: retrieving a secret from AWS Secrets Manager
aws secretsmanager get-secret-value --secret-id prod/api/stripe-key
This keeps the key out of source code entirely and gives me centralized access logging.
Best Practice 4: Rotate Keys on a Schedule
Even a well-protected key should have a shelf life. I set rotation schedules based on sensitivity — 30 to 90 days for high-value keys, and immediate rotation the moment a key is suspected of exposure. I go into the mechanics of this in Secret Rotation Best Practices.
Best Practice 5: Monitor and Alert on Key Usage
A key that suddenly starts making requests from a new country, at 3 a.m., at 50x the normal volume, is a signal — not noise. I set up usage alerts wherever the provider supports it (most major APIs do), and I pair that with centralized logging so I can trace anomalous activity back to a specific key.
Best Practice 6: Scan Repositories and CI Logs for Leaked Keys
Even with good habits, mistakes happen. I run automated secret scanning on every push using tools like gitleaks or trufflehog, and I extend that scanning to CI/CD pipeline logs, since keys frequently leak through debug output. I cover the full mechanics of this in How to Prevent Secret Leaks in Git Repositories.
Common Mistakes I See With API Key Handling
- Using one API key across dev, staging, and production
- Committing keys to version control “temporarily”
- Never rotating keys after an employee leaves the team
- Granting full-account-access keys for narrow tasks
- Logging full request headers, which accidentally captures the key
Best Practices Summary
| Area | Recommendation |
|---|---|
| Storage | Secrets manager, never source code |
| Scope | Least privilege, task-specific keys |
| Exposure | Server-side only, never client-side |
| Rotation | Scheduled + on-demand after suspected leak |
| Monitoring | Usage alerts and anomaly detection |
| Detection | Automated scanning in repos and CI logs |
If your stack includes containers, it’s also worth reviewing how secrets get injected into Docker and Kubernetes environments, since misconfigured environment variables in these platforms are a common leak source too.
FAQs
How often should I rotate API keys? For high-sensitivity keys (payment processors, admin-level access), I rotate every 30–90 days. Lower-risk, read-only keys can go longer, but I still rotate at least annually.
Is it safe to use API keys in mobile apps? Only if the key is scoped tightly and doesn’t grant sensitive access. Anything with write access or billing implications should be proxied through your own backend.
What’s the difference between an API key and an OAuth token? API keys are typically static, long-lived credentials tied to an application. OAuth tokens are usually short-lived, scoped to a specific user session, and can be refreshed — making them generally more secure for user-facing access.
What should I do if I accidentally commit a key to GitHub? Revoke and rotate the key immediately, then remove it from Git history. Rotation matters more than cleanup, since the key should be considered compromised the moment it’s pushed.
Conclusion
API key security comes down to a simple principle I keep coming back to: minimize exposure, minimize scope, and minimize lifetime. Keep keys server-side, scope them tightly, store them in a proper secrets manager, rotate them regularly, and monitor how they’re used. Do those five things consistently, and you’ll close off the vast majority of ways API keys actually get abused in the real world.
