Cancellation
http
POST /api/vendor/v1/orders/{orderId}/cancelCancels a delivery that has not been picked up yet.
Request
http
POST /api/vendor/v1/orders/e5a9f0d3-7c21-4b88-a06e-3f9182bd4471/cancel
Authorization: Bearer <token>
Content-Type: application/jsonjson
{
"reason": "CustomerCancelled"
}reason | Use when |
|---|---|
CustomerCancelled | The customer called off the order |
RestaurantCancelled | The restaurant cannot fulfil it |
AddressProblem | The address turned out to be wrong or unreachable |
Other | Anything else — add detail in note |
An optional note (max 250 characters) can accompany any reason.
Response
json
{
"success": true,
"message": "Order cancelled.",
"data": {
"orderId": "e5a9f0d3-7c21-4b88-a06e-3f9182bd4471",
"status": "Cancelled",
"cancelledAt": "2026-08-04T18:49:11+03:00"
}
}The cutoff is pickup
Once the courier has the package, cancellation is refused:
json
{
"success": false,
"message": "The package has been picked up by the courier and cannot be cancelled.",
"data": { "errorCode": "CANCEL_TOO_LATE", "status": "PickedUp" }
}There is no way around this through the API. The courier is carrying goods; what happens next is a conversation between the restaurant and the fleet.
Practically: hide or disable the cancel control in your interface as soon as you see PickedUp, either from the webhook or a status query. Letting a user press a button that is guaranteed to fail is worse than not showing it.
Billing
Cancelled deliveries are not billed. Neither are Failed ones. Only Delivered counts.