POST with a JSON body to the link’s callbackUrl. Fulfil purchases from these webhooks: they arrive even if the payer closed the checkout.
The request
order.settled, order.overpaid, order.expired, order.expired_underpaid, order.manual_review, order.refunded. See Payment statuses for what each means.
Respond quickly
Return any2xx within 10 seconds to acknowledge. Do slow work (emails, fulfilment) after responding, or in a queue. Paywire doesn’t follow redirects, so point callbackUrl at the final URL.
Anything else (a non-2xx, a timeout, a network error) is retried after 10 s, 30 s, 2 min, 10 min, 30 min, 1 h, 3 h and 6 h: 9 attempts over about 10 hours. After that the delivery is marked failed and a Paywire operator can resend it.
Verify the signature
Anyone can post to your URL, so check every webhook. TheWeb3Getaway-Signature header holds a Unix timestamp t and v1, a hex HMAC-SHA256 of "{t}.{raw body}" keyed with your webhook secret:
- Split the header on
,and readtandv1. - Compute
HMAC-SHA256(secret, t + "." + rawBody)as lowercase hex. Use the raw request bytes, before any JSON parsing. - Compare it with
v1in constant time. - Reject a
tmore than 5 minutes from your clock, so an old webhook can’t be replayed.
whsec_) with GET /notifications/merchants/me/webhook-secret.
Handle duplicates
The same event can arrive more than once: a retry after your server answered too slowly, or an operator’s resend. Every copy has the sameWeb3Getaway-Event-Id (and body id). Record the ids you’ve processed and skip repeats, or make your handler idempotent, for example “mark purchase paid” rather than “add a payment”.
Events about one order can also arrive out of order after retries. Use status as the truth, and if in doubt read the order with GET /payments/orders/{id}.