Skip to content

Authentication & key rotation

The Developer API data-plane (/api/v1/sources/..., /api/v1/sources/.../items, /api/v1/sources/.../runs, …) authenticates with a Developer API key sent as a Bearer token:

Authorization: Bearer sk_live_0123456789abcdef_<48 hex chars>

Keys are managed by a tenant administrator through the admin endpoints (/api/v1/admin/keys), which use the admin session (JWT) from the admin portal.

Key format & storage

  • A key looks like sk_live_<16 hex key id>_<48 hex secret>.
  • Only a lookup id (sk_live_<key id>) and a SHA-256 hash of the full key are stored. The plaintext secret is shown exactly once at creation or rotation and can never be retrieved again — store it in your secret manager.
  • Verification is a constant-time hash compare; errors never reveal whether the id or the secret was wrong.

Scopes

Grant each key the least privilege it needs:

ScopeAllows
sources:readList / read sources
sources:writeCreate / update / deactivate sources
items:readList staged items
items:writeUpsert / batch / snapshot / delete items
runs:readRead run status, diff and active generation
runs:executeStart a run
runs:applyApply (publish) a run

A request missing the required scope returns 403 insufficient_scope.

Creating a key (admin)

Terminal window
curl -X POST "$CHATBOT_API/v1/admin/keys" \
-H "Authorization: Bearer $ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{"name":"CI importer","scopes":["sources:write","items:write","runs:execute","runs:apply","runs:read"]}'

Response (secret shown once):

{
"key": { "id": "", "keyLookup": "sk_live_0123456789abcdef", "scopes": [""], "status": "active" },
"secret": "sk_live_0123456789abcdef_…"
}

You can also set "expiresAt": "2025-01-01T00:00:00Z" to auto-expire a key.

Rotation

Rotate regularly and whenever a secret may have leaked. Rotation mints a new secret and invalidates the old one immediately:

Terminal window
curl -X POST "$CHATBOT_API/v1/admin/keys/$KEY_ID/rotate" \
-H "Authorization: Bearer $ADMIN_JWT"
# → { "key": { … }, "secret": "sk_live_…NEW…" }

Zero-downtime rotation pattern:

  1. Create a second key and deploy it alongside the current one.
  2. Once all workers use the new key, revoke the old key.

This avoids the brief window where a single in-place rotation could race with in-flight workers.

Revocation

Terminal window
curl -X DELETE "$CHATBOT_API/v1/admin/keys/$KEY_ID" \
-H "Authorization: Bearer $ADMIN_JWT"

A revoked key returns 401 key_revoked on every subsequent request.