Authentication
Bearer API keys and JWT for DocAI REST and MCP.
All authenticated routes expect:
Authorization: Bearer <token>There is no separate X-API-Key header.
API keys (recommended for integrations)
- Sign in to the DocAI workstation.
- Open Settings → API keys and create a key.
- Copy the plaintext key once. It is shown only at creation time (and again after Rotate).
Keys use the prefix docai_sk_ (default live prefix docai_sk_live_). The server stores a hash only.
Treat a docai_sk_* like a Stripe secret: it can extract, spend org credits, and call other org routes. If you suspect a leak, Rotate that key or revoke all keys, then update DOCAI_API_KEY.
curl -s "$API/api/v1/billing/usage" \
-H "Authorization: Bearer docai_sk_live_..."Manage keys via REST (org required):
| Method | Path | Body |
|---|---|---|
POST | /org/api-keys | { "name": "ci", "ttl_days": 90 } → returns one-time key |
GET | /org/api-keys | list (prefixes, expires_at; no secrets) |
POST | /org/api-keys/{key_id}/rotate | { "ttl_days": 90 } → new one-time key (JWT only) |
DELETE | /org/api-keys/{key_id} | revoke |
Lifetime (ttl_days)
New keys default to 90 days. Allowed values: 30, 90, 365, or null (never expires). Other integers are rejected (422). Existing keys created before TTL shipped stay expires_at: null until you rotate them.
List and create responses include expires_at (ISO timestamp, or null for never). Expired keys stay in the table as Expired (still is_active) until you rotate or revoke them. They are not auto-revoked.
An expired Bearer key returns 401 API_KEY_EXPIRED and does not update last_used_at. Rotate it in Settings, then set DOCAI_API_KEY to the new secret. The Python client maps this to an authentication error and does not retry.
Rotate
Rotate is signed-in only (Authorization: Bearer with a Supabase JWT, as the workstation does). An API key Bearer gets 403. The old secret is revoked immediately in the same database transaction as the insert (no grace period). Copy the new key once. The Python SDK does not call rotate.
You can rotate expired-but-active keys to recover after TTL. Revoked keys and keys from another org return 404. The Settings UI hides Rotate on revoked rows.
Supabase JWT
Browser sessions send the Supabase access token as Bearer. JWT auth auto-resolves (or bootstraps) an org. Prefer API keys for servers, CI, and MCP.
Anonymous access
In non-production, anonymous calls may be allowed when no Bearer token is present. Production should require auth (ENVIRONMENT=production or ALLOW_ANONYMOUS_AUTH=false). Do not rely on anonymous auth for integrations.
Org-scoped routes
These endpoints require an authenticated org (require_org):
GET/PATCH/org- API key create, list, rotate, revoke
GET/billing/usagePOST/billing/checkoutDELETE/org/data
Extract and job routes accept API key or JWT with org context for billing and tenancy.