payment.paid.
Set the URL
On your app page in the dashboard, under Webhook, save the URL. The response includes a signing secret,whsec_..., shown once. Store it next to your secret key. Use an https URL.
Events
Delivery
Every delivery carries these headers:
And this body:
transactionHash is set for payment.paid and null otherwise. clientReferenceId is whatever you passed when creating the payment.
Return any 2xx within 10 seconds. Anything else, or a timeout, is retried with growing delays: about 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours and 24 hours, six attempts in total. Delivery is at-least-once, so the same event can arrive more than once.
Verify the signature
The signed string is the timestamp, a dot, and the raw request body exactly as received. Compute HMAC-SHA256 with yourwhsec_ secret, compare it to v1 in constant time, and reject timestamps older than a few minutes.
Handle the event
A safe handler does four things, in this order:- Verify the signature. Reject with 400 if it fails.
- Check
idagainst events you have already processed. If seen, return 200 and stop. - Record the
id, then act ontype. Onpayment.paid, look up your order byclientReferenceIdorpaymentId, check thatdata.amountmatches what the order costs, and fulfil it. - Return 200.