Generating Secure API Keys: Formats and Best Practices
API keys are the simplest form of API authentication. Unlike OAuth tokens or JWTs, they don't encode user identity or expiration — they're just random strings that identify a caller. Getting the format and handling right matters for both security and developer experience.
Key Formats Compared
UUID v4
550e8400-e29b-41d4-a716-446655440000
- 122 bits of randomness
- Universally understood format
- Easy to parse (five hyphen-separated groups)
- Downside: No visual indicator of what the key is for
Hex Token
a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0
- Arbitrary length (64 hex chars = 256 bits)
- Simple to generate with any crypto library
- Downside: Not human-friendly, easy to confuse with hashes
Prefixed API Key
tk_live_a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4c5
- Prefix identifies the service (
tk_) and environment (live_) - Immediately distinguishable from passwords, hashes, and other secrets
- Log scanning can detect leaked keys by prefix (like GitHub's secret scanning)
- This is the recommended format
Generate a prefixed API key with the Auth Toolkit API:
curl -X POST https://auth.toolkitapi.io/v1/auth/generate-key \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "api-key", "length": 32, "prefix": "tk_live_"}'
{
"key": "tk_live_a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4c5",
"type": "api-key",
"entropy_bits": 128.0
}
Entropy: How Much Randomness?
Entropy measures how hard a key is to guess. For API keys:
| Entropy | Security level | Example |
|---|---|---|
| 64 bits | Minimum viable | 16 hex chars |
| 128 bits | Standard | 32 hex chars, UUID v4 |
| 256 bits | High security | 64 hex chars |
128 bits of entropy is the practical standard — it would take billions of years to brute-force, even with all the world's computing power.
The Auth Toolkit reports entropy_bits in every response so you can verify your keys meet your security requirements.
Other Key Types
The Generate Key endpoint supports multiple formats:
# UUID v4
curl -X POST .../generate-key -d '{"type": "uuid"}'
# Hex secret
curl -X POST .../generate-key -d '{"type": "hex", "length": 64}'
# URL-safe token
curl -X POST .../generate-key -d '{"type": "url-safe", "length": 32}'
For asymmetric key pairs (RSA/EC), use the Generate Key Pair endpoint:
curl -X POST https://auth.toolkitapi.io/v1/auth/generate-keypair \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"algorithm": "RSA", "key_size": 2048}'
Storage Best Practices
Hash keys before storing
Never store API keys in plaintext in your database. If your database is breached, all keys are compromised. Instead:
- When a key is generated, show it to the user once.
- Store a SHA-256 hash of the key in your database.
- When a request arrives, hash the provided key and compare against stored hashes.
This is the same principle as password hashing, but SHA-256 is sufficient here because API keys have high entropy (unlike passwords).
Display only the prefix
In dashboards, show only the first 8–12 characters: tk_live_a3f8.... This lets users identify which key it is without exposing the full secret.
Scope keys to the minimum
Each key should have the narrowest permissions possible:
- Read-only vs. read-write
- Per-environment: Separate keys for development, staging, and production
- Per-service: Don't share keys between microservices
Rotation and Revocation
Keys should be rotatable without downtime:
- Generate a new key and add it to the system.
- Update the client to use the new key.
- Revoke the old key after confirming the transition.
Support multiple active keys per user/service so the transition is seamless. Set key expiration dates and alert users before keys expire.
Key Generation Checklist
- [ ] Use at least 128 bits of cryptographic randomness
- [ ] Add a descriptive prefix (service + environment)
- [ ] Hash keys (SHA-256) before database storage
- [ ] Show the full key only once at creation time
- [ ] Support multiple active keys for rotation
- [ ] Log key usage with key ID (not the key itself)
- [ ] Rate-limit API authentication to slow brute-force attempts