Assignments
11 API calls in this section.
Endpoints for managing delivery assignments. Assignments link deliveries to drivers and include routing information. When a staged order cannot move because its next child delivery is not ready, the localized English response message is This order cannot move yet because its next delivery step is not ready; clients must display the returned message rather than the internal no_active_child_leg key.
Update Driver Assignment Sequence
/delivery/assignments/driver/:driverId/sequenceUpdates a driver's assignment sequence. Dispatcher, tenant operations manager, system admin, or the matching authenticated driver is required. Body assignments must be a non-empty array. Success returns updated_count. HTTP 400, 403, and 500 response message values are localized using language or Accept-Language; the frontend must display the returned plain-language message and must not expect internal keys such as missing_required_params, unauthorized, or internal_error.
Path parameters
| Parameter | Type | Description |
|---|---|---|
driverIdRequired | string | Driver ID Example: |
Query parameters
| Parameter | Type | Description |
|---|---|---|
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
assignments | array<object> | — |
assignments.assignment_id | string | — |
assignments.sequence_number | number | — |
1curl --globoff --request PUT "https://staging-api.ondi.io/functions/v1/delivery/assignments/driver/${DRIVERID}/sequence?language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "assignments": [6 {7 "assignment_id": "assignment-uuid",8 "sequence_number": 19 }10 ]11}'Response examples
No saved response example. Use Try it to inspect a staging response.
Get Driver Assignment Sequence
/delivery/assignments/:driverId/sequenceReturns the driver's active assignments ordered by sequence_number. Authorization matches the update endpoint. Success returns assignments and total. HTTP 400, 403, and 500 response message values are localized using language or Accept-Language.
Path parameters
| Parameter | Type | Description |
|---|---|---|
driverIdRequired | string | Driver ID Example: |
Query parameters
| Parameter | Type | Description |
|---|---|---|
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/delivery/assignments/${DRIVERID}/sequence?language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"Response examples
No saved response example. Use Try it to inspect a staging response.
List Assignments
/delivery/assignmentsGet a list of delivery assignments with pagination, filtering, sorting and stats. Admin users can view all assignments; drivers can only view their own. Use the optional include query parameter for customer, delivery_details, and route expansions. Expanded pickup and delivery locations are resolved through their respective address relationships.
Query parameters
| Parameter | Type | Description |
|---|---|---|
page | string | Page number for pagination Example: |
limit | string | Number of items per page Example: |
status | string | Filter by assignment status (pending, accepted, rejected, completed) |
driver_id | string | Filter by driver ID (Admin only; drivers always see their own assignments) |
delivery_id | string | Filter by delivery ID |
bulk_assignment_id | string | Filter by bulk assignment ID |
sort_by | string | Column to sort by. Allowed: |
sort_order | string | Sort direction: asc or desc (default: desc) Example: |
column_filters | string | JSON string of column filters. Supported keys: status, |
includeOptional | string | Optional comma-separated expansions: customer, |
tenant_idOptional | string | Tenant ID (optional if in auth token) |
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/delivery/assignments?page=1&limit=10&status=&driver_id=&delivery_id=&bulk_assignment_id=&sort_by=&sort_order=desc&column_filters=&include=&tenant_id=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"Response examples
1{2 "success": true,3 "message": "Assignments retrieved successfully",4 "assignments": [5 {6 "id": "uuid",7 "tenant_id": "uuid",8 "delivery_id": "uuid",9 "assignment_time": "2025-01-15T08:00:00Z",10 "status": "pending",11 "sequence_number": 1,12 "estimated_pickup_time": "2025-01-15T09:00:00Z",13 "delivery": {14 "id": "uuid",15 "delivery_code": "DEL-001",16 "external_reference_id": "EXT-001",17 "customer": {18 "id": "uuid",19 "full_name": "Jane Doe",20 "phone": "+1234567890"21 }22 },23 "drivers": {24 "id": "uuid",25 "user": "John Driver"26 },27 "vehicle": {28 "id": "uuid",29 "name": "Toyota Hilux",30 "image_url": null31 },32 "assigned_by": {33 "id": "uuid",34 "full_name": "Admin User"35 }36 }37 ],38 "page": 1,39 "limit": 10,40 "total": 42,41 "stats": {42 "totalAssignments": 150,43 "pendingAssignments": 30,44 "completedAssignments": 100,45 "recentlyAddedCount": 1246 }47}Create Assignment
/delivery/assignmentsPOST /delivery/assignments accepts a Pending P&D outbound or warehouse-origin operational return only after Execute has created one completed picking order and reserved its full positive warehouse stock. Open delivery or warehouse-item exceptions block assignment with HTTP 409 (delivery_has_open_exception, parent_exception_open, warehouse_item_exception_open, or warehouse_preparation_inconsistent). Assignment and driver capacity commit atomically; eligible P&D work also creates one pending package handoff linked to the delivery, completed pick, assignment, and driver. Warehouse stock remains positive and reserved because assignment is responsibility, not custody. Before receipt, a manually returned P&D outbound is returned and cannot be assigned; its parent is arrived_at_warehouse. After receipt, the backend creates a fresh assignment row; the returned assignment remains immutable history and is never reused or rewritten. Frontend sends the Pending delivery ID in delivery_id and the selected active driver in driver_id using the normal request body. Realtime mobile contract: the existing delivery_realtime_assignments row includes assignment_status and requires_driver_response. The boolean is true only when the authoritative assignment status is exactly pending; assigned, later lifecycle states, missing status, and unknown status are informational. Mobile keeps the existing notification UI and shows Accept/Reject only when requires_driver_response === true.
Create a new delivery assignment. Only users with 'manage:operations:tenant' permission can create assignments. The assignment row, driver capacity, and directly-assigned delivery status are committed atomically. Google route calculation runs after creation and stores route_details asynchronously, so route availability does not delay or determine assignment success.
P&D parent resolution
A staged/P&D parent delivery ID is accepted in delivery_id. The backend resolves the first non-terminal, non-draft child by parent sequence_plan order and creates or reuses the assignment on that active child, never on the parent. Parent-resolved success includes resolved_delivery_id. If no operational child is active, the request fails with localized no_active_child_leg.
Open exception rule
An active assignment cannot be created while the resolved operational delivery has an open delivery exception or an open Waybill missing_on_receive discrepancy. The API returns HTTP 409 delivery_has_open_exception. A normal delivery exception must be resolved through its exception action; a missing receipt must be resolved as found or lost through the dedicated Waybill discrepancy endpoint before assignment becomes available.
Zone Validation
Uses
pickup_zone_id/dropoff_zone_idfromdelivery_list_view(persisted ondeliveries) and always validates driver zone access (no silent skip)If driver has
all_zones = true, they can be assigned to any deliveryIf driver has
all_zones = false, they must have the pickup zone and/or delivery zone assigned viadelivery_zone_driverstableErrors:
driver_not_allowed_in_pickup_zone,driver_not_allowed_in_delivery_zone,driver_not_allowed_in_zones,delivery_zone_validation_unavailable(row missing from view). On view query failure:internal_server_error(500)
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_idOptional | string | Tenant ID (optional if in auth token) |
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
delivery_id | string | — |
driver_id | string | — |
vehicle_id | string | — |
estimated_pickup_time | string | — |
estimated_delivery_time | string | — |
sequence_number | number | — |
notes | string | — |
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/delivery/assignments?tenant_id=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "delivery_id": "uuid",6 "driver_id": "uuid",7 "vehicle_id": "uuid",8 "estimated_pickup_time": "2023-08-01T13:00:00Z",9 "estimated_delivery_time": "2023-08-01T14:00:00Z",10 "sequence_number": 1,11 "notes": "Please deliver with care"12}'Response examples
1{2 "success": true,3 "message": "Assignment created successfully",4 "id": "child-assignment-uuid",5 "resolved_delivery_id": "active-child-delivery-uuid"6}Create Bulk Assignments
/delivery/assignments/bulkBulk assignment follows the same ownership rule as single assignment. Assignment rows, delivery activation, driver capacity, and all eligible P&D pending handoffs commit in one database transaction. Every P&D/operational-return row must already have one completed pick, full reservation, positive stock, and no open delivery or warehouse-item exception; any failure rolls back the complete bulk request. Concurrent state conflicts return a localized response with a stable code such as delivery_status_changed, delivery_already_assigned, driver_not_active, insufficient_vehicle_capacity, parent_exception_open, delivery_has_open_exception, warehouse_item_exception_open, or warehouse_preparation_inconsistent. Terminal assignment rows, including returned, are historical and do not block a new assignment for a Pending delivery. A failed operational return received back at its pickup warehouse can therefore be assigned without rewriting its prior returned assignment. Realtime mobile contract: the single existing bulk delivery_realtime_assignments row includes assignment_status and requires_driver_response. The boolean is true only when the tenant setting produces pending; assigned, missing, and unknown values are informational. Mobile shows Accept/Reject only when requires_driver_response === true.
Create multiple delivery assignments in a single request for a single driver. Only users with 'manage:operations:tenant' permission can create bulk assignments.
Request Format
driver_id(required): Single driver ID for all deliveriesdelivery_ids(required): Array of delivery IDs to assign
Parent/Leg Assignment Contract
A staged or hybrid parent delivery ID is accepted as dispatcher input.
The backend resolves each parent to its first active non-terminal child leg by
sequence_planorder and creates the assignment on that leg, never on the parent.A child leg in
draftstatus is not available for assignment and returnsno_active_child_leg(400). Warehouse receiving/execution must activate that leg first.If a parent and its active leg are both submitted, the resolved duplicate is rejected.
Successful responses include
resolved_deliverieswhen parent IDs were redirected. Each item containsrequested_delivery_idandassigned_delivery_id. Frontends should navigate to or refresh the assigned child leg.
Validation
All resolved deliveries must be in 'pending' status
All resolved deliveries must be internal carrier type
Driver must be active and have a vehicle assigned
Total unit size of all resolved deliveries must fit in driver's vehicle capacity
Every resolved delivery must appear in
delivery_list_viewfor the tenant; otherwisedeliveries_zone_context_incomplete(400) withdelivery_idsmissing from the viewDriver must have access to all required zones (
pickup_zone_id/dropoff_zone_idon the resolved delivery when present) unless driver hasall_zonesenabled; otherwisedriver_not_allowed_in_zonesand optionalmissing_zonesNo duplicate submitted or resolved delivery IDs allowed
Response
Returns assignment IDs, count, total units, driver capacity used, and optional parent-to-leg resolutions
Creates a single bulk realtime notification record in
delivery_realtime_assignmentstable with:is_bulk: truebulk_assignment_id: Unique ID for this bulk operationassignment_count: Number of deliveries assignedtotal_units: Total units consumed
Sends single bulk notification to driver (not individual notifications)
Individual assignments are created in
delivery_assignmentstable for querying
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_idOptional | string | Tenant ID (optional if in auth token) |
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
driver_id | string | — |
delivery_ids | array<string> | — |
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/delivery/assignments/bulk?tenant_id=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "driver_id": "uuid",6 "delivery_ids": [7 "uuid1",8 "uuid2"9 ]10}'Response examples
1{2 "success": true,3 "message": "Bulk assignments created successfully",4 "assignment_ids": [5 "uuid1",6 "uuid2"7 ],8 "count": 2,9 "total_units": 15,10 "driver_capacity_used": 30,11 "resolved_deliveries": [12 {13 "requested_delivery_id": "parent-uuid",14 "assigned_delivery_id": "active-leg-uuid"15 }16 ]17}Bulk Accept/Reject Assignments
/delivery/assignments/bulk/:bulkAssignmentIdAcceptance/rejection updates assignments, delivery status, capacity, and eligible P&D handoffs atomically. Accept keeps the same pending handoff actionable for the accepted driver. Reject keeps the completed pick and warehouse reservation but clears the same pending handoff's assignment and driver context so it cannot be executed until reassigned.
Accept or reject all assignments in a bulk operation. Only the assigned driver can accept/reject their own bulk assignments.
Request Format
action(required): "accept" or "reject"
Validation
Driver must be active
All assignments must belong to the specified
bulk_assignment_idAll assignments must belong to the authenticated driver
All assignments must be in 'pending' status
Accept Action
Updates all assignments to 'accepted' status
Updates all delivery statuses to 'assigned'
Sends notification to dispatchers
Reject Action
Updates all assignments to 'rejected' status
Frees up driver capacity (total units released)
Sends notification to dispatchers
Deliveries remain in 'pending' status (can be reassigned)
Any rejected delivery that belongs to a trip has
trip_idandtrip_sequencecleared
Response
Returns assignment IDs, count, and total units freed (if rejected)
Path parameters
| Parameter | Type | Description |
|---|---|---|
bulkAssignmentIdRequired | string | Bulk assignment ID from bulk assignment creation Example: |
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_idOptional | string | Tenant ID (optional if in auth token) |
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
action | string | — |
1curl --globoff --request PUT "https://staging-api.ondi.io/functions/v1/delivery/assignments/bulk/${BULKASSIGNMENTID}?tenant_id=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "action": "accept"6}'Response examples
1{2 "success": true,3 "message": "Bulk assignments accepted successfully",4 "assignment_ids": [5 "uuid1",6 "uuid2"7 ],8 "count": 2,9 "total_units_freed": 010}Update Assignment
/delivery/assignments/:assignmentIdFor a prepared P&D outbound or operational return, a pre-pickup driver change updates the same pending package handoff to the current assignment and driver. It never creates another pick or handoff and never moves warehouse stock. Rejection or unassignment preserves the completed pick and reservation while clearing the handoff's driver context.
Update an existing delivery assignment. Admin users can update any assignment. Drivers can only update their own assignments and are restricted to updating status, actual_pickup_time, actual_delivery_time, notes, and reason (supported as an alias for notes when self-unassigning). When assignment status becomes accepted or assigned, the related delivery row is synced to status=assigned; when assignment status becomes en_route_to_pickup, the related delivery row is synced to status=en_route_to_pickup.
P&D pickup boundary
When status=picked_up targets a lifecycle-managed P&D or operational-return assignment, the backend requires the existing completed picking order and current handoff, rechecks both exception systems and warehouse stock, then atomically completes the handoff, marks the pick handed_off, records the pick movement, clears warehouse stock/reservation, moves parcel custody to in_transit, and updates the delivery and assignment to picked_up. It does not create missing warehouse preparation during pickup. When a rejected or unassigned assignment record is reused after warehouse receipt and Retry, pickup validates only the newly assigned handoff and picking-order custody cycle; earlier completed cycles remain historical and do not block pickup or replay. Waybill and ordinary assignment updates keep their existing flow. Important conflicts are returned as localized stable codes such as pickup_picking_order_required, pickup_handoff_required, warehouse_item_exception_open, and pickup_stock_unavailable.
Unassign rule
status=unassigned is accepted before pickup when the operational delivery status is pending, assigned, or en_route_to_pickup and the resolved active assignment still has a driver. This includes withdrawing a pending driver offer before acceptance. The backend atomically changes delivery_assignments.status to unassigned, clears the driver/vehicle and route/trip state, releases driver capacity, and leaves or returns deliveries.status to pending. A plain Pending delivery without an active driver assignment returns HTTP 409 with code assignment_cannot_be_unassigned. picked_up, in_transit, and all later or terminal states return HTTP 409 with code delivery_status_does_not_allow_unassign.
Parent/leg contract
If the target assignment belongs to a staged/P&D parent, unassign or an admin driver_id change resolves to the first active non-terminal child leg in sequence_plan. Driver ownership changes only on that child assignment. When unassign returns the active inbound child delivery to pending, the staged parent delivery also returns to pending; other child legs remain unchanged. Assigning a driver to that unassigned active inbound leg is recorded as driver_assigned and synchronizes the parent to the leg's resulting pending or assigned lifecycle status. A genuine driver-to-driver change is recorded as driver_switched and remains child-scoped. Outbound-leg preparation also remains child-scoped. Successful responses include resolved_from_parent.
Driver change restriction
Changing driver_id on a routed delivery remains rejected with cannot_switch_driver_for_routed_delivery.
Error contract
HTTP 404 with code assignment_not_found is returned only when the requested assignment ID does not exist for the tenant. Assignment lookup failures return HTTP 500 with code internal_server_error; they are not reported as a missing assignment.
Zone validation (admin changing driver_id)
Same rules as create assignment; failures return delivery_zone_validation_unavailable or driver zone messages (driver_not_allowed_in_*). View load errors return internal_server_error (500).
Frontend integration contract
Keep the existing request shape. For status=picked_up, display the returned localized pickup conflict and keep the current assignment/delivery state; no separate handoff or picking-order completion call is required.
Event actor contract
when the assigned driver performs a status action, new assignment and delivery status events use actor_role=driver and actor_id=drivers.id. Dispatcher-performed actions use the dispatcher user ID. The backend derives the actor from the authenticated request and assignment; clients do not send actor_id.
Path parameters
| Parameter | Type | Description |
|---|---|---|
assignmentIdRequired | string | Assignment ID, parent assignment ID, or P&D parent delivery/order ID; parent inputs resolve to the active child assignment Example: |
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_idOptional | string | Tenant ID (optional if in auth token) |
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
status | string | — |
actual_pickup_time | string | — |
actual_delivery_time | null | — |
notes | string | — |
1curl --globoff --request PUT "https://staging-api.ondi.io/functions/v1/delivery/assignments/${ASSIGNMENTID}?tenant_id=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "status": "in_progress",6 "actual_pickup_time": "2023-08-01T13:05:00Z",7 "actual_delivery_time": null,8 "notes": "Customer called, will be home in 10 minutes"9}'Response examples
1{2 "success": true,3 "message": "Assignment updated successfully",4 "assignment": {5 "id": "child-assignment-uuid",6 "tenant_id": "uuid",7 "delivery_id": "active-child-delivery-uuid",8 "driver_id": "uuid",9 "status": "in_progress",10 "actual_pickup_time": "2023-08-01T13:05:00Z",11 "notes": "Customer called, will be home in 10 minutes",12 "updated_at": "2023-08-01T13:05:00Z"13 },14 "resolved_from_parent": {15 "parent_delivery_id": "parent-delivery-uuid",16 "delivery_id": "active-child-delivery-uuid",17 "assignment_id": "child-assignment-uuid"18 }19}Unassign Assignment (Dispatcher)
/delivery/assignments/:assignmentId/unassignThis action applies only to a current active assignment. For prepared P&D work, unassignment atomically clears the current driver/assignment from the same pending package handoff but preserves its completed picking order and warehouse stock reservation. The handoff becomes non-actionable until another driver is assigned. After a failed operational return is received at the warehouse, the old returned assignment is historical; do not send its ID to this endpoint. Show Assign for the Pending delivery and create a fresh assignment first. Change Driver or Unassign becomes available again only for that new active assignment.
Dispatcher-only. Unassign the current driver before pickup when the operational delivery status is pending, assigned, or en_route_to_pickup and the resolved active assignment still has a driver. This includes withdrawing a pending driver offer before acceptance. The path target may be an assignment ID or a staged/P&D parent delivery ID/parent assignment ID. Parent targets resolve to the first active non-terminal child leg in sequence_plan; driver ownership changes only on that child assignment. The operation is atomic: delivery_assignments.status becomes unassigned, driver/vehicle and route/trip state are cleared, driver capacity is released, and the active delivery remains or becomes pending. When that active child is the inbound P&D leg, its staged parent delivery also remains or becomes pending; other child legs remain unchanged. An outbound child unassign does not reset a parent already at warehouse staging. A plain Pending delivery without an active driver assignment returns HTTP 409 with code assignment_cannot_be_unassigned. picked_up, in_transit, and all later or terminal states return HTTP 409 with code delivery_status_does_not_allow_unassign. The tenant assignment-change feature must be enabled.
The previous driver receives one assignment_unassigned notification with priority=critical, display_mode=modal, requires_acknowledgement=true, portal_context=driver_app, the reason, and the existing delivery navigation action. Notification creation and push delivery are background work and do not extend this API response path.
Path parameters
| Parameter | Type | Description |
|---|---|---|
assignmentIdRequired | string | Assignment ID, parent assignment ID, or P&D parent delivery/order ID; parent inputs resolve to the active child assignment Example: |
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_idOptional | string | Tenant ID (optional if in auth token) |
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
reason | string | — |
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/delivery/assignments/${ASSIGNMENTID}/unassign?tenant_id=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "reason": "Operational change"6}'Response examples
1{2 "success": true,3 "message": "Assignment unassigned successfully",4 "assignment": {5 "id": "uuid",6 "status": "unassigned",7 "delivery_id": "uuid",8 "delivery_status": "pending",9 "previous_driver_id": "uuid",10 "resolved_from_parent": true11 },12 "resolved_from_parent": true13}Switch Assignment Driver (Dispatcher)
/delivery/assignments/:assignmentId/switch-driverBefore pickup, a prepared P&D driver switch updates the same pending package handoff with the current assignment and replacement driver. The completed picking order and reservation are preserved; no new handoff is created and physical custody stays with the warehouse. Existing post-pickup driver-to-driver behavior is unchanged.
Dispatcher-only. Switch the driver on a standalone delivery or operational child leg using the same assignment record. The path target may also be a staged/P&D parent delivery ID or parent assignment ID; the backend resolves it to the first active non-terminal child leg and changes only that child. A pre-pickup child leg may return to pending while the replacement driver awaits acceptance, but its staged parent keeps its existing lifecycle status. Respects assignment_change_settings and validates driver zones, capacity, and primary vehicle. If the active delivery already has route_id or route_session_id, the switch is rejected with cannot_switch_driver_for_routed_delivery.
One assignment_driver_switched event keeps the existing driver-specific notifications: the previous driver receives the acknowledgement modal and the replacement driver receives the existing toast or banner. At every delivery stage, operational custody transfers to the replacement driver during the switch itself. The switch leaves handoff_status null and does not block the replacement driver's next status action. The previous driver's “I understand” action acknowledges the notification only. Parent inputs still change only the resolved active child leg; the P&D parent lifecycle row is not directly reassigned. A successful switch also appends one driver_switched activity to the canonical root delivery's order_events in the same transaction. For a P&D child switch, the event includes delivery_id, delivery_code, direction, leg_sequence, and source=active_leg; past missing child driver events are backfilled without duplicates. This activity write does not change the parent lifecycle status or customer/driver status_updates. Snapshots include driver ID, user ID, full name, nullable avatar URL, and nullable phone. Copy/call secondary actions are omitted when phone is null. Push text never includes phone data. Notification enrichment, rendering, insertion, and push delivery run in the EdgeRuntime background task.
Path parameters
| Parameter | Type | Description |
|---|---|---|
assignmentIdRequired | string | Assignment ID, parent assignment ID, or P&D parent delivery/order ID; parent inputs resolve to the active child assignment Example: |
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_idOptional | string | Tenant ID (optional if in auth token) |
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
driver_id | string | — |
reason | string | — |
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/delivery/assignments/${ASSIGNMENTID}/switch-driver?tenant_id=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "driver_id": "uuid",6 "reason": "Driver changed"7}'Response examples
1{2 "success": true,3 "message": "Driver switched successfully",4 "assignment": {5 "id": "uuid",6 "driver_id": "uuid",7 "status": "pending",8 "delivery_id": "uuid"9 },10 "resolved_from_parent": true11}Update Assignment Route
/delivery/assignments/:assignmentId/routeUpdate the route details for an existing assignment. Admin users can update any assignment's route. Drivers can only update routes for their own assignments. HTTP 404 with code assignment_not_found is returned only when the assignment does not exist for the tenant. Assignment lookup failures return HTTP 500 with code internal_server_error.
Path parameters
| Parameter | Type | Description |
|---|---|---|
assignmentIdRequired | string | ID of the assignment to update route for Example: |
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_idOptional | string | Tenant ID (optional if in auth token) |
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
route_details | object | — |
route_details.distance | number | — |
route_details.duration | number | — |
route_details.polyline | string | — |
route_details.stops | array<object> | — |
route_details.stops.location | object | — |
route_details.stops.location.latitude | number | — |
route_details.stops.location.longitude | number | — |
route_details.stops.sequence | number | — |
route_details.stops.estimated_arrival | string | — |
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/delivery/assignments/${ASSIGNMENTID}/route?tenant_id=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "route_details": {6 "distance": 18.5,7 "duration": 55,8 "polyline": "updated_encoded_polyline_string",9 "stops": [10 {11 "location": {12 "latitude": 37.7749,13 "longitude": -122.419414 },15 "sequence": 1,16 "estimated_arrival": "2023-08-01T13:00:00Z"17 },18 {19 "location": {20 "latitude": 37.7694,21 "longitude": -122.486222 },23 "sequence": 2,24 "estimated_arrival": "2023-08-01T13:30:00Z"25 }26 ]27 }28}'Response examples
1{2 "success": true,3 "message": "Assignment route updated successfully",4 "assignment": {5 "id": "uuid",6 "tenant_id": "uuid",7 "delivery_id": "uuid",8 "driver_id": "uuid",9 "route_details": {10 "distance": 18.5,11 "duration": 55,12 "polyline": "updated_encoded_polyline_string",13 "stops": [14 {15 "location": {16 "latitude": 37.7749,17 "longitude": -122.419418 },19 "sequence": 1,20 "estimated_arrival": "2023-08-01T13:00:00Z"21 },22 {23 "location": {24 "latitude": 37.7694,25 "longitude": -122.486226 },27 "sequence": 2,28 "estimated_arrival": "2023-08-01T13:30:00Z"29 }30 ]31 },32 "updated_at": "2023-08-01T12:30:00Z"33 }34}Get Assignment
/delivery/assignments/:assignmentIdGet details for a specific delivery assignment. Admin users can view any assignment, while drivers can only view their own assignments. HTTP 404 with code assignment_not_found is returned only when the assignment is not visible for the tenant and caller. Assignment lookup failures return HTTP 500 with code internal_server_error.
Path parameters
| Parameter | Type | Description |
|---|---|---|
assignmentIdRequired | string | ID of the assignment to retrieve Example: |
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_idOptional | string | Tenant ID (optional if in auth token) |
language | string | Preferred language for response messages Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/delivery/assignments/${ASSIGNMENTID}?tenant_id=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"Response examples
1{2 "success": true,3 "message": "Assignment retrieved successfully",4 "assignment": {5 "id": "uuid",6 "tenant_id": "uuid",7 "delivery_id": "uuid",8 "driver_id": "uuid",9 "vehicle_id": "uuid",10 "assignment_time": "2023-08-01T12:00:00Z",11 "assigned_by": "uuid",12 "sequence_number": 1,13 "status": "assigned",14 "estimated_pickup_time": "2023-08-01T13:00:00Z",15 "estimated_delivery_time": "2023-08-01T14:00:00Z",16 "actual_pickup_time": null,17 "actual_delivery_time": null,18 "route_details": {19 "distance": 15.5,20 "duration": 45,21 "polyline": "encoded_polyline_string",22 "stops": [23 {24 "location": {25 "latitude": 37.7749,26 "longitude": -122.419427 },28 "sequence": 1,29 "estimated_arrival": "2023-08-01T13:00:00Z"30 }31 ]32 },33 "notes": "Sample delivery notes",34 "created_at": "2023-08-01T12:00:00Z",35 "updated_at": "2023-08-01T12:00:00Z",36 "deliveries": {37 "id": "uuid",38 "external_reference_id": "REF123",39 "status": "assigned",40 "customer_id": "uuid"41 },42 "drivers": {43 "id": "uuid",44 "user": "John Smith"45 },46 "vehicles": {47 "id": "uuid",48 "name": "Vehicle 1"49 }50 }51}