API keys
| Kind | Format | Secret? | Used for |
|---|---|---|---|
| Site key | rl_site_<env>_<22 chars base32> | No. Public, embedded in pages | Identifies a site to the loader and in bundle URLs |
| Secret API key | rl_sec_<env>_<32 chars base32> | Yes | Server-to-server calls: plugins, backends, CI. Sent as Authorization: Bearer rl_sec_... |
<env> is live or test.
Secret key rules#
- Generated from at least 20 random bytes, shown once, stored only as an HMAC-SHA256 hash with a server-side pepper plus an 8-character display prefix, compared in constant time.
- Belong to a tenant. Have a name, scopes, an optional single-site restriction, an optional expiry and a last-used time.
- Can be rotated (the new key works immediately, the old one for a configurable grace period) or revoked.
- Never log one, never return one after creation, never ship one to a browser, never commit one.
Scopes#
| Scope | Allows |
|---|---|
sites:read, sites:write | List and read sites; create, change and scan sites |
strings:write | Submit source strings |
translations:read, translations:write | Read, export and glossary; edit, translate and import |
bundles:publish | Build and publish bundles |
usage:read | Usage figures |
keys:manage | Create, rotate and revoke keys (test keys cannot create keys) |
webhooks:manage | Manage webhook endpoints |
audit:read, audit:manage | Read the audit log; change its retention |
billing:read, billing:manage | Reserved for billing; the routes currently check the signed-in role, not the key |
Give a key only what it needs: a CI job that publishes needs bundles:publish, not keys:manage.
The public signing key#
Separate from API keys: the Ed25519 public key given to the loader (data-public-key) verifies manifest signatures. It is public. The matching private key stays with the platform and never leaves it. Keys are per site, and several public keys can be listed so a key can be replaced.