Delivery status webhook

Receive a call on your server each time a delivery you dispatched changes status: driver assigned, at pickup, picked up, at drop-off, delivered, cancelled.

1. Register your endpoint

Register once, with the same API key you use for quotes and cancels. One endpoint per integration: every delivery you dispatch is reported there. It works the same way as the push_order webhook: we send back the header you give us, so you can check the call comes from OrderOut.

curl -X POST https://api.orderout.co/api/webhooks/delivery_status \
  -H "api-key: $ORDEROUT_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "endpoint": "https://example.com/orderout/delivery-status",
    "method": "POST",
    "authorization_header": {"Authorization": "Bearer your-secret"}
  }'
  • endpoint must be a public https (or http) URL.
  • method is required: POST, PUT, GET or DELETE (case doesn't matter). We recommend POST.
  • authorization_header is required: a JSON object of header names to values, sent back on every call. Use {} if you don't need one.
  • GET /api/webhooks/delivery_status returns your registration, and DELETE /api/webhooks/delivery_status removes it. To change the URL, delete it and register again. A second POST answers 409.

2. What you receive

{
  "event": "delivery.en_route_dropoff",
  "event_id": "5843160318214144:3",
  "emitted_at": "2026-10-15T18:42:10.512Z",
  "source": {
    "order_id": "4743465852338176",
    "delivery_id": "5843160318214144",
    "tracker_id": "5b1f3c20-0e4a-11f1-8c2d-3f9a7e6b1d42"
  },
  "destination": {
    "restaurantId": "5343190423044096",
    "restaurantName": "Acme's Restaurant"
  },
  "payload": {
    "status": "en_route_dropoff",
    "driver": {
      "name": "Sam R.",
      "phone": "+15555550188",
      "latitude": 40.7398,
      "longitude": -73.9903,
      "transport_type": "Bicycle"
    },
    "tracking_url": "https://trackdelivery.io/?orderId=5b1f3c20-0e4a-11f1-8c2d-3f9a7e6b1d42",
    "eta_pickup": "2026-10-15T18:31:00.000Z",
    "eta_dropoff": "2026-10-15T18:44:00.000Z"
  }
}
  • source.order_id is the order_id returned by POST /api/channel/order/push. delivery_id is the id you can also pass to Cancel Order.
  • Driver fields are null until a driver is assigned.
  • Every update has its own event_id: <delivery_id>:<n>, where n goes up by one for each update of that delivery. Use n (or emitted_at) to put updates in order. The same status can arrive more than once: the courier network may send it again, and after a reassign the new driver's statuses start over from en_route_pickup. Outside a reassign, treat a status you already have as a repeat.
  • Each update is sent once. If your endpoint is down or answers an error, that update is not sent again, so answer quickly (any 2xx) and do your processing afterwards.

3. Statuses

StatusMeaning
scheduledThe delivery is booked and waiting for a driver.
en_route_pickupA driver is assigned and on the way to the restaurant.
arrived_pickupThe driver is at the restaurant.
en_route_dropoffThe driver picked up the order and is on the way to the customer.
arrived_dropoffThe driver is at the customer's address.
completedDelivered.
reassignThe delivery moved to another courier. The previous one may then report cancelled, followed by a new en_route_pickup.
cancelledThe delivery was cancelled, by you, the restaurant or the courier network. After a reassign, a cancelled is not final.
unknownA status we don't recognise yet.

The first update you receive is usually scheduled. Answer 2xx to any event you don't handle, including ones not listed here. payload.status always carries the delivery's current status.

❗️

Deliveries on api.orderout.co are real

A delivery not cancelled before a driver is assigned costs a $10 cancellation fee, for you and for OrderOut.


Did this page help you?