Webhooks

Introduction

Burq's webhooks allow you to receive updates when status changes occur to an order. This way you do not need to poll our API for updates, but can instead receive and react to them as they happen. There are different events you can subscribe to. Collectively, these webhook events enable a number of use cases such as providing delivery status update, driver information and location update, eta update and etc.; notifying delivery reroute events; and allowing merchant application to programmatically track refund statuses.

To start receiving webhooks, first provide a url from the Developer section of Burq Dashboard (as shown below). Webhook url is configured separately for production and test environments. Please use the test mode toggle at the top of the screen to make sure you configure the url for the right environment.

Once a webhook url is configured, you can now choose the webhook events you want to subscribe to.

Webhook Request Payload

All webhooks are sent with the following top-level request payload:

{
	object: "event",
  type: "delivery_incident.updated" // or other event names
  data: {
  	// Each event may use different API resource. See below for documentation on the respective
  	// event payload.
	}
}

delivery.updated event

delivery.updated events are sent whenever Burq receives information from providers about deliveries under your account. The data object included in these events is the Delivery API resource. You can find detailed documentation for the included properties in Creating Delivery Requests.

Events that trigger webhook deliveries include:

  • Delivery status updates from provider.
  • Delivery status changes when you call Burq V1 cancel-delivery API or cancel a delivery via Burq dashboard.
  • Delivery ETA updates (whenever the pickup_eta and dropoff_eta properties change).

Below is a sample payload sent to the webhook address as a POST request when the status is first updated.

{
    "id": "19g68lawsqlrf",
    "delivery_type": "asap",
    "service": "doordash",
    "status": "delivery_created",
    "tracking_url": "https://burqup.com/track/19g68lawsqlrf",
    
    // Cost of delivery properties
    "currency": "USD",
    "fee": 869, 
    "payment_amount": 869,
    "tip": 300,
    "upsell": null,
    "subsidized": null,
    
    // General delivery properties
    "created_at": "2022-11-25T17:47:37.000Z",
    "cancellation_reason": null,
    "external_order_ref": "FantasyStore-Order#42123",
    "order_value": 4489,
    "proof_of_delivery": [],
    "quote_id": "19g68lawsqlqj",
    "signature": null,
    "status_history": [],
    "store_id": null,
    "test_mode": true,
    "updated_at": "2022-11-25T17:47:37.000Z",
    "vehicle": null,
    
    // Pickup and dropoff properties
    "pickup_at": null,
    "pickup_address": "43 E Ohio St, Chicago, IL 60611, USA",
    "pickup_eta": "2022-11-25T18:00:00.000Z",
    "pickup_name": "Eataly Restaurant",
    "pickup_notes": "Please look for package with order label #42123.",
    "pickup_phone_number": "15124439077",
    "pickup_unit": "Unit 3211",
    "dropoffs": [
        {
            "dropoff_at": null,
            "dropoff_address": "233 S Wacker Dr, Chicago, IL 60606, USA",
            "dropoff_eta": "2022-11-25T18:30:00.000Z",
            "dropoff_name": "John Doe",
            "dropoff_notes": "Please call upon arrival",
            "dropoff_phone_number": "14342118980",
            "dropoff_unit": "Apartment 908",
        }
    ],
    
    // Delivery items
    "items_description": "Food items",
    "items": [
        {
            "name": "Brisket Classic",
            "quantity": 4,
            "size": "small"
        }
    ],

    // Driver properties
    "courier_name": null,
    "courier_img": null,
    "courier_phone_number": null,
    "courier_vehicle_type": null,
    "courier_location_lat": null,
    "courier_location_lng": null
}

Note that the status_history field contains a list of statuses with the date that status was set. As a Delivery transitions through different statuses, those transitions will be recorded in the status_history field. Please see below for a sample data structure of this property:

{
  // ...
  "status_history": [
    {
      "status": "delivery_created",
      "created": "2022-05-31T14:58:56+00:00"
    },
    {
      "status": "driver_assigned",
      "created": "2022-05-31T15:00:30+00:00"
    }
  ]
}

The status_history field of a successfully completed Delivery may look like this:

"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",
    "status": "2022-11-26T19:40:00.000Z"
  },
  {
    "status": "delivered",
    "created": "2022-11-26T19:41:00.000Z"
  }
]

delivery.courier_location_updated event

delivery.updated events are sent whenever Burq receives information from providers about driver location updates. The data object included in these events is a Delivery API resource (see delivery.updated webhook request payload for more details).

delivery.rerouted event

When a delivery provider is having trouble finding drivers for a delivery or otherwise fulfilling the delivery, Burq may "reroute" the delivery to another provider (to learn more about enabling this option for your account, please reach out to your account manager or Burq support). When a delivery is rerouted, Burq system cancels the old delivery and creates a new delivery. This new delivery has a different Burq-generated id, and delivery updates henceforth will only be provided under the new delivery (and not reflected on the old delivery).

Merchants who want to track delivery reroutes can subscribe to the delivery.rerouted event. This event is fired whenever a delivery is rerouted, and has the following request payload:

{
  "object": "event",
  "type": "delivery.rerouted",
  "data": {
    "parent_delivery": {
      // Delivery API Resource      
   	},
    "child_delivery": {
      // Delivery API Resource
    }
  }
}

delivery_incident.created/updated events

Burq system creates delivery incidents automatically in response to potential refund events, such as when a delivery is canceled by provider or when a delivery is disputed by merchants. Merchants who want to programmatically monitor the refund status of delivery incidents can subscribe to delivery_incident.created and delivery_incident.updated events. Both events send Delivery Incident API resource under the data property. For more information on the Delivery Incident API resource, please refer to the response payload of GET Delivery Incident API.

Upgrading to Latest Webhooks Version

For merchants on older webhook versions (most merchants who signed up prior to July 2023), please refer to this guide on how to upgrade to the latest webhook version.


Webhook Security

You can verify authenticity of webhook events sent by Burq using signatures. The Burq-Signature header included in each event. It consists of a timestamp and signature that you must verify. The timestamp has a t= prefix, and signature has v1= prefix.

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

Burq generates signature using HMAC with SHA-256. Signature is generated using signing secret that is attached to your account. You can find yours under developer tab, Signing Secret field. All webhook events have same secret per environment. You can verify your solution using signing secret from test environment.

To verify authenticity of webhook request, you need to generate expected signature on your side and compare it to one provided by Burq under v1= prefix. Here are the detailed steps to achieve that.

Step 1: Extract the timestamp and signatures from the header

Split the header using the , character as the separator to get a list of elements. Then split each element using the = character as the separator to get a prefix and value pair. The value for the prefix t corresponds to the timestamp, and v1 corresponds to the signature.

Step 2: Create the expected signature

To create expected signature, first you need to construct the payload that needs to be signed. Payload string is created by concatenating following values:

  • The timestamp (timestamp value sent by Burq under t= prefix)
  • The character .
  • JSON payload of request body (data sent by Burq for specific event).

Now compute an HMAC with the SHA256 hash function of the payload using signing secret as the key.

Step 3: Compare the signatures

Compare the signature in the header to the expected signature. For additional check, compute the difference between the current timestamp and the received timestamp, then decide if the difference is appropriate and event is still valid to be processed. To protect against timing attacks, use a constant-time-string comparison to compare the expected signature to each of the received signatures.