Skip to content

Orders

Create and manage delivery orders. An order ships a package from one of your branches to a customer's address.

List orders

GET /integration/merchant/order

Returns a paginated list of your orders. Useful for reconciliation and dashboards.

Query parameters (all optional):

ParameterTypeNotes
pagenumberPage number (default 1).
limitnumberItems per page (default 20, max 100).
statusstringFilter by status. Defaults to all statuses except cancelled.
dateFrom / dateToISO dateFilter by creation date range.
referenceNumberstringFilter by your orderMerchantReferenceNumber.
sandbox1Include only sandbox orders.

Response: 200 OK

json
{
  "success": true,
  "data": {
    "list": [ /* order objects */ ],
    "pagination": { "page": 1, "limit": 20, "total": 42 }
  }
}

Create an order

POST /integration/merchant/order

Request body:

json
{
  "customerId": "<customer-id>",
  "customerAddressId": "<address-id>",
  "branchCode": "MAIN",
  "specialHandlingTags": ["none"],
  "paymentMethod": "cod",
  "amountToCollect": 12.500,
  "pricing": { "subtotal": 11.000, "deliveryFee": 1.500, "total": 12.500 },
  "items": [
    { "name": "T-Shirt", "sku": "TS-01", "qty": 2, "price": 5.500 }
  ],
  "merchantNotes": "Leave at reception",
  "orderMerchantReferenceNumber": "WEB-10042"
}
FieldRequiredNotes
customerIdYesA customer that belongs to your merchant.
customerAddressIdNoWhich address to deliver to. Defaults to the customer's default address.
branchId or branchCodeYesThe pickup branch. Use either the branch's _id or its code.
specialHandlingTagsYesArray; at least one tag required. Use ["none"] if nothing special. Allowed: fragile, liquid, heavy, oversized, temperature_sensitive, food, flowers, other, none.
paymentMethodNocod or prepaid (default).
amountToCollectCOD onlyRequired and non-negative for COD. Cannot exceed pricing.total.
pricingNo{ subtotal, deliveryFee, total }. If deliveryFee is omitted, Wasal resolves it automatically from your pricing zones for the delivery area.
itemsNoLine items: { name, sku, qty, price }.
merchantNotesNoInternal note shown to the driver.
agentNotesNoNote for the delivery agent.
orderMerchantReferenceNumberNoYour own reference (e.g. ecommerce order number). Echoed back and used for reconciliation.
packageSideNoOne of front, back, left, right, top, bottom, other.
packagePhotoUrlsNoArray of photo URLs. Required if your merchant has requirePackagePhoto enabled.
scheduledPickupAt, scheduledDeliveryAtNoISO timestamps.
forceDraftNotrue saves the order as a draft regardless of the order window.

Response: 201 Created

json
{
  "success": true,
  "data": {
    "order": { "_id": "665f...", "orderNumber": "MAIN-000123", "status": "pending" }
  }
}

Order window & drafts. If the delivery partner's order window is closed (or you pass forceDraft: true), the order is created as a draft and is not dispatched until activated. Otherwise it enters the live queue immediately.

Wallet. Production orders deduct the delivery fee from your Wasal wallet. If the balance is insufficient you receive 400 INSUFFICIENT_WALLET_BALANCE with the required amount and current balance. Sandbox orders never touch the wallet.

Get an order

GET /integration/merchant/order/:orderId

Returns the full order document — status, customer snapshot, pricing, items, assigned agent (if any), and timestamps.

Update an order

PUT /integration/merchant/order/:orderId

Updates mutable fields on a draft or pending order. Only the fields you send are changed; all others remain unchanged.

Editable fields:

FieldNotes
merchantNotesInternal note for the driver.
agentNotesNote for the delivery agent.
orderMerchantReferenceNumberYour reference number.
itemsReplaces the full items array.
pricing{ subtotal, deliveryFee, total }.
paymentMethodcod or prepaid.
amountToCollectCOD amount.
scheduledPickupAt, scheduledDeliveryAtISO timestamps.

Response: 200 OK — updated order object.

Activate a draft order

PUT /integration/merchant/order/:orderId/activate

Dispatches a draft order into the live queue. The order window must be open at the time of activation.

Response: 200 OK — order with status: "pending".

Returns 400 ORDER_WINDOW_CLOSED if the delivery partner's order window is not currently open.

Cancel an order

PUT /integration/merchant/order/:orderId/cancel

Cancels an order that has not yet been delivered. Sets the status to cancelled and records the cancellation timestamp.

Order status history

GET /integration/merchant/order/:orderId/history

Returns the chronological statusHistory[] — each entry includes the status, timestamp, an optional note, and who made the change. Use this to render a timeline.

Agent live location

GET /integration/merchant/order/:orderId/agent-location

Returns the assigned agent's latest location while the order is in transit. Returns no location if no agent is assigned, the agent is offline, or the order is not in an active delivery status.

Shipping label

GET /integration/merchant/order/:orderId/label

Returns a printable PDF shipping label for the order. The response Content-Type is application/pdf.

Order lifecycle

StatusMeaning
draftCreated but not yet dispatched (order window closed or forceDraft).
pendingIn the live queue, awaiting a driver.
assignedA driver has accepted the order.
on_way_to_merchantDriver is heading to your branch for pickup.
picked_upDriver has collected the package.
in_transitEn route to the customer.
deliveredSuccessfully delivered (terminal).
failedDelivery failed (terminal).
returnedReturned to merchant (terminal).
cancelledCancelled (terminal).

In the sandbox, you advance these statuses yourself via the advance-status endpoint. In production, real drivers move the order and you observe the changes via polling or webhooks.

Errors

HTTPcodeMeaning
400CUSTOMER_REQUIREDcustomerId missing.
400SPECIAL_HANDLING_REQUIREDspecialHandlingTags empty.
400INVALID_SPECIAL_HANDLING_TAGA tag is not in the allowed list.
400INVALID_PACKAGE_SIDEpackageSide not in the allowed list.
400INVALID_AMOUNT_TO_COLLECTCOD amount missing or negative.
400AMOUNT_EXCEEDS_TOTALCOD amount greater than pricing.total.
400PACKAGE_PHOTO_REQUIREDMerchant requires a package photo.
400VALIDATION_FAILEDOther field errors — see errors.
400INSUFFICIENT_WALLET_BALANCEWallet cannot cover the delivery fee (production only).
400ORDER_NOT_DRAFTActivate was called on an order that is not a draft.
400ORDER_WINDOW_CLOSEDActivate was called outside the delivery partner's order window.
404CUSTOMER_NOT_FOUNDCustomer not found or not linked to your merchant.
404CUSTOMER_NO_DELIVERY_ADDRESSCustomer has no address.

See the full Error Reference.

Wasal Delivery Platform · Integration API v1.0.0