In order that you might verify that events you receive were sent by Synthesia, we include a signature in the Synthesia-Signature header of each event. You are then able to construct and verify this signature using a unique secret that we provide for each webhook subscription.

Note that if this signature is compromised, it is critical that you recreate the webhook subscription, else a bad actor would be able to send events to your systems under the guise of Synthesia.

How do you verify our signatures?

The following steps describe how you may construct the signing signature, allowing for a comparison with the one we provide. If they are the same, you can be confident the event was sent by us.

Step 1: Fetch the request contents

We need two things from the request; the request timestamp, found in the Synthesia-Timestamp header, and the request body.

from flask import request

request_timestamp = request.headers["Synthesia-Timestamp"]
request_body = request.data.decode("utf-8")

Step 2: Create the message

To create the message to be signed, concatenate the timestamp and the request body (the actual JSON payload) using the character .:

message = ".".join((request_timestamp, request_body))

Step 3: Construct the signature

Then create the signature, an HMAC created using the SHA256 hash function, by signing the message using the your webhook secret as the signing key.

import hashlib
import hmac

key = "..."  # This is your webhook secret.

signature = hmac.new(
    key.encode("utf-8"),
    message.encode("utf-8"),
    hashlib.sha256,
).hexdigest()

Step 4: Compare the signatures

Compare the computed signature with the one we provide in the Synthesia-Signature header.

assert signature == request.headers["Synthesia-Signature"]

Step 5: Compare the timestamps

Optionally, protect yourself from timing attacks by check that the Synthesia-Timestamp is within your tolerance. For example, you might choose to ignore events that were created more than 10 minutes ago.