Webhooks

Introduction

Burq webhooks allow you to receive real-time updates when events occur across your deliveries, routes, and orders, without polling the API.

You can configure multiple webhook URLs, each subscribed to a specific set of event types. For example, one URL can receive delivery status updates while another receives route dispatch events.

Setup

Go to the Developer section of the Burq Dashboard to manage your webhooks.

Click Add Webhook, enter your endpoint URL, and select the event types you want to receive. A single URL can subscribe to any combination of events, and the same event can be sent to multiple URLs.

Webhook URLs are configured separately for production and test environments — use the environment toggle at the top of the screen to make sure you're configuring the right one.

Event Types

Delivery Events

EventDescription
delivery.updatedFired when a delivery status changes, or when pickup_eta or dropoff_eta updates.
delivery.courier_location_updatedFired when Burq receives a driver location update from a provider.
delivery.reroutedFired when a delivery is rerouted to a different provider.
delivery_incident.createdFired when a delivery incident (e.g. cancellation, dispute) is created.
delivery_incident.updatedFired when a delivery incident is updated.

Route Events

EventDescription
route.quote_creation_startedFired when quote generation begins for a route.
route.quote_creation_completeFired when quotes are ready for a route.
route.quote_creation_failedFired when quote generation fails.
route.quote_createdFired when an individual route quote is created.
route.dispatchedFired when a route dispatch completes — successfully or not. Check the success field before treating it as a success.
route.updatedFired when a route status changes.
route.canceledFired when an asynchronous route cancellation completes — successfully or not. Check the success field.

Batch Events

EventDescription
batch.order_creation_startedFired when batch order creation begins.
batch.order_creation_completeFired when batch orders are successfully created.
batch.order_creation_failedFired when batch order creation fails.
batch.route_creation_startedFired when batch route creation begins.
batch.route_creation_completeFired when batch routes are successfully created.
batch.route_creation_failedFired when batch route creation fails.
batch.quote_creation_startedFired when batch quote generation begins.
batch.quote_creation_completeFired when batch quotes are ready.
batch.quote_creation_failedFired when batch quote generation fails.
batch.vehicle_recommendation_startedFired when vehicle recommendation begins for a batch.
batch.vehicle_recommendation_completeFired when vehicle recommendation completes.
batch.vehicle_recommendation_failedFired when vehicle recommendation fails.

Webhook Request Payload

All webhook events share the same top-level envelope:

{
  "object": "event",
  "type": "delivery.updated",
  "data": {
    // Event-specific payload
  }
}

For delivery events, the data object is a Delivery resource. You can find full property documentation in Creating Delivery Requests.

The status_history field on the Delivery resource records each status transition with its timestamp:

"status_history": [
  { "status": "delivery_created", "created": "2022-11-26T19:05:24.000Z" },
  { "status": "driver_assigned", "created": "2022-11-26T19:05:34.000Z" },
  { "status": "enroute_pickup", "created": "2022-11-26T19:05:38.000Z" },
  { "status": "arrived_at_pickup", "created": "2022-11-26T19:15:49.000Z" },
  { "status": "pickup_complete", "created": "2022-11-26T19:16:00.000Z" },
  { "status": "enroute_dropoff", "created": "2022-11-26T19:21:00.000Z" },
  { "status": "arrived_at_dropoff", "created": "2022-11-26T19:40:00.000Z" },
  { "status": "delivered", "created": "2022-11-26T19:41:00.000Z" }
]

delivery.rerouted

When a delivery is rerouted, Burq cancels the original and creates a new delivery with a new ID — future updates will only be sent under the new delivery ID. The payload includes both:

{
  "object": "event",
  "type": "delivery.rerouted",
  "data": {
    "parent_delivery": {
      // Original Delivery resource
    },
    "child_delivery": {
      // New Delivery resource
    }
  }
}

delivery_incident.created / delivery_incident.updated

The data object is a Delivery Incident resource — see GET Delivery Incident for the full schema.

Handling Events

Terminal — the operation is over, no further event is coming

EventConditionWhat it means
route.dispatchedsuccess: falseDispatch failed. The route is failed and no deliveries are live. Inspect the error object. Re-dispatching requires a new quote.
route.dispatchedsuccess: trueDispatch succeeded for at least one order. Track progress per delivery via delivery.updated from here.
route.canceledsuccess: falseCancellation failed. The route is not canceled and its deliveries may still be live. Inspect error and retry or escalate.
route.canceledsuccess: trueThe route and its deliveries are canceled. Expect a matching terminal delivery.updated per delivery.
route.quote_creation_failedNo quotes were produced. The route cannot be dispatched as-is.
batch.order_creation_failedNo orders were created from the batch.
batch.route_creation_failedOnly fires when auto_route: true. Orders may still exist; routes do not.
batch.quote_creation_failedOnly fires when auto_quote: true.
batch.vehicle_recommendation_failedOnly fires when recommend_vehicle: true.
delivery.updatedstatus is delivered or disputedThe delivery was fulfilled.
delivery.updatedstatus is provider_canceled, customer_canceled, burq_canceled, or failed and reroute.reroute_status is not_reroutable, disabled_for_account, or not_applicableThe delivery is canceled and will not resume. When not_reroutable, reroute.not_rerouted_reason explains why.
delivery.reroutedTerminal for parent_delivery.id only. All future events arrive under child_delivery.id
delivery_incident.createdFollows a provider_canceled deliveryAlways raised when a provider cancels. Not raised for most merchant-initiated cancellations.

Non-terminal — cancelled, but Burq is still working the order

A cancelled delivery status does not mean the order has failed. Any cancel status — provider_canceled, burq_canceled, or customer_canceled — can be the first step of a reroute. Always check reroute.reroute_status before treating a cancellation as final.

EventConditionWhat it means
delivery.updatedreroute.reroute_status is provider_searchBurq is sourcing a replacement provider. Do not surface this as a failure. Wait for either delivery.rerouted, or a follow-up delivery.updated moving the status to not_reroutable.
delivery.updatedreroute.reroute_status is reroutedA replacement delivery exists. Follow reroute.new_delivery_id, or subscribe to delivery.rerouted to receive both deliveries in one payload.

Progress events - events which are sent for progress tracking

EventWhat it means
route.quote_creation_startedProgress ping. The matching _complete / _failed event is authoritative.
batch.order_creation_startedProgress ping. The matching _complete / _failed event is authoritative.
batch.route_creation_startedProgress ping. The matching _complete / _failed event is authoritative.
batch.quote_creation_startedProgress ping. The matching _complete / _failed event is authoritative.
batch.vehicle_recommendation_startedProgress ping. The matching _complete / _failed event is authoritative.
route.quote_createdEmitted per individual quote. The full set arrives in route.quote_creation_complete. Handle it only if you want to display quotes as they stream in.
route.updatedA route-level rollup that is fully derivable from the per-delivery events, and it is not guaranteed to be sent. Never block logic on receiving it.
delivery.courier_location_updatedThe highest-volume event by a wide margin. Ignore it unless you render a live driver map.
delivery.updatedWhen status matches the last status you recorded. These are ETA-only or location-only refreshes, not state transitions.

Webhook Security

Each webhook request includes a Burq-Signature header you can use to verify the request came from Burq:

Burq-Signature: t=1492774577,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

Burq signs requests using HMAC with SHA-256. Your signing secret is available in the Dashboard under Developer → Signing Secret. Each environment (production / test) has its own secret.

Step 1: Extract timestamp and signature

Split the header on ,, then split each part on = to get key-value pairs:

  • t → timestamp
  • v1 → signature

Step 2: Construct the signed payload

Concatenate:

  1. The timestamp value
  2. A literal .
  3. The raw JSON request body

Step 3: Compute and compare

Compute HMAC-SHA256(payload, signingSecret) and compare it to the v1 value using a constant-time string comparison to prevent timing attacks.

As an additional check, compare the timestamp against the current time and reject requests that are too old.