Routes
16 API calls in this section.
List Routes
/delivery/routes?page=1&limit=20&status=&driver_id=&search=&include_inactive=falseList active routes with optional filters. Excludes inactive routes by default.
1curl --request GET "$ONDI_BASE_URL/delivery/routes?page=1&limit=20&status=&driver_id=&search=&include_inactive=false" \2 --header "Authorization: Bearer {{access_token}}"Query parameters
pageOptional1
Page number
limitOptional20
Items per page (max 100)
statusOptionalFilter: unassigned | assigned
driver_idOptionalFilter by driver UUID
searchOptionalPartial match on route_name
include_inactiveOptionalfalse
Include soft-deleted routes
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Routes retrieved successfully",4 "data": {5 "routes": [6 {7 "id": "route-uuid",8 "route_name": "Warehouse A → Zone 5",9 "origin_type": "warehouse",10 "origin_warehouse_id": "wh-uuid",11 "destination_type": "location",12 "destination_location": {13 "lat": 33.5,14 "lng": 44.2,15 "address": "Zone 5 Hub"16 },17 "status": "assigned",18 "is_active": true,19 "schedule_time": "08:00:00",20 "schedule_days": [21 1,22 2,23 3,24 4,25 526 ],27 "notes": null,28 "created_at": "2026-04-14T10:00:00Z",29 "driver": {30 "id": "driver-uuid",31 "full_name": "Ahmed Hassan",32 "avatar_url": "https://..."33 },34 "active_orders_count": 835 }36 ],37 "total": 1,38 "page": 1,39 "limit": 2040 }41}Create Route
/delivery/routesCreate a new route. - origin_type / destination_type: warehouse | location - If type is warehouse: provide *_warehouse_id - If type is location: provide *_location as {lat, lng, address} - driver_id optional — if provided, route status becomes assigned - schedule_time, schedule_days, start_date are informational only (no backend scheduling)
1curl --request POST "$ONDI_BASE_URL/delivery/routes" \2 --header "Authorization: Bearer {{access_token}}" \3 --header "Content-Type: application/json" \4 --header "Content-Type: application/json" \5 --data '{6 "route_name": "Warehouse A → Zone 5",7 "origin_type": "warehouse",8 "origin_warehouse_id": "wh-uuid",9 "destination_type": "location",10 "destination_location": {11 "lat": 33.5,12 "lng": 44.2,13 "address": "Zone 5 Hub"14 },15 "driver_id": "driver-uuid",16 "schedule_time": "08:00:00",17 "schedule_days": [18 1,19 2,20 3,21 4,22 523 ],24 "start_date": "2026-04-15",25 "notes": "Morning route"26}'1{2 "route_name": "Warehouse A → Zone 5",3 "origin_type": "warehouse",4 "origin_warehouse_id": "wh-uuid",5 "destination_type": "location",6 "destination_location": {7 "lat": 33.5,8 "lng": 44.2,9 "address": "Zone 5 Hub"10 },11 "driver_id": "driver-uuid",12 "schedule_time": "08:00:00",13 "schedule_days": [14 1,15 2,16 3,17 4,18 519 ],20 "start_date": "2026-04-15",21 "notes": "Morning route"22}Request body fields
route_nameExampleExample field from the request body.
origin_typeExampleExample field from the request body.
origin_warehouse_idExampleExample field from the request body.
destination_typeExampleExample field from the request body.
destination_locationExampleExample field from the request body.
destination_location.latExampleExample field from the request body.
destination_location.lngExampleExample field from the request body.
destination_location.addressExampleExample field from the request body.
driver_idExampleExample field from the request body.
schedule_timeExampleExample field from the request body.
schedule_daysExampleExample field from the request body.
start_dateExampleExample field from the request body.
notesExampleExample field from the request body.
Headers
AuthorizationOptionalBearer {{access_token}}
Content-TypeOptionalapplication/json
Responses
1{2 "success": true,3 "message": "Route created successfully",4 "data": {5 "id": "route-uuid",6 "route_name": "Warehouse A → Zone 5",7 "status": "assigned",8 "is_active": true,9 "created_at": "2026-04-14T10:00:00Z"10 }11}1{2 "success": false,3 "message": "Route name already exists",4 "data": null5}Get Route
/delivery/routes/:routeIdGet route detail including driver info, warehouse names, and current open/started session.
1curl --request GET "$ONDI_BASE_URL/delivery/routes/:routeId" \2 --header "Authorization: Bearer {{access_token}}"Path parameters
routeIdRequiredroute-uuid
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Route retrieved successfully",4 "data": {5 "id": "route-uuid",6 "route_name": "Warehouse A → Zone 5",7 "origin_type": "warehouse",8 "origin_warehouse": {9 "id": "wh-uuid",10 "name": "Warehouse A",11 "code": "WH-001"12 },13 "destination_type": "location",14 "destination_location": {15 "lat": 33.5,16 "lng": 44.2,17 "address": "Zone 5 Hub"18 },19 "driver": {20 "id": "driver-uuid",21 "full_name": "Ahmed Hassan",22 "avatar_url": "https://..."23 },24 "current_session": {25 "id": "session-uuid",26 "session_number": 3,27 "status": "started",28 "started_at": "2026-04-14T08:05:00Z"29 },30 "session_counts": {31 "active": 1,32 "completed": 1,33 "total": 334 },35 "status": "assigned",36 "is_active": true37 }38}Update Route
/delivery/routes/:routeIdPartial update. All fields optional. If driver_id changes, the request is rejected whenever the route has any non-terminal session (open, started, picked_up, or in_transit).
1curl --request PUT "$ONDI_BASE_URL/delivery/routes/:routeId" \2 --header "Authorization: Bearer {{access_token}}" \3 --header "Content-Type: application/json" \4 --header "Content-Type: application/json" \5 --data '{6 "route_name": "Warehouse A → Zone 6",7 "notes": "Updated route",8 "schedule_days": [9 1,10 3,11 512 ]13}'1{2 "route_name": "Warehouse A → Zone 6",3 "notes": "Updated route",4 "schedule_days": [5 1,6 3,7 58 ]9}Path parameters
routeIdRequiredroute-uuid
Request body fields
route_nameExampleExample field from the request body.
notesExampleExample field from the request body.
schedule_daysExampleExample field from the request body.
Headers
AuthorizationOptionalBearer {{access_token}}
Content-TypeOptionalapplication/json
Responses
1{2 "success": true,3 "message": "Route updated successfully",4 "data": {5 "id": "route-uuid",6 "route_name": "Warehouse A → Zone 6",7 "updated_at": "2026-04-14T11:00:00Z"8 }9}Delete Route (Deactivate)
/delivery/routes/:routeIdSoft-deactivate a route (sets is_active=false). Rejected if the route has open/started sessions with active deliveries.
1curl --request DELETE "$ONDI_BASE_URL/delivery/routes/:routeId" \2 --header "Authorization: Bearer {{access_token}}"Path parameters
routeIdRequiredroute-uuid
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Route deactivated successfully",4 "data": null5}1{2 "success": false,3 "message": "Cannot deactivate route with active sessions that have deliveries",4 "data": null5}Assign Driver
/delivery/routes/:routeId/assign-driverAssign a driver to the route. Validates: - Driver is active with a primary vehicle - Driver has zone access for route origin and destination - Route has no non-terminal session (open, started, picked_up, in_transit) If the route has any active session, driver switching is rejected instead of transferring ownership mid-session.
1curl --request POST "$ONDI_BASE_URL/delivery/routes/:routeId/assign-driver" \2 --header "Authorization: Bearer {{access_token}}" \3 --header "Content-Type: application/json" \4 --header "Content-Type: application/json" \5 --data '{6 "driver_id": "driver-uuid"7}'1{2 "driver_id": "driver-uuid"3}Path parameters
routeIdRequiredroute-uuid
Request body fields
driver_idExampleExample field from the request body.
Headers
AuthorizationOptionalBearer {{access_token}}
Content-TypeOptionalapplication/json
Responses
1{2 "success": true,3 "message": "Route driver assigned successfully",4 "data": {5 "id": "route-uuid",6 "driver_id": "driver-uuid",7 "status": "assigned"8 }9}1{2 "success": false,3 "message": "Driver not allowed in route origin zone",4 "data": null5}Unassign Driver
/delivery/routes/:routeId/unassign-driverRemove the assigned driver from the route. Rejected if the route has any non-terminal session (open, started, picked_up, in_transit).
1curl --request POST "$ONDI_BASE_URL/delivery/routes/:routeId/unassign-driver" \2 --header "Authorization: Bearer {{access_token}}"Path parameters
routeIdRequiredroute-uuid
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Route driver unassigned successfully",4 "data": {5 "id": "route-uuid",6 "driver_id": null,7 "status": "unassigned"8 }9}Assign Deliveries to Route
/delivery/routes/:routeId/assign-deliveriesAssign deliveries to a route. Validates each delivery: - carrier_type must be internal - status must be pending - must not be in an active waybill Checks driver capacity before assigning. Creates a delivery_assignment for each delivery. Resolves existing open/started session or creates a new one. Driver is notified via BULK_DELIVERY_ASSIGNED notification.
1curl --request POST "$ONDI_BASE_URL/delivery/routes/:routeId/assign-deliveries" \2 --header "Authorization: Bearer {{access_token}}" \3 --header "Content-Type: application/json" \4 --header "Content-Type: application/json" \5 --data '{6 "delivery_ids": [7 "delivery-uuid-1",8 "delivery-uuid-2",9 "delivery-uuid-3"10 ]11}'1{2 "delivery_ids": [3 "delivery-uuid-1",4 "delivery-uuid-2",5 "delivery-uuid-3"6 ]7}Path parameters
routeIdRequiredroute-uuid
Request body fields
delivery_idsExampleExample field from the request body.
Headers
AuthorizationOptionalBearer {{access_token}}
Content-TypeOptionalapplication/json
Responses
1{2 "success": true,3 "message": "Deliveries assigned to route successfully",4 "data": {5 "session": {6 "id": "session-uuid",7 "session_number": 3,8 "status": "open"9 },10 "assigned_count": 311 }12}1{2 "success": false,3 "message": "Route must have an assigned driver before adding deliveries",4 "data": null5}1{2 "success": false,3 "message": "Driver does not have enough capacity for these deliveries",4 "data": null5}Remove Deliveries from Route
/delivery/routes/:routeId/remove-deliveriesRemove deliveries from the route session. Only allowed if session is open or started. For each delivery: deletes the delivery_assignment record and resets delivery status to pending. Decrements driver capacity.
1curl --request POST "$ONDI_BASE_URL/delivery/routes/:routeId/remove-deliveries" \2 --header "Authorization: Bearer {{access_token}}" \3 --header "Content-Type: application/json" \4 --header "Content-Type: application/json" \5 --data '{6 "delivery_ids": [7 "delivery-uuid-1"8 ]9}'1{2 "delivery_ids": [3 "delivery-uuid-1"4 ]5}Path parameters
routeIdRequiredroute-uuid
Request body fields
delivery_idsExampleExample field from the request body.
Headers
AuthorizationOptionalBearer {{access_token}}
Content-TypeOptionalapplication/json
Responses
1{2 "success": true,3 "message": "Deliveries removed from route successfully",4 "data": {5 "removed_count": 16 }7}1{2 "success": false,3 "message": "Cannot remove deliveries from a session that is picked_up or beyond",4 "data": null5}List Sessions for Route
/delivery/routes/:routeId/sessions?status=&page=1&limit=20Dispatcher view — paginated sessions for a route ordered newest first. Response also includes statuses matrix for the route session tabs/counts, unaffected by the active status filter.
1curl --request GET "$ONDI_BASE_URL/delivery/routes/:routeId/sessions?status=&page=1&limit=20" \2 --header "Authorization: Bearer {{access_token}}"Path parameters
routeIdRequiredroute-uuid
Query parameters
statusOptionalFilter: open | started | picked_up | completed | cancelled
pageOptional1
Page number (default: 1)
limitOptional20
Items per page (default: 20, max: 100)
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Route sessions retrieved successfully",4 "data": {5 "sessions": [6 {7 "id": "session-uuid-2",8 "session_number": 2,9 "status": "open",10 "orders_count": 3,11 "started_at": null,12 "created_at": "2026-04-14T08:00:00Z"13 },14 {15 "id": "session-uuid",16 "session_number": 1,17 "status": "completed",18 "orders_count": 5,19 "started_at": "2026-04-13T08:00:00Z",20 "picked_up_at": "2026-04-13T08:15:00Z",21 "completed_at": "2026-04-13T14:00:00Z",22 "created_at": "2026-04-13T07:55:00Z"23 }24 ],25 "statuses": [26 {27 "status": "open",28 "label": "Open",29 "count": 130 },31 {32 "status": "started",33 "label": "Started",34 "count": 035 },36 {37 "status": "picked_up",38 "label": "Picked Up",39 "count": 040 },41 {42 "status": "completed",43 "label": "Completed",44 "count": 145 },46 {47 "status": "cancelled",48 "label": "Cancelled",49 "count": 050 }51 ],52 "total": 2,53 "page": 1,54 "limit": 2055 }56}List Driver Route Sessions
/delivery/route-sessions?status=&page=1&limit=20Driver-facing. Returns paginated sessions assigned to the authenticated driver (resolved from JWT context — no driver_id query param accepted). Ordered newest first, includes route origin/destination for each session, and returns a statuses matrix for the driver session tabs/counts unaffected by the active status filter.
1curl --request GET "$ONDI_BASE_URL/delivery/route-sessions?status=&page=1&limit=20" \2 --header "Authorization: Bearer {{access_token}}"Query parameters
statusOptionalFilter: open | started | picked_up | completed | cancelled
pageOptional1
Page number (default: 1)
limitOptional20
Items per page (default: 20, max: 100)
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Route sessions retrieved successfully",4 "data": {5 "sessions": [6 {7 "id": "session-uuid",8 "session_number": 2,9 "status": "started",10 "orders_count": 4,11 "created_at": "2026-04-14T09:00:00Z",12 "route": {13 "id": "route-uuid",14 "route_name": "Warehouse A → Zone 5",15 "origin_type": "warehouse",16 "destination_type": "location",17 "destination_location": {18 "lat": 33.5,19 "lng": 44.2,20 "address": "Zone 5 Hub"21 }22 }23 }24 ],25 "statuses": [26 {27 "status": "open",28 "label": "Open",29 "count": 030 },31 {32 "status": "started",33 "label": "Started",34 "count": 135 },36 {37 "status": "picked_up",38 "label": "Picked Up",39 "count": 040 },41 {42 "status": "completed",43 "label": "Completed",44 "count": 045 },46 {47 "status": "cancelled",48 "label": "Cancelled",49 "count": 050 }51 ],52 "total": 1,53 "page": 1,54 "limit": 2055 }56}Get Route Session Detail
/delivery/route-sessions/:sessionIdReturns session detail with route info and all deliveries. Accessible by the assigned driver or a dispatcher. Route origin/destination in response tells the driver where to travel. Individual delivery addresses are preserved in each delivery record.
1curl --request GET "$ONDI_BASE_URL/delivery/route-sessions/:sessionId" \2 --header "Authorization: Bearer {{access_token}}"Path parameters
sessionIdRequiredsession-uuid
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Route session retrieved successfully",4 "data": {5 "session": {6 "id": "session-uuid",7 "session_number": 2,8 "status": "started",9 "started_at": "2026-04-14T08:05:00Z",10 "picked_up_at": null11 },12 "route": {13 "id": "route-uuid",14 "route_name": "Warehouse A → Zone 5",15 "origin_type": "warehouse",16 "destination_type": "location",17 "destination_location": {18 "lat": 33.5,19 "lng": 44.2,20 "address": "Zone 5 Hub"21 }22 },23 "deliveries": [24 {25 "id": "del-uuid",26 "delivery_code": 1234,27 "status": "assigned",28 "unit_size": 1,29 "deliveryService": {30 "id": "service-uuid",31 "name": "Standard Delivery",32 "deliveryType": "Pickup and Delivery"33 },34 "customer": {35 "id": "cust-uuid",36 "full_name": "Sara Ahmed",37 "phone": "+9647501111111"38 }39 }40 ],41 "summary": {42 "total": 5,43 "status_breakdown": {44 "assigned": 3,45 "picked_up": 246 }47 }48 }49}Start Session (Driver)
/delivery/route-sessions/:sessionId/startDriver action. Transitions session: open → started. Sets started_at.
1curl --request POST "$ONDI_BASE_URL/delivery/route-sessions/:sessionId/start" \2 --header "Authorization: Bearer {{access_token}}"Path parameters
sessionIdRequiredsession-uuid
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Route session started successfully",4 "data": {5 "id": "session-uuid",6 "status": "started",7 "started_at": "2026-04-14T08:05:00Z"8 }9}1{2 "success": false,3 "message": "Cannot start a session with status 'picked_up'",4 "data": null5}Pickup Session (Driver)
/delivery/route-sessions/:sessionId/pickupDriver action. Transitions session: started → picked_up. Sets picked_up_at. After pickup, the session is closed for new orders. Any new assign-deliveries on this route will create a new session.
1curl --request POST "$ONDI_BASE_URL/delivery/route-sessions/:sessionId/pickup" \2 --header "Authorization: Bearer {{access_token}}"Path parameters
sessionIdRequiredsession-uuid
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Route session picked up successfully",4 "data": {5 "id": "session-uuid",6 "status": "picked_up",7 "picked_up_at": "2026-04-14T08:20:00Z"8 }9}List Eligible Deliveries for Route
/delivery/routes/:routeId/eligible-deliveries?page=1&limit=20&search=Returns paginated list of deliveries eligible to be assigned to this route. Eligibility criteria: - status = pending - carrier_type = internal - not already in a route session (route_session_id IS NULL)
1curl --request GET "$ONDI_BASE_URL/delivery/routes/:routeId/eligible-deliveries?page=1&limit=20&search=" \2 --header "Authorization: Bearer {{access_token}}"Path parameters
routeIdRequiredroute-uuid
Query parameters
pageOptional1
Page number
limitOptional20
Items per page (max 100)
searchOptionalSearch by delivery_code or external_reference_id
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Eligible deliveries retrieved successfully",4 "data": {5 "deliveries": [6 {7 "id": "del-uuid",8 "delivery_code": 1865,9 "barcode": "BAR1865",10 "external_reference_id": "ORD-001",11 "status": "pending",12 "unit_size": 1,13 "pickup_location": {14 "address": "Erbil, 60m Street"15 },16 "delivery_location": {17 "address": "Sulaymaniyah, Salim St"18 },19 "customer": {20 "id": "cust-uuid",21 "full_name": "Ahmad Karimi",22 "phone": "+9647501111111"23 }24 }25 ],26 "total": 24,27 "page": 1,28 "limit": 2029 }30}Cancel Session (Dispatcher)
/delivery/route-sessions/:sessionId/cancelDispatcher action. Cancels session if it is open or started. Rejected for picked_up/completed sessions. For each non-terminal delivery: deletes the assignment record and resets delivery to pending. Decrements driver capacity. Notifies driver.
1curl --request POST "$ONDI_BASE_URL/delivery/route-sessions/:sessionId/cancel" \2 --header "Authorization: Bearer {{access_token}}"Path parameters
sessionIdRequiredsession-uuid
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Route session cancelled successfully",4 "data": {5 "id": "session-uuid",6 "status": "cancelled",7 "cancelled_at": "2026-04-14T09:00:00Z"8 }9}1{2 "success": false,3 "message": "Cannot cancel a session that has been picked up — driver already has the orders",4 "data": null5}