API Key Authentication Best Practices for Developers
A practical guide to securing APIs with API keys — covering generation, storage, rotation, scoping, and common mistakes to avoid.
API keys are the most common authentication method for developer-facing APIs. They're simple to implement, easy for consumers to use, and work in every language and framework. But that simplicity hides real security risks if you don't handle them carefully.
This guide covers what API keys are, how to generate and manage them securely, and the mistakes that lead to breaches — with concrete advice you can apply today.
What Is an API Key?
An API key is a long, random string that a client sends with every request to prove its identity. Unlike OAuth tokens, API keys are static credentials — they don't expire automatically, and they're not scoped to a specific user session. They identify the application (or developer), not the end user.
curl "https://api-snap.com/api/qr?data=hello" \
-H "Authorization: Bearer snp_a1b2c3d4e5f6..."
The key above tells the server which account is making the request, what plan they're on, and how many calls they've used this month.
Generating Secure API Keys
A good API key has three properties: it's long enough to resist brute force, random enough to be unpredictable, and prefixed for easy identification.
import crypto from "node:crypto";
function generateApiKey(prefix = "snp") {
const random = crypto.randomBytes(32).toString("base64url");
return `${prefix}_${random}`;
}
// Output: snp_k7Xm9pQ2vR4wB6yN1zA3cE5gI8jL0nP...Key design decisions:
- Use 32+ bytes of randomness — 256 bits of entropy makes brute force infeasible even at massive scale.
- Add a recognizable prefix — prefixes like
snp_,sk_, orpk_help developers (and secret scanners like GitHub's) identify keys instantly. - Use base64url encoding — avoids special characters that break in URLs, headers, or config files.
Storing Keys Securely
This is where most teams get it wrong. API keys need to be protected on both sides — the provider and the consumer.
Provider Side (Your Backend)
- Hash keys before storing — store
SHA-256(key)in your database, not the plaintext. When a request comes in, hash the provided key and look up the hash. If your database is compromised, attackers get useless hashes. - Show the full key only once — at creation time. After that, show only the last 4 characters as an identifier (
...nP3x). - Index on the prefix — if you hash the full key, you need a way to look it up efficiently. Store the prefix portion (e.g., first 8 chars) in a separate, indexed column.
Consumer Side (The Developer Using the Key)
- Environment variables — store keys in
.envfiles that are listed in.gitignore. Never hardcode keys in source files. - Secret managers — for production, use services like AWS Secrets Manager, HashiCorp Vault, or Doppler instead of plain environment variables.
- CI/CD secrets — use your CI platform's secret store (GitHub Actions secrets, GitLab CI variables) rather than committing credentials.
Key Rotation
Keys get leaked. Developers leave companies. Laptops get stolen. You need a rotation strategy.
- Support multiple active keys — let users create a new key before revoking the old one. This enables zero-downtime rotation.
- Set expiration policies — force rotation every 90 days for high-security environments. At minimum, make it easy to rotate on demand.
- Log key usage — if a revoked key is used after rotation, alert the account owner. It may indicate a compromised deployment that wasn't updated.
Scoping and Permissions
Not every key should have full access. Good API key systems support scoping:
- Read vs write — a reporting dashboard only needs read access. Don't give it a key that can also delete resources.
- Endpoint-level scopes — allow keys to be restricted to specific API endpoints or resource types.
- Rate limit tiers — tie keys to usage plans. A free-tier key gets 100 calls/month; a paid key gets 50,000. API Snap's pricing works exactly this way.
Common Mistakes to Avoid
- Putting keys in URLs —
?api_key=snp_secretgets logged in server access logs, browser history, and CDN caches. Always use theAuthorizationheader instead. - Committing keys to git — even in private repos, leaked keys in git history are a top vector for breaches. Use
.gitignoreand pre-commit hooks to catch this. - Sharing keys between environments — use different keys for dev, staging, and production. A leaked dev key shouldn't compromise prod.
- No usage monitoring — if you don't track which keys are used and how often, you won't notice a compromise until the bill arrives.
API Key Auth vs OAuth vs JWT
API keys aren't the right choice for every scenario:
- API keys — best for server-to-server calls, developer integrations, and simple public APIs. Easy to implement, easy to use.
- OAuth 2.0 — best when you need to act on behalf of a user (e.g., access their GitHub repos). More complex, but scoped to user consent.
- JWT — best for stateless authentication in microservices. The API Snap JWT decode endpoint can help you inspect tokens during development.
For most developer APIs, API keys hit the sweet spot of simplicity and security.
Get Started
Create a free API Snap account to see API key authentication done right — prefixed keys, per-key rate limits, usage tracking, and instant revocation. Check the documentation for implementation details, or test your keys in the API playground.