Overview

You can create webhooks to receive notifications when certain events occur in your account. For example, you can create webhooks to receive notifications when a campaign is created, updated, or deleted.

To receive notifications, you need to specify the URL where the notifications will be sent. When an event occurs, your URL will receive an HTTP POST request with the details of the event. Your URL:

  • Must be publicly accessible
  • Must be able to receive POST requests
  • Must return a 2xx HTTP status code for successful requests

To create a webhook, you need to call the Create Webhook API. You can specify the event that will trigger the webhook by using the channel field.

You can only create one webhook per channel.

Retries

If your webhook URL is unreachable at the time of the event, we will retry sending the request up to 5 times with exponential backoff within the next 1 minute.

We will only retry the request for 5xx or 429 HTTP status code.

Validation

To ensure that your server only processes webhook deliveries that were sent by Topsort and that the delivery was not tampered with, you should validate the webhook signature before processing the delivery further.

Topsort will use your webhook secret and the event payload to generate a signature and include it in the X-TS-Signature-256 HTTP header for every delivery.

You can specify your webhook secret when creating a webhook. If you don’t specify a secret, we will generate one for you. You should store your secret safely on your server.

Topsort uses HMAC hex digest to compute the hash of the signature. The signature will always start with sha256=. You should verify that the signature is correct by recomputing the hash on your side and comparing it to the signature in the X-TS-Signature-256 header.

Example signature verification

import hmac
import hashlib

secret = "my-webhook-secret"
request = ... # incoming request from the webhook delivery

signature = hmac.new(
    key=secret.encode(),
    msg=await request.body(),
    digestmod=hashlib.sha256,
).hexdigest()

expected_signature = "sha256=" + signature
incoming_signature = request.headers["X-TS-Signature-256"]
if not hmac.compare_digest(incoming_signature, expected_signature):
    # The signature is not valid, do not process the delivery
else:
    # The signature is valid, process the delivery