Authentication
Keys, scopes, the two kinds of key, and how to rotate one.
A server calls the API with a key in the Authorization header: Authorization: Bearer <key>. A key goes only in that header, never in a URL or query string, because URLs end up in logs.
Making a key
Keys are made in Settings, API keys. A key is shown once, when it is made; we keep only a hash, so a lost key cannot be recovered, only replaced. A key has a name, an owner, an access list, limits and an end date.
What a key looks like
A key is 53 characters: a prefix that says what it is, 43 random base62 characters (256 bits), and a 6-character checksum. A scanner can recognize a leaked key and check it offline, and a mistyped key is refused before any lookup.
| Prefix | Kind | Acts as |
|---|---|---|
lmp_ | Personal | The person who made it. It can never do more than they can. |
lmo_ | Organization | The org, within its scopes. Made by an admin and tied to them: it works only while they still administer the org. |
Scopes
A key lists what it may do. Every endpoint names the one scope it needs, and a key without it is refused with 403 insufficient-scope. Writing a thing includes reading it. A key made with Full access carries every ordinary scope its kind may, including ones added later. It does not include running for another account. A key that lists scopes carries only those.
Running a match for a realtor
An agent that many realtors use holds one key. It is not signed in as them. A Livia admin ticks Run for another account (account:associate) when making that key. Only a Livia admin can tick it, and the key is checked again on every request: if they are no longer a Livia admin, naming an account is refused.
Send Livia-Account with the realtor's email, or their user id. The search, the match and anything else that key does are saved to that account, so the realtor signs in and sees them. Omit the header to act as the key's maker. A key without the scope that sends the header is refused (403 account-not-permitted), rather than quietly writing into the maker's account. An email or id with no Livia account is 404 account-unknown. The request does not create an account. The header is not a client. Clients are the people a realtor works for.
| Scope | Lets a key | Key kinds | Includes | Used by |
|---|---|---|---|---|
search:read | Matches, their runs, the homes they found and what they cost. | PersonalOrganization | Nothing | 17 endpoints |
search:run | Start, save, run, cancel and delete matches, and curate a match's shortlist. Includes reading them. | PersonalOrganization | search:read | 11 endpoints |
clients:read | Your clients: their names, emails and notes. | PersonalOrganization | Nothing | 2 endpoints |
clients:write | Add and edit clients, and archive or restore them. Includes reading them. | PersonalOrganization | clients:read | 3 endpoints |
briefs:read | What each client needs. | PersonalOrganization | Nothing | 4 endpoints |
briefs:write | Make and change searches, including drafting one from words. Includes reading them. | PersonalOrganization | briefs:read | 6 endpoints |
shares:read | The shortlists shared with clients, and what clients answered. | PersonalOrganization | Nothing | 4 endpoints |
shares:write | Give a client access, share a shortlist, email it and stop sharing it. Includes reading shares. | PersonalOrganization | shares:read | 7 endpoints |
profile:read | For a personal key, your name, email and organization. For an organization key, the organization and the admin who made it. | PersonalOrganization | Nothing | 1 endpoint |
org:read | Its members and this month's usage. | Organization | Nothing | 3 endpoints |
audit:read | Who did what in the organization. | Organization | Nothing | 1 endpoint |
members:write | Invite people, revoke invites, and change or remove members. Never the owner. Includes reading the organization. | Organization | org:read | 4 endpoints |
org:write | The name, the brand policy, client sign-in, and each person's monthly matches. Includes reading the organization. | Organization | org:read | 3 endpoints |
account:associate | Send Livia-Account with the realtor's email or user id. The match is saved to their account. Full access does not include this. | PersonalOrganization | Nothing | 0 endpoints |
A signed-in browser session can call these endpoints too, as the person. A few endpoints belong only to the app and refuse a key; the reference marks them Browser-only.
Personal and organization keys
- A personal key acts as its maker. Every search it starts is saved in that person's workspace and counts against their limit and the org's month.
- An organization key is made by an admin for the whole org. Its searches land in its maker's workspace and count against the org's allowance, and the usage report lists them by key.
- An org key is checked against its maker on every request. Demote or remove the admin and their org keys are revoked at once, with a line in the audit trail. A later re-promotion never brings a key back.
- Both kinds may carry
profile:read, so a script can callGET /api/v1/meand learn whose key it holds: the person for a personal key, the organization and its admin for an org key. Personal keys never carry the org's scopes. - No endpoint changes the owner. Ownership moves only in Settings, by the owner.
Limits and lifetime
| Limit | Default | Least | Most |
|---|---|---|---|
| Requests a minute | 120 | 1 | 600 |
| Requests a month | None | 1 | 1,000,000 |
| Lifetime | 3 months | 1 week | 5 years |
What a refused call looks like
| Status | Code | Header | Means |
|---|---|---|---|
| 401 | unauthenticated | WWW-Authenticate: Bearer realm="livia-match" | No key and no session. |
| 401 | invalid-api-key | WWW-Authenticate: Bearer error="invalid_token" | Misspelled, expired, revoked, or its maker lost admin. We never say which. |
| 403 | insufficient-scope | WWW-Authenticate: Bearer error="insufficient_scope", scope="search:run" | The key is live but lacks the scope named in the header. |
| 403 | account-not-permitted | Livia-Account | The key may not name another account, or its maker is no longer a Livia admin. |
| 400 | account-invalid | Livia-Account | The header is neither an email nor a user id. |
| 404 | account-unknown | Livia-Account | No Livia account has that email or id. The call does not create one. |
| 429 | rate-limited / monthly-cap-reached | Retry-After | Over a limit. See Rate limits. |
A call that presents a key never falls back to a browser session when the key is wrong. A server that sent a bad key hears so.
Rotating a key
A key's name, kind and end date never change, which keeps rotation honest: a new end date is a new key. To rotate without downtime:
- Make a new key with the same access under a new name, like
crm-search-2. Names must be unique among live keys. - Deploy it. Check
GET /api/v1/meor any read with it. - Revoke the old key. A revoked key is refused at once, and its name is free again.
Access and limits can change in place (Change access in Settings), and the change is in the audit trail with the old and new values. Make keys short-lived and rotate them on a schedule; a week to five years is allowed, three months is the default.
If a key leaks