Custom courier API
Hand your own courier's API to the dispatch screen.
NCM and Pathao connect with their own credentials under Settings → Delivery. Every other delivery company works through one webhook: paste a URL under Any other courier, and each dispatch is POSTed to it as JSON. Anything that can receive an HTTP request is now a courier — a Google Apps Script that appends to a Sheet, a Zapier or n8n hook that sends a Viber message, or the courier's own order intake if it has one.
The request is POST, content-type: application/json, with a ten-second timeout. This is the body:
{
"version": 1,
"dispatchId": "b7c1…", // unique per attempt — use it for idempotency
"sentAt": "2026-09-01T09:15:00.000Z",
"shop": { "tenantId": "…", "name": "Sunrise Collection" },
"orderNumber": "SO-40391",
"customer": { "name": "Priya Shrestha", "phone": "98…", "email": null },
"address": { "line": "Baluwatar, house 12", "city": "Kathmandu",
"area": "Baluwatar", "landmark": "opposite the pharmacy" },
"items": [
{ "name": "Fancy T-Shirt", "qty": 2, "unitPrice": 1200, "sku": "TS-RED-M" }
],
"codAmount": 2400, // rupees to collect on delivery; 0 if paid online
"orderTotal": 2400, // what the parcel is worth, collected or not
"weightGrams": 400, // null when the shop did not weigh it
"instructions": "Call before 6pm"
}Check the version. It is 1 today and will only change for a breaking change — refuse a version you do not recognise rather than guessing at it.
The reply can be almost anything. Any 2xx counts as booked, including a bare OK. If the body happens to be JSON containing a tracking_number, tracking_id, id or reference — at the top level or under data — that value is recorded against the order as the tracking number, and a tracking_url is recorded as the link. Nothing is required. Anything other than 2xx is recorded as a failed dispatch with your response body attached, so you can read your own error message in BaseBlock.
Nothing is ever retried. A courier booking is not idempotent — a retry is a second van — so a failure waits for somebody to press the button again.
Verifying it came from us. Set a signing secret and every request carries an X-BaseBlock-Signature header: HMAC-SHA256 of the exact request body, hex-encoded, keyed with your secret. Verify against the raw bytes you received, not against a re-serialised object — re-encoding the JSON first is the single most common reason a webhook signature “randomly” fails.
Your URL must be https and reachable from the internet. Addresses on private networks, loopback and cloud metadata endpoints are refused when you save the setting and again on every request, which is why a URL that works from your laptop may still be rejected here.