Authorization: Bearer <token>:
Recommended for any code you write: use an
sk_live_ API key. Mint
one at Hub UI → Settings → API Keys.
X-Account-ID header needed. The backend resolves your
account from the sk_live_ prefix.
Hostnames
api.kataven.ai is decoupled from the dashboard — outages on hub.* don’t
affect programmatic access, and rate-limit / monitoring policies apply
independently.
Mint, list, revoke API keys
API key management is Hub UI / Zitadel-JWT only. A leakedsk_live_ cannot mint another sk_live_, by design — otherwise key
rotation wouldn’t be a real defense. The POST/PATCH/DELETE
operations on /api/v1/api-keys return 403 Forbidden for
sk_live_ callers; the SDK doesn’t even expose them.
In the Hub UI:
- Settings → API Keys → Create API key
- Pick a name (e.g.
ci-deploy-bot) and an expiry (Never, 1 year, 90 days, 30 days). Per-tenant policy may restrict the max expiry. - Click Create. The full token shows up once — copy it immediately. We don’t store the plaintext, only an HMAC-SHA256 hash with a server-side pepper.
- Use the token in
Authorization: Bearer ….
Two key types, two purposes
After the 2026-05-08 split, credentials live in two separate tables with two separate prefixes:
Visitor-JWT signing on your backend uses any
sk_live_ API key — no
paired pk_live_ required. The widget key is purely an account
identifier the browser hands back to /api/v1/widget/config.
Both are managed at Settings → API Keys in the Hub UI. Widget key
CRUD is also available via the SDK (it’s a public identifier, so
minting one carries no security risk).
Per-account databases
Kataven is multi-tenant by database isolation, not by row-level filtering. Each account has its own PostgreSQL database. TheX-Account-ID header (or, for sk_live_ tokens, the prefix) tells the
API which one to connect to — there is no account_id column anywhere.
Account names are validated against a regex
(^[a-z0-9][a-z0-9_-]{0,62}$) — anything else is rejected at the edge.
The reserved account kataven-admin is rejected on regular endpoints
with 403. It’s used only for the operator console.
Public endpoints
A small set of endpoints intentionally requires no auth:GET /api/accountsandGET /api/accounts/validate/{account}— account discovery before any token exists.POST /api/v1/widget/auth/*andGET /api/v1/widget/config— called cross-origin from customer-page widgets, before any end-user has a Kataven session. These have their own per-key auth (pk_live_*/sk_live_*) — see Widget concepts.

