Webhooks
Webhooks (Web Callback, HTTP Push API or Reverse API) are one way that a web application can send information to another application in real-time when a specific event happens.
Webhook Vs API
APIs send you the data when you request it. For Webhooks, you do not need to make a request. You receive the data when it is available, based on the subscriotion of events.
Configuring webhooks
- Configure webhooks in the configuration center.
This way we know which event(s) you are interested in and to which endpoints we should send them. - Set up your webhooks endpoint.
This means that you need to build an application that handles incoming webhooks events and run that on an HTTPS endpoint on your server. These webhooks also need to be verified.
Configuring webhooks in the configuration center
To set up webhooks in the configuration center you need to do the following:
- Add a webhooks endpoint.
- Subscribe from the list of available events.
- Webhook signature is auto generated.
Setting up your webhooks endpoint
The webhooks messages will be sent to your endpoints via HTTPS POST requests. The body of the request contains JSON.
To actually handle these incoming messages you should set up your server to listen to POST requests on the endpoints you've set up in the configuration center.
In order to prevent attackers impersonating services by simply sending a fake webhook to an endpoint, Bureau signs every webhook and its metadata with a unique key for each endpoint. This signature can then be used to verify the webhook indeed comes from Bureau, and only process it if it is.
Verifying signatures manually
Each webhook call includes three headers with additional information that are used for verification:
svix-id
- the unique message identifier for the webhook message. This identifier is unique across all messages, but will be the same when the same webhook is being resent (e.g. due to a previous failure).svix-timestamp
- timestamp in seconds since epochsvix-signature
: the Base64 encoded list of signatures (space delimited).
Constructing the signed content
The content to sign is composed by concatenating the id, timestamp and payload, separated by the full-stop character (.). In code, it will look something like:
signedContent = "${svix_id}.${svix_timestamp}.${body}"
Where body
is the raw body of the request. The signature is sensitive to any changes, so even a small change in the body will cause the signature to be completely different. This means that you should not change the body in any way before verifying.
Determining the expected signature
Bureau uses an HMAC with SHA-256 to sign its webhooks.
So to calculate the expected signature, you should HMAC the signedContent from above using the base64 portion of your signing secret (this is the part after the whsec_ prefix) as the key. For example, given the secret whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw
you will want to use MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw
.
This generated signature should match one of the ones sent in the svix-signature header.
// Node JS Code
const crypto = require('crypto');
signedContent = `${svix_id}.${svix_timestamp}.${body}`
const secret = "whsec_5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH";
// Need to base64 decode the secret
const secretBytes = new Buffer(secret.split('_')[1], "base64");
const signature = crypto
.createHmac('sha256', secretBytes)
.update(signedContent)
.digest('base64');
console.log(signature);
Retry Schedule
We attempt to deliver each webhook message based on a retry schedule with exponential backoff.
The schedule
Each message is attempted based on the following schedule, where each period is started following the failure of the preceding attempt:
Immediately
5 seconds
5 minutes
30 minutes
2 hours
5 hours
10 hours
10 hours (in addition to the previous)
If an endpoint is removed or disabled delivery attempts to the endpoint will be disabled as well.
For example, an attempt that fails three times before eventually succeeding will be delivered roughly 35 minutes and 5 seconds following the first attempt.
Note
- An event represents a single unique workflowID(or capability). Whenever a transaction is run for that workflowID, a webhook is sent to the endpoint which has subscribed to that event.
- Webhook invocation is async from our end. Workflow does not get blocked.
Updated about 1 month ago