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:
| Scope | Allows |
|---|---|
sources:read | List / read sources |
sources:write | Create / update / deactivate sources |
items:read | List staged items |
items:write | Upsert / batch / snapshot / delete items |
runs:read | Read run status, diff and active generation |
runs:execute | Start a run |
runs:apply | Apply (publish) a run |
A request missing the required scope returns 403 insufficient_scope.
Creating a key (admin)
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:
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:
- Create a second key and deploy it alongside the current one.
- 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
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.