How to Generate API Keys: Formats, Security & Best Practices
API keys authenticate machine-to-machine requests — from mobile apps to backend services to third-party integrations. Unlike JWTs, API keys are typically long-lived static credentials, which makes generation and storage practices even more important.
What Makes a Good API Key?
A secure API key is:
- Random — generated from a cryptographically secure source
- Long enough — at least 128 bits of entropy (256 bits recommended)
- Unique — never reused across services or environments
- Prefixable — includes a recognizable prefix for log filtering (e.g.,
sk_live_)
Choosing a Format
| Format | Example Length | Best For |
|---|---|---|
| UUID v4 | 36 chars | Human-readable, standard format |
| Hex | 64 chars | Maximum entropy density |
| Alphanumeric | 32–64 chars | URL-safe, compact |
| Base64 | ~44 chars | Binary-safe transport |
Use the API Key Generator to generate keys in any of these formats directly in your browser.
Generating API Keys
Browser Tool
Open the API Key Generator, select your preferred format and length, and click Generate. All generation uses crypto.getRandomValues() — nothing leaves your browser.
Node.js
const crypto = require('crypto');
// Hex format (recommended)
const apiKey = 'sk_live_' + crypto.randomBytes(32).toString('hex');
// UUID v4 format
const { randomUUID } = require('crypto');
const apiKey = 'sk_live_' + randomUUID().replace(/-/g, '');Python
import secrets
api_key = 'sk_live_' + secrets.token_hex(32)Prefix Strategy
Prefixes help you identify key type and environment in logs without exposing the full key:
sk_live_a3f8b2c1... # production secret key
sk_test_9b1deb4d... # test environment key
pk_live_7c2e9f1a... # production publishable keyNever log the full key — truncate after the prefix in log output.
Server-Side Validation
Store only a hash of the API key in your database, not the plaintext:
const crypto = require('crypto');
function hashApiKey(key) {
return crypto.createHash('sha256').update(key).digest('hex');
}
// On key creation
const plainKey = generateApiKey();
const storedHash = hashApiKey(plainKey);
// Store storedHash in DB, return plainKey to user once
// On request validation
const providedHash = hashApiKey(req.headers['x-api-key']);
if (providedHash !== storedHash) throw new UnauthorizedError();Use the Hash Generator to understand SHA-256 hashing used here.
Storage Rules
- Show the plaintext key to the user once at creation time
- Store only the hash in your database
- Use environment variables or a secrets manager for your own service keys
- Never commit API keys to git — use
.gitignoreand pre-commit hooks
Rate Limiting and Abuse Prevention
API keys authenticate callers, but they do not replace rate limiting. Implement per-key quotas to prevent abuse if a key is leaked:
const keyHash = hashApiKey(req.headers['x-api-key']);
const count = await redis.incr(`ratelimit:${keyHash}:${currentMinute}`);
if (count > 1000) return res.status(429).json({ error: 'Rate limit exceeded' });Combine per-key limits with IP-based throttling. Alert on sudden spikes in 401 or 429 responses — they may indicate a compromised key.
Monitoring and Audit Logging
Log API key usage without logging the full key:
console.log({
event: 'api_request',
keyPrefix: apiKey.slice(0, 12) + '...',
endpoint: req.path,
status: res.statusCode,
});Retain audit logs for compliance reviews. Track which keys access sensitive endpoints and flag anomalous geographic or temporal patterns.
Rotation
Rotate API keys on a schedule (quarterly for production) or immediately after suspected compromise:
1. Generate a new key
2. Allow a grace period where both old and new keys work
3. Notify integrators to update
4. Revoke the old key
API Keys vs JWTs
| API Keys | JWTs | |
|---|---|---|
| Lifetime | Long-lived | Short-lived |
| Revocation | Immediate (delete from DB) | Wait for expiry or blacklist |
| Stateless | No (lookup required) | Yes (verify signature only) |
| Best for | Service-to-service, public APIs | User sessions |
For user authentication, prefer JWTs. For machine-to-machine access, API keys are appropriate when combined with proper hashing and rotation.
Scoped Permissions
Assign each API key a scope rather than granting full account access:
// Example key record
{
keyHash: 'sha256...',
prefix: 'sk_live_',
scopes: ['read:users', 'write:orders'],
createdAt: '2026-01-15T00:00:00Z',
expiresAt: '2026-07-15T00:00:00Z',
}Validate scopes in middleware after key authentication. A read-only integration key should not be able to call destructive endpoints even if the key itself is valid.
Choosing Key Length
| Format | Entropy | Recommendation |
|---|---|---|
| UUID v4 | 122 bits | Acceptable for low-risk internal tools |
| 32-char hex | 128 bits | Minimum for production |
| 64-char hex | 256 bits | Recommended default |
Generate 256-bit keys with the API Key Generator for production integrations. Longer keys add security margin; shorter keys reduce header size but increase brute-force risk.