Account and keys
Destructive actions on a live key should feel slightly annoying. That is the point.
Minting and listing keys
Signed in, GET /v1/account/keys lists your keys (name, hint, created, last used, revoked) and POST /v1/account/keys mints a new one, optionally with { "name": "laptop" }. The full secret is returned exactly once and works immediately. Plan key counts: free 1, Starter 2, Pro 5, Business 12. See billing.
Use the account page or the JSON routes below. You send your current Bearer token. We never echo the full secret back.
Safety rails
| Action | You must type | Also |
|---|---|---|
| Revoke | DELETE plus the last 4 characters of the key |
Authenticator code if TOTP is on |
| Turn TOTP off | FETCH plus the last 4 characters |
Current authenticator code |
A wrong confirm string does nothing. A wrong challenge does nothing. That stops “revoke the other tab’s key” accidents.
To replace a key, mint a new one from Your keys, swap it into your code, then revoke the old one. There is no single-call rotate: the old POST /v1/account/keys/rotate path returns HTTP 410 and never minted a replacement.
GET /v1/account/me returns the live confirm phrases under confirm.revoke and confirm.totp_off. The account page uses those same strings, so the UI and the API cannot disagree.
Authenticator (TOTP)
POST /v1/account/totp/startwith your Bearer token. You get asecretandotpauth_urlonce.- Add it to Authy, 1Password, Google Authenticator, or similar.
POST /v1/account/totp/enablewith{ "code": "123456" }.- After that, revoke needs the 6-digit code as well as the typed phrase.
Do not put the TOTP secret in a GET query, a screenshot folder, or frontend JavaScript. On disk we store iv, auth tag, and ciphertext, not the seed. The encryption key lives in TOTP_ENCRYPTION_KEY and must not sit in the same backup as guard.json.
Revoke
curl -sS https://fetch.li/v1/account/keys/revoke \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"confirm":"DELETE","challenge":"A9F3","totp":"123456"}'
challenge is the last 4 characters of this key, shown on GET /v1/account/me. After a successful revoke the key is dead on the next request, even if an upstream dashboard is slow.
From the signed-in account page you can also revoke any of your keys: send key_id in the body and the challenge becomes the last 4 characters of that key, shown in the keys list.
Who this is for
Anyone with a paid key. The free demo has no key to revoke. See Demo tier, Authentication, and Pricing.