Form K-99 · Operating manual
User guide
Everything the register can do, in the order you'll meet it.
Registering a key
- Scan it. Hit Register key and the scan step opens. Plug the key into the machine you're browsing from and touch it when it blinks. Keeyo reads the model fingerprint (AAGUID), matches it against the live FIDO registry, and pre-fills vendor, model and form factor. Scanning also pairs the key, which unlocks identification and secret notes later. Nothing is written to the key and none of its passkey storage is used.
- Or add it manually. The small link below the scan button opens the plain form. Vendors, models, form factors and colors all accept custom entries — anything you type is remembered in your personal catalog (Settings → Catalog) for next time.
- Pick the variant if asked. Fingerprints identify a series — a YubiKey 5 NFC and 5C NFC share one — so when it's ambiguous, Keeyo narrows the model list and you pick the plug you're holding.
- Give it a name and a color. Name it for where it lives ("Desk drawer backup"), and match the color tag to a real sticker on the physical key. You can upload a photo instead of the schematic drawing.
Logging what's on a key
Open a key's tag and add sign-ins (passkeys and 2FA registrations) and TOTP codes. The service picker searches your existing services, offers one-tap buttons for common ones (GitHub, Google, …) and creates new services inline — with automatic favicons. Tick add another to log a whole key's contents in one sitting.
Registrations can be edited, moved to another key, or removed — deletions come with a 5-second Undo instead of a confirmation dialog.
Services & backup coverage
The Services view (the globe icon in the left rail) is the reverse lookup: every service, and colored squares for each key that covers it. Open a service to see exactly which keys hold it. Two warnings matter:
- no backup — add one: only one usable key covers this service. The chip is a button — it opens a key picker and pre-fills the registration form.
- not on any key — fix: no usable key covers it at all (e.g. the only key is marked lost).
The same warnings surface as a strip on the dashboard so gaps don't hide.
Every service can carry an icon: upload your own, or search the selfh.st and Dashboard Icons catalogs by name, or pull the site’s favicon through DuckDuckGo. Catalog icons load from jsDelivr in your browser; uploads are stored with the service.
Losing a key
Set the key's status to lost. Its registrations become a revocation checklist — go to each service, remove the key there, and tick it off. The dashboard shows a hazard strip until the checklist is clean. If the key turns up later, the identify feature will recognize it and remind you it was marked lost.
"Which key is this?"
The identify button on the dashboard answers the question the whole app exists for. Plug in the mystery key, touch it, and Keeyo names the exact record — even several keys plugged in at once is fine, because the key you physically touch is the one that answers. Works for paired keys; unpaired ones fall back to a model read with candidate matches.
Secret notes (tap to reveal)
A paired key can hold one secret note — typically its PIN. The note is never shown in the app; revealing it requires tapping that exact physical key, and the server verifies the cryptographic response before releasing it.
On modern keys (anything supporting the WebAuthn PRF extension — YubiKey 5 series included), the note is also end-to-end encrypted: your browser derives the encryption key from the hardware itself, so the server only ever stores ciphertext. Saving asks for one extra tap; revealing doesn't — the same tap proves possession and unlocks the note. The key page labels every note E2E encrypted or server-stored so you always know which mode you're in; re-pairing an old key upgrades it.
Health check-ins
Backup keys rot in drawers. Whenever you actually use or test a key, press Tested on its page — the dashboard nudges you about any active or backup key that hasn't been confirmed working in six months.
The logbook
Every key keeps an append-only ledger: registered, paired, status changes, services added and removed, revocations, tests, files. It answers "when did I add this?" without you ever writing anything down.
Printing & exports
- Asset tag (key page → printer icon): a physical label with the key's name, tag number, barcode and a QR code linking back to its record. Stick it on the keychain.
- Register sheet (Settings → Account → Backup → Export PDF): the whole inventory as one ledger table — save it as a PDF or print it.
- CSV (Settings → Account → Backup): the same data for spreadsheets.
Protecting Keeyo itself
Settings → Security: add a second factor and logging in requires your password plus that factor.
- Security keys — enroll one or more hardware keys; sign-in asks for a tap. Enroll at least two so losing one never locks you out.
- Authenticator app — any TOTP app (Aegis, Ente Auth, Google Authenticator, …) works as an alternative or additional factor. Handy where WebAuthn isn't available, e.g. plain-HTTP LAN deployments don't support key taps but codes still work.
- Recovery codes — generate ten single-use codes and store them safely (password manager, printed sheet). Each signs you in once when your second factor is unavailable. They're shown only at generation time, and regenerating replaces the whole set.
If every factor is lost, the server owner still has the recovery paths: KEEYO_DISABLE_MFA=1 or scripts/reset-password.js.
Access tokens
Settings → Access tokens creates personal tokens for scripts and integrations. Send one as Authorization: Bearer keeyo_… and the API answers as you, for example GET /api/data for the whole register or GET /api/export for a backup.
- Scope — Read only tokens can only fetch; Read & write tokens can also add and change keys, services and registrations.
- Never for account settings — a token cannot change your password or email, touch second factors, create other tokens, or reach admin pages. Those need a real sign-in.
- Shown once — Keeyo stores only a hash. Give each script its own token so revoking one never breaks another, and set an expiry when the job is temporary.
Resetting a password with scripts/reset-password.js revokes every token on that account.
Using a token
Every request is the same as the web app's own API — just add the header. Reading the whole register:
curl -H "Authorization: Bearer keeyo_xxxxxxxxxxxx" \
https://keys.example.com/api/data
That returns one JSON object with your keys, services and registrations. A nightly off-site backup is one cron line (a read-only token is enough):
0 3 * * * curl -sf -H "Authorization: Bearer $KEEYO_TOKEN" \
https://keys.example.com/api/export > /backups/keeyo-$(date +\%F).json
With a read & write token you can add records. Register a key, then log a passkey on it — services are created inline if the name is new:
curl -H "Authorization: Bearer $KEEYO_TOKEN" -H "Content-Type: application/json" \
-d '{"name": "Drawer spare", "vendor": "Yubico", "model": "YubiKey 5 NFC", "formFactor": "usb-a", "status": "backup"}' \
https://keys.example.com/api/keys
# → {"id": 7, ...}
curl -H "Authorization: Bearer $KEEYO_TOKEN" -H "Content-Type: application/json" \
-d '{"keyId": 7, "kind": "passkey", "service": {"name": "GitHub", "url": "github.com"}}' \
https://keys.example.com/api/registrations
Same thing from PowerShell:
$headers = @{ Authorization = "Bearer $env:KEEYO_TOKEN" }
Invoke-RestMethod -Uri "https://keys.example.com/api/data" -Headers $headers
Useful endpoints: GET /api/data (everything), GET /api/export (backup JSON), GET /api/keys/ID/events (a key's logbook), POST /api/keys, POST /api/services, POST /api/registrations (with serviceId or an inline service), POST /api/keys/ID/verify (record a health check-in — handy after a scripted test), and PUT/DELETE on any of those by id. Registration kind is passkey, second-factor or totp.
What the errors mean: 401 — the token is wrong, expired or revoked; 403 This access token is read-only — a write with a read-only token; 403 Not available to access tokens — that route needs a real sign-in (account, security and admin settings always do).
Keyboard shortcuts
| Key | Action |
|---|---|
| / | Focus the search box |
| N | Register a new key (dashboard) |
| Esc | Close the open dialog |