Skip to main content

Verifying requests

You can verify inbound requests from our webhooks using HMAC SHA256 verification. Once you've created a webhook you'll see a notice showing you the secret value that you can use for for verifying requests from us. If you need to find the secret again at a later stage you can also find it on the edit page of the webhook.

How to verify

  1. Grab the secret value for the webhook shown in the UI once created.
  2. Use the secret and incoming request body as inputs for your HMAC function using a SHA256 algorithm.
  3. Compare the HMAC hash you've generated with the value in the signature header of the incoming request
  4. If they match you can trust that the request is legitimate

Important Security Considerations

  1. Protect Your Secret Key: Never expose your secret key in client-side code or logs.
  2. Use Secure Comparisons: Always use timing-safe comparisons to prevent attackers from exploiting timing differences.
  3. Validate Incoming Data: Ensure that you handle exceptions and validate all incoming data to prevent security vulnerabilities.

Below is a simple Python example showing how you can compute the HMAC value of an incoming request and verify it.

import hashlib
import hmac


def verify_hmac(secret_key: str, request_body: str, signature_header: str) -> bool:
"""
Verifies the HMAC SHA256 signature of an incoming request.

Args:
secret_key (str): The secret key provided by the webhook UI.
request_body (str): The raw body of the incoming HTTP request.
signature_header (str): The value of the 'signature' header from the incoming request.

Returns:
bool: True if the signature is valid, False otherwise.
"""
encoded_key: bytes = secret_key.encode("utf-8")
encoded_body: bytes = request_body.encode("utf-8")

computed_signature: str = hmac.new(
key=encoded_key, msg=encoded_body, digestmod=hashlib.sha256
).hexdigest()

return hmac.compare_digest(computed_signature, signature_header)


def main() -> None:
secret_key: str = "64a2a90e-1359-4ff6-a89e-4ab448773654"
request_body: str = "Incoming request body data..."
signature_header: str = "Value of incoming request 'signature' header..."

if verify_hmac(secret_key, request_body, signature_header):
print("Signature is valid.")
else:
print("Signature is invalid.")


if __name__ == "__main__":
main()