Lesson 5 — Receive and verify webhooks
Polling wastes requests and lags. Webhooks push each payment transition to
your server, signed so you can trust them. This lesson registers an endpoint,
passes verification, and processes events idempotently.
Register an endpoint
transxact webhooks:create \
--url "https://you.example.com/hooks/transxact"
or use the webhook card in the Developer section. The response
contains a signing secret — store it; it is shown once.
An endpoint becomes active only after it answers the challenge event,
webhook.verified, with a 2xx.
Verify every delivery
Each delivery carries:
Transxact-Signature: v1=<hex>Transxact-Timestamp: <unix-seconds>
The signature is HMAC-SHA256("<timestamp>.<body>") keyed with your signing
secret. Compute it over the *raw* request body — not a re-serialised copy —
and reject deliveries older than 5 minutes (replay window).
Every first-party SDK ships this verification built in; see your SDK's README
(sdks/<language>/README.md) for its verifyWebhook helper.
The events that matter
| Event | When |
|---|---|
webhook.verified | Once, after registration or secret rotation |
payment.processing | Intent moved to processing |
payment.succeeded | Intent reached succeeded |
payment.failed | Intent reached failed |
disbursement.sent | Daily disbursement run included you |
disbursement.failed | A disbursement bounced |
Process idempotently
Deliveries can be retried, so the same event may arrive more than once.
Deduplicate on X-Transxact-Event-Id (also present as event_id in the
payload): record processed ids and skip repeats before running side
effects like fulfilment emails.
Exercise
1. Register an endpoint against your local server and catch the
webhook.verified challenge to activate it.
2. Force a payment to succeeded with magic values and verify your handler
checks out: signature valid, timestamp fresh, event id unseen.
3. Replay the same delivery body twice and confirm your deduplication holds.
4. Rotate the secret from the Developer section and confirm old signatures
now fail closed.
What's next
You have the full API loop. Lesson 6
covers the no-code surface — payment links — and the move to live mode.
Nearby lessons
5. Receive webhooks