API Key Management: Generation, Rotation, and Revocation
API Key Management: Generation, Rotation, and Revocation
API keys are the most common authentication method for APIs. They're simple, effective, and universally understood. But simplicity creates risk — a leaked key is a breached system. Secure key management covers the full lifecycle: generation, storage, distribution, rotation, and revocation.
API Key Lifecycle
Generate → Distribute → Use → Monitor → Rotate → Revoke
↑ |
└────────────────────────────────────────┘
Key Generation
Format Matters
Good API keys are:
- Identifiable — prefixed so you know what they are
- Unique — cryptographically random, no collisions
- Secure — enough entropy to resist brute force
Prefix patterns from top APIs:
| API | Key Format | Purpose |
|---|---|---|
| Stripe | sk_live_..., sk_test_... | Environment + type |
| GitHub | ghp_..., ghs_..., ghu_... | Scope (personal, server, user-to-server) |
| OpenAI | sk-proj-... | Project-scoped |
| AWS | AKIA... (20 chars) | IAM access key |
| Twilio | 34-char hex string | Account SID + Auth Token |
Recommended format:
{provider}_{environment}_{random}
Examples:
myapi_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
myapi_test_x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4
Generation Best Practices
✅ Use crypto.randomBytes(32) or equivalent (256 bits of entropy)
✅ Use a prefix that identifies the key type and environment
✅ Make keys long enough (40+ characters) to prevent brute force
✅ Generate server-side only — never on the client
❌ Don't use UUIDs (only 122 bits of entropy, predictable structure)
❌ Don't use sequential IDs
❌ Don't derive keys from user data (email, username)
❌ Don't use short keys (<32 characters)
Key Storage
Server-Side (Your Database)
Never store API keys in plain text. Hash them like passwords:
What you store: SHA-256(api_key) or bcrypt(api_key)
What the user sees: sk_live_a1b2c3d4... (shown once, never again)
What you compare: SHA-256(incoming_key) === stored_hash
Show the full key exactly once — at creation time. After that, show only the last 4 characters: sk_live_...o5p6.
Key Metadata
Store alongside the hash:
| Field | Purpose |
|---|---|
key_hash | SHA-256 hash for lookup |
key_prefix | First 8 chars for identification |
key_suffix | Last 4 chars for display |
user_id | Owner of the key |
name | User-defined label ("Production Server") |
scopes | Permissions (read, write, admin) |
created_at | When the key was generated |
last_used_at | Last successful authentication |
expires_at | Expiration date (null = never) |
rate_limit | Per-key rate limit override |
ip_allowlist | Restrict to specific IPs |
Client-Side (Developer's App)
Developers need to store API keys securely in their applications:
| Environment | Storage Method | Security |
|---|---|---|
| Backend server | Environment variables | Good |
| Backend server | Secrets manager (AWS SM, Vault) | Best |
| Mobile app | Keychain (iOS) / Keystore (Android) | Good |
| Browser | Never store API keys in frontend code | N/A |
| CI/CD | Pipeline secrets (GitHub Secrets, etc.) | Good |
Never commit API keys to source code. Use environment variables or secret managers.
Key Scoping
Permission Levels
Not all keys should have the same access:
| Scope | Access | Use Case |
|---|---|---|
read | GET only | Public dashboards, read-only integrations |
write | GET + POST + PUT | Standard API usage |
admin | Full access + key management | Account administration |
billing | Billing endpoints only | Finance integrations |
Resource Scoping
Limit keys to specific resources:
{
"key": "sk_live_...",
"scopes": ["orders:read", "orders:write", "products:read"],
"resources": {
"organizations": ["org_123"],
"projects": ["proj_456", "proj_789"]
}
}
A key scoped to orders:read can't access user data, even if the API has user endpoints.
Environment Separation
Always separate test and production keys:
| Key Type | Prefix | Access | Billing |
|---|---|---|---|
| Test | sk_test_ | Sandbox only | No charges |
| Live | sk_live_ | Production | Real charges |
Test keys should never work in production. Production keys should never work in sandbox.
Key Rotation
Why Rotate
- Reduce blast radius of leaked keys
- Comply with security policies (SOC 2, PCI DSS)
- Limit exposure window
- Force key hygiene
Rotation Policy
| Key Type | Rotation Period | Enforcement |
|---|---|---|
| Production API keys | Every 90 days | Recommended, warn at 60 days |
| Service-to-service keys | Every 30 days | Automated rotation |
| CI/CD keys | Every 90 days | Pipeline-enforced |
| Admin keys | Every 30 days | Required |
| Test keys | No rotation needed | Optional |
Graceful Rotation (Overlap Period)
Never invalidate the old key immediately. Allow an overlap period:
Day 0: Generate new key → Both old and new keys work
Day 1-7: Developer updates their applications to use new key
Day 7: Old key is revoked
During overlap: Both keys authenticate successfully
After overlap: Only new key works
Automated Rotation
For service-to-service keys, automate the entire process:
1. Secrets manager generates new key
2. New key is registered with the API
3. Secrets manager updates the consuming service's config
4. Service restarts or hot-reloads the new key
5. Old key is revoked after grace period
6. Audit log records the rotation
Tools: AWS Secrets Manager, HashiCorp Vault, Doppler, 1Password Connect
Key Revocation
When to Revoke
| Trigger | Action | Urgency |
|---|---|---|
| Key leaked in public repo | Immediate revocation | Emergency |
| Employee leaves company | Revoke their keys | Same day |
| Key compromised | Immediate revocation | Emergency |
| Key unused for 90+ days | Revoke with notification | Low |
| Key rotation complete | Revoke old key | Scheduled |
Revocation Process
1. Mark key as revoked in database (don't delete — keep for audit)
2. Clear key from all caches
3. Return 401 with clear error: "API key has been revoked"
4. Log the revocation event with reason
5. Notify the key owner (email, webhook, dashboard alert)
6. If emergency: check for unauthorized usage in recent logs
GitHub's Automatic Revocation
GitHub scans public repositories for leaked API keys and automatically:
- Notifies the API provider
- Provider revokes the key
- Notifies the developer
If you're an API provider, join GitHub's Secret Scanning Partner Program to get automatic leak notifications.
Monitoring and Alerts
What to Monitor
| Signal | Indicates | Alert Threshold |
|---|---|---|
| Key used from new IP | Potential compromise | Any new IP (notify) |
| Sudden usage spike | Abuse or compromise | 5x normal volume |
| Key used from unexpected country | Potential compromise | Any unexpected location |
| Failed auth attempts | Brute force attack | 10+ failures in 1 minute |
| Key approaching expiration | Needs rotation | 14 days before expiry |
| Key unused for 60+ days | Orphaned key | Notify owner |
Audit Logging
Every key event should be logged:
{
"event": "api_key.used",
"key_prefix": "sk_live_a1b2",
"ip": "203.0.113.42",
"endpoint": "POST /api/orders",
"timestamp": "2026-03-08T14:30:00Z",
"user_agent": "MyApp/2.1",
"status": 200
}
Log these events: key.created, key.used, key.rotated, key.revoked, key.expired, key.auth_failed.
Patterns from Top APIs
| API | Notable Practice |
|---|---|
| Stripe | Test/live prefix, last 4 visible, scope by mode |
| GitHub | Fine-grained tokens with per-repo permissions, auto-expiry |
| AWS | Access key + secret key pair, IAM policy-based scoping |
| Google Cloud | Service account JSON keys, workload identity federation |
| Twilio | Account SID + Auth Token, sub-account isolation |
Common Mistakes
| Mistake | Impact | Fix |
|---|---|---|
| Storing keys in plain text | Database breach = all keys compromised | Hash with SHA-256 |
| No key rotation policy | Leaked keys stay valid forever | 90-day rotation policy |
| Same key for test and prod | Test code accidentally hits production | Separate keys with prefixes |
| No scope restrictions | Every key has admin access | Principle of least privilege |
| Showing full key after creation | Keys visible in dashboards, emails | Show once, then mask |
| No monitoring on key usage | Can't detect compromise | Alert on anomalous patterns |
Securing your API keys? Explore API security tools and best practices on APIScout — comparisons, guides, and developer resources.