<!-- APIScout AI-readable guide source -->
<!-- Canonical: https://apiscout.dev/guides/api-key-management-rotation-2026 -->
<!-- Raw Markdown: https://apiscout.dev/guides/api-key-management-rotation-2026/raw.md -->
<!-- Source path: content/guides/api-key-management-rotation-2026.mdx -->

---
og_image: "/images/guides/api-key-management-rotation-2026.webp"
title: "API Key Management: Rotation & Revocation 2026"
description: "API key management and rotation in 2026 — key generation, storage, rotation policies, revocation, scoping, and patterns from Stripe, GitHub, and AWS Updated."
date: "2026-03-08"
author: "APIScout Team"
tags: ["api-security", "api-keys", "key-management", "authentication", "best-practices"]
tier: 1
---

# 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:

```json
{
  "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:
1. Notifies the API provider
2. Provider revokes the key
3. 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:

```json
{
  "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 |

## Key Management at Scale

Managing API keys for hundreds of customers is operationally straightforward. Managing them for hundreds of thousands introduces problems that the basics don't address.

**Key lookup performance.** Authenticating a key on every API request must be fast — you're adding it to the critical path of every authenticated call. Hashing the incoming key and looking up the hash in a database is correct, but needs to be sub-millisecond. Use a key-value cache (Redis or Memcached) as the primary lookup, backed by the database. Cache TTL should be short — 60 to 300 seconds — so revocations propagate quickly. A revoked key that still authenticates from cache for 5 minutes is operationally acceptable in most systems; one that remains valid for hours is not.

**Bulk revocation events.** When an organization member leaves, you may need to revoke many keys simultaneously. When a security incident occurs, you may need to force-rotate all customer keys at once. Design bulk revocation as a first-class operation: a background job that processes revocations in batches, writes audit records, sends notifications to owners, and handles partial failures gracefully. Revoking thousands of keys synchronously in a single web request is not viable.

**Orphaned key cleanup.** In any large deployment, keys will be created and forgotten. A regular cleanup process — identify keys unused for more than 90 days, notify the owner with a 14-day warning before revocation, then revoke if no response — reduces attack surface and keeps your key inventory reflective of actual usage.

## Short-Lived Tokens vs. Long-Lived Keys

Traditional API keys are long-lived credentials. Once issued, they're valid until explicitly revoked. This is convenient: a developer pastes the key into their configuration and it works indefinitely. The risk is symmetric: a leaked key is valid indefinitely too.

Short-lived tokens — OAuth 2.0 access tokens are the most common example — expire automatically, bounding the exposure window for any compromised credential. The tradeoff is implementation complexity. Consuming applications must handle 401 responses when tokens expire, refresh them using a refresh token or client credentials flow, and retry the original request. For sophisticated server-side integrations with proper secret management, this is manageable. For developer quickstarts or CI/CD scripts, the friction meaningfully reduces adoption.

The pragmatic approach most mature API providers use: offer both. Long-lived API keys for developer exploration, testing, and CI/CD pipelines where the lifecycle is well-understood. Short-lived OAuth tokens for production integrations where automated rotation is expected. GitHub's fine-grained personal access tokens — which support 7, 30, or 90-day expiration and per-repository scoping — model this dual approach well.

## 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](https://apiscout.dev) — comparisons, guides, and developer resources.*

*Related: [Best Webhook Management APIs in 2026](/blog/best-webhook-management-apis-2026), [How AI Is Transforming API Design and Documentation](/blog/ai-transforming-api-design-documentation-2026), [API Breaking Changes Without Breaking Clients](/blog/api-breaking-changes-without-breaking-clients-2026)*
