How the signature works
Three headers carry the signature:
To verify a request:
- Take the raw request body, exactly as received. Don’t parse and re-encode the JSON first, or the bytes will differ.
- Build the signed content:
{webhook-id}.{webhook-timestamp}.{raw body}. - Take your signing secret, remove the
whsec_prefix, and base64-decode the rest. The result is the HMAC key. - Compute HMAC-SHA256 of the signed content with that key, and base64-encode it.
- Compare it with each signature in
webhook-signature, using a constant-time comparison. The request is valid if any one matches. - Reject the request if
webhook-timestampis more than 5 minutes from your clock. This stops someone replaying an old request.
webhook-signature can hold two signatures, separated by a space. KYC sends both the new and the old
signature for 24 hours after your signing secret is rotated, so you can update your secret without
missing events.Code samples
Test your code
Check your implementation against this example from the Standard Webhooks specification. Skip the timestamp check for this test, since the timestamp is in the past.
Then ask KYC for a ping to your endpoint, signed with your own secret.
Keep your secret safe
- Store the signing secret in a secrets manager or environment variable, never in source code.
- Never log it, or the raw
webhook-signatureheader. - If you think the secret has leaked, ask KYC to rotate it.
