Every automation you ship runs on an API key. Keys are identity for machines — and most systems treat them like afterthoughts. This article is the production playbook for API keys: how to design them, store them, scope them, rotate them, and detect when they leak. The yas.sh key model is used as the reference implementation because it follows every rule below.
Anatomy of a good API key
A production key has recognizable structure:
yas_live_8f3a91c2e5b7d6041a9f2c8e7b6d5a4f3c2b1a09
└───┬───┘ └────┬────────────────────────────────────┘
prefix 256-bit random value (32 hex chars)
The prefix (yas_live_) serves three purposes: humans recognize the key type instantly; support teams can triage by prefix; and secret scanners, log greps, and git hooks can detect leaks with a trivial pattern (yas_live_[0-9a-f]{32}). Prefixes also let you run two key spaces (e.g. yas_test_ for staging) with separate policies.
The entropy is the security. 256 bits of CSPRNG output is more than enough to make guessing infeasible — brute force is not the threat model; leakage is. That's why the storage design matters more than the length.
Storage: hash or don't ship
The raw key must be shown exactly once, at creation. Everything after that is a one-way hash:
Client sees: yas_live_8f3a91c2...
Database: sha256("yas_live_8f3a91c2...") = a1b2c3...
Auth request: Authorization: Bearer yas_live_8f3a91c2...
Authentication hashes the presented key and looks up the hash. Because the key has full entropy, SHA-256 is the right choice — no need for slow KDFs like bcrypt, which exist to protect low-entropy passwords. If the database leaks, attackers get hashes they cannot reverse.
Supporting hygiene: the API response for a key list shows only the prefix and last-used timestamp, never a recoverable secret; keys are revocable in one call; and the dashboard displays "shown once" prominently because that's the only moment it exists.
# Create (key returned once)
curl -X POST https://yas.sh/api/v1/api-keys \
-H "Authorization: Bearer yas_live_..." \
-d '{"name":"ci-deploy","scopes":["links:write","links:read"]}'
# → 201 { "id": "...", "key": "yas_live_8f3a...", "warning": "Copy now — shown once" }
# Revoke instantly
curl -X DELETE https://yas.sh/api/v1/api-keys/<id> \
-H "Authorization: Bearer yas_live_..."
Scopes: least privilege for machines
A key that can do everything is a standing vulnerability. Scope keys to the smallest permission set the automation needs:
| Scope | Grants |
|---|---|
links:read |
List, search, export links |
links:write |
Create, update, delete links |
analytics:read |
Read click analytics |
CI pipelines typically need links:write + links:read; read-only dashboards need only links:read; a key pasted into a public repo should exist for minutes, not months.
Rotation and revocation lifecycle
Rotation is cheap; leaked keys are expensive. The lifecycle that works:
- Create with a name that says where it's used (
ci-deploy,print-vendor,analytics-bot). - Detect exposure with secret scanning (gitleaks, GitHub secret scanning,
grep -r "yas_live_"in CI). - Revoke the exposed key immediately — revocation is instant because the hash lookup simply stops matching.
- Rotate on schedule: on any employee departure with access to the key store, on any suspected leak, and on a quarterly calendar if policy demands it.
- Monitor
lastUsedAt— a key that hasn't been used in 90 days is a candidate for revocation.
Monitoring: keys as infrastructure
The operational view of keys: names, prefixes, scopes, last-used timestamps, creation dates. That small dataset answers the questions that matter — is anything using this key? when did it last authenticate? which automation owns it? The API key endpoints return exactly these fields, and the dashboard renders them in a table so key hygiene is a two-minute review, not an audit project.
Common failure modes
- Keys in client-side code. Anything shipped to a browser is public. Move key usage behind a server proxy or use short-lived sessions instead.
- One mega-key for everything. A leaked mega-key grants the attacker everything. Scope by environment and by function.
- No rotation on departure. Former employees' keys keep authenticating forever. Revoke on offboarding, always.
- Raw keys in logs. Log the prefix and the last four characters if you must, never the full key.
Scopes: the principle that protects you
The single most effective API-key control is scoping — giving each key only the reach its workload needs. A key that can only create links should not be able to delete them or read billing; a read-only key should not mutate anything. Scoped keys shrink the blast radius of a leaked key: if a key is stolen, the attacker can do only what that key's scope permits, not everything your account can do. This is least privilege applied to machine credentials, and it is the same discipline that governs team permissions and model tool scoping. Deciding the narrowest scope each integration needs is the first line of defense.
Rotation and a rotation habit
Scoped keys reduce damage but rotation limits how long any leaked key remains useful. Adopt a rotation habit: generate keys with an expiry, rotate them on a schedule, and rotate immediately on any suspicion of compromise. The practical pattern is to have keys that you can revoke and re-issue without disrupting the integration — which argues for giving each workload its own key so rotating one does not take down others. A key you never rotate is a key you have essentially granted permanently; rotation turns a credential into a time-boxed one.
Secrets hygiene: where the real leaks happen
Most API-key leaks are not elaborate attacks; they are secrets committed to code, exposed in logs, or pasted into the wrong chat. The hygiene that prevents these is simple but must be enforced:
- Never commit keys to a repository, even a private one — scan for them and block the commit if found.
- Store keys in environment variables or a secrets manager, not in source files.
- Do not log keys — redact them from request and response logs.
- Use a separate key per environment (dev, staging, prod) so a leak in one does not expose the others.
Treating keys as secrets that must be protected, not as tokens you can paste around, eliminates most leaks before they happen.
Monitoring and revoking
Detection and response close the loop. Watch for anomalous usage — a key suddenly making requests it never makes, or traffic from an unexpected source — and alert on it. Keep the ability to revoke a key instantly, and document the procedure so a suspected leak is contained in minutes rather than hours. The combination of scoped, rotated, well-guarded, and monitored keys is what makes API-key-based integration safe enough to rely on at scale. This pairs with the API keys vs OAuth decision for choosing the right credential model in the first place.
Conclusion
API keys are identity for machines, and the design rules are the same as for passwords: high entropy, hashed at rest, shown once, scoped narrowly, rotated routinely, revoked instantly. The yas.sh API implements all of it — the key management endpoints are a working reference you can copy into any platform.
