Authentication
Every authenticated call to Lucerna — whether you make it yourself against the Waitlist API or an SDK makes it for you — sends one header:
Authorization: Bearer <key>There is no OAuth flow and no session. A key is the whole credential.
The three key flavors
| Key | Looks like | What it is |
|---|---|---|
| Server key | ck_srv_prod_… | Secret, per product and environment. Full access to that product's endpoints. Backend only. |
| Client key | ck_client_prod_… | Publishable. Safe to ship in browsers and mobile apps — it can only fetch decisions and write people. |
| Scoped key | ck_key_… | Secret, hand-made. Carries exactly the grants you chose at creation and nothing else. |
Two properties hold for every key:
- The key picks the environment. The
prod/stg/devsegment in a server key names it, and every key pins one workspace and one environment. Point staging at your staging key — there's no separate environment setting. - The key must match the surface. The SDKs enforce this at construction:
@lucerna-dev/gates-noderefuses a client key,@lucerna-dev/gates-browserrefuses a secret key — both fail at startup with the fix in the message.
Grants
Access is a property of the key, not of a product. Server keys grant their whole product (gates:*, waitlist:*, …); scoped keys carry an explicit list:
| Grant | Allows |
|---|---|
gates:runtime | Downloading compiled rules — what @lucerna-dev/gates-node polling uses. |
gates:evaluate | Server-side flag / experiment / kill-switch evaluation — what its remote evaluation uses. |
gates:events | Sending experiment exposure events. |
people:identify | Creating and updating People profiles. |
people:erase | Erasing a person's data. |
waitlist:signup | Capturing waitlist signups. |
A key without a grant gets 403 from that endpoint no matter what else it can do — see One key, many doors for creating scoped keys. The publishable client key is fixed at people:identify plus fetching Gates decisions, and it is write-only: the API never echoes stored data back to it.
Getting and rotating keys
In the dashboard, open Settings → API keys. Each environment has its per-product server keys and its one publishable client key; scoped keys are created there too. The full secret is shown once, at creation.
Rotating revokes the old key immediately and issues a new one — update your environment variables before rotating in production.
Keep secret keys secret
A server or scoped key is a password:
- Backend only. Never embed it in a web page, mobile app, or anything that ships to users. (That's what the client key is for.)
- Environment variables, not source control.
- Rotate if it's ever exposed.
If you need to call a server-key endpoint from a browser (for example, waitlist signups without a backend), proxy the request through a small server-side endpoint of your own that holds the key.
Auth errors
| Status | code | When |
|---|---|---|
401 | unauthorized | The key is missing, malformed, unknown, or revoked. |
403 | forbidden | The key is valid but wasn't granted what this endpoint requires. |
{ "code": "unauthorized", "message": "Missing or invalid API key" }See Errors for the full envelope and every status code.