Drop Docs
Webhooks
Order and delivery state changes are asynchronous. Configure a webhook endpoint, verify the Drop signature, and process Drop lifecycle events idempotently.
Outbound webhooks are automatic. Once a merchant has an active webhook endpoint configured, Drop sends events to that endpoint whenever state changes happen inside Drop. No manual trigger is required for normal event delivery.
order.created
Order request accepted by Drop.
order.driver_assigned
A driver accepted the assignment.
order.arrived_pickup
Driver reached the pickup point.
order.picked_up
Driver has collected the package.
order.in_transit
Order is on the way to the customer.
order.delivered
Delivery completed successfully.
order.failed
Delivery failed and requires reconciliation.
order.cancelled
Order cancelled before completion.
Example webhook payload
json{
"id": "evt_8d2e5db7-4d93-4b8c-a6d3-2d96d3a1f2c7",
"type": "order.in_transit",
"created_at": "2026-04-12T10:15:22.431Z",
"data": {
"order_id": "cmnuz0bc80004nz01purkbm81",
"reference": "ORD-2026-1042",
"merchant_id": "cmngd6cjl0000ni01nt15bfeb",
"store_id": "cmngd6clq0002ni01juetjbc1",
"order_status": "IN_TRANSIT",
"delivery_id": "cmnuz0bc80005nz01x1j2a3b4",
"delivery_status": "IN_TRANSIT",
"tracking_url": "https://dropsa.co.za/track/cmnuz0bc80007nz01cwr1kqj8",
"driver": {
"id": "drv_01",
"first_name": "Lerato",
"last_name": "Mokoena",
"phone": "+27825550123"
},
"customer": {
"id": "cus_01",
"name": "Lebo Ndlovu",
"phone": "+27825550124"
},
"customer_note": "Please call when outside.",
"proof_of_delivery": null,
"driver_id": "drv_01"
}
}Signature header
textx-drop-signature: t=1711111111,v1=<hex_hmac_signature>Node.js signature verification
jsimport crypto from "node:crypto";
const payload = rawBody;
const header = req.headers["x-drop-signature"];
const secret = process.env.DROP_WEBHOOK_SECRET;
const [timestampPart, signaturePart] = header.split(",");
const timestamp = timestampPart.split("=")[1];
const signature = signaturePart.split("=")[1];
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${payload}`)
.digest("hex");
if (expected !== signature) {
throw new Error("Invalid webhook signature");
}