Report
This section contains 1 subgroups.
Delivery Report
/report/deliverySummary GET /report/delivery Delivery dashboard report. Storage model - One row per tenant in public.delivery_report (refreshed nightly). - API reads the stored lifetime payload; there is no range query param. - If stored zone_stats are still on the legacy shape, the API rebuilds zone stats live from public.deliveries. Auth - Header Authorization: Bearer {{access_token}} - All auth failures come from middleware and return { "success": false, "message": string, "data": null } with 401/403. 200 Response (JSON) Body is wrapped: Zone stats rules - All tenant zones are returned in zone_stats, even when a zone has no deliveries in the reporting window - Zones without deliveries return 0 for all totals - total_inbound_deliveries counts deliveries where pickup_zone_id = zone_id - total_outbound_deliveries counts deliveries where dropoff_zone_id = zone_id - total_deliveries counts unique deliveries touching the zone by pickup and/or dropoff - If both pickup and dropoff point to the same zone, that delivery is counted once in total_deliveries - total_completed_deliveries counts delivered rows from those unique deliveries Error responses - 401/403 (auth/middleware): { "success": false, "message": string, "data": null } - 404 (report not ready): { "success": false, "message": "report_not_ready", "data": null } - 404 (unknown module): { "success": false, "message": string, "data": null } - 405 (method not allowed): { "success": false, "message": string, "data": null } - 500: { "success": false, "message": string, "data": null }
1curl --request GET "$ONDI_BASE_URL/report/delivery" \2 --header "Authorization: Bearer {{access_token}}"Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "",4 "data": {5 "kpis": {6 "total_deliveries": {7 "value": 0,8 "trend_percentage": 0,9 "trend_direction": "up",10 "chart_data": [11 0,12 0,13 0,14 0,15 0,16 0,17 018 ]19 },20 "completed": {21 "value": 0,22 "trend_percentage": 0,23 "trend_direction": "up",24 "chart_data": [25 0,26 0,27 0,28 0,29 0,30 0,31 032 ]33 },34 "in_progress": {35 "value": 0,36 "trend_percentage": 0,37 "trend_direction": "up",38 "chart_data": []39 },40 "failed": {41 "value": 0,42 "trend_percentage": 0,43 "trend_direction": "up",44 "chart_data": [45 0,46 0,47 0,48 0,49 0,50 0,51 052 ]53 }54 },55 "charts": {56 "status_breakdown": {57 "completed": 0,58 "in_progress": 0,59 "pending": 0,60 "failed": 061 },62 "weekly_performance": {63 "dates": [64 "2025-12-08",65 "2025-12-09",66 "2025-12-10",67 "2025-12-11",68 "2025-12-12",69 "2025-12-13",70 "2025-12-14"71 ],72 "completed": [73 0,74 0,75 0,76 0,77 0,78 0,79 080 ],81 "failed": [82 0,83 0,84 0,85 0,86 0,87 0,88 089 ]90 },91 "metrics_trends": {92 "success_rate": [93 0,94 0,95 0,96 0,97 0,98 0,99 0100 ],101 "avg_delivery_time": [102 0,103 0,104 0,105 0,106 0,107 0,108 0109 ],110 "active_drivers": [111 0,112 0,113 0,114 0,115 0,116 0,117 0118 ]119 }120 },121 "performance": {122 "success_rate": {123 "value": 0,124 "percentage": 0125 },126 "on_time_delivery": {127 "value": 0,128 "percentage": 0129 },130 "customer_satisfaction": {131 "value": 0,132 "percentage": 0133 },134 "first_attempt_success": {135 "value": 0,136 "percentage": 0137 }138 },139 "cod": {140 "collected": 0,141 "remitted": 0,142 "outstanding": 0,143 "wallet_settled": 0144 },145 "top_drivers": [146 {147 "driver_id": "00000000-0000-0000-0000-000000000001",148 "name": "",149 "avatar_url": "",150 "completed_jobs": 0,151 "failed_jobs": 0,152 "avg_time_minutes": 0153 }154 ],155 "zone_stats": [156 {157 "zone_id": "11111111-1111-1111-1111-111111111111",158 "zone_code": "ZN-001",159 "zone_name": "Central Zone",160 "total_deliveries": 0,161 "total_inbound_deliveries": 0,162 "total_outbound_deliveries": 0,163 "total_completed_deliveries": 0164 }165 ],166 "recent_activity": [167 {168 "id": "00000000-0000-0000-0000-000000000100",169 "order_ref": "",170 "type": "pending",171 "message": "",172 "timestamp": "2025-12-14T00:00:00.000Z"173 }174 ]175 }176}1{2 "success": false,3 "message": "invalid_token",4 "data": null5}1{2 "success": false,3 "message": "Endpoint for module 'delivery' not found",4 "data": null5}1{2 "success": false,3 "message": "method_not_allowed",4 "data": null5}1{2 "success": false,3 "message": "Internal Server Error",4 "data": null5}1type ResponseEnvelope<T> = { success: boolean; message: string; data: T | null };23type DeliveryDashboardEnvelope = ResponseEnvelope<DeliveryDashboardResponse>;45interface DeliveryDashboardResponse {6 kpis: {7 total_deliveries: KPIItem;8 completed: KPIItem;9 in_progress: KPIItem;10 failed: KPIItem;11 };12 charts: {13 status_breakdown: { completed: number; in_progress: number; pending: number; failed: number };14 weekly_performance: { dates: string[]; completed: number[]; failed: number[] };15 metrics_trends: { success_rate: number[]; avg_delivery_time: number[]; active_drivers: number[] };16 };17 performance: {18 success_rate: { value: number; percentage: number };19 on_time_delivery: { value: number; percentage: number };20 customer_satisfaction: { value: number; percentage: number };21 first_attempt_success: { value: number; percentage: number };22 };23 cod: { collected: number; remitted: number; outstanding: number; wallet_settled: number };24 top_drivers: Array<{ driver_id: string; name: string; avatar_url: string; completed_jobs: number; failed_jobs: number; avg_time_minutes: number }>;25 zone_stats: Array<{26 zone_id: string;27 zone_code: string;28 zone_name: string;29 total_deliveries: number;30 total_inbound_deliveries: number;31 total_outbound_deliveries: number;32 total_completed_deliveries: number;33 }>;34 recent_activity: Array<{ id: string; order_ref: string; type: 'completed'|'failed'|'in_transit'|'pending'|'assigned'; message: string; timestamp: string }>;35}3637type KPIItem = {38 value: number;39 trend_percentage: number;40 trend_direction: 'up' | 'down';41 chart_data: number[];42};Storefront Report
/report/storefrontSummary GET /report/storefront Storefront dashboard report. Storage model - One row per tenant in public.storefront_report (refreshed nightly). - API reads the stored lifetime payload; there is no range query param. Auth - Header Authorization: Bearer {{access_token}} 200 Response (JSON) Body is wrapped: Error responses Same envelope: - { "success": false, "message": string, "data": null }
1curl --request GET "$ONDI_BASE_URL/report/storefront" \2 --header "Authorization: Bearer {{access_token}}"Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "",4 "data": {5 "kpis": {6 "weekly_sales": {7 "value": 0,8 "trend_percentage": 0,9 "trend_direction": "up",10 "chart_data": [11 0,12 0,13 0,14 0,15 0,16 0,17 018 ]19 },20 "new_customers": {21 "value": 0,22 "trend_percentage": 0,23 "trend_direction": "up",24 "chart_data": []25 },26 "purchase_orders": {27 "value": 0,28 "trend_percentage": 0,29 "trend_direction": "up",30 "chart_data": []31 },32 "messages": {33 "value": 0,34 "trend_percentage": 0,35 "trend_direction": "up",36 "chart_data": []37 }38 },39 "summary": {40 "product_sold": {41 "value": 0,42 "trend_percentage": 043 },44 "total_balance": {45 "value": 0,46 "trend_percentage": 047 },48 "sales_profit": {49 "value": 0,50 "trend_percentage": 051 }52 },53 "charts": {54 "sale_by_gender": [55 {56 "label": "Men",57 "value": 058 },59 {60 "label": "Women",61 "value": 062 },63 {64 "label": "Kids",65 "value": 066 }67 ],68 "yearly_sales": {69 "categories": [70 "Jan",71 "Feb",72 "Mar",73 "Apr",74 "May",75 "Jun",76 "Jul",77 "Aug",78 "Sep",79 "Oct",80 "Nov",81 "Dec"82 ],83 "series": [84 {85 "name": "2023",86 "data": [87 0,88 0,89 0,90 0,91 0,92 0,93 0,94 0,95 0,96 0,97 0,98 099 ]100 },101 {102 "name": "2024",103 "data": [104 0,105 0,106 0,107 0,108 0,109 0,110 0,111 0,112 0,113 0,114 0,115 0116 ]117 }118 ]119 }120 },121 "finances": {122 "sales_overview": {123 "total_profit": {124 "value": 0,125 "percentage": 0126 },127 "total_income": {128 "value": 0,129 "percentage": 0130 },131 "total_expenses": {132 "value": 0,133 "percentage": 0134 }135 },136 "current_balance": {137 "total": 0,138 "breakdown": {139 "order_total": 0,140 "earning": 0,141 "refunded": 0142 }143 }144 },145 "best_sellers": [146 {147 "seller_id": "00000000-0000-0000-0000-000000000001",148 "name": "",149 "avatar_url": "",150 "product_category": "",151 "country_code": "",152 "total_sales": 0,153 "rank": 1154 }155 ],156 "latest_products": [157 {158 "id": "00000000-0000-0000-0000-000000000010",159 "name": "",160 "image_url": "",161 "price": 0,162 "original_price": 0,163 "is_active": true164 }165 ]166 }167}1{2 "success": false,3 "message": "invalid_token",4 "data": null5}1{2 "success": false,3 "message": "method_not_allowed",4 "data": null5}1{2 "success": false,3 "message": "Internal Server Error",4 "data": null5}1type ResponseEnvelope<T> = { success: boolean; message: string; data: T | null };23type StorefrontDashboardEnvelope = ResponseEnvelope<StorefrontDashboardResponse>;45interface StorefrontDashboardResponse {6 kpis: {7 weekly_sales: KPIItem;8 new_customers: KPIItem;9 purchase_orders: KPIItem;10 messages: KPIItem;11 };12 summary: {13 product_sold: { value: number; trend_percentage: number };14 total_balance: { value: number; trend_percentage: number };15 sales_profit: { value: number; trend_percentage: number };16 };17 charts: {18 sale_by_gender: Array<{ label: string; value: number }>;19 yearly_sales: { categories: string[]; series: Array<{ name: string; data: number[] }> };20 };21 finances: {22 sales_overview: {23 total_profit: { value: number; percentage: number };24 total_income: { value: number; percentage: number };25 total_expenses: { value: number; percentage: number };26 };27 current_balance: {28 total: number;29 breakdown: { order_total: number; earning: number; refunded: number };30 };31 };32 best_sellers: Array<{ seller_id: string; name: string; avatar_url: string; product_category: string; country_code: string; total_sales: number; rank: number }>;33 latest_products: Array<{ id: string; name: string; image_url: string; price: number; original_price?: number; is_active: boolean }>;34}3536type KPIItem = { value: number; trend_percentage: number; trend_direction: 'up'|'down'; chart_data: number[] };Warehouse Report
/report/warehouseSummary GET /report/warehouse Warehouse dashboard report. Storage model - One row per tenant in public.warehouse_report (refreshed nightly). - API reads the stored lifetime payload; there is no range query param. Auth - Header Authorization: Bearer {{access_token}} 200 Response (JSON) Body is wrapped: Error responses Same envelope: - { "success": false, "message": string, "data": null }
1curl --request GET "$ONDI_BASE_URL/report/warehouse" \2 --header "Authorization: Bearer {{access_token}}"Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "",4 "data": {5 "kpis": {6 "items_received": {7 "value": 0,8 "trend_percentage": 0,9 "trend_direction": "up",10 "chart_data": [11 0,12 0,13 0,14 0,15 0,16 0,17 018 ]19 },20 "items_dispatched": {21 "value": 0,22 "trend_percentage": 0,23 "trend_direction": "up",24 "chart_data": [25 0,26 0,27 0,28 0,29 0,30 0,31 032 ]33 },34 "total_stock": {35 "value": 0,36 "trend_percentage": 0,37 "trend_direction": "up",38 "chart_data": []39 },40 "picking_orders": {41 "value": 0,42 "trend_percentage": 0,43 "trend_direction": "up",44 "chart_data": []45 }46 },47 "charts": {48 "weekly_receiving": [49 0,50 0,51 0,52 0,53 0,54 0,55 056 ],57 "weekly_dispatching": [58 0,59 0,60 0,61 0,62 0,63 0,64 065 ],66 "completed_audits": [67 0,68 0,69 0,70 0,71 0,72 0,73 074 ],75 "capacity_utilization": {76 "used": 0,77 "available": 0,78 "percentage": 079 },80 "inventory_movement": {81 "dates": [82 "2025-12-08",83 "2025-12-09",84 "2025-12-10",85 "2025-12-11",86 "2025-12-12",87 "2025-12-13",88 "2025-12-14"89 ],90 "received": [91 0,92 0,93 0,94 0,95 0,96 0,97 098 ],99 "dispatched": [100 0,101 0,102 0,103 0,104 0,105 0,106 0107 ]108 }109 },110 "performance": {111 "items_received": {112 "current": 0,113 "target": 0,114 "percentage": 0115 },116 "items_dispatched": {117 "current": 0,118 "target": 0,119 "percentage": 0120 },121 "picking_orders": {122 "current": 0,123 "target": 0,124 "percentage": 0125 },126 "audits_completed": {127 "current": 0,128 "target": 0,129 "percentage": 0130 }131 },132 "summary": {133 "total_stock_items": 0,134 "total_stock_value": 0,135 "capacity_used_percentage": 0136 },137 "stock_levels": [138 {139 "item_name": "",140 "sku": "",141 "quantity": 0,142 "capacity_max": 0,143 "status": "In Stock",144 "status_color": "green"145 }146 ],147 "recent_activity": [148 {149 "id": "00000000-0000-0000-0000-000000000001",150 "type": "received",151 "message": "",152 "timestamp": "2025-12-14T00:00:00.000Z",153 "reference_id": ""154 }155 ]156 }157}1{2 "success": false,3 "message": "invalid_token",4 "data": null5}1{2 "success": false,3 "message": "method_not_allowed",4 "data": null5}1{2 "success": false,3 "message": "Internal Server Error",4 "data": null5}1type ResponseEnvelope<T> = { success: boolean; message: string; data: T | null };23type WarehouseDashboardEnvelope = ResponseEnvelope<WarehouseDashboardResponse>;45interface WarehouseDashboardResponse {6 kpis: {7 items_received: KPIItem;8 items_dispatched: KPIItem;9 total_stock: KPIItem;10 picking_orders: KPIItem;11 };12 charts: {13 weekly_receiving: number[];14 weekly_dispatching: number[];15 completed_audits: number[];16 capacity_utilization: { used: number; available: number; percentage: number };17 inventory_movement: { dates: string[]; received: number[]; dispatched: number[] };18 };19 performance: {20 items_received: { current: number; target: number; percentage: number };21 items_dispatched: { current: number; target: number; percentage: number };22 picking_orders: { current: number; target: number; percentage: number };23 audits_completed: { current: number; target: number; percentage: number };24 };25 summary: {26 total_stock_items: number;27 total_stock_value: number;28 capacity_used_percentage: number;29 };30 stock_levels: Array<{ item_name: string; sku: string; quantity: number; capacity_max: number; status: 'In Stock'|'Low Stock'|'Out of Stock'; status_color: 'green'|'yellow'|'red' }>;31 recent_activity: Array<{ id: string; type: 'received'|'dispatched'|'picking'|'audit'|'transfer'; message: string; timestamp: string; reference_id: string }>;32}3334type KPIItem = { value: number; trend_percentage: number; trend_direction: 'up'|'down'; chart_data: number[] };Restaurant Report
/report/restaurantSummary GET /report/restaurant Restaurant dashboard report. Storage model - One row per tenant in public.restaurant_report (refreshed nightly). - API reads the stored lifetime payload; there is no range query param. Auth - Header Authorization: Bearer {{access_token}} 200 Response (JSON) Body is wrapped: Error responses Same envelope: - { "success": false, "message": string, "data": null }
1curl --request GET "$ONDI_BASE_URL/report/restaurant" \2 --header "Authorization: Bearer {{access_token}}"Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "",4 "data": {5 "kpis": {6 "todays_orders": {7 "value": 0,8 "trend_percentage": 0,9 "trend_direction": "up",10 "chart_data": [11 0,12 0,13 0,14 0,15 0,16 0,17 018 ]19 },20 "todays_revenue": {21 "value": 0,22 "trend_percentage": 0,23 "trend_direction": "up",24 "chart_data": [25 0,26 0,27 0,28 0,29 0,30 0,31 032 ]33 },34 "active_tables": {35 "value": 0,36 "trend_percentage": 0,37 "trend_direction": "up",38 "chart_data": []39 },40 "avg_prep_time": {41 "value": 0,42 "trend_percentage": 0,43 "trend_direction": "up",44 "chart_data": []45 }46 },47 "charts": {48 "weekly_orders": [49 0,50 0,51 0,52 0,53 0,54 0,55 056 ],57 "weekly_revenue": [58 0,59 0,60 0,61 0,62 0,63 0,64 065 ],66 "avg_order_value": [67 0,68 0,69 0,70 0,71 0,72 0,73 074 ],75 "order_status_breakdown": {76 "completed": 0,77 "in_progress": 0,78 "pending": 0,79 "cancelled": 080 },81 "revenue_by_type": {82 "dates": [83 "2025-12-08",84 "2025-12-09",85 "2025-12-10",86 "2025-12-11",87 "2025-12-12",88 "2025-12-13",89 "2025-12-14"90 ],91 "dine_in": [92 0,93 0,94 0,95 0,96 0,97 0,98 099 ],100 "takeaway": [101 0,102 0,103 0,104 0,105 0,106 0,107 0108 ]109 }110 },111 "performance": {112 "total_revenue": {113 "current": 0,114 "target": 0,115 "percentage": 0116 },117 "total_orders": {118 "current": 0,119 "target": 0,120 "percentage": 0121 },122 "total_expenses": {123 "current": 0,124 "target": 0,125 "percentage": 0126 },127 "todays_summary": {128 "revenue": 0,129 "orders": 0,130 "aov": 0131 }132 },133 "popular_items": [134 {135 "item_id": "00000000-0000-0000-0000-000000000001",136 "name": "",137 "image_url": "",138 "category": "",139 "orders_count": 0,140 "revenue": 0,141 "status": "Available",142 "status_color": "green"143 }144 ],145 "recent_orders": [146 {147 "id": "00000000-0000-0000-0000-000000000010",148 "order_ref": "",149 "description": "",150 "status": "Pending",151 "timestamp": "2025-12-14T00:00:00.000Z"152 }153 ]154 }155}1{2 "success": false,3 "message": "invalid_token",4 "data": null5}1{2 "success": false,3 "message": "method_not_allowed",4 "data": null5}1{2 "success": false,3 "message": "Internal Server Error",4 "data": null5}1type ResponseEnvelope<T> = { success: boolean; message: string; data: T | null };23type RestaurantDashboardEnvelope = ResponseEnvelope<RestaurantDashboardResponse>;45interface RestaurantDashboardResponse {6 kpis: {7 todays_orders: KPIItem;8 todays_revenue: KPIItem;9 active_tables: KPIItem;10 avg_prep_time: KPIItem;11 };12 charts: {13 weekly_orders: number[];14 weekly_revenue: number[];15 avg_order_value: number[];16 order_status_breakdown: { completed: number; in_progress: number; pending: number; cancelled: number };17 revenue_by_type: { dates: string[]; dine_in: number[]; takeaway: number[] };18 };19 performance: {20 total_revenue: { current: number; target: number; percentage: number };21 total_orders: { current: number; target: number; percentage: number };22 total_expenses: { current: number; target: number; percentage: number };23 todays_summary: { revenue: number; orders: number; aov: number };24 };25 popular_items: Array<{ item_id: string; name: string; image_url: string; category: string; orders_count: number; revenue: number; status: 'Available'|'Low Stock'|'Out of Stock'; status_color: 'green'|'orange'|'red' }>;26 recent_orders: Array<{ id: string; order_ref: string; description: string; status: 'Completed'|'In Progress'|'Preparing'|'Pending'|'Cancelled'; timestamp: string }>;27}2829type KPIItem = { value: number; trend_percentage: number; trend_direction: 'up'|'down'; chart_data: number[] };Express Shipping Report
/report/expressSummary GET /report/express Express (shipping) dashboard report. Storage model - One row per tenant in public.express_report (refreshed nightly). - API reads the stored lifetime payload; there is no range query param. Auth - Header Authorization: Bearer {{access_token}} 200 Response (JSON) Body is wrapped: Error responses Same envelope: - { "success": false, "message": string, "data": null }
1curl --request GET "$ONDI_BASE_URL/report/express" \2 --header "Authorization: Bearer {{access_token}}"Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "",4 "data": {5 "kpis": {6 "total_packages": {7 "value": 0,8 "trend_percentage": 0,9 "trend_direction": "up",10 "chart_data": [11 0,12 0,13 0,14 0,15 0,16 0,17 018 ]19 },20 "delivered": {21 "value": 0,22 "trend_percentage": 0,23 "trend_direction": "up",24 "chart_data": []25 },26 "in_transit": {27 "value": 0,28 "trend_percentage": 0,29 "trend_direction": "up",30 "chart_data": []31 },32 "pending_claim": {33 "value": 0,34 "trend_percentage": 0,35 "trend_direction": "up",36 "chart_data": []37 }38 },39 "charts": {40 "weekly_volume": [41 0,42 0,43 0,44 0,45 0,46 0,47 048 ],49 "total_weight_kg": [50 0,51 0,52 0,53 0,54 0,55 0,56 057 ],58 "avg_delivery_time": [59 0,60 0,61 0,62 0,63 0,64 0,65 066 ],67 "status_distribution": {68 "delivered": 0,69 "in_transit": 0,70 "processing": 0,71 "received": 0,72 "pending_claim": 073 },74 "shipping_volume_bar": {75 "dates": [76 "2025-12-08",77 "2025-12-09",78 "2025-12-10",79 "2025-12-11",80 "2025-12-12",81 "2025-12-13",82 "2025-12-14"83 ],84 "received": [85 0,86 0,87 0,88 0,89 0,90 0,91 092 ],93 "delivered": [94 0,95 0,96 0,97 0,98 0,99 0,100 0101 ]102 }103 },104 "revenue": {105 "domestic_fees": 0,106 "international_fees": 0,107 "delivery_fees": 0,108 "total_revenue": 0109 },110 "metrics": {111 "delivered": {112 "value": 0,113 "percentage": 0114 },115 "in_transit": {116 "value": 0,117 "percentage": 0118 },119 "processing": {120 "value": 0,121 "percentage": 0122 },123 "pending_claim": {124 "value": 0,125 "percentage": 0126 }127 },128 "top_stores": [129 {130 "store_name": "",131 "package_count": 0132 }133 ],134 "recent_packages": [135 {136 "tracking_number": "",137 "store_name": "",138 "customer_name": "",139 "weight_kg": 0,140 "status": "Received",141 "status_color": "orange",142 "payment_status": "Pending",143 "created_at": "2025-12-14T00:00:00.000Z"144 }145 ],146 "recent_activity": [147 {148 "id": "00000000-0000-0000-0000-000000000001",149 "message": "",150 "type": "received",151 "timestamp": "2025-12-14T00:00:00.000Z"152 }153 ]154 }155}1{2 "success": false,3 "message": "invalid_token",4 "data": null5}1{2 "success": false,3 "message": "method_not_allowed",4 "data": null5}1{2 "success": false,3 "message": "Internal Server Error",4 "data": null5}1type ResponseEnvelope<T> = { success: boolean; message: string; data: T | null };23type ExpressDashboardEnvelope = ResponseEnvelope<ExpressDashboardResponse>;45interface ExpressDashboardResponse {6 kpis: {7 total_packages: KPIItem;8 delivered: KPIItem;9 in_transit: KPIItem;10 pending_claim: KPIItem;11 };12 charts: {13 weekly_volume: number[];14 total_weight_kg: number[];15 avg_delivery_time: number[];16 status_distribution: { delivered: number; in_transit: number; processing: number; received: number; pending_claim: number };17 shipping_volume_bar: { dates: string[]; received: number[]; delivered: number[] };18 };19 revenue: { domestic_fees: number; international_fees: number; delivery_fees: number; total_revenue: number };20 metrics: {21 delivered: { value: number; percentage: number };22 in_transit: { value: number; percentage: number };23 processing: { value: number; percentage: number };24 pending_claim: { value: number; percentage: number };25 };26 top_stores: Array<{ store_name: string; package_count: number }>;27 recent_packages: Array<{ tracking_number: string; store_name: string; customer_name: string; weight_kg: number; status: 'Delivered'|'In transit'|'Processing'|'Received'|'Claimed'; status_color: 'green'|'red'|'blue'|'orange'|'purple'; payment_status: 'Paid'|'Pending'|'Unpaid'; created_at: string }>;28 recent_activity: Array<{ id: string; message: string; type: 'delivered'|'in_transit'|'processing'|'received'|'claimed'; timestamp: string }>;29}3031type KPIItem = { value: number; trend_percentage: number; trend_direction: 'up'|'down'; chart_data: number[] };Tenant App Report (Common)
/report/appSummary GET /report/app Tenant application (common) report that returns the exact dashboard widget payload the portal uses. Storage model - One row per tenant in public.tenant_app_report (refreshed nightly). Auth - Header Authorization: Bearer {{access_token}} 200 Response (JSON) Body is wrapped: Error responses Same envelope: - { "success": false, "message": string, "data": null }
1curl --request GET "$ONDI_BASE_URL/report/app" \2 --header "Authorization: Bearer {{access_token}}"Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "",4 "data": {5 "delivery_overview": {6 "total_deliveries_period": 0,7 "completed_deliveries_period": 0,8 "pending_deliveries_current": 0,9 "in_progress_deliveries_current": 0,10 "failed_deliveries_period": 0,11 "delivery_success_rate_period": 0,12 "avg_delivery_time_minutes_period": 0,13 "avg_pickup_to_delivery_time_minutes_period": 014 },15 "cod_summary": {16 "total_cod_collected_period": 0,17 "total_cod_remitted_period": 0,18 "total_cod_outstanding_current": 0,19 "total_cod_settled_by_wallet_period": 020 },21 "warehouse_overview": {22 "total_items_received_period": 0,23 "total_items_dispatched_period": 0,24 "current_total_stock_items": 0,25 "current_total_stock_value": 0,26 "overall_capacity_utilization_percent_current": 0,27 "total_picking_orders_completed_period": 0,28 "total_batches_dispatched_period": 029 },30 "warehouse_activity_by_warehouse": {31 "data": [32 {33 "warehouse_id": "00000000-0000-0000-0000-000000000001",34 "warehouse_name": "",35 "items_received_period": 0,36 "items_dispatched_period": 0,37 "current_stock_items": 0,38 "capacity_utilization_percent": 039 }40 ],41 "columns": [42 {43 "field": "warehouse_name",44 "label": "Warehouse",45 "description": "Warehouse name",46 "type": "string"47 },48 {49 "field": "items_received_period",50 "label": "Received",51 "description": "Items received in period",52 "type": "number"53 },54 {55 "field": "items_dispatched_period",56 "label": "Dispatched",57 "description": "Items dispatched in period",58 "type": "number"59 },60 {61 "field": "current_stock_items",62 "label": "Stock",63 "description": "Current stock items",64 "type": "number"65 },66 {67 "field": "capacity_utilization_percent",68 "label": "Capacity %",69 "description": "Capacity utilization percent",70 "type": "number"71 }72 ]73 },74 "warehouse_stock_by_category": {75 "data": [76 {77 "category_id": "00000000-0000-0000-0000-000000000010",78 "category_name": {79 "en": ""80 },81 "stock_items": 082 }83 ],84 "columns": [85 {86 "field": "category_name",87 "label": "Category",88 "description": "Inventory category",89 "type": "jsonb"90 },91 {92 "field": "stock_items",93 "label": "Stock Items",94 "description": "Stock items in category",95 "type": "number"96 }97 ]98 }99 }100}1{2 "success": false,3 "message": "invalid_token",4 "data": null5}1{2 "success": false,3 "message": "report_not_ready",4 "data": null5}1{2 "success": false,3 "message": "method_not_allowed",4 "data": null5}1{2 "success": false,3 "message": "Internal Server Error",4 "data": null5}1type ResponseEnvelope<T> = { success: boolean; message: string; data: T | null };23type TenantAppDashboardEnvelope = ResponseEnvelope<TenantAppDashboardResponse>;45interface TenantAppDashboardResponse {6 delivery_overview: {7 total_deliveries_period: number;8 completed_deliveries_period: number;9 pending_deliveries_current: number;10 in_progress_deliveries_current: number;11 failed_deliveries_period: number;12 delivery_success_rate_period: number;13 avg_delivery_time_minutes_period: number;14 avg_pickup_to_delivery_time_minutes_period: number;15 };16 cod_summary: {17 total_cod_collected_period: number;18 total_cod_remitted_period: number;19 total_cod_outstanding_current: number;20 total_cod_settled_by_wallet_period: number;21 };22 warehouse_overview: {23 total_items_received_period: number;24 total_items_dispatched_period: number;25 current_total_stock_items: number;26 current_total_stock_value: number;27 overall_capacity_utilization_percent_current: number;28 total_picking_orders_completed_period: number;29 total_batches_dispatched_period: number;30 };31 warehouse_activity_by_warehouse: {32 data: Array<{33 warehouse_id: string;34 warehouse_name: string;35 items_received_period: number;36 items_dispatched_period: number;37 current_stock_items: number;38 capacity_utilization_percent: number;39 }>;40 columns: Array<{ field: string; label: string; description: string; type: string }>;41 };42 warehouse_stock_by_category: {43 data: Array<{ category_id: string; category_name: unknown; stock_items: number }>;44 columns: Array<{ field: string; label: string; description: string; type: string }>;45 };46}Trigger Daily Aggregation (Cron)
/reportSummary POST /report Triggers the daily aggregation job. Auth - Header Authorization: Bearer {{access_token}} Request body (JSON) - Optional: If omitted/unparseable, server defaults to yesterday (UTC via toISOString().split('T')[0]). 200 Response (JSON) Wrapped envelope: Error responses Same envelope: - { "success": false, "message": string, "data": null }
1curl --request POST "$ONDI_BASE_URL/report" \2 --header "Authorization: Bearer {{access_token}}" \3 --header "Content-Type: application/json" \4 --header "Content-Type: application/json" \5 --data '{6 "date": "2025-12-12"7}'1{2 "date": "2025-12-12"3}Request body fields
dateExampleExample field from the request body.
Headers
AuthorizationOptionalBearer {{access_token}}
Content-TypeOptionalapplication/json
Responses
1{2 "success": true,3 "message": "Lifetime report refresh completed",4 "data": {5 "duration_ms": "12.34",6 "tenants_ok": 0,7 "tenants_failed": 0,8 "failed": []9 }10}1{2 "success": false,3 "message": "RPC Execution",4 "data": null5}1{2 "success": false,3 "message": "Unknown",4 "data": null5}1{2 "success": false,3 "message": "invalid_token",4 "data": null5}1type ResponseEnvelope<T> = { success: boolean; message: string; data: T | null };23type CronTriggerData = {4 duration_ms: string;5 tenants_ok: number;6 tenants_failed: number;7 failed: Array<{ tenant_id: string; ok: boolean; error?: string }>;8};910type CronTriggerEnvelope = ResponseEnvelope<CronTriggerData>;Legacy - Delivery Overview
/report/tenant/delivery/overviewSummary GET /report/tenant/delivery/overview Legacy route. Router maps any /report/tenant/delivery/* to module delivery. Effective route - GET /report/delivery Auth - Header Authorization: Bearer {{access_token}} 200 Response (JSON) Same as Delivery Report but wrapped envelope: - { success: true, message: "", data: DeliveryDashboardResponse } Error responses Same envelope: - { success: false, message: string, data: null }
1curl --request GET "$ONDI_BASE_URL/report/tenant/delivery/overview" \2 --header "Authorization: Bearer {{access_token}}"Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "",4 "data": {5 "kpis": {6 "total_deliveries": {7 "value": 0,8 "trend_percentage": 0,9 "trend_direction": "up",10 "chart_data": [11 0,12 0,13 0,14 0,15 0,16 0,17 018 ]19 },20 "completed": {21 "value": 0,22 "trend_percentage": 0,23 "trend_direction": "up",24 "chart_data": [25 0,26 0,27 0,28 0,29 0,30 0,31 032 ]33 },34 "in_progress": {35 "value": 0,36 "trend_percentage": 0,37 "trend_direction": "up",38 "chart_data": []39 },40 "failed": {41 "value": 0,42 "trend_percentage": 0,43 "trend_direction": "up",44 "chart_data": [45 0,46 0,47 0,48 0,49 0,50 0,51 052 ]53 }54 },55 "charts": {56 "status_breakdown": {57 "completed": 0,58 "in_progress": 0,59 "pending": 0,60 "failed": 061 },62 "weekly_performance": {63 "dates": [64 "2025-12-08",65 "2025-12-09",66 "2025-12-10",67 "2025-12-11",68 "2025-12-12",69 "2025-12-13",70 "2025-12-14"71 ],72 "completed": [73 0,74 0,75 0,76 0,77 0,78 0,79 080 ],81 "failed": [82 0,83 0,84 0,85 0,86 0,87 0,88 089 ]90 },91 "metrics_trends": {92 "success_rate": [93 0,94 0,95 0,96 0,97 0,98 0,99 0100 ],101 "avg_delivery_time": [102 0,103 0,104 0,105 0,106 0,107 0,108 0109 ],110 "active_drivers": [111 0,112 0,113 0,114 0,115 0,116 0,117 0118 ]119 }120 },121 "performance": {122 "success_rate": {123 "value": 0,124 "percentage": 0125 },126 "on_time_delivery": {127 "value": 0,128 "percentage": 0129 },130 "customer_satisfaction": {131 "value": 0,132 "percentage": 0133 },134 "first_attempt_success": {135 "value": 0,136 "percentage": 0137 }138 },139 "cod": {140 "collected": 0,141 "remitted": 0,142 "outstanding": 0,143 "wallet_settled": 0144 },145 "top_drivers": [146 {147 "driver_id": "00000000-0000-0000-0000-000000000001",148 "name": "",149 "avatar_url": "",150 "completed_jobs": 0,151 "failed_jobs": 0,152 "avg_time_minutes": 0153 }154 ],155 "zone_stats": [156 {157 "zone_id": "11111111-1111-1111-1111-111111111111",158 "zone_code": "ZN-001",159 "zone_name": "Central Zone",160 "total_deliveries": 0,161 "total_inbound_deliveries": 0,162 "total_outbound_deliveries": 0,163 "total_completed_deliveries": 0164 }165 ],166 "recent_activity": [167 {168 "id": "00000000-0000-0000-0000-000000000100",169 "order_ref": "",170 "type": "pending",171 "message": "",172 "timestamp": "2025-12-14T00:00:00.000Z"173 }174 ]175 }176}Driver Performance
/report/tenant/delivery/driver-performance?tenant_id={{tenant_id}}&language=enSummary GET /report/tenant/delivery/driver-performance Returns driver performance metrics computed by the nightly report scheduler. Data is read from the driver_performance_metrics table (populated during cron). Auth - Header Authorization: Bearer {{access_token}} Response fields | Field | Type | Description | |-------|------|-------------| | driver_id | UUID | Driver identifier | | driver_name | string | Driver's full name | | total_deliveries | integer | Total terminal-status assignments (completed + failed) | | successful_deliveries | integer | Assignments with status completed/delivered/closed | | failed_deliveries | integer | Assignments with status failed/cancelled/rejected/returned | | on_time_deliveries | integer | Completed before scheduled_delivery_time | | late_deliveries | integer | Completed after scheduled_delivery_time | | success_rate | decimal | (successful / total) × 100 | | on_time_rate | decimal | (on_time / (on_time + late)) × 100 | | average_delivery_time_minutes | integer | Mean minutes from pickup to drop-off | | total_distance_km | decimal | Sum of distance_traveled across assignments | | km_per_delivery | decimal | total_distance / successful_deliveries | | total_delivery_value | decimal | Sum of (cod_amount + delivery_fee) for completed | KPI Cards (aggregate across all drivers) - Total Deliveries — sum of total_deliveries - Overall Success Rate — sum(successful) / sum(total) × 100 - Overall On-Time Rate — sum(on_time) / sum(on_time + late) × 100 - Avg Delivery Time — weighted average of average_delivery_time_minutes - Total Revenue Handled — sum of total_delivery_value - Active Drivers — count of drivers with total_deliveries > 0 Column Filters (planned) All numeric columns support {min, max} range filtering: - total_deliveries, success_rate, on_time_rate, average_delivery_time, km_per_delivery, total_delivery_value Error responses - 400: { "success": false, "message": "tenantId missing in request context", "data": null } - 500: { "success": false, "message": "query_failed", "data": null }
1curl --request GET "$ONDI_BASE_URL/report/tenant/delivery/driver-performance?tenant_id={{tenant_id}}&language=en" \2 --header "Authorization: Bearer {{access_token}}"Query parameters
tenant_idOptional{{tenant_id}}
languageOptionalen
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "",4 "data": [5 {6 "driver_id": "a1b2c3d4-0000-0000-0000-000000000001",7 "driver_name": "Ahmed Ali",8 "total_deliveries": 120,9 "successful_deliveries": 108,10 "failed_deliveries": 12,11 "on_time_deliveries": 95,12 "late_deliveries": 13,13 "success_rate": 90,14 "on_time_rate": 87.96,15 "average_delivery_time_minutes": 28,16 "total_distance_km": 840.5,17 "km_per_delivery": 7.78,18 "total_delivery_value": 4500019 },20 {21 "driver_id": "a1b2c3d4-0000-0000-0000-000000000002",22 "driver_name": "Mohammed Saeed",23 "total_deliveries": 95,24 "successful_deliveries": 90,25 "failed_deliveries": 5,26 "on_time_deliveries": 82,27 "late_deliveries": 8,28 "success_rate": 94.74,29 "on_time_rate": 91.11,30 "average_delivery_time_minutes": 24,31 "total_distance_km": 620.3,32 "km_per_delivery": 6.89,33 "total_delivery_value": 3850034 }35 ]36}1{2 "success": true,3 "message": "",4 "data": []5}1{2 "success": false,3 "message": "tenantId missing in request context",4 "data": null5}1{2 "success": false,3 "message": "query_failed",4 "data": null5}