Webhooks

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

  1. Configure what events to listen to and where they will be sent on the developer settings page.
  2. 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.
  3. 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

{
"id": "e8b71cb2-b03c-4813-978e-0b4c75d7e09d",
"type": "feed.updated",
"created": 1734112402231,
"data": {...}
}

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.

Ready to give it a try?

Sign up for free