Authentication & API keys
Every request your backend makes carries an API key in the X-API-Key header. Keys are
tenant-scoped and minted in the admin console.
X-API-Key: ek_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
This is distinct from identity signing: the API key authenticates your backend (what it may do), while the identity assertion vouches for the reader acting (who is acting). Most acting writes need both.
Minting a key
In the console: API Keys → New. Choose a label, an optional set of capabilities, and an
optional expiry. The raw ek_… value is returned once — store it securely; only a prefix is
shown afterwards.
You can also mint programmatically — POST /api/v1/admin/keys (admin JWT) or POST /api/v1/keys
(an existing key with the manage_api_keys capability). See the
API Reference.
Capabilities (scoping)
A key holds a flat set of capabilities — least-privilege rather than all-or-nothing. A
moderation bot can hold only moderate_content; a settings tool only manage_settings.
Capabilities gate admin-style routes (settings, moderation actions, webhook CRUD, key management, analytics). The publisher surface — posting comments, reacting, voting, reading — is not capability-gated: any authenticated key may call those, including a key with an empty capability set. So a least-privilege key minted purely for posting comments still works.
Expiry
A key may carry an optional expiresAt. After it lapses the key is rejected and no longer counts
against your active-key budget. Rotation today is manual: mint a new key, cut over, revoke the old one.
Key handling
- Treat
ek_…keys as secrets — backend only, never in client code. - Use separate keys per integration (widget backend, moderation bot, analytics export) so you can revoke one without disrupting the others.
- Revoke via the console or
DELETE /api/v1/admin/keys/{id}.
Admin vs API-key paths
Many endpoints accept either an API key or an admin-console JWT (dual-auth). Your backend integration uses the API-key path. The admin JWT is what the console UI uses; you won't issue those from your backend.