REST API: Auth
Runtime ScaiKey config, BFF token exchange, refresh, and the caller-identity endpoint.
All endpoints under /api/v1/auth (except /v1/me which is under /v1).
GET /v1/auth/config#
Returns the canvas's runtime configuration for OIDC sign-in. The browser fetches this before redirecting to the Authorization endpoint so it knows the right client_id, audience, etc.
Response:
{
"auth_mode": "scaikey", // or "dev_token"
"scaikey_base_url": "https://scaikey.scailabs.ai",
"client_id": "rr1k00w8tbeej3xquqzklevs55zp6dp1",
"audience": "rr1k00w8tbeej3xquqzklevs55zp6dp1",
"redirect_uri": "https://scaiflow.example/auth/callback"
}
Public — no auth required. Surfaces only the public fields needed for PKCE redirection; the client_secret stays server-side.
POST /v1/auth/exchange#
BFF token exchange. The canvas posts the authorization code + PKCE verifier; the API adds the client_secret and forwards to ScaiKey's token endpoint.
Body:
{
"code": "auth_code_from_authorize_redirect",
"code_verifier": "the_pkce_verifier_the_browser_generated",
"redirect_uri": "https://scaiflow.example/auth/callback"
}
Response:
{
"access_token": "...",
"refresh_token": "...",
"id_token": "...",
"token_type": "Bearer",
"expires_in": 3600
}
Errors:
- 400 — ScaiKey rejected the exchange (invalid grant, expired code, mismatched verifier). The detail forwards ScaiKey's
error+error_description. - 502 — ScaiKey upstream 5xx.
- 503 — ScaiKey OIDC not configured on the server (missing
SCAIKEY_BASE_URL/SCAIFLOW_SCAIKEY_CLIENT_ID/SCAIFLOW_SCAIKEY_CLIENT_SECRET).
redirect_uri must match what was sent on the /authorize redirect — ScaiKey enforces this strict equality.
POST /v1/auth/refresh#
Refresh-token grant. Same proxy pattern — client_secret stays server-side.
Body:
{ "refresh_token": "..." }
Response: Same shape as /v1/auth/exchange.
Errors: same as exchange.
GET /v1/me#
The caller's principal, merged with their ScaiFlow-local admin role.
Response:
{
"sub": "usr_xxx",
"tenant_id": "tnt_acme",
"tenant_slug": "acme",
"partner_id": null,
"email": "alice@acme.example",
"name": "Alice",
"display_name": "Alice Johnson",
"admin_role": "super_admin" // null | "tenant_admin" | "super_admin"
}
admin_role comes from the local mirror in the ScaiFlow DB — independent of ScaiKey roles. See Concepts: Multi-tenancy and auth.
Used by the canvas to decide what admin chrome to show (the toolbar dropdown's Admin link, the catalog publish form, the tenant flows list).