REST API
The ScaiFlow backend exposes a tenant-scoped REST API at /api/v1/* on whatever hostname your tenant deploys it under.
This is the public surface — the canvas uses it, your CI can use it, third-party tools can use it. Every endpoint that mutates requires ScaiKey authentication (or the deprecated dev-token fallback); read endpoints obey per-flow ACLs.
Base URL#
1 | |
Substitute <your-domain> with whatever your tenant deploys at (scaiflow.scailabs.ai, scaiflow.acme.example, etc.).
Authentication#
Two auth flows are supported:
ScaiKey OIDC (primary)#
Bearer token from the BFF token exchange:
1 | |
To obtain a token from a service that already has a refresh token, use POST /v1/auth/refresh (see Auth router). For interactive browser logins, the canvas runs the OAuth Authorization Code + PKCE flow against ScaiKey directly and exchanges the code via POST /v1/auth/exchange.
Dev token (deprecated, only for POST /v1/dev/deploy)#
Shared bearer set via SCAIFLOW_API_TOKEN env at the API process. Only the legacy /v1/dev/deploy endpoint honors it. New code should use ScaiKey OIDC.
Routers#
The API is split into routers by domain. Each router page lists every endpoint with method, path, request, response, and required permissions.
| Router | Surface | Page |
|---|---|---|
| Flows | flow CRUD, deploy, run-tests, versions, presence, deployments | ./rest-api/flows |
| Auth | runtime config, BFF token exchange + refresh, /v1/me |
./rest-api/auth |
| Admin | ScaiKey-driven user/group sync, super_admin grants, tenant views | ./rest-api/admin |
| Catalog | per-tenant flow packages: list, publish, install, visibility | ./rest-api/catalog |
| Tenants | per-tenant ScaiGrid credentials | ./rest-api/tenants |
| Lookups | read-only proxies into ScaiQueue / ScaiBunker / ScaiGrid | ./rest-api/lookups |
| ScaiCore | events, checkpoints, invoke proxy | ./rest-api/scaicore |
| Flow ACLs | per-flow access control: list / grant / revoke | ./rest-api/flow-acls |
| Preview | live compile + validate (no persistence) | ./rest-api/preview |
| Webhooks | ScaiKey signed-webhook receiver | ./rest-api/webhooks |
| Deploy (legacy) | POST /v1/dev/deploy and POST /v1/flows/{id}/deploy |
./rest-api/deploy |
Permissions#
Two canonical permissions, inherited from ScaiCore:
| Permission | Required for |
|---|---|
scaicore:view |
All read endpoints, live preview, validation, browsing catalog, watching events. |
scaicore:manage |
All mutating endpoints, deploy, run-tests, publish catalog, resolve checkpoints, invoke. |
Plus two ScaiFlow-local admin roles (stored in the ScaiFlow DB, not in ScaiKey):
tenant_admin— tenant-wide visibility + tenant credential management.super_admin— platform-wide.
Error shape#
Errors follow the FastAPI default {"detail": ...} shape. Some endpoints return a structured detail dict for machine consumption:
// 412 — missing tenant credentials
{
"detail": {
"error": "missing_credentials",
"message": "no ScaiGrid credentials for tenant 'acme'",
"fix": "Sign in with ScaiKey, or set this tenant's API key via POST /v1/tenants/me/scaigrid_credentials."
}
}
// 502 — upstream ScaiGrid auth rejected
{
"detail": {
"error": "scaigrid_auth",
"message": "...",
"fix": "Caller needs `scaicore:view` on this tenant."
}
}
Versioning#
The API is at /v1. There is no /v2 yet. Breaking changes will bump to /v2; additive changes (new fields, new endpoints) land on /v1.
Rate limiting#
No rate limiting is enforced by ScaiFlow itself today. Upstream (ScaiGrid) may rate-limit per its own policy; ScaiFlow returns the upstream's rate-limit response unchanged.
CORS#
The canvas runs on http://localhost:5173 in dev and on its production host in prod. The API allows those origins by default; check apps/api/scaiflow_api/app.py for the exact list if you need to add another.