Webhooks
Listen and respond to real-time events.
Introduction
When building integrations with Behold you may want your applications to receive notifications as events occur, so that your backend systems can respond accordingly.
Receiving webhook events is particularly useful for listening to asynchronous events such as when a source is disconnected from Instagram and needs to be reauthorized.
Setup
- Configure what events to listen to and where they will be sent on the developer settings page.
- Set up your handler. A webhooks handler is a publicly accessible URL. When an event is triggered, a
POST
request will be sent to this URL with a JSON payload describing the event. Your handler must use HTTPS and promptly return a successful status code (2xx
). If a request fails, it will be retried up to 3 times over the course of 24 hours. - Verify incoming webhooks using a webhook secret.
Verifying requests
HMAC hashes
It’s a good idea to verify the authenticity of incoming webhooks. To do this, first create a webhook secret on the developer settings page.
If you have an active webhook secret, we will create a hex encoded SHA-256 HMAC hash of the event payload and add it to the Behold-Signature request header.
To verify an incoming webhook request, create your own SHA-256 HMAC hash of the raw request body using your webhook secret and compare it to the hash in the Behold-Signature header. If they match you can be confident the request is authentic.
HMAC hashing is a common cryptographic technique and there are excellent libraries available for all major languages that will help you do this.
Rolling secrets
If you want to change your webhook secret in production without downtime you can generate a second secret in the dashboard. You can then update your handler to check requests with both the current secret and the new one, validating if either one matches. When this is done, click the three dots next to the new secret, and select “Set active”. We will then start sending requests using the new secret. You can safely delete the old secret at this point.
All pending requests at the time you switch secrets will still use the old secret, so it’s a good idea to check both secrets for a while, until you’re confident all pending requests have been handled. You can then remove the old secret from your handler code.
If you get a lot of webhook events and want to be 100% confident you don’t miss any, wait 24 hours after activating the new secret. Because of our retry policy all requests are guaranteed to be using the new secret at this point.
Request format
Webhook POST
requests send a JSON object in the request body with the following fields:
id string
A unique ID for the event. This remains the same across retries.
type enum
The type of event. One of source.created
, source.updated
, source.deleted
, feed.created
, feed.updated
, or feed.deleted
.
created number
A UNIX timestamp with millisecond resolution marking when the event occurred.
data map
An object containing a partial source or feed object.
Example request body
Events
Sources
source.created
Triggers when a new source is added to your account. data
includes the full source
object.
source.updated
Triggers when the reauthorize
, username
, website
, followsCount
, followersCount
, mediaCount
, or biography
attributes change. This is not real-time, there may be a multi-day lag between updates to these fields in Instagram and updates in Behold.
The most important purpose of this event is listening for reauthorize
being be set to true
. That means all feeds connected to this source will stop fetching fresh content until the source is reauthorized using your auth link. Unlike the other attributes, reauthorize
will generally trigger within an hour of a source being disconnected.
data
contains the full source
object.
source.deleted
Triggers when a source is deleted. data
will include the id
, type
and label
attributes of the deleted source.
Feeds
feed.created
Triggers when a feed is created. data
contains the full feed object with views: 0
.
feed.updated
Triggers when the title
, settings
, widgetSettings
, or views
, fields are updated. data
contains the full feed object with expanded views
. We increment views
in batches. For very active feeds this will happen frequently, less active feeds might only update once per hour.
feed.deleted
Triggers when a feed is deleted. data
will include id
, sourceType
, sourceId
, instagramUserId
and title
. Feeds with an advanced source will also include the associatedAccountId
attribute.