Authentication
Bearer tokens, rotating and revoking them, and what to do if one leaks.
Building something other people use?
Personal access tokens are for your own scripts and integrations. If you're building a product where your users connect their own Savee accounts, use OAuth instead — they approve specific permissions, you never handle their credentials, and they can revoke you at any time.
Bearer tokens
Every request must include a token in the Authorization header. This page
covers personal access tokens; an OAuth access token (sv_at_…)
goes in the same header and reaches the same endpoints.
A token is the prefix sv_live_ followed by 24 characters. Tokens are generated
under API Access at Savee → Settings → Developers.
Each user has at most one active token at a time — generating a new one revokes
the previous.
Savee stores only a SHA-256 hash of the token; the raw value is shown exactly once on generation. If you lose it, generate a new one — the old token is unrecoverable.
Tokens don't expire on their own. They stop working when you regenerate or revoke them, or while your subscription is lapsed.
Subscription required
The API is available on any active Savee subscription. If yours lapses, existing
tokens stop working until renewal — they aren't deleted, just rejected with
402 PAYMENT_REQUIRED until billing is current again.
Managing a token
Both actions live next to the token in Settings → Developers:
| Action | What it does |
|---|---|
| Regenerate | Issues a new token and invalidates the current one. Use this to rotate. |
| Revoke | Deletes the token without issuing a replacement. Use this to turn access off. |
Either way, integrations still holding the old token start getting 401 within
seconds. There's no grace period, so update your clients first when rotating a
token that's in active use.
The settings page also shows when each token was generated and roughly when it was last used. "Last used" is throttled to about half an hour, so a token you just called with may still read as older than that.
Treat it like a password
- Never commit tokens to source control.
- Never expose them in client-side code that runs in a browser.
- Rotate immediately if you suspect a leak.
Browser requests work, but shouldn't be used
The API sends Access-Control-Allow-Origin: *, so a fetch() from a web page
will succeed. That's there for local tooling and server-side clients that send
a browser-ish preflight — not an invitation to ship a token to the browser.
Anything in client-side JavaScript is readable by anyone who opens devtools,
and one token is your whole account. Call the API from your server and pass
the results down.
Errors
Auth failures use the same envelope as everything else — see Errors for the full list. The ones you'll meet here:
| HTTP | error.code | When |
|---|---|---|
| 401 | UNAUTHORIZED | Missing, malformed, or unknown token |
| 402 | PAYMENT_REQUIRED | Token valid but the user has no active subscription |
| 403 | FORBIDDEN | API access is not available on this account |