Webhooks Guide

Uber Direct notifies your application of delivery updates in real-time via two DaaS Webhooks: delivery_status and courier_update. This guide explains how to receive, authenticate, and process the notifications.

Receiving Webhooks

Webhook notifications are sent as POST requests from Uber Direct to an Internet endpoint that you specify. When your endpoints are up and listening, you can add their URLs via the Direct Dashboard (direct.uber.com).

  1. Click the Developer tab on the left, followed by the Webhooks tab in the middle:

Webhooks tab

  1. Click Create Webhook

Create an endpoint

  1. Fill in the Webhook URL with your service endpoint.

  2. Choose which Webhook(s) should be sent to this URL. You can use one URL for both Webhook types, or a separate URL for each.

  3. Click Save.

Authenticating Webhooks

Each Webhook you create provides you with a Webhook Signing Key. This shared secret key is used by your application to verify that incoming messages to your Webhook endpoint are legitimately sent from Uber.

To get a Webhook’s signing key, click the triple dots next to it and select Edit:

Edit Webhook

When a Webhook POST message is sent to your endpoint, it includes the header X-Postmates-Signature, which is a SHA-256 hash of the message payload generated using the secret key. In other words, to verify the signature:

  1. Take a SHA-256 HASH of the message using your secret key, perhaps using a standard HMAC function provided by your language (example below).

  2. Compare the checksum to the hash in X-Postmates-Signature a. If it matches, process the message b. Else, ignore

Here is an example of a Python script that computes what the X-Postmates-Signature should be, given a secret key and a message payload:

import hashlib, hmac

api_secret = 'c5c26d5a-70d6-46c7-a652-d7c09825ad29'

# Shortened for this example
payload = '{"kind": "event.courier_update", "location": {"lat": 37.7974109, "lng": -122.424145}}'

hmac.new(api_secret, payload, hashlib.sha256).hexdigest()

# → 'cdff8133fb065f8d37a2c1c94c3331b6a82766d14e7ea4faacc4886558cedd65'

Processing Webhooks

Delivery status

A Webhook of type event.delivery_status will be sent each time the status field of a delivery changes:

status description
pending Delivery has been created successfully, but does not yet have a courier assigned
pickup Courier is assigned and is en route to pick up the items
pickup_complete Courier has picked up the items and has begun moving towards the dropoff
dropoff Courier is moving towards the dropoff
delivered Courier has completed the dropoff
canceled Delivery has been canceled; for example by using the Cancel Delivery endpoint
returned The delivery was canceled, and a new delivery was created to return items to the sender

The delivery status Webhook event will contain a status field to give you the new status, and a data field which gives you an up-to-date copy of the delivery object / all of the delivery data.

Here is an example of a delivery_status Webhook payload, showing that an order has reached pickup_complete state after satisfying barcode verification:

{
  "status": "pickup_complete",
  "kind": "event.delivery_status",
  "created": "2022-04-14T17:39:18.287Z",
  "live_mode": true,
  "delivery_id": "XXXXXXXXXXXXXXXX",
  "id": "evt_XXXXXXXXXXXXX",
  "data": {
    "id": "del_XXXXXXXXXXXXX",
    "quote_id": "dqt_XXXXXXXXXXXXX",
    "status": "pickup_complete",
    "complete": false,
    "kind": "delivery",
    "pickup": {
      "name": "XXXXXXXXX",
      "phone_number": "+15555555555",
      "address": "XXXXXXXXXXXXX, Test City, CA 99999-9999, US",
      "detailed_address": {
        "street_address_1": "XXXXXXXXXXXXX",
        "street_address_2": "",
        "city": "Test City",
        "state": "CA",
        "zip_code": "XXXXX-XXXX",
        "country": "US"
      },
      "notes": "",
      "location": {
        "lat": 99.99999,
        "lng": -99.99999
      },
      "verification_requirements": {
        "barcodes": [
          {
            "type": "QR",
            "value": "XXXXXXXXXXXXX-1"
          }
        ]
      },
      "status": "completed",
      "status_timestamp": "2022-04-14T17:39:18.187Z"
    },
    "dropoff": {
      "name": "Zach Z.",
      "phone_number": "+15555555555",
      "address": "XXXXXXXXXXXXX, 406, Test City, CA, 99999-9999",
      "detailed_address": {
        "street_address_1": "XXXXXXXXXXXXX",
        "street_address_2": "",
        "city": "Test City",
        "state": "",
        "zip_code": "99999-9999",
        "country": "US"
      },
      "notes": "",
      "location": {
        "lat": 99.9999,
        "lng": -99.99999
      },
      "verification": {
        "picture":
        {
          "image_url": "https://tb-static.uber.com/prod/file-upload/uploads/direct-image-capture/XXXXXXXXXXXXX"
        },
        "completion_location":
        {
          "lat": 99.9999,
          "lng": -99.99999
        }
      },
      "verification_requirements": {
        "picture": true
      }
    },
    "manifest": {
      "reference": "XXXXXXXXXXXXX-1",
      "description": "1 X Cardboard Box\n"
    },
    "manifest_items": [
      {
        "name": "Cardboard Box",
        "quantity": 1,
        "size": "medium",
        "price": 0,
        "dimensions": {
          "length": 27,
          "height": 19,
          "depth": 12
        },
        "must_be_upright": false,
        "weight": 150
      }
    ],
    "created": "2022-04-14T17:28:03.808Z",
    "updated": "2022-04-14T17:39:18.187Z",
    "pickup_ready": "2022-04-14T17:28:04Z",
    "pickup_deadline": "2022-04-14T17:48:04Z",
    "dropoff_ready": "2022-04-14T17:28:04Z",
    "dropoff_deadline": "2022-04-14T18:47:30Z",
    "pickup_eta": "2022-04-14T17:39:18.187Z",
    "dropoff_eta": "2022-04-14T18:03:30.572Z",
    "fee": 1549,
    "currency": "usd",
    "tracking_url": "https://www.ubereats.com/orders/XXXXXXXXXXXXX",
    "undeliverable_action": "",
    "courier_imminent": false,
    "courier": {
      "name": "Cori R.",
      "vehicle_type": "car",
      "phone_number": "+15555555555",
      "location": {
        "lat": 99.999999,
        "lng": -99.99999
      },
      "img_href": "https://XXXXXXXXXXXXX.cloudfront.net/XXXXXXXXXXXXX",
      "rating": "5.00",
      "vehicle_make": "Toyota",
      "vehicle_model": "Prius",
      "location_description": "",
      "vehicle_color": "dimgray"
    },
    "live_mode": true,
    "undeliverable_reason": "",
    "uuid": "XXXXXXXXXXXXX",
    "external_id": "XXXXXXXXXXXXX-1",
    "route_id": "rte_XXXXXXXXXXXXX"
  },
  "customer_id": "cus_XXXXXXXXXXXXX",
  "developer_id": "dev_XXXXXXXXXXXXX",
  "account_id": "acc_XXXXXXXXXXXXX",
  "route_id": "rte_XXXXXXXXXXXXX"
}

Descriptions of all fields can be found in the Delivery Status API Reference

Courier update

A Webhook of type event.courier_update will be sent every 20 seconds, starting from when a Courier is assigned (i.e. when the status transitions to pickup). The payload provides lat and long fields to give your application the up-to-date location of the Courier.

Here is an example of a courier_update Webhook payload. Like delivery_status, courier_update also includes the data object containing an up-to-date copy of all delivery information.

{
  "id": "evt_XXXXXXXXXXXXXXXXXXX",
  "location": {
    "lat": 12.345678,
    "lng": -32.168454
  },
  "kind": "event.courier_update",
  "live_mode": true,
  "delivery_id": "del_1bqA1-XXXXXXXXXXXXXX",
  "data": {
    "id": "del_1bqA1-XXXXXXXXXXXXXXXX",
    "quote_id": "dqt_1bqA1-XXXXXXXXXXXXXXXX",
    "status": "delivered",
    "complete": true,
    "kind": "delivery",
    "pickup": {
      "name": "storename",
      "phone_number": "+11111111111",
      "address": "XXXXXXXXXXXXXXXXX",
      "detailed_address": {
        "street_address_1": "XXXXXXXXXXXXXXXX",
        "street_address_2": "",
        "city": "Portland",
        "state": "OR",
        "zip_code": "97210-1430",
        "country": "US"
      },
      "notes": "",
      "location": {
        "lat": 99.99999,
        "lng": -99.99999
      },
      "verification": {
        "barcodes": [
          {
            "type": "QR",
            "value": "XXXXXXXXXX-1",
            "scan_result": {
              "outcome": "SUCCESS",
              "timestamp": "2022-03-29T22:43:43.839Z"
            }
          }
        ]
      },
      "verification_requirements": {
        "barcodes": [
          {
            "type": "QR",
            "value": "XXXXXXXXXX-1"
          }
        ]
      },
      "status": "completed",
      "status_timestamp": "2022-03-29T22:43:44.965Z"
    },
    "dropoff": {
      "name": "Zach Z.",
      "phone_number": "+11111111111",
      "address": "XXXXXXXXXXXXXXXX",
      "detailed_address": {
        "street_address_1": "XXXXXXXXXXXXXXXX",
        "street_address_2": "",
        "city": "Portland",
        "state": "",
        "zip_code": "97209",
        "country": "US"
      },
      "notes": "",
      "location": {
        "lat": 99.99999,
        "lng": -99.99999
      },
      "verification": {
        "picture": {
          "image_url": "https://tb-static.uber.com/XXXXXXXXXXXXXXXXXXXX"
        }
      },
      "verification_requirements": {
        "picture": true
      },
      "status": "completed",
      "status_timestamp": "2022-03-29T22:57:20.129Z"
    },
    "manifest": {
      "reference": "XXXXXXXXX-1",
      "description": "1 x Cardboard Box\n"
    },
    "manifest_items": [
      {
        "name": "Cardboard Box",
        "quantity": 1,
        "size": "medium",
        "price": 0,
        "dimensions": {
          "length": 27,
          "height": 37,
          "depth": 10
        },
        "must_be_upright": false,
        "weight": 120
      }
    ],
    "created": "2022-03-29T21:50:27.554Z",
    "updated": "2022-03-29T22:52:11.404Z",
    "pickup_ready": "2022-03-29T21:50:27Z",
    "pickup_deadline": "2022-03-29T22:10:27Z",
    "dropoff_ready": "2022-03-29T21:50:27Z",
    "dropoff_deadline": "2022-03-29T23:10:27Z",
    "pickup_eta": "2022-03-29T22:43:44.965Z",
    "dropoff_eta": "2022-03-29T22:57:14.161Z",
    "fee": 500,
    "currency": "usd",
    "tracking_url": "https://www.ubereats.com/orders/XXXXXXXXXXXXXXXX",
    "undeliverable_action": "",
    "courier_imminent": true,
    "courier": {
      "name": "Cori R.",
      "vehicle_type": "car",
      "phone_number": "+11111111111",
      "location": {
        "lat": 45.432121,
        "lng": -123.12341
      },
      "img_href": "https://XXXXXXXXXXXXXXXX.cloudfront.net/XXXXXXXXXXXXXXXX",
      "rating": "5.00",
      "vehicle_make": "Ford",
      "vehicle_model": "Focus",
      "location_description": "",
      "vehicle_color": "white"
    },
    "live_mode": true,
    "undeliverable_reason": "",
    "uuid": "XXXXXXXXXXXXXXXX",
    "external_id": "XXXXXXXXX-1",
    "route_id": "rte_XXXXXXXXXXXXXXXX"
  },
  "created": "2022-03-29T22:56:45.895Z"
}

Descriptions of all fields can be found in the Courier Update API Reference

Next Steps

© 2023 Uber Technologies Inc.