Verifying webhooks
Outbound webhooks (like checkout_session.succeeded) are signed with
HMAC-SHA256 over timestamp.payload, carried in the Transxact-Signature
header. Verify this signature before trusting a webhook body — otherwise
anything that can reach your endpoint’s URL can forge a fake payment
notification.
Set your endpoint’s URL, reveal the signing secret and send a signed
webhook.test event from the Webhooks section of your dashboard
(Business accounts only). Endpoints must be https://.
Verification also rejects any request where the signed timestamp is more
than 5 minutes old. The HMAC signature itself never expires on its own, so
without this tolerance window a captured valid webhook call would be
replayable indefinitely.
Verifying manually
The Transxact-Signature header carries t=<timestamp>,v1=<hmac>, where
timestamp is milliseconds since epoch and hmac is the hex-encoded
HMAC-SHA256 of `${timestamp}.${rawPayload}` using your webhook signing
secret (from the dashboard’s Webhooks section):
Always pass the raw request body, exactly as received — re-serializing JSON
before verifying can change byte-for-byte content and produce a signature
mismatch even for a genuine webhook. A helper for this will ship in the
@transxact/node SDK once it’s published; until then, verify manually as
above.
Retries and duplicate events
Every event carries an id (evt_…). Answer with any 2xx status to
acknowledge it. Anything else, or no answer within 10 seconds, and we retry
the same event, with the same id, after 15 minutes, then 45 minutes, 2, 3,
6 and 12 hours — about a day in all — before giving up.
Delivery is at least once: a retry or a manual resend can reach you more than
once, so record the ids you’ve handled and skip repeats. Each retry is
signed afresh, so its timestamp is always current.
The Webhooks section of your dashboard lists recent deliveries, whether your endpoint got them, and has a Resend button for sending one again straight away.