Authentication

API keys as bearer credentials — token format, scopes, key types, rotation, and security notes.

Updated 2026-06-11

The Customer API uses API keys as bearer credentials. Mint keys in the dashboard at /api-keys.

Token format

fs_<env>_<32 characters, A-Z and 0-9>
  • fs_live_… keys are for production traffic.
  • fs_test_… keys are for non-destructive integration work. The split is cosmetic in v1 — both keys hit the same database. Use the prefix to keep test scripts from accidentally calling a live key.

The full token is shown once at creation. Store it in your secret manager. If you lose it, mint a new key and revoke the old one.

Sending the token

Authorization: Bearer fs_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Every authenticated endpoint requires this header. Missing or malformed tokens return 401 with a WWW-Authenticate: Bearer header.

Scopes

Each key carries a list of <resource>:<action> scopes. The action is read, write, or *. The wildcard *:* is allowed but should be reserved for tightly-controlled internal integrations.

Common scope shapes:

GoalScopes
Read-only reportingforms:read, records:read, organizations:read
Submit recordsrecords:write, forms:read
Configure webhookswebhooks:read, webhooks:write
Manage membersusers:read, users:write
Manage formsforms:read, forms:write
Report automationreports:read, reports:write
Full instance admin*:* — reserve it for instance keys

A request with a valid key but the wrong scope returns 403 forbidden with the required scope echoed in the error message.

Key types

  • Organization-scoped key (organization_id set) — only addresses paths under /organizations/{org_id}/… where {org_id} matches the key's binding. Attempting to address a different org returns 403.
  • Instance-scoped key (organization_id is NULL) — can address any org, plus the instance-level surfaces (/users, /instance, POST /organizations, DELETE /organizations/{id}). Only instance owners can mint these.

Lifecycle

  • The dashboard offers no edit operation for a key. To change the name, scopes, or rate limit, mint a new key and revoke the old one.
  • Revocation is permanent. Revoked keys remain visible in the dashboard for audit; subsequent requests return 401.
  • Optional expires_at makes a key auto-expire. After that timestamp, the key returns 401 even if it isn't explicitly revoked.

Rotating a key

  1. Mint a new key with the same scopes.
  2. Update the integration to use the new key.
  3. Verify the new key is in use (look at the audit log or watch the old key's last_used_at stop changing).
  4. Revoke the old key.

Security notes

  • We store the SHA-256 of the plaintext, never the plaintext itself.
  • The plaintext is shown exactly once at creation; the dashboard then shows only the prefix.
  • The Authorization header is the only bearer mechanism in v1. Query-string tokens are not supported.
  • Constant-time hash comparison is used in the auth middleware.