Webhooks

Webhooks make it possible for your application to be notified of important system events, as soon as these take place within Bponi Storeopen in new window.

While you are generally able to create as many webhook entries as you'd like, remember that a single webhook always targets a single trigger. The following triggers are available:

IDNameDescriptionIncludesLimitations
0taskStartedTask started by worker.taskId, data.taskNone
1taskEtaWorker ETA less than or equal to threshold value provided, in seconds.taskId, data.task, etaSecondsLimit of 10 webhooks. Each will fire once per task, at most once every 30 seconds, when threshold is met.
2taskArrivalWorker arriving, at or closer than threshold value provided, in meters.taskId, data.task, distanceLimit of 10 webhooks. Each will fire once per task, at most once every 30 seconds, when threshold is met.
3taskCompletedTask completed by worker.taskId, data.taskNone
4taskFailedTask failed.taskId, data.taskNone
5workerDutyWorker status changed (0 for off-duty, 1 for on-duty).workerId, status, data.workerNone
6taskCreatedNew task created.taskId, data.taskDoes not include tasks created via task import from the Bponi Storeopen in new window dashboard.
7taskUpdatedTask updatedtaskId, data.taskNone
8taskDeletedTask deleted.taskId, data.taskNone
9taskAssignedTask assigned to worker.taskId, data.taskNone
10taskUnassignedTask unassigned from worker.taskId, data.taskNone
12taskDelayedTask is delay time is greater than or equal to threshold value provided, in seconds.taskId, data.task, delayLimit of 10 webhooks, applies only to active tasks, will only fire once.
13taskClonedTask cloned via dashboard or API. Note that the taskCreated trigger will not fire when a task is cloned.taskId, data.taskNone
14smsRecipientResponseMissedRecipient responds to a notification via SMS, but the organization is unable to handle it at that time.from, to, bodyNone
15workerCreatedA new worker has been created.adminId, workerId, actionContext , triggerId,triggerName, taskId,data.worker, timeNone
16workerDeletedA worker has been deleted.adminId, workerId, actionContext , triggerId,triggerName, taskId,data.worker, timeNone.
17SMSRecipientOptOutWhen a recipient replied "STOP" to opt out of SMS communicationsrecipient, timestamp, SMS, triggerId, triggerName,timeNone

Webhooks can be maintained via dashboard or API. All standard, non-validation requests from Bponi Storeopen in new window to you are made via POST.

In addition to the properties from the Includes column above, the JSON body we will POST to your url will include a time property along with triggerId and triggerName so you may overload the same url on your application as required. In addition, full objects will be provided in the data property, as relevant. Note that all other properties not relevant to the trigger may be provided as null.

Quick Start

Bponi Storeopen in new window offers a webhook developer tool in our open-source developer repository. The webhook tool serves up a Python Flask application that acts as your webhook server and allows you to test out different webhooks. The tool includes an endpoint for each Bponi Storeopen in new window webhook trigger, validates the webhook, and prints the payload to screen.

Webhook Validation

All URLs are validated through a simple token exchange mechanism so we may trust that you actually control the target server. Note that validation happens right at webhook creation, meaning that we will issue a request to you before successfully registering the webhook. The validation will send a GET request to your url with a query string of check=<random_string>, your webhook server should respond back with the <random_string> to be validated.

Webhook Authentication

Bponi Storeopen in new window uses HMAC (hash-based message authentication code) with the SHA-512 hash function for additional authentication. By using the webhook secret obtained on the Bponi Storeopen in new window dashboard, your webhook server should verify that the source of webhook requests are indeed coming from Bponi Storeopen in new window and is associated with your organization.

Each webhook request contains a signature from Bponi Storeopen in new window in X-Bponi-Signature header. To authenticate the webhook request received on your webhook server, you will need to validate against this header.

To validate against X-Bponi-Signature, you will need to compare its value with an HMAC you have generated using the hexadecimal format of your webhook secrets and the full body of the webhook POST request in raw bytes. We have provided some coding examples in Python and NodeJS.

import hashlib, hmac, binascii

hash = hmac.new(binascii.a2b_hex(secret), body, 'sha512').hexdigest()

# Compare hash with the received X-Bponi-Signature in raw bytes
1
2
3
4
5
const crypto = require('crypto')
const secret_in_hex = Buffer.from(secret, 'hex');

const hash = crypto.createHmac('sha512', secret_in_hex)
  .update(body)
  .digest('hex')

// Compare hash with the received X-Bponi-Signature in raw bytes
1
2
3
4
5
6
7
8

Retry

Any failed requests will be retried in 30-minute cycles, up to one full day. A failed request is any non-200 response that a webhook request gets from your application. If there are more than 300 consecutive failures, the webhook will be automatically disabled.

Testing

You may find a tool like ngrokopen in new window useful to test your webhook integrations, however in order to pass the initial validation step, you will need to ensure that your tool of choice allows you to respond to our validation request, unless it has been automatically validated.

Use Bponi Storeopen in new window developer tools for webhook testing, learn more here.

Create webhook

Body parameters

NameTypeDescription
urlstringThe URL that Bponi Storeopen in new window should issue a request against as soon as the trigger condition is met. It must be HTTPS and have a valid certificate.
namestringA name for the webhook for identification.
triggernumberThe number corresponding to the trigger condition on which the webhook should fire.
thresholdnumberOptional. For trigger 1, the time threshold in seconds; for trigger 2, the distance threshold in meters.

The url value provided will receive a GET request from our servers, with a check query parameter. You need to respond to our validation request with exactly this value, untouched, as a simple string response.

In a Node.js/CoffeeScript environment, the following would suffice:

server.get '/bponi-store/taskStart', (req, res, next) ->
    res.send req.params.check
  return next()
1
2
3

To create a new webhook, provide a verifiable url and trigger.

curl -X POST "https://store.bponi.com/api/v2/webhooks" \
     -u "cd3b3de84cc1ee040bf06512d233719c:" \
     -d '{"url":"https://11ec4a02.ngrok.com/bponi-store/taskStart","trigger":0}'
1
2
3
{
    "id": "9zqMxI79mRcHpXE111nILiPn",
    "count": 0,
    "url": "https://11ec4a02.ngrok.com/bponi-store/taskStart",
    "trigger": 0
}
1
2
3
4
5
6

As previously mentioned, you will need to respond to our validation request with the check query parameter value, as a simple string response in order to avoid validation failures. This applies if you're not using the automatic validation from Zapier and Requestbin.

List webhooks

count provides a total number of successful requests made for a webhook. If a webhook failed consecutively for 300 times or more, the isEnabled parameter will be turned to false.

curl -X GET "https://store.bponi.com/api/v2/webhooks" \
       -u "cd3b3de84cc1ee040bf06512d233719c:"
1
2
[
    {
        "id": "ZnVRY8rdfUwNPjHQy2QthtxZ",
        "name": "Webhook 1 - Driver Nearby",
        "count": 7,
        "url": "https://11ec4a02.ngrok.com/bponi-store/driverNearby",
        "trigger": 2,
            "isEnabled": true
    },
    {
        "id": "9zqMxI79mRcHpXE111nILiPn",
        "name": "Webhook 2 - TaskStarted",
        "count": 3,
        "url": "https://11ec4a02.ngrok.com/bponi-store/taskStart",
        "trigger": 0,
            "isEnabled": true      
    },
    {
            "id": "8KD3PcIMsG*bC0imJ~EjR9GX",
            "name": "Webhook 3 - TaskCompleted on Zapier",
            "count": 6,
            "url": "https://hooks.zapier.com/hooks/catch/4212020/0z5pha/",
            "trigger": 3,
            "isEnabled": true
    }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Delete webhook

curl -i -X DELETE "https://store.bponi.com/api/v2/webhooks/ZnVRY8rdfUwNPjHQy2QthtxZ" \
       -u "cd3b3de84cc1ee040bf06512d233719c:"
1
2
HTTP/1.1 200 OK
1
Last Updated: 11/29/2021, 10:25:26 PM