Bulk Operations
5 API calls in this section.
Validate Bulk Action
/delivery/bulk/validatePre-flight check: validates whether each order is eligible for the requested action without making any changes. action_id values: - mark_pending — params: reason (optional) - assign_driver — params: driver_id (required). Each delivery is also checked against the driver's allowed zones at execute time; deliveries outside the driver's zones fail with driver_not_allowed_in_pickup_zone / driver_not_allowed_in_delivery_zone. - mark_picked_up — params: none. Requires an active assignment/driver on every delivery. - mark_in_transit — params: none. Requires an active assignment/driver on every delivery. - mark_delivered — params: none. Requires an active assignment/driver on every delivery. - mark_staged_at_warehouse — params: driver_id (optional, required when any inbound child has no active assignment). Children outside the driver's zones are rejected per-row. - cancel_orders — params: reason (required) - mark_returned — params: none - reassign_driver — params: driver_id (required). Same zone check as assign_driver. Also supports deliveries that were self-unassigned after pickup or in transit; the new driver continues from the current delivery progress. - unassign — params: reason (optional) - assign_to_route — params: route_id (required) Max 500 order_codes per request.
1curl --request POST "$ONDI_BASE_URL/delivery/bulk/validate" \2 --header "Authorization: Bearer {{access_token}}" \3 --header "Content-Type: application/json" \4 --header "Content-Type: application/json" \5 --data '{6 "order_codes": [7 "1865",8 "1853"9 ],10 "action_id": "assign_driver",11 "params": {12 "driver_id": "uuid-of-driver"13 }14}'1{2 "order_codes": [3 "1865",4 "1853"5 ],6 "action_id": "assign_driver",7 "params": {8 "driver_id": "uuid-of-driver"9 }10}Request body fields
order_codesExampleExample field from the request body.
action_idExampleExample field from the request body.
paramsExampleExample field from the request body.
params.driver_idExampleExample field from the request body.
Headers
AuthorizationOptionalBearer {{access_token}}
Content-TypeOptionalapplication/json
Responses
1{2 "success": true,3 "message": "Validation completed",4 "data": {5 "results": [6 {7 "order_code": "1865",8 "valid": true9 },10 {11 "order_code": "1853",12 "valid": false,13 "error_message": "Order status does not allow this action"14 }15 ],16 "total_valid": 1,17 "total_failed": 118 }19}Execute Bulk Action
/delivery/bulk/executeExecute the bulk action on the given orders. Re-validates each order at execution time (optimistic concurrency). Orders that fail re-validation are skipped and reported in results. Same request body as validate. Each order is processed in a single batched DB round-trip. Driver progress actions (mark_picked_up, mark_in_transit, mark_delivered): - Every delivery must still have an active assignment. If the driver self-unassigned, these actions fail with bulk_no_active_assignment until the delivery is reassigned. Driver-assignment actions (assign_driver, reassign_driver, and mark_staged_at_warehouse when creating new assignments): - All target deliveries are validated against the driver's allowed zones in O(1) DB calls. Per-delivery failures (driver_not_allowed_in_pickup_zone, driver_not_allowed_in_delivery_zone) are returned alongside successes; eligible deliveries still proceed. - reassign_driver also supports deliveries that were self-unassigned after pickup or in transit. A fresh assignment row is created for the new driver and the delivery keeps its current progress status. - Inserted assignments share a single bulk_assignment_id so the per-row realtime trigger is suppressed; the API emits one consolidated realtime row and one bulk_delivery_assigned notification.
1curl --request POST "$ONDI_BASE_URL/delivery/bulk/execute" \2 --header "Authorization: Bearer {{access_token}}" \3 --header "Content-Type: application/json" \4 --header "Content-Type: application/json" \5 --data '{6 "order_codes": [7 "1865",8 "1853"9 ],10 "action_id": "assign_driver",11 "params": {12 "driver_id": "uuid-of-driver"13 }14}'1{2 "order_codes": [3 "1865",4 "1853"5 ],6 "action_id": "assign_driver",7 "params": {8 "driver_id": "uuid-of-driver"9 }10}Request body fields
order_codesExampleExample field from the request body.
action_idExampleExample field from the request body.
paramsExampleExample field from the request body.
params.driver_idExampleExample field from the request body.
Headers
AuthorizationOptionalBearer {{access_token}}
Content-TypeOptionalapplication/json
Responses
1{2 "success": true,3 "message": "Bulk operation completed",4 "data": {5 "results": [6 {7 "order_code": "1865",8 "success": true9 },10 {11 "order_code": "1853",12 "success": false,13 "error_message": "Order status does not allow this action"14 }15 ],16 "total_success": 1,17 "total_failed": 118 }19}1{2 "success": true,3 "message": "Bulk operation completed",4 "data": {5 "results": [6 {7 "order_code": "1865",8 "success": true9 },10 {11 "order_code": "1853",12 "success": false,13 "error_message": "Driver is not allowed to operate in the pickup zone"14 }15 ],16 "total_success": 1,17 "total_failed": 118 }19}Search Orders
/delivery/orders/search?q=1865Autocomplete search for the bulk operations order picker. Searches by delivery_code or customer name. Returns up to 20 results scoped to the authenticated tenant.
1curl --request GET "$ONDI_BASE_URL/delivery/orders/search?q=1865" \2 --header "Authorization: Bearer {{access_token}}"Query parameters
qOptional1865
Search query — matches delivery_code (prefix) or customer name (partial). Min 1 character.
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Orders retrieved successfully",4 "data": [5 {6 "id": "uuid",7 "delivery_code": 1865,8 "customer_name": "John Doe",9 "status": "pending",10 "address": "123 Main St",11 "unit_size": 112 }13 ]14}Bulk Print — Shipping Labels
/delivery/bulk/print?order_codes[]=1865&order_codes[]=1853&type=shipping_labelReturns shipment_label_url from each delivery record. If not generated yet, url is null with a message. Frontend handles opening/printing.
1curl --request GET "$ONDI_BASE_URL/delivery/bulk/print?order_codes[]=1865&order_codes[]=1853&type=shipping_label" \2 --header "Authorization: Bearer {{access_token}}"Query parameters
order_codes[]Optional1865
Order code
order_codes[]Optional1853
Order code
typeOptionalshipping_label
shipping_label | receipt
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Print data retrieved successfully",4 "data": {5 "type": "shipping_label",6 "results": [7 {8 "order_code": "1865",9 "url": "https://label-url...",10 "status": "generated"11 },12 {13 "order_code": "1853",14 "url": null,15 "status": "pending",16 "message": "label_not_generated"17 }18 ]19 }20}Bulk Print — Receipts
/delivery/bulk/print?order_codes[]=1865&order_codes[]=1853&type=receiptReturns signed receipt URLs from the payments table (receipt_storage_path). Receipt must have been generated by the payment receipt job (receipt_status = success). If not ready, url is null with message receipt_not_ready. Signed URLs expire after 1 hour.
1curl --request GET "$ONDI_BASE_URL/delivery/bulk/print?order_codes[]=1865&order_codes[]=1853&type=receipt" \2 --header "Authorization: Bearer {{access_token}}"Query parameters
order_codes[]Optional1865
Order code
order_codes[]Optional1853
Order code
typeOptionalreceipt
shipping_label | receipt
Headers
AuthorizationOptionalBearer {{access_token}}
Responses
1{2 "success": true,3 "message": "Print data retrieved successfully",4 "data": {5 "type": "receipt",6 "results": [7 {8 "order_code": "1865",9 "url": "https://signed-url...",10 "receipt_generated_at": "2026-04-06T18:14:20Z"11 },12 {13 "order_code": "1853",14 "url": null,15 "message": "receipt_not_ready"16 }17 ]18 }19}