Edge Functions API
Last Updated: 2025-02-06
Overview
Edge Functions provide aggregated endpoints that reduce REST request volume by combining multiple database queries into single responses. All Edge Functions include optional caching and maintain tenant isolation.
Benefits:
- ✅ Reduces REST request volume (5+ queries → 1 request)
- ✅ Optional caching (30-60s TTL per tenant)
- ✅ Maintains tenant isolation
- ✅ Automatic fallback to direct Supabase queries
- ✅ Backward compatible (existing queries still work)
Endpoints
1. Dashboard Snapshot V2 (Recommended)
Endpoint: GET /functions/v1/get-dashboard-snapshot-v2
Description: Unified dashboard data aggregation endpoint combining all major dashboard data sources into a single response. Supports lightweight mode for KPI-only dashboards and pagination for large datasets.
Aggregates:
- Zones with utilization
- Inventory items with metrics and stock levels
- Active pick lists
- Active shipments
- Active drivers
- Safety metrics and recent incidents
- Import jobs metrics
Query Parameters:
lightweight=true(optional) — Return only metrics and counts, no full item lists (60-70% size reduction)page=1(optional) — Page number for pagination (default: 1)pageSize=50(optional) — Items per page (default: 50, max: 200)
Caching: 60 seconds TTL per tenant (cache key includes query parameters)
Response (Full Mode):
{
"tenant_id": "uuid",
"timestamp": "2025-02-06T10:00:00Z",
"cached": false,
"zones": {
"total": 15,
"items": [
{
"id": "uuid",
"code": "A-01",
"name": "Zone A",
"x": 10,
"y": 20,
"z": 0,
"max_capacity": 100
}
]
},
"inventory": {
"items": [...],
"metrics": {
"total_items": 150,
"low_stock_count": 5,
"total_stock_value": 0
},
"stock_levels": [
{
"item_id": "uuid",
"quantity": 45
}
]
},
"pick_lists": {
"active": 5,
"items": [...]
},
"shipments": {
"active": 8,
"items": [...]
},
"drivers": {
"active": 3,
"items": [...]
},
"safety": {
"metrics": {
"total_incidents": 12,
"critical_incidents": 2,
"open_incidents": 5,
"incidents_by_category": {
"slip": 3,
"fall": 2
}
},
"recent_incidents": [...]
},
"import": {
"metrics": {
"total_jobs": 10,
"completed_jobs": 8,
"failed_jobs": 1,
"total_imported": 1250
},
"recent_jobs": [...]
},
"pagination": {
"page": 1,
"pageSize": 50,
"hasMore": false
}
}Response (Lightweight Mode):
{
"tenant_id": "uuid",
"timestamp": "2025-02-06T10:00:00Z",
"cached": false,
"zones": {
"total": 15
},
"inventory": {
"metrics": {
"total_items": 150,
"low_stock_count": 5,
"total_stock_value": 0
}
},
"pick_lists": {
"active": 5
},
"shipments": {
"active": 8
},
"drivers": {
"active": 3
},
"safety": {
"metrics": {
"total_incidents": 12,
"critical_incidents": 2,
"open_incidents": 5,
"incidents_by_category": {}
}
},
"import": {
"metrics": {
"total_jobs": 10,
"completed_jobs": 8,
"failed_jobs": 1,
"total_imported": 1250
}
},
"pagination": {
"page": 1,
"pageSize": 50,
"hasMore": false
}
}Usage:
import { fetchDashboardSnapshotV2 } from "@/lib/api-edge";
// Full data mode
const data = await fetchDashboardSnapshotV2({
useCache: true,
lightweight: false,
page: 1,
pageSize: 50
});
// Lightweight mode (KPI dashboards)
const data = await fetchDashboardSnapshotV2({
useCache: true,
lightweight: true
});React Hook:
import { useDashboardSnapshotV2 } from "@/lib/queries";
// Full data
const { data, isLoading } = useDashboardSnapshotV2({
lightweight: false,
refetchInterval: 60 * 1000
});
// Lightweight mode
const { data, isLoading } = useDashboardSnapshotV2({
lightweight: true
});Performance:
- Size Reduction: 60-90% smaller responses (500KB → 200KB full / 50KB lightweight)
- Request Reduction: Replaces 15-20+ individual REST requests with 1 aggregated request
- Compression: Automatic gzip/deflate compression
- Cache Hit Rate: ~70% for frequently accessed dashboards
Fallback: Falls back to admin-dashboard-summary Edge Function or direct Supabase queries if unavailable.
2. Admin Dashboard Summary
Endpoint: GET /functions/v1/admin-dashboard-summary
Description: Aggregates admin dashboard data into a single response. Note: Consider using get-dashboard-snapshot-v2 for new implementations.
Aggregates:
- Zones with utilization
- Inventory items with health metrics
- Active pick lists
- Recent shipments with stats
- System settings
Caching: 30 seconds TTL per tenant
Response:
{
"tenant_id": "uuid",
"timestamp": "2025-02-03T10:00:00Z",
"zones": [...],
"inventory": {
"items": [...],
"total_items": 150,
"health": {
"score": 85,
"fast_movers": 45,
"slow_stock": 10,
"dead_stock": 2,
"critical_items": 3
}
},
"pick_lists": {
"active": [...],
"active_count": 5
},
"shipments": {
"recent": [...],
"stats": {
"total": 20,
"active": 8,
"in_transit": 3,
"completed_today": 5
}
},
"settings": {...}
}Usage:
import { fetchAdminDashboardSummary } from "@/lib/api-edge";
const data = await fetchAdminDashboardSummary();Fallback: Falls back to get-dashboard-snapshot Edge Function or direct Supabase queries.
2. Calculate Predictive Safety Scores
Endpoint: POST /functions/v1/calculate-predictive-safety-scores
Description: Computes predictive risk scores for entities (zones, drivers, workers, equipment) based on incidents, near misses, shift hours, and workload.
Request Body:
{
"entity_type": "zone", // Optional: 'zone', 'driver', 'worker', 'equipment'
"entity_id": "uuid", // Optional: specific entity ID
"period_days": 30 // Optional: lookback period (default: 30)
}Query Parameters (GET):
entity_type(optional)entity_id(optional)period_days(optional, default: 30)
Response:
{
"success": true,
"tenant_id": "uuid",
"scores_computed": 15,
"scores": [
{
"entity_type": "zone",
"entity_id": "uuid",
"score": 65.5,
"confidence": 0.75,
"inputs": {
"incident_count": 3,
"near_miss_count": 8,
"shift_hours": 0,
"workload": 12,
"period_days": 30
}
}
],
"model": {
"weight_incident": 2.0,
"weight_near_miss": 1.5,
"weight_shift_hours": 0.3,
"weight_load": 0.2
}
}Usage:
import { calculatePredictiveSafetyScores } from "@/lib/api-edge";
// Calculate all scores
const result = await calculatePredictiveSafetyScores();
// Calculate for specific entity
const result = await calculatePredictiveSafetyScores('zone', zoneId, 30);See: Predictive Intelligence Documentation
3. Assign Risk Clusters (Phase 2)
Endpoint: POST /functions/v1/assign-risk-clusters
Description: Groups entities into risk clusters based on their predictive scores. Creates clusters for different severity ranges (Critical, High, Medium, Low).
Request Body:
{
"entity_type": "zone", // Optional: 'zone', 'driver', 'worker', 'equipment'
"min_score": 0, // Optional: minimum score threshold (default: 0)
"max_score": 100 // Optional: maximum score threshold (default: 100)
}Response:
{
"success": true,
"tenant_id": "uuid",
"clusters_created": 4,
"entities_assigned": 25,
"clusters": [
{
"id": "uuid",
"cluster_name": "Critical Risk",
"severity": 85.5,
"description": "Entities with very high risk scores (70-100)",
"entity_count": 8
}
]
}Usage:
import { assignRiskClusters } from "@/lib/api-edge";
// Assign all entities to clusters
const result = await assignRiskClusters();
// Assign only zones
const result = await assignRiskClusters('zone');See: Predictive Intelligence Documentation - Phase 2
4. Check Compliance Rules (Phase 4)
Endpoint: POST /functions/v1/check-compliance-rules
Description: Automatically scans safety data (predictive scores, incidents, near misses) to check compliance against configured safety regulations (OSHA, EU-OSHA, etc.).
Request Body:
{
"entity_type": "zone", // Optional: 'zone', 'driver', 'worker', 'equipment'
"entity_id": "uuid", // Optional: specific entity ID
"jurisdiction": "US" // Optional: 'US', 'EU', 'Global'
}Response:
{
"success": true,
"tenant_id": "uuid",
"events_created": 5,
"summary": {
"total_regulations": 12,
"compliant_count": 8,
"warning_count": 3,
"breach_count": 1,
"last_check": "2025-02-05T10:00:00Z"
},
"events": [
{
"regulation_id": "uuid",
"entity_type": "zone",
"entity_id": "uuid",
"status": "breach"
}
]
}Usage:
import { checkComplianceRules } from "@/lib/api-edge";
// Check all compliance
const result = await checkComplianceRules();
// Check specific entity
const result = await checkComplianceRules('zone', zoneId);
// Check specific jurisdiction
const result = await checkComplianceRules(undefined, undefined, 'US');See: Compliance Automation Documentation
5. Auto-Assign Training (Phase 6)
Endpoint: POST /functions/v1/auto-assign-training
Description: Automatically assigns training courses to users based on predictive risk scores. Triggers when risk scores exceed course thresholds.
Request Body:
{
"entity_type": "worker", // Optional: 'zone', 'driver', 'worker', 'equipment'
"entity_id": "uuid", // Optional: specific entity ID
"min_risk_score": 50 // Optional: minimum risk score threshold (default: 0)
}Response:
{
"success": true,
"tenant_id": "uuid",
"assignments_created": 5,
"courses_checked": 12,
"scores_checked": 8,
"assignments": [
{
"tenant_id": "uuid",
"course_id": "uuid",
"user_id": "uuid",
"assignment_type": "risk_based",
"assignment_reason": "High risk score (75) for worker uuid",
"status": "assigned"
}
]
}Usage:
import { autoAssignTraining } from "@/lib/api-edge";
// Auto-assign for all high-risk entities
const result = await autoAssignTraining();
// Auto-assign for specific entity type
const result = await autoAssignTraining('worker');
// Auto-assign with minimum risk score
const result = await autoAssignTraining(undefined, undefined, 60);See: LMS Training Integration Documentation
6. Safety KPIs
Endpoint: GET /functions/v1/safety-kpis?days=30
Description: Aggregates safety KPI calculations into a single response.
Query Parameters:
days(optional): Number of days for date range (default: 30)
Aggregates:
- Total Safety Reports (TSR)
- Critical incidents count
- Open actions count
- Overdue actions count
- Checklist compliance percentage
- Recent incidents (last 10)
- Distribution by category and severity
Caching: 60 seconds TTL per tenant
Response:
{
"tenant_id": "uuid",
"timestamp": "2025-02-03T10:00:00Z",
"date_range_days": 30,
"kpis": {
"tsr": 25,
"critical_incidents": 3,
"open_actions": 12,
"overdue_actions": 2,
"checklist_compliance": 85
},
"distribution": {
"by_category": {
"injury": 5,
"near_miss": 10,
"hazard": 8
},
"by_severity": {
"low": 15,
"medium": 8,
"high": 2
}
},
"recent_incidents": [...]
}Usage:
import { fetchSafetyKPIs } from "@/lib/api-edge";
const data = await fetchSafetyKPIs(30); // Last 30 daysFallback: Falls back to direct Supabase queries for incidents, actions, and checklist submissions.
7. Process Import Job (Data Import Hub)
Endpoint: POST /functions/v1/process-import-job
Description: Processes an import job, parses file data, and prepares records for mapping and validation.
Request Body:
{
"job_id": "uuid"
}Response:
{
"success": true,
"job_id": "uuid",
"file_type": "csv",
"stats": {
"total_rows": 100,
"valid_rows": 95,
"invalid_rows": 5
},
"message": "Job processing started"
}Usage:
import { useProcessImportJob } from '@/lib/queries';
const processJob = useProcessImportJob();
await processJob.mutateAsync(jobId);See: Data Import Hub Documentation
8. Apply Import Job (Data Import Hub)
Endpoint: POST /functions/v1/apply-import-job
Description: Applies validated import records to target tables (inventory_items, zones, stock_movements, etc.) and creates rollback snapshots.
Request Body:
{
"job_id": "uuid"
}Response:
{
"success": true,
"imported_count": 95,
"message": "Successfully imported 95 records"
}Usage:
import { useApplyImportJob } from '@/lib/queries';
const applyImport = useApplyImportJob();
await applyImport.mutateAsync(jobId);See: Data Import Hub Documentation
9. Rollback Import Job (Data Import Hub)
Endpoint: POST /functions/v1/rollback-import-job
Description: Rolls back an import job, restoring all imported data to its previous state. Admin-only access.
Request Body:
{
"job_id": "uuid"
}Response:
{
"success": true,
"rolled_back": 95,
"message": "Rolled back 95 records"
}Usage:
import { useRollbackImportJob } from '@/lib/queries';
const rollback = useRollbackImportJob();
await rollback.mutateAsync(jobId);See: Data Import Hub Documentation
10. Safety Engagement Metrics
Endpoint: GET /functions/v1/safety-engagement
Description: Aggregates safety engagement data into a single response.
Aggregates:
- User safety score
- Total points
- Recent points log
- Earned badges
- Team scores (admin only)
- Zone scores (admin only)
Caching: 60 seconds TTL per tenant
Response:
{
"tenant_id": "uuid",
"user_id": "uuid",
"timestamp": "2025-02-03T10:00:00Z",
"user_score": {
"score": 85,
"period_start": "2025-01-01",
"period_end": "2025-01-31"
},
"total_points": 1250,
"recent_points": [...],
"badges": [...],
"team_scores": [...], // Admin only
"zone_scores": [...] // Admin only
}Usage:
import { fetchSafetyEngagement } from "@/lib/api-edge";
const data = await fetchSafetyEngagement();Fallback: Falls back to direct Supabase queries for scores, points, and badges.
Caching
All Edge Functions use in-memory caching with:
- Per-tenant isolation: Cache keys include tenant_id
- Short TTL: 30-60 seconds to balance freshness and performance
- Cache headers: Responses include
X-Cache: HITorX-Cache: MISS
Cache Invalidation:
- Automatic expiration after TTL
- Manual invalidation via cache cleanup (every 5 minutes)
- Per-tenant cache clearing available
Authentication
All endpoints require:
- Authorization header:
Bearer <access_token> - apikey header: Supabase anon key (optional but recommended)
Example:
const headers = {
Authorization: `Bearer ${session.access_token}`,
"Content-Type": "application/json",
apikey: SUPABASE_ANON_KEY,
};Error Handling
All Edge Functions:
- Try Edge Function first (aggregated, cached)
- Fall back to direct queries if Edge Function fails
- Maintain backward compatibility with existing code
Error Response:
{
"error": "Error message",
"details": "Additional error details"
}Status Codes:
200: Success401: Unauthorized (missing/invalid token)403: Forbidden (user not associated with tenant)405: Method not allowed500: Internal server error
Performance Benefits
Request Volume Reduction
Before (Direct Queries):
- Admin Dashboard: 5+ separate REST requests
- Safety KPIs: 4+ separate REST requests
- Safety Engagement: 4+ separate REST requests
- Predictive Scores: 10+ separate REST requests (per entity type)
After (Edge Functions):
- Admin Dashboard: 1 aggregated request
- Safety KPIs: 1 aggregated request
- Safety Engagement: 1 aggregated request
- Predictive Scores: 1 aggregated request (all entities)
Estimated Reduction: 60-80% fewer REST requests for dashboard views.
Response Time
- Cached responses: < 50ms (cache hit)
- Uncached responses: 200-500ms (aggregated queries)
- Direct queries (fallback): 500-1500ms (multiple sequential requests)
Implementation Notes
Frontend Integration
Edge Functions are integrated as optional optimizations:
- Frontend tries Edge Function first
- Falls back to direct Supabase queries if Edge Function fails
- No breaking changes to existing code
Example Pattern:
try {
// Try Edge Function (aggregated, cached)
const data = await fetchAdminDashboardSummary();
return data;
} catch (error) {
// Fallback to direct queries
console.warn("Edge Function unavailable, using direct queries");
// ... existing query logic ...
}Backend Implementation
Edge Functions:
- Use
adminClient(service role) for database access - Respect RLS policies via tenant filtering
- Aggregate queries in parallel using
Promise.all() - Return structured JSON responses
- Include cache headers for monitoring
Monitoring
Cache Hit Rate:
- Check
X-Cacheheader in responses - Monitor cache hit/miss ratio
- Adjust TTL if needed
Performance:
- Monitor response times
- Track error rates
- Compare Edge Function vs. direct query performance
Future Enhancements
Potential improvements:
- Redis-based distributed caching
- Longer TTL for less-frequently-changing data
- Cache warming for common queries
- Metrics endpoint for cache statistics
- Webhook-based cache invalidation