Authentication
Bearer API keys — format, plan resolution, per-plan key limits, and what a 401 means.
Every request carries an API key as a bearer token. There is no anonymous access to any endpoint on this API, and no other credential: the REST API is key-only. (The MCP endpoint accepts the same keys and OAuth.)
Authorization: Bearer rvd_<prefix>_<secret>Create a key
Keys are free on every plan, including free. Create one at getrevised.com/account.
The secret half is shown once, at creation, and is stored only as sha256(secret + pepper) with a server-side pepper. Keep it somewhere you can read it back — Revised cannot.
curl "https://getrevised.com/api/v1/domains?limit=2" \
-H "Authorization: Bearer rvd_yourprefix_yoursecret"Token format
A token is three parts joined by underscores.
| Part | Example | What it is |
|---|---|---|
rvd | rvd | A fixed, greppable marker, so a key pasted into a repository or a log is findable by secret scanners. |
| prefix | a1b2c3d4e5f6 | 12 lowercase alphanumeric characters. Public, stored in the clear, and the only thing authentication looks the row up by. It appears in GET /api/v1/me as key.prefix and on the account page. |
| secret | 43 URL-safe characters | 32 bytes of entropy. Never stored; only sha256(secret + pepper) is. |
A token that is not shaped like this is rejected without a database lookup.
A key carries no entitlement of its own
The key identifies the account. The owner’s current plan is resolved behind it on every request and refreshed at least once a minute, so a subscription that lapses, upgrades or downgrades moves your rate limit, your reveal budget and your access to the since feed without anything being reissued. A lapsed subscription reads as plan: "free" on GET /api/v1/me while the key itself keeps working.
Two consequences worth designing for:
- Do not cache a plan. Read
GET /api/v1/mewhen you need the current one. - Do not treat a
402as permanent. It may be an allowance that rolls over, or a plan that changed under the key.
Keys per account
| Plan | Live keys |
|---|---|
| Free | 2 |
| Pro | 5 |
| Business | 10 |
Revoked keys never count against the ceiling. Source: PLAN_LIMITS in the application.
Separate keys for separate systems separate the rate-limit bookkeeping and nothing else. Holds, reveals and the reveal ledger are account-scoped: a hold taken by one key is visible to, extendable by and releasable by every other key on the account.
The same key authenticates MCP
https://getrevised.com/api/mcp accepts the same rvd_ bearer token, and REST calls and MCP calls come out of one per-minute counter. See MCP authentication for the OAuth alternative, which needs no key at all.
When authentication fails
Missing, malformed, unknown, revoked and mistyped keys are all 401:
{
"error": {
"code": "unauthorized",
"message": "Provide your API key as `Authorization: Bearer rvd_...`. Keys are created at /account."
}
}A 401 also carries WWW-Authenticate: Bearer realm="revised".
Missing and invalid keys share one message deliberately — the API does not confirm whether a prefix exists.
Failed authentications are counted against a separate budget keyed by client IP. Over it, the answer is 429 rate_limited with Too many failed key attempts. Retry in Ns., raised before any lookup. Authenticated traffic never touches that guard; only a failure spends from it.
Do not retry a 401 with the same key. Check that:
- The header is
Authorization: Bearer <token>— one space, one token. The scheme is compared case-insensitively. - Nothing has trimmed or wrapped the secret. The full token is
rvd_plus 12 characters plus an underscore plus the secret. - The key has not been revoked on the account page.
Handling keys
- Send keys from a server, not from a browser. The API sets
Access-Control-Allow-Origin: *because there is no cookie or session to protect — a key on a page you do not control is the one thing that policy does expose. - Keep the secret in an environment variable or a secret store. The examples throughout these docs read
$REVISED_API_KEY. - A key that has leaked is revoked on the account page; revoking frees the slot immediately.
See Errors for the full status code table.