Skip to main content

Source of truth

The cloud control plane is a FastAPI service. Its OpenAPI document is the canonical reference; this page summarizes the direct FastAPI surface and the BFF routes the dashboard calls.
GET /openapi.json
GET /docs
To regenerate the dashboard’s TypeScript client from that document:
cd web
npm run generate:api

Traffic model

The CLI talks to FastAPI directly with Authorization: Bearer <api-key>. The dashboard sits behind Supabase auth and uses two BFF layers: named /api/cloud/* routes for higher-level dashboard actions, and a guarded catch-all /api/[...path] proxy for a narrow allowlist of Cloud read/sync routes. /openapi.json remains the source of truth for generated clients.

FastAPI route families

FamilyRoutes
System/, /healthz, /health, /health/db, /health/r2
StatusGET /api/status, GET /api/status/operational
Workspaces/api/workspaces, /api/workspaces/{workspace_id}, invitations, transfer ownership
Projects/api/projects, /api/projects/{project_id}
SyncPOST /api/sync/runs, GET /api/sync/ledger-head, POST /api/sync/ledger-head, artifact initiate/commit/abort
Runs/api/runs, /api/runs/{run_id}, manifest, metrics, log, signature, compliance mapping, artifact download, delete
API keys/api/api-keys, rotate, revoke
Shares/api/shares, revoke, /api/public/shares/{token}
Billingcheckout, portal, webhook
Usagereserve, commit, revert
Profile / DSAR/api/me, object, restrict, export, delete, cancel delete
Claims/api/claims, /api/claims/{claim_id}
Museum/api/museum
Audit logs/api/audit/logs
Machine-checked Cloud route list:
  • GET /
  • GET /api/api-keys
  • POST /api/api-keys
  • DELETE /api/api-keys/{api_key_id}
  • POST /api/api-keys/{api_key_id}/rotate
  • GET /api/artifacts/{artifact_id}
  • GET /api/audit/logs
  • POST /api/billing/checkout
  • POST /api/billing/portal
  • POST /api/billing/webhook
  • GET /api/claims
  • GET /api/claims/{claim_id}
  • GET /api/me
  • PATCH /api/me
  • POST /api/me/delete
  • POST /api/me/delete/cancel
  • GET /api/me/export
  • POST /api/me/object
  • POST /api/me/restrict
  • GET /api/museum
  • GET /api/projects
  • POST /api/projects
  • DELETE /api/projects/{project_id}
  • GET /api/projects/{project_id}
  • PATCH /api/projects/{project_id}
  • DELETE /api/projects/{project_id}/staging-e2e-tree
  • POST /api/projects/{project_id}/staging-retention-proof
  • GET /api/public/shares/{token}
  • GET /api/runs
  • DELETE /api/runs/{run_id}
  • GET /api/runs/{run_id}
  • POST /api/runs/{run_id}/evidence-package
  • GET /api/runs/{run_id}/log
  • GET /api/runs/{run_id}/manifest
  • GET /api/runs/{run_id}/metrics
  • GET /api/shares
  • POST /api/shares
  • POST /api/shares/{share_id}/reliability-consent
  • DELETE /api/shares/{share_id}/reliability-consent/{consent_id}
  • GET /api/shares/{share_id}/reliability-consent/{consent_id}/export
  • POST /api/shares/{share_id}/reliability-consent/{consent_id}/revoke
  • POST /api/shares/{share_id}/revoke
  • GET /api/status
  • GET /api/status/operational
  • POST /api/sync/artifacts/abort
  • POST /api/sync/artifacts/commit
  • POST /api/sync/artifacts/initiate
  • GET /api/sync/ledger-head
  • POST /api/sync/ledger-head
  • POST /api/sync/runs
  • POST /api/usage/reserve
  • POST /api/usage/commit
  • POST /api/usage/revert
  • GET /api/workspaces
  • POST /api/workspaces
  • DELETE /api/workspaces/{workspace_id}
  • GET /api/workspaces/{workspace_id}
  • PATCH /api/workspaces/{workspace_id}
  • GET /api/workspaces/{workspace_id}/invitations
  • POST /api/workspaces/{workspace_id}/invitations
  • PATCH /api/workspaces/{workspace_id}/transfer-ownership
  • GET /health
  • GET /health/db
  • GET /health/r2
  • GET /healthz

BFF routes

These are the dashboard’s own routes. Most are thin proxies that add auth and forward the body to FastAPI.
RouteFastAPI targetUsed by
GET /api/cloud/me/api/meProfile panel
PATCH /api/cloud/me/api/meProfile opt-ins
POST /api/cloud/me/api/me/...DSAR actions (export, delete, restrict)
GET /api/cloud/workspaces/api/workspacesWorkspace switcher
POST /api/cloud/workspaces/api/workspacesWorkspace creation
GET /api/cloud/projects/api/projectsProject list
POST /api/cloud/projects/api/projectsProject creation
GET /api/cloud/runs/api/runsRecent runs table
POST /api/cloud/api-keys/api/api-keysAPI key issuance (one-time secret)
POST /api/cloud/shares/api/sharesCreate / revoke public share
POST /api/cloud/billing/checkout/api/billing/checkoutStripe Checkout session
POST /api/cloud/billing/portal/api/billing/portalStripe Customer Portal
POST /api/cloud/sample-run/api/runs (synthetic)Onboarding “upload sample run”
POST /api/workspace/selectionlocal selection stateWorkspace switcher
The catch-all proxy /api/[...path] is intentionally allowlisted. It forwards only:
  • GET /health
  • GET /api/status
  • GET /api/runs, GET /api/runs/{run_id}, and run manifest/metrics/log/signature/compliance mapping reads
  • GET /api/artifacts/{artifact_id}
  • GET /api/claims, GET /api/claims/{claim_id}
  • GET /api/museum
  • workspace/project list and creation
  • API-key creation
  • share list/create/revoke
  • sync run create and artifact initiate/commit/abort
Unsupported methods, paths, or query parameters are rejected before Cloud is called. Machine-checked BFF proxy allowlist:
  • GET /health
  • GET /api/status
  • GET /api/runs
  • GET /api/runs/{id}
  • GET /api/runs/{id}/{manifest|metrics|log|signature|compliance_mapping}
  • GET /api/artifacts/{id}
  • GET /api/claims
  • GET /api/claims/{id}
  • GET /api/museum
  • GET /api/workspaces
  • POST /api/workspaces
  • GET /api/projects
  • POST /api/projects
  • POST /api/api-keys
  • GET /api/shares
  • POST /api/shares
  • POST /api/shares/{uuid}/revoke
  • POST /api/sync/runs
  • POST /api/sync/artifacts/{initiate|commit|abort}
Plus auth routes used by the dashboard’s session flow:
RoutePurpose
POST /api/auth/loginSupabase email/password sign-in
POST /api/auth/signupSupabase email/password sign-up
POST /api/auth/logoutSupabase sign-out
POST /api/auth/reset-passwordSupabase reset email request
POST /api/auth/sessionCurrent session check
Dashboard pages also cover forgot-password, reset-password, and verify-email flows. Public-share routes are separate from authenticated dashboard routes:
RoutePurpose
GET /api/public/r/[token]Resolve a public share token to a run snapshot
GET /api/public/vla-leaderboardReturn public VLA leaderboard snapshots
Public share reads use stable public-safe states:
StateHTTP statusCodeCache
Active share200n/aprivate, no-store
Token not found or token mismatch404share_not_foundno-store
Revoked410share_revokedno-store
Expired410share_expiredno-store
Missing password401share_password_requiredno-store
Wrong password401share_wrong_passwordno-store
Password locked429share_password_lockedno-store + rate-limit headers
Read rate limited429share_rate_limitedno-store + rate-limit headers
Evidence verification failure409evidence_unverifiedno-store
Artifact filtered or unavailable409artifact_filteredno-store
Public payload policy rejected409public_payload_policy_rejectedno-store
Web clients must render public-only unavailable states for these codes and must not fall back to dashboard controls or internal identifiers. Machine-checked named BFF route list:
  • DELETE /api/[...path]
  • GET /api/[...path]
  • PATCH /api/[...path]
  • POST /api/[...path]
  • PUT /api/[...path]
  • POST /api/auth/login
  • POST /api/auth/logout
  • POST /api/auth/reset-password
  • POST /api/auth/session
  • POST /api/auth/signup
  • DELETE /api/cloud/api-keys
  • POST /api/cloud/api-keys
  • POST /api/cloud/billing/checkout
  • POST /api/cloud/billing/portal
  • GET /api/cloud/me
  • PATCH /api/cloud/me
  • POST /api/cloud/me
  • DELETE /api/cloud/projects
  • GET /api/cloud/projects
  • POST /api/cloud/projects
  • POST /api/cloud/projects/[projectId]/staging-retention-proof
  • GET /api/cloud/runs
  • POST /api/cloud/runs
  • POST /api/cloud/sample-run
  • GET /api/cloud/shares
  • POST /api/cloud/shares
  • DELETE /api/cloud/workspaces
  • GET /api/cloud/workspaces
  • POST /api/cloud/workspaces
  • POST /api/e2e/cli-sync
  • GET /api/public/r/[token]
  • GET /api/public/vla-leaderboard
  • POST /api/workspace/selection

Auth header

All /api/cloud/* calls expect a Supabase session cookie when called from the dashboard. The CLI does not call these BFF routes; it sends Authorization: Bearer <wfx_…> directly to FastAPI.

Error shape

The BFF normalizes failures into one shape:
{
  "error": {
    "code": "login_required",
    "message": "Please log in again."
  }
}
code is stable. Common values seen by the dashboard:
CodeWhen
login_requiredSession missing or expired. The dashboard redirects to /login.
validation_errorBody shape mismatch. details carries the offending field path.
quota_exceededWorkspace plan cap hit. The Billing panel surfaces an upgrade CTA.
not_foundResource id does not exist or is invisible to this caller.
unsupported_actionMethod not allowed (e.g. POST /api/cloud/runs without the e2e fixture flag).

E2E fixtures

When WORLDFLUX_WEB_E2E_FIXTURES=1 is set, the BFF returns deterministic in-memory data instead of proxying to FastAPI. This is what Playwright tests use.
if (e2eFixturesEnabled()) {
  return NextResponse.json(listE2ERuns());
}
/api/e2e/cli-sync is the synthetic endpoint the test suite hits to seed runs.