Webhooks
Verifying Signatures
Anyone can send a request to a public URL. The signature proves an event really came from Transmit, so check it before you act on anything.
The signature header
X-Transmit-Signature: t=1790431391,v1=5a3f0c…- t: When the request was sent, in Unix seconds.
- v1: An HMAC-SHA256 of
{t}.{raw body}signed with your endpoint's secret. Right after you rotate a secret there are two — one per secret.
How to verify
- 1: Compute an HMAC-SHA256 of
t + "." + raw bodywith your secret, as hex. - 2: Accept the event if any v1 value matches it.
- 3: Reject it if t is more than 5 minutes old — this stops old requests from being replayed.
The example handler does all three in Node.js, Python and PHP.
Common mistakes
- Using the parsed body: Use the raw bytes.
express.json()orbodyParser.json()re-encodes the body and the signature will never match — useexpress.raw(). - Checking only the first v1: After a rotation there are two. Check them all.
- Comparing with ==: Use timingSafeEqual, hmac.compare_digest or hash_equals.
Use the Test button on the Webhooks page to send a signed
webhook.test event and check your handler before going live.
