Orders
5 API calls in this section.
Create Order
/customer/delivery/ordersCreates a delivery order from the authenticated customer portal. When tenant setting delivery_external_reference.unique_per_customer=true (default), a non-empty external_reference_id must be unique among this customer root orders; duplicates return HTTP 400 external_reference_id_already_exists. When false, duplicates are allowed. The backend enforces customer_id from the access token and calculates unit size from package dimensions.
Package contract
Single package: send
package.weight,package.length,package.width, andpackage.height. These values are stored at the top level ofdeliveries.package_detailsand used to calculateunit_size.Multipart shipment: send
package.items[]. Each item is persisted indelivery_package_items;deliveries.package_detailsis rebuilt as the item/totals/status-summary object.Package details are optional; when no usable measurements exist,
general.unit_size.settings.missing_unit_size_fallbackselects service minimum, half of service maximum, service maximum, or rejects the request.Optional
is_draft=truecreates the order as Draft; it may be sent in the JSON body or as?is_draft=true. Missing or false preserves the current Pending behavior. For a wallet-paid draft, the fee moves from usablebalancetoreservedwithout creating a wallet transaction or payment. Execute captures the reservation and creates the delivery-fee transaction; cancelling the draft releases it back to usable balance. Draft orders do not queue driver assignment until Execute.
Warehouse staging
The frontend does not send
requires_warehouse_stagingorstaging_warehouse_id.The backend resolves the selected delivery service's effective warehouse policy.
When
warehouse_policies.pickup_delivery_required=true, the backend selects the configured default staging warehouse or appliesstaging_selection_strategy.A staged order creates a parent delivery and two child legs: pickup to warehouse, then warehouse to delivery.
When
package.itemsis absent or empty, the backend creates one fallback warehouse inventory item named from the delivery code and customer name; it usespackage.weightwhen supplied.Staged P&D database persistence is atomic: the parent, A/B legs, package items, inventory items, receiving order, and sequence plan either all commit or all roll back. Automatically allocated inventory item codes skip codes already claimed manually.
Payment
Use payment.method_id (UUID from GET /customer/delivery/payment-methods).
Wallet:
method_id= wallet UUID. Pending orders charge immediately. Draft orders reserve first and charge only when executed.COD/cash:
method_id= cod UUID.payment.cod_amountis optional goods COD money; omit it or send 0 for fee-only orders. Positive values remain independent from the delivery fee and must fit tenant COD min/max settings.Gateway (
e.g. Nass):method_id= gateway UUID,back_refREQUIRED (return URL).
Frontend integration contract
For a single package, submit package dimensions directly and do not create an item row.
For multipart, submit
package.items; its item summary replaces the direct package-details shape.Do not require COD amount for fee-only orders. Omit
payment.cod_amountor send numeric 0; do not submit an empty string.Do not prompt for or submit a staging warehouse.
Use
data.order.idas the parent order ID anddata.childrenfor staged leg details.Handle HTTP 400 for non-delivery service types, unresolved warehouse, ambiguous warehouse selection, unavailable route segments, invalid payment method, or invalid positive COD amount.
Default the create-as-draft checkbox to false. The backend accepts either body
is_draft: trueor query?is_draft=true. Dispatcher Execute should callPOST /delivery/deliveries/:deliveryId/statuswith{ "target_delivery_status": "pending" }.
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
pickup | object | — |
pickup.location | object | — |
pickup.location.full_address | string | — |
pickup.location.latitude | number | — |
pickup.location.longitude | number | — |
pickup.location.country | string | — |
pickup.location.city | string | — |
pickup.location.state | string | — |
pickup.location.postal_code | string | — |
pickup.location.contact_info | object | — |
pickup.location.contact_info.name | string | — |
pickup.location.contact_info.phone | string | — |
Show 31 more body fields
Additional body parameters
| Parameter | Type | Description |
|---|---|---|
pickup.scheduled_pickup_time | string | — |
dropoff | object | — |
dropoff.location | object | — |
dropoff.location.full_address | string | — |
dropoff.location.latitude | number | — |
dropoff.location.longitude | number | — |
dropoff.location.country | string | — |
dropoff.location.city | string | — |
dropoff.location.state | string | — |
dropoff.location.postal_code | string | — |
dropoff.location.contact_info | object | — |
dropoff.location.contact_info.name | string | — |
dropoff.location.contact_info.phone | string | — |
dropoff.scheduled_delivery_time | string | — |
delivery_service_id | string | — |
payer_type | string | — |
payment | object | — |
payment.method_id | string | — |
external_reference_id | string | — |
is_draft | boolean | — |
notes | string | — |
special_instructions | string | — |
package | object | — |
package.items | array<object> | — |
package.items.name | string | — |
package.items.quantity | number | — |
package.items.description | string | — |
package.items.weight | number | — |
package.items.length | number | — |
package.items.width | number | — |
package.items.height | number | — |
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/customer/delivery/orders" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "pickup": {6 "location": {7 "full_address": "123 Main St, New York, NY 10001, US",8 "latitude": 40.7128,9 "longitude": -74.006,10 "country": "US",11 "city": "New York",12 "state": "NY",13 "postal_code": "10001",14 "contact_info": {15 "name": "John Doe",16 "phone": "+1234567890"17 }18 },19 "scheduled_pickup_time": "2026-02-05T10:00:00Z"20 },21 "dropoff": {22 "location": {23 "full_address": "456 Oak Ave, Brooklyn, NY 11201, US",24 "latitude": 40.7589,25 "longitude": -73.9851,26 "country": "US",27 "city": "Brooklyn",28 "state": "NY",29 "postal_code": "11201",30 "contact_info": {31 "name": "Jane Smith",32 "phone": "+1987654321"33 }34 },35 "scheduled_delivery_time": "2026-02-05T14:00:00Z"36 },37 "delivery_service_id": "uuid",38 "payer_type": "sender",39 "payment": {40 "method_id": "0760f75f-4aee-4776-afc0-4057d7ad458f"41 },42 "external_reference_id": "ORD-12345",43 "is_draft": false,44 "notes": "Handle with care",45 "special_instructions": "Fragile items",46 "package": {47 "items": [48 {49 "name": "Product A",50 "quantity": 2,51 "description": "Electronics",52 "weight": 1.5,53 "length": 30,54 "width": 20,55 "height": 1556 },57 {58 "name": "Product B",59 "quantity": 1,60 "description": "Clothing",61 "weight": 0.5,62 "length": 25,63 "width": 15,64 "height": 1065 }66 ]67 }68}'Response examples
1{2 "success": false,3 "code": "invalid_payer_type",4 "message": "Invalid payer type",5 "field": "payer_type"6}List Orders
/customer/delivery/ordersLists the authenticated customer's delivery orders with filters and pagination. Every row includes compact pickup.location and dropoff.location objects containing the nullable localized title map and full_address; existing from and to strings remain unchanged. Every row also includes the nullable relationship fields return_delivery_id, return_delivery_code, original_delivery_id, and original_delivery_code. An original delivery populates the return_delivery_* pair; a return delivery populates the original_delivery_* pair. The values come from the maintained delivery projection, so this list performs no per-row return lookup or join. return_eligible is true only for a delivered order without an existing return relationship. For a linked operational return, the original/P&D parent has literal status=returning only after physical pickup or in-transit starts; assignment alone keeps it staged_at_warehouse.
Query parameters
| Parameter | Type | Description |
|---|---|---|
page | string | Page number (>=1) Example: |
limit | string | Items per page (1-50) Example: |
status | string | Filter by status Example: |
payment_methodOptional | string | Filter by payment method (wallet/cod) |
payment_statusOptional | string | Filter by payment status: pending, paid, failed, or refunded |
payer_typeOptional | string | Filter by payer type: sender | receiver |
start_dateOptional | string | Start date filter (ISO format) |
end_dateOptional | string | End date filter (ISO format) |
searchOptional | string | Search by delivery code or reference |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/customer/delivery/orders?page=1&limit=10&status=pending" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"Response examples
1{2 "success": true,3 "data": {4 "orders": [5 {6 "id": "delivery-uuid",7 "source_transfer_manifest_id": "manifest-uuid"8 }9 ],10 "pagination": {11 "page": 1,12 "limit": 10,13 "total": 114 }15 }16}Export Orders (CSV)
/customer/delivery/orders/exportStreams a CSV export of the customer's orders using the same filters as List Orders. Supports realtime progress (stream) and abort by canceling the HTTP request.
Response headers
Content-Disposition (filename)
X-Total-Rows (for progress)
X-Export-Tenant-Id
X-Export-Customer-Id
text/csv
Query parameters
| Parameter | Type | Description |
|---|---|---|
statusOptional | string | Filter by status Example: |
debugOptional | string | Debug mode (local/dev only; returns JSON with counts instead of CSV) Example: |
payment_methodOptional | string | Filter by payment method |
payment_statusOptional | string | Filter by payment status: pending, paid, failed, or refunded |
payer_typeOptional | string | Filter by payer type: sender | receiver |
start_dateOptional | string | Start date (YYYY-MM-DD or ISO) Example: |
end_dateOptional | string | End date (YYYY-MM-DD or ISO) Example: |
searchOptional | string | Search by delivery code/reference |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/customer/delivery/orders/export?status=pending&start_date=2026-03-01&end_date=2026-03-03" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"Response examples
No saved response example. Use Try it to inspect a staging response.
Get Order
/customer/delivery/orders/:idGets full order details for a delivery owned by the authenticated customer. data.order.notes and data.order.special_instructions are separate nullable fields; when a package snapshot is present, data.order.package.special_instructions contains the same handling instructions saved from the create request. data.order.pickup.location.title and data.order.dropoff.location.title contain the nullable localized title map captured in each historical delivery-location snapshot; clients should read the requested language key and fall back to full_address when it is missing or empty. data.order also includes the nullable relationship fields return_delivery_id, return_delivery_code, original_delivery_id, and original_delivery_code. For an original order, data.return_delivery contains the linked return's basic id, delivery_code, status, and customer-visible driver. For a return order, data.original_delivery has the same shape. A linked operational return changes the canonical original/P&D parent to literal data.order.status=returning at physical pickup/in-transit and to returned at completion; data.order.return_status remains the separate return lifecycle. Driver is null when customer portal driver visibility is disabled or no driver is assigned. Existing return_request metadata remains on the order. Returns 404 when the order is absent or not owned by the customer, and 500 when delivery or return-context lookup fails.
Path parameters
| Parameter | Type | Description |
|---|---|---|
idRequired | string | Delivery order ID Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/customer/delivery/orders/${ID}" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"Response examples
1{2 "success": true,3 "data": {4 "order": {5 "id": "delivery-uuid",6 "source_transfer_manifest_id": "manifest-uuid",7 "pickup": {8 "location": {9 "title": {10 "en": "Processing point"11 },12 "full_address": "100 Meter Road, Erbil"13 }14 }15 }16 }17}Cancel Order
/customer/delivery/orders/:id/cancelCancels an order owned by the authenticated customer. Cancellation is blocked transactionally with HTTP 409 cannot_cancel_delivery_after_driver_assignment once any assignment in the logical order is active, and with HTTP 409 cannot_cancel_delivery_in_terminal_status after final delivery or another terminal logical state. For staged/P&D, the parent or any operational child ID resolves to the canonical parent; a completed inbound warehouse leg does not block cancellation while final delivery remains incomplete. Paid family delivery fees and collected COD are refunded once to the sender wallet, and the success response returns the canonical root order ID.
Path parameters
| Parameter | Type | Description |
|---|---|---|
idRequired | string | Delivery order ID 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/customer/delivery/orders/${ID}/cancel" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "reason": "Customer requested cancellation"6}'Response examples
1{2 "success": true,3 "data": {4 "order": {5 "id": "uuid",6 "status": "cancelled",7 "updated_at": "2026-02-04T12:00:00Z"8 }9 }10}