Authentication
API keys
The primary auth method is an API key issued from the portal.
- Format:
cloak_<base32>— 256 bits of entropy. - Header:
Authorization: Bearer cloak_… - Scope: per-organisation. Sub-organisations (partner mode) get distinct keys with their own quotas, rate limits, and balances.
- Rotation: rotate at any time from API keys → Rotate. The previous key is deactivated immediately — deploy the new key right away (see Key rotation).
- Revocation: instant. Revoked keys return
401with a structurederror.code: "key_revoked"payload.
OIDC SSO
For human (portal) login, the gateway exposes a standard OIDC discovery surface:
| Endpoint | Path |
|---|---|
| Discovery | /.well-known/openid-configuration |
| JWKS | /oauth/jwks |
| Userinfo | /oauth/userinfo |
| Token | /oauth/token (standard OAuth2) |
| Authorize | /oauth/authorize |
Today this is backed by Laravel Passport. An Authentik identity provider is live at auth.cloakapi.io for federated / enterprise SSO flows; portal password login remains Laravel-native.
Per-request scoping
Inside the gateway, requests are scoped by:
- Tenant — derived from the API key.
- Sub-organisation — for partner / white-label flows.
- Capability — fine-grained allowlist (
gpt-4o,claude-sonnet-4-6, …) enforced before provider routing. - Quota — monthly token budget per (tenant, capability).
- Rate limit — sliding-window per (tenant, capability) at 60s and 3600s scales.
Per-key scope allowlist (permissions)
Each cloak_* API key carries a permissions array. The current enforced
vocabulary is published at GET /api/v1/keys/scopes
and contains:
| Scope | What it grants |
|---|---|
messages | POST /api/v1/messages (Anthropic-format chat) |
completions | POST /api/v1/chat/completions (OpenAI-format chat) |
buffer | Reserved for portal-side buffered-response reads (Sanctum-PAT) |
Semantics:
-
An empty or null
permissionsarray is treated as fully permissive (back-compat with keys minted before the allowlist was enforced). -
When
permissionsis non-empty and does not contain the scope a route requires, the gateway returns HTTP 403 with the structured envelope:{"error": {"type": "permission_error","code": "insufficient_scope","message": "This API key is not authorised for the 'completions' capability.","required": ["completions"],"granted": ["messages"]}}
Portal personal-access tokens (Sanctum PATs) are a separate axis used by
the dashboard and /api/v1/keys, /api/v1/billing/*, /api/v1/webhooks*
and the admin-session/* console. Their vocabulary is published in the UI
and includes abilities:write, ability:keys.read, ability:keys.write,
ability:billing.read, ability:billing.write, ability:byok.write, and
ability:admin. A cloak_* gateway key is never valid for those
portal routes, and a Sanctum PAT is never valid for /api/v1/messages
or /api/v1/chat/completions.