Skip to main content

Report

This section contains 1 subgroups.

Delivery Report​

Reporting, Audit & Webhooks / Report
GET/report/delivery

Summary

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.

  • Header Authorization: Bearer {{access_token}}

  • All auth failures come from middleware and return { "success": false, "message": string, "data": null } with 401/403.

Failure aggregation

  • Delivery failure KPIs and series include the distinct delivery statuses failed, cancelled, and returned. Raw delivery rows and exports keep those statuses separate; an RTS-failed hybrid outbound leg remains failed and is not rewritten as cancelled.

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 }

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Staging
Request
curl
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/report/delivery" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"

Response examples

200OK
Response body
json
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}

Storefront Report​

Reporting, Audit & Webhooks / Report
GET/report/storefront

Summary

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.

  • Header Authorization: Bearer {{access_token}}

Same envelope

  • { "success": false, "message": string, "data": null }

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Staging
Request
curl
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/report/storefront" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"

Response examples

200OK
Response body
json
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}

Warehouse Report​

Reporting, Audit & Webhooks / Report
GET/report/warehouse

Summary

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.

  • Header Authorization: Bearer {{access_token}}

Same envelope

  • { "success": false, "message": string, "data": null }

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Staging
Request
curl
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/report/warehouse" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"

Response examples

200OK
Response body
json
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}

Restaurant Report​

Reporting, Audit & Webhooks / Report
GET/report/restaurant

Summary

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.

  • Header Authorization: Bearer {{access_token}}

Same envelope

  • { "success": false, "message": string, "data": null }

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Staging
Request
curl
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/report/restaurant" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"

Response examples

200OK
Response body
json
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}

Express Shipping Report​

Reporting, Audit & Webhooks / Report
GET/report/express

Summary

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.

  • Header Authorization: Bearer {{access_token}}

Same envelope

  • { "success": false, "message": string, "data": null }

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Staging
Request
curl
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/report/express" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"

Response examples

200OK
Response body
json
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}

Tenant App Report (Common)​

Reporting, Audit & Webhooks / Report
GET/report/app

Summary

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).

  • Header Authorization: Bearer {{access_token}}

Same envelope

  • { "success": false, "message": string, "data": null }

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Staging
Request
curl
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/report/app" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"

Response examples

200OK
Response body
json
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}

Trigger Daily Aggregation (Cron)​

Reporting, Audit & Webhooks / Report
POST/report

Summary

POST /report

Refreshes stored lifetime-to-date reports for each tenant across delivery, storefront, warehouse, restaurant, express, and tenant-app modules.

Internal backend/cron only. Send apikey: {{supabase_secret_key}} with the default managed Supabase secret key (SUPABASE_SECRET_KEYS.default). Never put this value in a frontend or mobile application. Missing, invalid, publishable, legacy anon, and legacy service-role bearer credentials return HTTP 401 before work is dispatched. Authorization: Bearer ... alone is not accepted. Frontend handoff: none; application clients must not call this internal endpoint. The unauthorized message is localized using the request language.

Only literal recalculate_all: true expands the driver-performance recalculation and top-driver range to start at 2020-01-01. Omitted/false/unparseable bodies use the current UTC month for that range. Lifetime delivery totals, recent chart windows, and other module reports still refresh. date is not read by this handler.

HTTP 200 may report success: false when one or more tenants fail; inspect tenants_failed and failed[] in addition to HTTP status.

Error responses

  • HTTP 401: { "success": false, "message": "Unauthorized" } (localized).

  • Scheduler failures use the same response envelope:

  • { "success": false, "message": string, "data": null }

Headers

ParameterTypeDescription
Content-Typestring

Example: application/json

apikeystring

Default managed Supabase secret key; backend only.

Example: {{supabase_secret_key}}

Body parameters

ParameterTypeDescription
recalculate_allboolean—
Staging
Request
curl
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/report" \2  --header "Content-Type: application/json" \3  --header "apikey: ${SUPABASE_SECRET_KEY}" \4  --data-raw '{5  "recalculate_all": false6}'

Internal backend endpoint. Run from a trusted server; keep backend secret keys out of the browser.

Response examples

200OK
Response body
json
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}

Legacy - Delivery Overview​

Reporting, Audit & Webhooks / Report
GET/report/tenant/delivery/overview

Summary

GET /report/tenant/delivery/overview

Legacy route. Router maps any /report/tenant/delivery/* to module delivery.

Effective route

  • GET /report/delivery

  • Header Authorization: Bearer {{access_token}}

Same as Delivery Report but wrapped envelope:

  • { success: true, message: "", data: DeliveryDashboardResponse }

Same envelope

  • { success: false, message: string, data: null }

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Staging
Request
curl
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/report/tenant/delivery/overview" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"

Response examples

200OK
Response body
json
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​

Reporting, Audit & Webhooks / Report
GET/report/tenant/delivery/driver-performance

Summary

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).

  • Header Authorization: Bearer {{access_token}}

Response fields

FieldTypeDescription
driver_idUUIDDriver identifier
driver_namestringDriver's full name
total_deliveriesintegerTotal terminal-status assignments (completed + failed)
successful_deliveriesintegerAssignments with status completed/delivered/closed
failed_deliveriesintegerAssignments with status failed/cancelled/rejected/returned
on_time_deliveriesintegerCompleted before scheduled_delivery_time
late_deliveriesintegerCompleted after scheduled_delivery_time
success_ratedecimal(successful / total) × 100
on_time_ratedecimal(on_time / (on_time + late)) × 100
average_delivery_time_minutesintegerMean minutes from pickup to drop-off
total_distance_kmdecimalSum of distance_traveled across assignments
km_per_deliverydecimaltotal_distance / successful_deliveries
total_delivery_valuedecimalSum 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 }

Query parameters

ParameterTypeDescription
tenant_idstring

Example: {{tenant_id}}

languagestring

Example: en

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Staging
Request
curl
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/report/tenant/delivery/driver-performance?tenant_id=${TENANT_ID}&language=en" \2  --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"

Response examples

200OK
Response body
json
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}