Skip to main content

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.