Authenticated API
This endpoint requires a valid JWT Bearer token. Accessible via the API gateway at /v1/analytics/*.
Dashboard API
Access real-time and historical dashboard metrics.
Overview
The Dashboard API provides comprehensive analytics:
| Feature | Description |
|---|---|
| Real-Time Metrics | Live operational data |
| KPIs | Key performance indicators |
| Trends | Historical comparisons |
| Widgets | Configurable dashboard components |
| Alerts | Threshold-based notifications |
Get Dashboard Overview
Request
GET /api/v1/analytics/dashboard?
location_id=loc-xyz789&
period=today
Authorization: Bearer {access_token}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
location_id | string | Location to query |
period | string | Time period (today, yesterday, week, month) |
timezone | string | Timezone for date calculations |
Response
{
"period": {
"start": "2026-01-18T00:00:00Z",
"end": "2026-01-18T23:59:59Z",
"timezone": "America/Los_Angeles"
},
"summary": {
"revenue": {
"total": 8542.50,
"vs_last_period": 12.5,
"vs_last_year": 8.2
},
"orders": {
"total": 245,
"vs_last_period": 8.3,
"avg_ticket": 34.87
},
"guests": {
"total": 412,
"avg_per_order": 1.68
},
"labor": {
"cost": 1250.00,
"percentage": 14.6
}
},
"hourly": [
{"hour": "11:00", "revenue": 450.00, "orders": 12},
{"hour": "12:00", "revenue": 1250.00, "orders": 35},
{"hour": "13:00", "revenue": 980.00, "orders": 28}
],
"by_channel": {
"dine_in": {"revenue": 5200.00, "orders": 145, "percentage": 60.9},
"takeout": {"revenue": 1842.50, "orders": 55, "percentage": 21.6},
"delivery": {"revenue": 1500.00, "orders": 45, "percentage": 17.5}
},
"top_items": [
{"name": "Classic Burger", "quantity": 85, "revenue": 1189.15},
{"name": "Fries", "quantity": 120, "revenue": 598.80},
{"name": "Crispy Wings", "quantity": 45, "revenue": 584.55}
]
}
Real-Time Metrics
Request
GET /api/v1/analytics/realtime?location_id=loc-xyz789
Authorization: Bearer {access_token}
Response
{
"timestamp": "2026-01-18T14:30:00Z",
"current_hour": {
"revenue": 650.00,
"orders": 18,
"avg_ticket": 36.11
},
"open_orders": 8,
"tables": {
"occupied": 12,
"available": 8,
"reserved": 3
},
"kitchen": {
"tickets_in_queue": 15,
"avg_prep_time_minutes": 12,
"late_tickets": 2
},
"staff": {
"clocked_in": 12,
"on_break": 2
},
"alerts": [
{
"type": "kitchen_backed_up",
"message": "Kitchen queue exceeds threshold",
"severity": "warning"
}
]
}
Sales Metrics
Request
GET /api/v1/analytics/sales?
location_id=loc-xyz789&
start_date=2026-01-01&
end_date=2026-01-18&
group_by=day
Authorization: Bearer {access_token}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
location_id | string | Location to query |
start_date | date | Start of date range |
end_date | date | End of date range |
group_by | string | Grouping (hour, day, week, month) |
Response
{
"period": {
"start": "2026-01-01",
"end": "2026-01-18"
},
"totals": {
"gross_sales": 145000.00,
"discounts": 4350.00,
"refunds": 1250.00,
"net_sales": 139400.00,
"tax_collected": 12150.00,
"tips": 21000.00,
"orders": 4250,
"avg_ticket": 32.80
},
"data": [
{
"date": "2026-01-01",
"gross_sales": 7500.00,
"net_sales": 7125.00,
"orders": 220
},
{
"date": "2026-01-02",
"gross_sales": 8200.00,
"net_sales": 7790.00,
"orders": 245
}
]
}
Labor Metrics
Request
GET /api/v1/analytics/labor?
location_id=loc-xyz789&
start_date=2026-01-18&
end_date=2026-01-18
Authorization: Bearer {access_token}
Response
{
"period": {
"start": "2026-01-18",
"end": "2026-01-18"
},
"summary": {
"total_hours": 98.5,
"total_cost": 2462.50,
"labor_percentage": 14.2,
"sales_per_labor_hour": 175.12
},
"by_role": [
{
"role": "Server",
"hours": 42.0,
"cost": 840.00,
"employees": 6
},
{
"role": "Cook",
"hours": 32.0,
"cost": 800.00,
"employees": 4
},
{
"role": "Manager",
"hours": 16.0,
"cost": 640.00,
"employees": 2
}
],
"by_hour": [
{"hour": "11:00", "employees": 8, "cost": 160.00},
{"hour": "12:00", "employees": 12, "cost": 240.00}
]
}
KPI Dashboard
Request
GET /api/v1/analytics/kpis?
location_id=loc-xyz789&
period=month
Authorization: Bearer {access_token}
Response
{
"kpis": [
{
"key": "revenue",
"name": "Revenue",
"value": 125000.00,
"target": 120000.00,
"vs_target": 4.2,
"trend": "up",
"unit": "currency"
},
{
"key": "avg_ticket",
"name": "Average Ticket",
"value": 34.50,
"target": 32.00,
"vs_target": 7.8,
"trend": "up",
"unit": "currency"
},
{
"key": "labor_percentage",
"name": "Labor %",
"value": 28.5,
"target": 30.0,
"vs_target": -5.0,
"trend": "down",
"unit": "percentage"
},
{
"key": "food_cost_percentage",
"name": "Food Cost %",
"value": 31.2,
"target": 30.0,
"vs_target": 4.0,
"trend": "up",
"unit": "percentage"
},
{
"key": "customer_satisfaction",
"name": "Customer Satisfaction",
"value": 4.6,
"target": 4.5,
"vs_target": 2.2,
"trend": "stable",
"unit": "rating"
}
]
}
Product Mix
Request
GET /api/v1/analytics/product-mix?
location_id=loc-xyz789&
start_date=2026-01-01&
end_date=2026-01-18&
limit=20
Authorization: Bearer {access_token}
Response
{
"items": [
{
"id": "item-burger",
"name": "Classic Burger",
"category": "Entrees",
"quantity_sold": 1250,
"gross_sales": 17487.50,
"percentage_of_sales": 12.5,
"food_cost": 4375.00,
"margin": 75.0
},
{
"id": "item-fries",
"name": "Fries",
"category": "Sides",
"quantity_sold": 1800,
"gross_sales": 8982.00,
"percentage_of_sales": 6.4,
"food_cost": 1620.00,
"margin": 82.0
}
],
"categories": [
{
"name": "Entrees",
"gross_sales": 65000.00,
"percentage": 46.4
},
{
"name": "Sides",
"gross_sales": 25000.00,
"percentage": 17.9
}
]
}
Dashboard Widgets
Get Configured Widgets
GET /api/v1/analytics/dashboard/widgets?user_id=user-abc123
Authorization: Bearer {access_token}
Response
{
"widgets": [
{
"id": "widget-001",
"type": "revenue_chart",
"title": "Today's Revenue",
"position": {"row": 0, "col": 0, "width": 2, "height": 1},
"config": {
"period": "today",
"chart_type": "line"
}
},
{
"id": "widget-002",
"type": "kpi_card",
"title": "Orders",
"position": {"row": 0, "col": 2, "width": 1, "height": 1},
"config": {
"metric": "order_count",
"period": "today"
}
}
]
}
Update Widget Configuration
PUT /api/v1/analytics/dashboard/widgets/{widget_id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
"config": {
"period": "week",
"chart_type": "bar"
},
"position": {"row": 1, "col": 0, "width": 2, "height": 1}
}
Comparison Analytics
Request
GET /api/v1/analytics/compare?
location_id=loc-xyz789&
current_start=2026-01-11&
current_end=2026-01-18&
compare_start=2026-01-04&
compare_end=2026-01-11
Authorization: Bearer {access_token}
Response
{
"current_period": {
"start": "2026-01-11",
"end": "2026-01-18",
"revenue": 62500.00,
"orders": 1850
},
"comparison_period": {
"start": "2026-01-04",
"end": "2026-01-11",
"revenue": 58000.00,
"orders": 1720
},
"changes": {
"revenue": {
"absolute": 4500.00,
"percentage": 7.8
},
"orders": {
"absolute": 130,
"percentage": 7.6
},
"avg_ticket": {
"absolute": 0.12,
"percentage": 0.4
}
}
}
Error Responses
Invalid Date Range (400)
{
"error": {
"code": "INVALID_DATE_RANGE",
"message": "Start date must be before end date"
}
}
Data Not Available (404)
{
"error": {
"code": "DATA_NOT_AVAILABLE",
"message": "No data available for the specified period"
}
}
Related Documentation
- Reports API - Generate reports
- AI Insights - AI-powered analytics
- WebSocket Events - Real-time updates