ORbit uses Supabase PostgREST for most data operations (no custom REST API needed). Next.js API routes are only used for operations requiring server-side secrets or multi-step orchestration (invitations, demo data generation, auth checks).
API routes
ORbit exposes the following Next.js API routes:User management
| Method | Route | Purpose |
|---|---|---|
| POST | /api/invite/accept | Accept a user invitation |
| POST | /api/admin/invite | Send an admin invitation (global admin) |
| POST | /api/resend-invite | Resend a pending invitation |
| POST | /api/send-rep-invite | Send a device rep invitation |
| POST | /api/create-device-rep | Create a device rep account |
Authentication
| Method | Route | Purpose |
|---|---|---|
| GET | /api/check-auth-status | Verify current auth session |
| GET | /api/check-user-status | Check user account status and permissions |
Demo data
| Method | Route | Purpose |
|---|---|---|
| POST | /api/demo-data | Manage demo data (purge, configure) |
| POST | /api/demo-data/generate | Generate demo data with SSE streaming progress |
Admin tools
| Method | Route | Purpose |
|---|---|---|
| GET | /api/admin/scan-pages | Scan codebase for page documentation metadata |
RPC functions
Supabase RPC functions handle operations that require transactional integrity or multi-table coordination. These are called viasupabase.rpc('function_name', params).
Case lifecycle
| Function | Parameters | Description |
|---|---|---|
create_case_with_milestones | case data, facility_id | Creates a case and pre-populates milestones from the resolved template |
finalize_draft_case | case_id | Transitions a draft case to scheduled status |
get_surgeon_day_overview | surgeon_id, date | Returns a surgeon’s cases for a given date |
Analytics
| Function | Parameters | Description |
|---|---|---|
get_milestone_interval_medians | facility_id, procedure_type_id, surgeon_id, milestone_template_id | Returns median intervals between milestones with 3-tier cascade resolution |
get_phase_medians | facility_id, procedure_type_id, surgeon_id, milestone_template_id | Returns median phase durations |
resolve_template_phase_boundaries | milestone_template_id | Derives phase boundaries from template items |
Facility provisioning
| Function | Parameters | Description |
|---|---|---|
seed_facility_with_templates | facility_id, config (JSONB) | Seeds a new facility with configuration from global templates across 13+ categories |
Data access layer
The web application uses a TypeScript data access layer (DAL) inlib/dal/:
| Module | Scope |
|---|---|
core.ts | Shared utilities and base query patterns |
cases.ts | Case CRUD, status transitions, milestone recording |
facilities.ts | Facility settings and configuration |
users.ts | User management and role operations |
lookups.ts | Cached lookup data (procedures, rooms, surgeons) |
flag-rules.ts | Flag rule CRUD operations |
phase-resolver.ts | Template-based phase boundary resolution |
Client-side data fetching
All client-side data fetching uses theuseSupabaseQuery hook:
Authentication
All API access requires a valid Supabase Auth session. The auth flow:- User authenticates via Supabase Auth (email/password)
- Next.js middleware validates the session on every request
- The Supabase client automatically includes the auth token
- RLS policies on every table enforce facility-scoped access
Rate limiting
API routes that handle authentication (login, password reset) implement rate limiting to prevent abuse. Rate limits are tracked per IP and per user.Key conventions
When to use API routes vs. direct Supabase
When to use API routes vs. direct Supabase
Use direct Supabase for standard CRUD operations — PostgREST + RLS handles security automatically. Use API routes only when you need server-side secrets (e.g., sending invite emails), SSE streaming (demo generator), or operations that shouldn’t expose the implementation to the client.
When to use RPC functions vs. client queries
When to use RPC functions vs. client queries
Use RPC functions for operations requiring transactional integrity (case creation with milestones), complex multi-table joins (analytics medians), or when the logic is too complex for PostgREST’s query syntax. Use client queries for simple reads, filters, and pagination.
Error handling pattern
Error handling pattern
DAL functions throw errors that are caught by
useSupabaseQuery. API routes return JSON with { error: string } and appropriate HTTP status codes. Never return raw Supabase errors to the client.