Verifying webhook signatures

Verify the events sent from Iterate to your webhooks

Updated over a week ago

Iterate webhook requests include a signature in the request's iterate-signature header. This signature can be used to verify that the request was sent from Iterate and not by a third party.


  • Get the webhook secret from the 'webhooks' integration for your survey. If you do not see a secret, this means you have an older version of our webhooks. To generate a secret you'll need to create a new webhook.

  • Get the value of the iterate-signature header. The format of the value includes a timestamp and a signature. It is in the format shown below (the actual value has no newlines, those have been added below for clarity):


Verifying the Signature

Step 1: Extract the timestamp and signature from the header

Split the header, using the , character as the separator, to get a list of elements. Then split each element, using the = character as the separator, to get a prefix and value pair.

The value for the prefix t corresponds to the timestamp, and v1 corresponds to the signature. You can discard all other elements.

Step 2: Prepare the signed_payload string

The signed_payload string is created by concatenating:

  • The timestamp (as a string)

  • The character .

  • The actual JSON payload (i.e., the request body)

Step 3: Determine the expected signature

Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the signed_payload string as the message.

Step 4: Compare the signatures

Compare the signature in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.

To protect against timing attacks, use a constant-time string comparison to compare the expected signature to each of the received signatures.


Preventing replay attacks

A replay attack is when an attacker intercepts a valid payload and its signature, then re-transmits them. To mitigate such attacks, Iterate includes a timestamp in the iterate-signature header. Because this timestamp is part of the signed payload, it is also verified by the signature, so an attacker cannot change the timestamp without invalidating the signature. If the signature is valid but the timestamp is too old, you can have your application reject the payload.

Did this answer your question?