Skip to main content

Deliveries

13 API calls in this section.

List Deliveries

Delivery & Last-Mile / Deliveries
GET/delivery/deliveries?page=1&limit=10&status=&customer_id=&driver_id=&bulk_group=&delivery_type=&tenant_id=&column_filters=&sort_by=&sort_order=&language=en

Get a list of deliveries with filtering and pagination. Access is restricted by role. Zones: Each row includes pickup_zone_id and dropoff_zone_id (from deliveries, exposed on delivery_list_view). Query zone_ids matches if either column is in the list (same as driver zone scoping). Includes carrier fields: - carrier_type, direction, pickup_warehouse_id, dropoff_warehouse_id, sequence_plan (hybrid only).

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/delivery/deliveries?page=1&limit=10&status=&customer_id=&driver_id=&bulk_group=&delivery_type=&tenant_id=&column_filters=&sort_by=&sort_order=&language=en" \2  --header "Authorization: Bearer {{access_token}}"

Query parameters

pageOptional
query string

1

Page number for pagination

limitOptional
query string

10

Number of items per page

statusOptional
query string

Filter by delivery status (pending, in_transit, delivered, etc.)

customer_idOptional
query string

Filter by customer ID

driver_idOptional
query string

Filter by driver ID

bulk_groupOptional
query string

Filter by bulk group identifier

delivery_typeOptional
query string

Filter by delivery type (Delivery, Pickup, OnDemand, etc.)

tenant_idOptional
query string

Tenant ID (optional if in auth token)

column_filtersOptional
query string

Optional JSON string for column-level filters. Keys are AND-combined and ANDed with existing standalone filters. Supported keys: delivery_code, customer, driver, barcode, pickup_zone, dropoff_zone, pickup_address, delivery_address, pickup_warehouse, vehicle, notes, external_reference_id (ILIKE); status, assignment_status, carrier_type, payment_status, payer_type, payment_method, direction, priority (=); cod_amount, delivery_fee (number or {min,max}); created_at, updated_at ({from,to}). Example: {"status":"pending","carrier_type":"internal","delivery_fee":{"min":500,"max":2000},"created_at":{"from":"2025-01-01","to":"2025-12-31"}}.

sort_byOptional
query string

Optional column to sort by. Allowed values: delivery_code, delivery_status, priority, created_at, updated_at, cod_amount, delivery_fee, customer, driver. Default: created_at.

sort_orderOptional
query string

Optional sort order: asc or desc. Default: desc.

languageOptional
query string

en

Preferred language for response messages

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200OK
Error - Insufficient Permissions403Forbidden

Get Driver Deliveries

Delivery & Last-Mile / Deliveries
GET/delivery/driver-deliveries?page=1&limit=10&status=&search=&tenant_id=&language=en

Driver deliveries list (driver-only). Default behavior (no status filter): - Returns normal deliveries assigned to the driver - Excludes delivered deliveries - Excludes child deliveries whose Waybill is active (drafted, sealed, picked_up, or in_transit). Those packages are represented by the Waybill card from GET /delivery/driver-waybills and must not be independently startable from the normal delivery list. Filtering: - status=delivered: returns only delivered deliveries - status=pending: returns pending deliveries. If tenant driver_config.claim_unassigned_deliveries is true (legacy: driver_can_self_assign), it also includes unassigned pending deliveries. Pending deliveries that are already assigned to this driver (pending acceptance) are returned first and include pending_acceptance: true. - Active-Waybill children are excluded from every status and search filter. Children of received, closed, or cancelled Waybills follow normal delivery filtering. Frontend contract: - Render and navigate active Waybill work from /delivery/driver-waybills, not from a child delivery card. - The backend also suppresses delivery_realtime_assignments rows for active-Waybill children; use waybill_realtime to refresh Waybill cards. Response includes: - deliveries: simplified UI shape - statuses: list of status counts for the driver UI tabs/filters

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/delivery/driver-deliveries?page=1&limit=10&status=&search=&tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}"

Query parameters

pageOptional
query string

1

Page number for pagination (default: 1)

limitOptional
query string

10

Number of items per page (default: 10)

statusOptional
query string

Filter by delivery status (optional)

searchOptional
query string

Search term for filtering deliveries (optional)

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success - Default (Assigned, excluding delivered)200OK
Success - Pending (includes pending acceptance + unassigned if enabled)200OK
Success - Delivered filter200OK
Error - Not a Driver403Forbidden
Error - Driver Not Found404Not Found

Get Driver Delivery Status Summary

Delivery & Last-Mile / Deliveries
GET/delivery/driver-deliveries/status-summary?tenant_id=&language=en

Get driver delivery status summary with counts and labels (driver-only). Purpose: - Lightweight endpoint that returns only status counts and labels - Useful for displaying status tabs/cards in the driver UI - Does not include delivery list data - Uses the same visibility rule as GET /delivery/driver-deliveries: children of active Waybills (drafted, sealed, picked_up, in_transit) are excluded from all counts. Response includes: - statuses: Array of status objects with status, label, and count fields - Statuses include: assigned, in_transit, picked_up, delivered, cancelled, pending (if self-assign enabled)

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/delivery/driver-deliveries/status-summary?tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}"

Query parameters

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200OK
Error - Not a Driver403Forbidden
Error - Driver Not Found404Not Found

Get Delivery

Delivery & Last-Mile / Deliveries
GET/delivery/deliveries/:deliveryId?tenant_id=&language=en

Get delivery details. Includes carrier fields (carrier_type, direction, pickup_warehouse_id, dropoff_warehouse_id). If hybrid parent, also includes sequence_plan and children; if prime, includes prime object. Replacement orders: - delivery_flow indicates if this is a replacement_forward or replacement_return (null for normal deliveries). - If delivery_flow = 'replacement_forward' and the return delivery has been auto-created, response includes replacement_delivery with the full return delivery details and its current status. - If delivery_flow = 'replacement_return', response includes replacement_delivery with the forward delivery details. - replacement_delivery is absent if not a replacement, or if the return has not yet been created (forward not yet completed).

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/delivery/deliveries/:deliveryId?tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}"

Path parameters

deliveryIdRequired
path string

uuid

ID of the delivery to retrieve

Query parameters

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200OK
Error - Unauthorized403Forbidden

Create Delivery

Delivery & Last-Mile / Deliveries
POST/delivery/deliveries?language=en

Create a new delivery (JSON-first). Key rules: - Provide pickup_location and delivery_location as JSON objects with lat/long and country; these are authoritative. - Optionally provide pickup_warehouse_id/dropoff_warehouse_id to indicate warehouse endpoints. - If only IDs are provided by legacy callers, the API resolves them once and embeds JSON. - Contact info for labels/notifications is taken from the address JSON contact_info. Warehouse staging: - If requires_warehouse_staging=true, the API creates a HYBRID parent with 2 legs (pickup→warehouse, warehouse→dropoff). - staging_warehouse_id is optional; if null, system auto-selects. - Guard: staging is supported ONLY for delivery_type "Pickup and Delivery"; otherwise API returns warehouse_staging_only_supported_for_pickup_and_delivery. Replacement orders: - Set is_replacement=true to create a replacement forward delivery. - When the forward delivery is completed (delivered), the system auto-creates a return delivery assigned to the same driver. - The return delivery flips pickup/delivery locations so the driver returns the old item to the original pickup source. - No need to reference any original order — replacements are standalone. Required: - delivery_service_id, customer_id, payer_type, payment_method.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/delivery/deliveries?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "requires_warehouse_staging": false,7  "staging_warehouse_id": null,8  "is_replacement": false,9  "pickup_location": {10    "full_address": "Baghdad HQ",11    "lat": 33.3152,12    "long": 44.3661,13    "country": "IQ",14    "contact_info": {15      "phone": "+964700000000",16      "email": "sender@example.com"17    }18  },19  "delivery_location": {20    "full_address": "Basra Customer",21    "lat": 30.5081,22    "long": 47.7835,23    "country": "IQ",24    "contact_info": {25      "phone": "+964711111111",26      "name": "Customer Name"27    }28  },29  "pickup_warehouse_id": null,30  "dropoff_warehouse_id": null,31  "delivery_service_id": "uuid",32  "package_details": {33    "special_instructions": "Handle with care",34    "items": [35      {36        "name": "Mobile phone",37        "description": "Mobile phone",38        "quantity": 2,39        "weight": 2.5,40        "length": 30,41        "width": 20,42        "height": 1543      }44    ]45  },46  "customer_id": "uuid",47  "external_reference_id": "ORD-12345",48  "status": "pending",49  "scheduled_pickup_time": "2023-08-02T14:00:00Z",50  "scheduled_delivery_time": "2023-08-02T16:00:00Z",51  "priority": 1,52  "notes": "Customer prefers delivery after 3pm",53  "payer_type": "sender",54  "payment_method": "wallet"55}'
Request body
json
1{2  "requires_warehouse_staging": false,3  "staging_warehouse_id": null,4  "is_replacement": false,5  "pickup_location": {6    "full_address": "Baghdad HQ",7    "lat": 33.3152,8    "long": 44.3661,9    "country": "IQ",10    "contact_info": {11      "phone": "+964700000000",12      "email": "sender@example.com"13    }14  },15  "delivery_location": {16    "full_address": "Basra Customer",17    "lat": 30.5081,18    "long": 47.7835,19    "country": "IQ",20    "contact_info": {21      "phone": "+964711111111",22      "name": "Customer Name"23    }24  },25  "pickup_warehouse_id": null,26  "dropoff_warehouse_id": null,27  "delivery_service_id": "uuid",28  "package_details": {29    "special_instructions": "Handle with care",30    "items": [31      {32        "name": "Mobile phone",33        "description": "Mobile phone",34        "quantity": 2,35        "weight": 2.5,36        "length": 30,37        "width": 20,38        "height": 1539      }40    ]41  },42  "customer_id": "uuid",43  "external_reference_id": "ORD-12345",44  "status": "pending",45  "scheduled_pickup_time": "2023-08-02T14:00:00Z",46  "scheduled_delivery_time": "2023-08-02T16:00:00Z",47  "priority": 1,48  "notes": "Customer prefers delivery after 3pm",49  "payer_type": "sender",50  "payment_method": "wallet"51}

Query parameters

languageOptional
query string

en

Preferred language for response messages

Request body fields

requires_warehouse_stagingExample
boolean

Example field from the request body.

staging_warehouse_idExample
null

Example field from the request body.

is_replacementExample
boolean

Example field from the request body.

pickup_locationExample
object

Example field from the request body.

pickup_location.full_addressExample
string

Example field from the request body.

pickup_location.latExample
number

Example field from the request body.

pickup_location.longExample
number

Example field from the request body.

pickup_location.countryExample
string

Example field from the request body.

pickup_location.contact_infoExample
object

Example field from the request body.

pickup_location.contact_info.phoneExample
string

Example field from the request body.

pickup_location.contact_info.emailExample
string

Example field from the request body.

delivery_locationExample
object

Example field from the request body.

delivery_location.full_addressExample
string

Example field from the request body.

delivery_location.latExample
number

Example field from the request body.

delivery_location.longExample
number

Example field from the request body.

delivery_location.countryExample
string

Example field from the request body.

delivery_location.contact_infoExample
object

Example field from the request body.

delivery_location.contact_info.phoneExample
string

Example field from the request body.

delivery_location.contact_info.nameExample
string

Example field from the request body.

pickup_warehouse_idExample
null

Example field from the request body.

dropoff_warehouse_idExample
null

Example field from the request body.

delivery_service_idExample
string

Example field from the request body.

package_detailsExample
object

Example field from the request body.

package_details.special_instructionsExample
string

Example field from the request body.

package_details.itemsExample
array<object>

Example field from the request body.

package_details.items.nameExample
string

Example field from the request body.

package_details.items.descriptionExample
string

Example field from the request body.

package_details.items.quantityExample
number

Example field from the request body.

package_details.items.weightExample
number

Example field from the request body.

package_details.items.lengthExample
number

Example field from the request body.

package_details.items.widthExample
number

Example field from the request body.

package_details.items.heightExample
number

Example field from the request body.

customer_idExample
string

Example field from the request body.

external_reference_idExample
string

Example field from the request body.

statusExample
string

Example field from the request body.

scheduled_pickup_timeExample
string

Example field from the request body.

scheduled_delivery_timeExample
string

Example field from the request body.

priorityExample
number

Example field from the request body.

notesExample
string

Example field from the request body.

payer_typeExample
string

Example field from the request body.

payment_methodExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response201Created
Error - Invalid Payment Method400Bad Request
Error - Insufficient Wallet Balance400Bad Request
Error - Receiver User ID Required400Bad Request

Create Delivery (Carrier Routing)

Delivery & Last-Mile / Deliveries
POST/delivery/deliveries?language=en

Create a delivery using the carrier-aware routing engine (JSON-first). Behavior: - Provide pickup_location and delivery_location as JSON with lat/long/country. - Optional pickup_warehouse_id/dropoff_warehouse_id indicate warehouse endpoints. - Routing planner is JSON-only; it never fetches address records by id. Warehouse staging: - If requires_warehouse_staging=true, the API creates a HYBRID parent with 2 legs. - staging_warehouse_id is optional; if null, system auto-selects. - Guard: staging is supported ONLY for delivery_type "Pickup and Delivery"; otherwise API returns warehouse_staging_only_supported_for_pickup_and_delivery. Notes: - Pure PRIME eligibility requires carrier-enabled zones and at least one endpoint being a warehouse in a zone with configured warehouse. - HYBRID creates parent + two children and sequence plan. - Non-carrier flow unchanged when carrier_routing is false.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/delivery/deliveries?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "carrier_routing": true,7  "requires_warehouse_staging": false,8  "staging_warehouse_id": null,9  "pickup_location": {10    "full_address": "Baghdad HQ",11    "lat": 33.3152,12    "long": 44.3661,13    "country": "IQ"14  },15  "delivery_location": {16    "full_address": "Basra Customer",17    "lat": 30.5081,18    "long": 47.7835,19    "country": "IQ"20  },21  "pickup_warehouse_id": null,22  "dropoff_warehouse_id": null,23  "delivery_service_id": "uuid",24  "customer_id": "uuid",25  "payer_type": "sender",26  "payment_method": "wallet",27  "unit_size": 1,28  "notes": "Optional notes",29  "cod_amount": 0,30  "external_reference_id": "ORD-12345",31  "scheduled_pickup_time": "2025-09-30T10:00:00Z",32  "scheduled_delivery_time": "2025-09-30T12:00:00Z",33  "receiver_user_id": "uuid",34  "priority": 1,35  "package_details": {36    "special_instructions": "Handle with care",37    "items": [38      {39        "name": "Mobile phone",40        "description": "Mobile phone",41        "quantity": 1,42        "weight": 2.5,43        "length": 30,44        "width": 20,45        "height": 1546      }47    ]48  }49}'
Request body
json
1{2  "carrier_routing": true,3  "requires_warehouse_staging": false,4  "staging_warehouse_id": null,5  "pickup_location": {6    "full_address": "Baghdad HQ",7    "lat": 33.3152,8    "long": 44.3661,9    "country": "IQ"10  },11  "delivery_location": {12    "full_address": "Basra Customer",13    "lat": 30.5081,14    "long": 47.7835,15    "country": "IQ"16  },17  "pickup_warehouse_id": null,18  "dropoff_warehouse_id": null,19  "delivery_service_id": "uuid",20  "customer_id": "uuid",21  "payer_type": "sender",22  "payment_method": "wallet",23  "unit_size": 1,24  "notes": "Optional notes",25  "cod_amount": 0,26  "external_reference_id": "ORD-12345",27  "scheduled_pickup_time": "2025-09-30T10:00:00Z",28  "scheduled_delivery_time": "2025-09-30T12:00:00Z",29  "receiver_user_id": "uuid",30  "priority": 1,31  "package_details": {32    "special_instructions": "Handle with care",33    "items": [34      {35        "name": "Mobile phone",36        "description": "Mobile phone",37        "quantity": 1,38        "weight": 2.5,39        "length": 30,40        "width": 20,41        "height": 1542      }43    ]44  }45}

Query parameters

languageOptional
query string

en

Preferred language for response messages

Request body fields

carrier_routingExample
boolean

Example field from the request body.

requires_warehouse_stagingExample
boolean

Example field from the request body.

staging_warehouse_idExample
null

Example field from the request body.

pickup_locationExample
object

Example field from the request body.

pickup_location.full_addressExample
string

Example field from the request body.

pickup_location.latExample
number

Example field from the request body.

pickup_location.longExample
number

Example field from the request body.

pickup_location.countryExample
string

Example field from the request body.

delivery_locationExample
object

Example field from the request body.

delivery_location.full_addressExample
string

Example field from the request body.

delivery_location.latExample
number

Example field from the request body.

delivery_location.longExample
number

Example field from the request body.

delivery_location.countryExample
string

Example field from the request body.

pickup_warehouse_idExample
null

Example field from the request body.

dropoff_warehouse_idExample
null

Example field from the request body.

delivery_service_idExample
string

Example field from the request body.

customer_idExample
string

Example field from the request body.

payer_typeExample
string

Example field from the request body.

payment_methodExample
string

Example field from the request body.

unit_sizeExample
number

Example field from the request body.

notesExample
string

Example field from the request body.

cod_amountExample
number

Example field from the request body.

external_reference_idExample
string

Example field from the request body.

scheduled_pickup_timeExample
string

Example field from the request body.

scheduled_delivery_timeExample
string

Example field from the request body.

receiver_user_idExample
string

Example field from the request body.

priorityExample
number

Example field from the request body.

package_detailsExample
object

Example field from the request body.

package_details.special_instructionsExample
string

Example field from the request body.

package_details.itemsExample
array<object>

Example field from the request body.

package_details.items.nameExample
string

Example field from the request body.

package_details.items.descriptionExample
string

Example field from the request body.

package_details.items.quantityExample
number

Example field from the request body.

package_details.items.weightExample
number

Example field from the request body.

package_details.items.lengthExample
number

Example field from the request body.

package_details.items.widthExample
number

Example field from the request body.

package_details.items.heightExample
number

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success - Internal Only201Created
Success - Pure Prime201Created
Success - Hybrid (Parent)201Created
Error - Prime Price Missing400Bad Request

Get Delivery Receipt

Delivery & Last-Mile / Deliveries
GET/delivery/deliveries/:deliveryId/receipt?tenant_id=&language=en

Returns the primary signed receipt URL for a delivery. Access: - tenant admin / dispatcher with delivery module access - delivery owner customer Resolution priority: - COD_COLLECTION receipt - DELIVERY_FEE receipt

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/delivery/deliveries/:deliveryId/receipt?tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}"

Path parameters

deliveryIdRequired
path string

uuid

ID of the delivery whose receipt should be retrieved

Query parameters

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200OK

Update Delivery

Delivery & Last-Mile / Deliveries
PUT/delivery/deliveries/:deliveryId?tenant_id=&language=en

Update editable delivery fields such as notes, schedule, addresses, service, and package details. This endpoint does not perform delivery status transitions. Use POST /delivery/deliveries/:deliveryId/status for status changes. Locations & zones (admin): If the body includes any of pickup_location_id, delivery_location_id, delivery_service_id, or unit_size, the server re-resolves pickup_location / delivery_location JSON from address + warehouse ids, recomputes pickup_zone_id / dropoff_zone_id, and runs pricing. delivery_fee is updated from the new quote only when payment_status is not already paid (avoids desync after wallet charge). For package_details.items: - Items with id field (that exists in DB) will be updated - Items without id field will be created as new items - Items existing in DB but not present in the items array will be deleted

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request PUT "$ONDI_BASE_URL/delivery/deliveries/:deliveryId?tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "notes": "Updated delivery notes",7  "priority": 2,8  "scheduled_delivery_time": "2023-08-02T17:00:00Z",9  "package_details": {10    "special_instructions": "Handle with care",11    "items": [12      {13        "id": "uuid",14        "name": "Updated item name",15        "description": "Updated description",16        "quantity": 2,17        "weight": 3,18        "length": 35,19        "width": 25,20        "height": 2021      },22      {23        "name": "New item",24        "description": "New item description",25        "quantity": 1,26        "weight": 2.5,27        "length": 30,28        "width": 20,29        "height": 1530      }31    ]32  },33  "last_location": {34    "latitude": 37.7749,35    "longitude": -122.419436  }37}'
Request body
json
1{2  "notes": "Updated delivery notes",3  "priority": 2,4  "scheduled_delivery_time": "2023-08-02T17:00:00Z",5  "package_details": {6    "special_instructions": "Handle with care",7    "items": [8      {9        "id": "uuid",10        "name": "Updated item name",11        "description": "Updated description",12        "quantity": 2,13        "weight": 3,14        "length": 35,15        "width": 25,16        "height": 2017      },18      {19        "name": "New item",20        "description": "New item description",21        "quantity": 1,22        "weight": 2.5,23        "length": 30,24        "width": 20,25        "height": 1526      }27    ]28  },29  "last_location": {30    "latitude": 37.7749,31    "longitude": -122.419432  }33}

Path parameters

deliveryIdRequired
path string

uuid

ID of the delivery to update

Query parameters

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Request body fields

notesExample
string

Example field from the request body.

priorityExample
number

Example field from the request body.

scheduled_delivery_timeExample
string

Example field from the request body.

package_detailsExample
object

Example field from the request body.

package_details.special_instructionsExample
string

Example field from the request body.

package_details.itemsExample
array<object>

Example field from the request body.

package_details.items.idExample
string

Example field from the request body.

package_details.items.nameExample
string

Example field from the request body.

package_details.items.descriptionExample
string

Example field from the request body.

package_details.items.quantityExample
number

Example field from the request body.

package_details.items.weightExample
number

Example field from the request body.

package_details.items.lengthExample
number

Example field from the request body.

package_details.items.widthExample
number

Example field from the request body.

package_details.items.heightExample
number

Example field from the request body.

last_locationExample
object

Example field from the request body.

last_location.latitudeExample
number

Example field from the request body.

last_location.longitudeExample
number

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response200OK
Error - Unauthorized403Forbidden

Update Delivery Status

Delivery & Last-Mile / Deliveries
POST/delivery/deliveries/:deliveryId/status?tenant_id=&language=en

Update delivery status from the dispatcher/admin panel using the delivery workflow rules. Allowed target statuses: - pending - assigned - picked_up - in_transit - delivered - cancelled - returned Rules: - Requires manage:operations:tenant or manage:module:delivery - reason is optional - If the requested status needs an assignment and the delivery has no active assignment, the backend uses driver_id from the request first - If driver_id is not provided, the backend falls back to assignment_change_settings.default_driver_id from tenant settings - If neither source provides a driver, the request is rejected with driver_id_required_for_delivery_status - proof_of_delivery is optional when marking delivered - For picked_up, in_transit, and delivered, if tenant driver settings normally require accept/reject, the backend auto-considers acceptance and continues the transition - Active waybill deliveries are blocked - Non-internal deliveries are blocked except for cancelled - Uses assignment-aware status synchronization where required

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/delivery/deliveries/:deliveryId/status?tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "target_delivery_status": "delivered",7  "driver_id": "uuid",8  "notes": "Driver confirmed delivery by phone",9  "proof_of_delivery": {10    "signature_url": "https://example.com/signature.png",11    "photo_urls": [12      "https://example.com/photo-1.jpg"13    ]14  }15}'
Request body
json
1{2  "target_delivery_status": "delivered",3  "driver_id": "uuid",4  "notes": "Driver confirmed delivery by phone",5  "proof_of_delivery": {6    "signature_url": "https://example.com/signature.png",7    "photo_urls": [8      "https://example.com/photo-1.jpg"9    ]10  }11}

Path parameters

deliveryIdRequired
path string

uuid

ID of the delivery to update status for

Query parameters

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Request body fields

target_delivery_statusExample
string

Example field from the request body.

driver_idExample
string

Example field from the request body.

notesExample
string

Example field from the request body.

proof_of_deliveryExample
object

Example field from the request body.

proof_of_delivery.signature_urlExample
string

Example field from the request body.

proof_of_delivery.photo_urlsExample
array<string>

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response200OK
Error - Active Waybill409Conflict

Cancel Delivery

Delivery & Last-Mile / Deliveries
POST/delivery/deliveries/:deliveryId/cancel?tenant_id=&language=en

Cancel a delivery order. This endpoint: - Updates delivery status to 'cancelled' - Processes refunds for wallet payments - Sends notifications to customer Business Rules: - Allowed: tenant admin (manage:operations:tenant), delivery module manager (manage:module:delivery), or order owner (customer_id = authenticated user) - Cannot cancel deliveries that are already delivered, cancelled, or failed - Wallet payments are automatically refunded - Does not modify assignments or driver capacity Note: No request body required

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/delivery/deliveries/:deliveryId/cancel?tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json"

Path parameters

deliveryIdRequired
path string

uuid

ID of the delivery to cancel

Query parameters

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response200OK
Error - Delivery Not Found404Not Found
Error - Cannot Cancel Terminal Status400Bad Request
Error - Insufficient Permissions403Forbidden

Delete Delivery

Delivery & Last-Mile / Deliveries
DELETE/delivery/deliveries/:deliveryId?tenant_id=&language=en

Soft delete a delivery (marks as deleted but keeps in database). Only admin users can delete deliveries.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request DELETE "$ONDI_BASE_URL/delivery/deliveries/:deliveryId?tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}"

Path parameters

deliveryIdRequired
path string

uuid

ID of the delivery to delete

Query parameters

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200OK
Error - Insufficient Permissions403Forbidden

Create Bulk Deliveries

Delivery & Last-Mile / Deliveries
POST/delivery/deliveries/bulk?tenant_id=&language=en

Create multiple deliveries in bulk. Only admin users can create bulk deliveries. All deliveries in the batch must have the same bulk_group value.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/delivery/deliveries/bulk?tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '[6  {7    "pickup_location": {8      "full_address": "Baghdad HQ",9      "lat": 33.3152,10      "long": 44.3661,11      "country": "IQ"12    },13    "delivery_location": {14      "full_address": "Basra Customer",15      "lat": 30.5081,16      "long": 47.7835,17      "country": "IQ"18    },19    "package_details": {20      "special_instructions": "Handle with care",21      "items": [22        {23          "name": "Book",24          "description": "Book",25          "quantity": 1,26          "weight": 1.5,27          "length": 20,28          "width": 15,29          "height": 1030        }31      ]32    },33    "customer_id": "uuid",34    "status": "pending",35    "scheduled_pickup_time": "2023-08-02T10:00:00Z",36    "scheduled_delivery_time": "2023-08-02T14:00:00Z",37    "priority": 1,38    "bulk_group": "batch-2023-08-01"39  },40  {41    "pickup_location": {42      "full_address": "Baghdad HQ 2",43      "lat": 33.3152,44      "long": 44.3661,45      "country": "IQ"46    },47    "delivery_location": {48      "full_address": "Basra Customer 2",49      "lat": 30.5081,50      "long": 47.7835,51      "country": "IQ"52    },53    "package_details": {54      "special_instructions": "Handle with care",55      "items": [56        {57          "name": "Electronics",58          "description": "Electronics",59          "quantity": 2,60          "weight": 2.5,61          "length": 30,62          "width": 20,63          "height": 1564        }65      ]66    },67    "customer_id": "uuid",68    "status": "pending",69    "scheduled_pickup_time": "2023-08-02T11:00:00Z",70    "scheduled_delivery_time": "2023-08-02T15:00:00Z",71    "priority": 1,72    "bulk_group": "batch-2023-08-01"73  }74]'
Request body
json
1[2  {3    "pickup_location": {4      "full_address": "Baghdad HQ",5      "lat": 33.3152,6      "long": 44.3661,7      "country": "IQ"8    },9    "delivery_location": {10      "full_address": "Basra Customer",11      "lat": 30.5081,12      "long": 47.7835,13      "country": "IQ"14    },15    "package_details": {16      "special_instructions": "Handle with care",17      "items": [18        {19          "name": "Book",20          "description": "Book",21          "quantity": 1,22          "weight": 1.5,23          "length": 20,24          "width": 15,25          "height": 1026        }27      ]28    },29    "customer_id": "uuid",30    "status": "pending",31    "scheduled_pickup_time": "2023-08-02T10:00:00Z",32    "scheduled_delivery_time": "2023-08-02T14:00:00Z",33    "priority": 1,34    "bulk_group": "batch-2023-08-01"35  },36  {37    "pickup_location": {38      "full_address": "Baghdad HQ 2",39      "lat": 33.3152,40      "long": 44.3661,41      "country": "IQ"42    },43    "delivery_location": {44      "full_address": "Basra Customer 2",45      "lat": 30.5081,46      "long": 47.7835,47      "country": "IQ"48    },49    "package_details": {50      "special_instructions": "Handle with care",51      "items": [52        {53          "name": "Electronics",54          "description": "Electronics",55          "quantity": 2,56          "weight": 2.5,57          "length": 30,58          "width": 20,59          "height": 1560        }61      ]62    },63    "customer_id": "uuid",64    "status": "pending",65    "scheduled_pickup_time": "2023-08-02T11:00:00Z",66    "scheduled_delivery_time": "2023-08-02T15:00:00Z",67    "priority": 1,68    "bulk_group": "batch-2023-08-01"69  }70]

Query parameters

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Request body fields

pickup_locationExample
object

Example field from the request body.

pickup_location.full_addressExample
string

Example field from the request body.

pickup_location.latExample
number

Example field from the request body.

pickup_location.longExample
number

Example field from the request body.

pickup_location.countryExample
string

Example field from the request body.

delivery_locationExample
object

Example field from the request body.

delivery_location.full_addressExample
string

Example field from the request body.

delivery_location.latExample
number

Example field from the request body.

delivery_location.longExample
number

Example field from the request body.

delivery_location.countryExample
string

Example field from the request body.

package_detailsExample
object

Example field from the request body.

package_details.special_instructionsExample
string

Example field from the request body.

package_details.itemsExample
array<object>

Example field from the request body.

package_details.items.nameExample
string

Example field from the request body.

package_details.items.descriptionExample
string

Example field from the request body.

package_details.items.quantityExample
number

Example field from the request body.

package_details.items.weightExample
number

Example field from the request body.

package_details.items.lengthExample
number

Example field from the request body.

package_details.items.widthExample
number

Example field from the request body.

package_details.items.heightExample
number

Example field from the request body.

customer_idExample
string

Example field from the request body.

statusExample
string

Example field from the request body.

scheduled_pickup_timeExample
string

Example field from the request body.

scheduled_delivery_timeExample
string

Example field from the request body.

priorityExample
number

Example field from the request body.

bulk_groupExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response201Created
Error - Invalid Request Body400Bad Request
Error - Inconsistent Bulk Group400Bad Request

Handle Delivery Action

Delivery & Last-Mile / Deliveries
POST/delivery/action/:deliveryId?tenant_id=&language=en

Handle delivery status transitions by drivers. Only drivers can perform actions on their assigned deliveries. Supported Assignment Statuses: - assigned / accepted → en_route_to_pickup - en_route_to_pickup → picked_up - picked_up → en_route_to_delivery (delivery status transitions to in_transit) - en_route_to_delivery → completed (requires proof of delivery, delivery status transitions to delivered) Replacement Orders: - When completing a delivery with delivery_flow = 'replacement_forward', the response includes a replacement_return object. - This is the auto-created return delivery, already assigned to the same driver with assignment status en_route_to_pickup. - The driver should display this return delivery immediately — no refresh needed. - If the return creation fails, the forward delivery still succeeds; replacement_return is simply absent. COD Payment Record (after completion): - If the delivery payment method is COD, the system records a payments row for the COD amount only after the delivery is marked delivered. Note: If a delivery is still in picked_up status when completing (assignment status en_route_to_delivery), the system will automatically transition the delivery to in_transit first before marking it as delivered to ensure proper status flow. Proof of Delivery (required for completion): - signature_url (required): URL to the delivery signature image - photo_urls (required): Array of photo URLs (at least one photo required) - notes (optional): Additional delivery notes Location Tracking: - current_lat (optional): Current latitude for location tracking - current_lng (optional): Current longitude for location tracking - Route calculation is queued after the status transition so Google Directions latency does not delay the action response. - delivery_assignments.route_details may still contain the previous route immediately after this response and is updated asynchronously when calculation succeeds. Hybrid Parent Status: - Inbound leg status drives the parent through assigned, picked_up, in_transit, and arrived_at_warehouse. - Warehouse receiving sets the parent to staged_at_warehouse; assigning the outbound leg does not regress that stage. - Outbound pickup sets the parent to picked_up, outbound in-transit sets it to in_transit, and outbound completion sets it to delivered. - Parent status_updates inherit actor_id and actor_role from the child status event that caused the parent transition. Response: - Returns updated delivery object with current status - For replacement forwards, also returns replacement_return with the auto-created return delivery

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/delivery/action/:deliveryId?tenant_id=&language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "assignment_status": "en_route_to_delivery",7  "signature_url": "https://example.com/signatures/signature-123.png",8  "photo_urls": [9    "https://example.com/photos/photo-1.jpg",10    "https://example.com/photos/photo-2.jpg"11  ],12  "notes": "Optional delivery notes",13  "current_lat": "33.3152",14  "current_lng": "44.3661"15}'
Request body
json
1{2  "assignment_status": "en_route_to_delivery",3  "signature_url": "https://example.com/signatures/signature-123.png",4  "photo_urls": [5    "https://example.com/photos/photo-1.jpg",6    "https://example.com/photos/photo-2.jpg"7  ],8  "notes": "Optional delivery notes",9  "current_lat": "33.3152",10  "current_lng": "44.3661"11}

Path parameters

deliveryIdRequired
path string

uuid

ID of the delivery to perform action on

Query parameters

tenant_idOptional
query string

Tenant ID (optional if in auth token)

languageOptional
query string

en

Preferred language for response messages

Request body fields

assignment_statusExample
string

Example field from the request body.

signature_urlExample
string

Example field from the request body.

photo_urlsExample
array<string>

Example field from the request body.

notesExample
string

Example field from the request body.

current_latExample
string

Example field from the request body.

current_lngExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success - Delivery Completed200OK
Error - Missing Signature400Bad Request
Error - Missing Photos400Bad Request
Error - Insufficient Permissions403Forbidden