Webhooks

Pusher Beams can be configured to send webhooks to your server when important events occur within the system. These webhooks allow you to trigger different behaviors in your server depending on the status of the notifications you send.

Webhooks for Pusher Beams are currently in beta. Let us know if we can make any improvements at betterbeams@pusher.com

Webhook Event Types

Webhooks are sent as POST requests with a JSON body. The request body contains a generic wrapper around an event-specific payload:

v1.PublishToUsersAttempt

Contains a summary of what happened during a publish to a collection of Authenticated Users.

See schema reference

v1.UserNotificationAcknowledgement

Sent when a notification is acknowledged as delivered by an Authenticated User's device.

See schema reference

v1.UserNotificationOpen

Sent when a notification is opened by an Authenticated User on one of their devices.

See schema reference

Minimum Requirements

The v1.UserNotificationAcknowledgement and v1.UserNotificationOpenwebhooks require that the target device be running at least one of the following SDK versions:

  • iOS - 1.3.0
  • Android - 1.4.0

Configuration

To configure a webhook for your instance:

  • Navigate to the Settings tab on the dashboard and click the Add a webhook button.
  • Select the events on which you would like to trigger a request, and point the target URL to somewhere you control.
  • Set your server up to receive POST requests on your target URL.

You can configure as many webhooks as you want. Each optionally targetting different endpoints.

Configuration options

  • Secret – Used to compute the request signature which we attach to every request we send. You should use this to verify the integrity and authenticity of the request. See Verification.
  • Custom data – Any custom data you provide will be included in the body of every webhook request under the key custom_data.

Request format

Headers

KeyValue
User-Agentalways pusher-webhooks
Content-Typealways application/json
Webhook-Event-Typethe type of event that triggered the webhook.
Webhook-ID-UUIDthe ID of the configured webhook that led to this request
Webhook-Request-ID-UUIDa UUID representing the specific request, this will stay the same if the webhook is retried
Webhook-Signaturea hex encoded HMAC of the request body computed with the webhook secret as the key

Body

The request body will always take the following form:

{
  payload: object,      // the event specific payload
  metadata: {
    created_at: string, // request creation time
    event_type: string, // the event which the request describes
    event_id:   string, // an ID unique to this request (to detect retries)
    product:    string  // the Pusher product the event relates to
  },
  custom_data: object   // the custom data configured in your dashboard
}

Expected response

We expect your server to respond to webhook requests with a 2XX status code within three seconds. Non-2XX responses, or responses that take more than three seconds, will be considered failures.

Retry strategy

If your server fails to reply with the expected response, we will retry the webhook request up to four times – first after 10 seconds, then a further 30 seconds, a further 120 seconds, and finally a further 300 seconds.

If after four retries (five attempts total) we still don’t receive the expected response your webhook will be marked inactive and no further requests will be attempted until it is marked active again. A webhook can be marked active in the dashboard.

Verification

When you register a new webhook you provide a secret. Each time we send a webhook request to your server, we compute an HMAC (SHA-1) derived from the message body of the webhook request and the webhook’s secret. A hex digest is included as a header with the webhook request. To verify the integrity and authenticity of the webhook request, compute the same HMAC based on your secret and compare it to the one received in the request header.

For example, if your server is written in node and express, you would do something like the following to verify requests before processing them.

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
27
28
29
30
31
32
33
const app = require("express")()
const bodyParser = require("body-parser")
const crypto = require("crypto")

const secret = process.env.PUSHER_WEBHOOK_SECRET

function verify(req) {
  const signature = crypto
    .createHmac("sha1", secret)
    .update(req.body)
    .digest("hex")

  return signature === req.get("webhook-signature")
}

app.use(
  bodyParser.text({
    // Treat body as raw text regardless of content-type
    type: () => true,
  }),
)

app.post("/pusher-webhooks", (req, res) => {
  if (verify(req)) {
    console.log("Got a request with body", req.body)
    res.sendStatus(200)
  } else {
    console.log("Got an unverified request; ignoring.")
    res.sendStatus(401)
  }
})

app.listen(5000, () => console.log("listening on :5000"))
Note in particular that we’re treating the request body as plain text here for the purposes of generating the signature.

Publish Webhooks (deprecated)

If you specify a webhookUrl when publishing a notification we will send requests to that URL to keep you up to date on how your publish is doing (including any errors that may occur).

The publish webhook format is deprecated. In the future these webhooks will be sent using the format described above.

Set up a webhook URL

The first step to using webhooks is to set up a URL route on a webserver capable of receiving POST requests and parsing JSON request bodies.

Securing Webhooks

When you receive an incoming webhook you may want to check that the incoming request actually came from Pusher. You can do this by adding secret basic auth credentials to your webhook URL: https://username:password@yourwebsite.com/webhook-path

You can then check that incoming webhooks are really coming from Pusher by parsing your credentials out of the Authorizationheader of the incoming request.

Basic Auth Authorization headers look something like this:

1
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
where the encoded part can be created by base64 encoding your secret username and password separated by a colon (in this example username:password)

You can find more information on how to do this here.

Make sure your webhook URL is using https. Otherwise you could be leaking sensitive data.

Publish a push notification

Using one of our server SDKs (or raw HTTP) send a request to the publish API making sure to set the webhookUrl parameter to the URL you just created.

Example Publish Body

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "interests": [
    "my_interest",
  ],
  "webhookUrl": "http://mysite.com/push-webhook",
  "apns": {
    "aps": {
      "alert": {
        "title": "New Message",
        "body": "Alex Smith just sent you a new message"
      }
    }
  }
}

Parse the webhook body

Some post requests should now have been sent to your webhook URL. To find out what to expect in the request body take a look at the webhook reference documentation.