Authentication
Two credentials for servers, one for browsers — which key goes in which header, and what each is allowed to do.
| Credential | Format | Header | Scope |
|---|---|---|---|
| SDK app key | gk_ + 48 hex | x-api-key | One app. Config, event ingestion, errors, surveys, push registration, and the entitlements check. |
| Links API key | fk_live_… | Authorization: Bearer | The Links API (/v1/links…). Secret — shown once at creation, stored hashed, revocable. |
| Dashboard session | JWT | Authorization: Bearer + x-app-id | The operator endpoints the dashboard itself uses. Not for server integrations. |
The SDK app key
From Dashboard → Setup, always retrievable. It identifies your app rather than authenticating a person — treat it as publishable. A missing key answers 401 {"ok": false, "error": "missing x-api-key"}; an unknown one 401 … "unauthorized". The key selects the app: querying an entitlement with app A's key can only ever see app A's users — another app's user id simply answers status: "none".
Links API keys
Minted on Dashboard → Links → API. The plaintext appears exactly once, in the create response; only a hash is stored, so nobody — including Fictura — can read a key back later. Revocation is immediate: a revoked key fails on its next request, no cache window. Each key records last_used_at, so an unused key is visibly unused before you rotate it away.
# SDK app key — x-api-key
curl https://api.fictura.co/api/v1/entitlements/8f14e45f \
-H "x-api-key: gk_..."
# Links API key — Bearer
curl https://api.fictura.co/v1/links \
-H "Authorization: Bearer fk_live_..."Two base paths, not two versions
/api/v1/… (SDK and app surface) and /v1/… (the public Links API) are separately authenticated surfaces, not versions of each other. There is exactly one API version today.