Webhook Setup
Configure webhook endpoints to receive real-time payment notifications
Important: Failed webhooks are not retried automatically, and the same event can still arrive twice (for example after a Resend). Your server must dedupe events and run a reconciliation job. How webhooks work
Step 1: Select Organization or Agent
Choose the appropriate webhook configuration type for your usage

Step 2: API Key & Webhook Configuration
Configure webhook URL to receive notifications (IP whitelist can be configured)

IP Whitelist for Webhook
If you use IP Whitelist in your system, please add the following IP addresses for Webhook to work correctly:
13.228.225.19
18.142.128.26
54.254.162.138
74.220.52.0/24
74.220.60.0/24Note: Note: These IP addresses are our server IPs that will send webhook requests to your system
Step 3: Webhook Logs
Check all webhook sending history and can click Resend

How webhooks work
Most integration bugs are webhook bugs. Read this before going live.
What a webhook is
When money moves, we call you: the platform sends a POST to your webhook URL with the result. You do not have to keep asking. There is one URL per shop, set in the dashboard under Developer → API Key & Webhook.
Why only the webhook counts
The customer can close the tab, press back, or type your success URL by hand. A redirect or the create response is never proof of payment. Only a webhook with a valid signature is.
Check it really came from us
x-signature is sha256= + HMAC-SHA256 of x-timestamp + "." + JSON of data with your webhook secret. Only data is signed, and this timestamp is in seconds.
Answer fast
Reply with any 2xx within 10 seconds; the body is ignored. Save the event first and do the heavy work afterwards.
No automatic retry
If your server is down or slow, that webhook is lost. Run a job that polls /v1/payment/info or /v1/withdrawal/info by order_id for orders still pending past their expiry.
Duplicates and out-of-order
The same event can arrive twice — dedup on X-Idempotency-Key, never on request_id. Order is not guaranteed: a PAYMENT_PAID after PAYMENT_CANCELED still means paid.
The events that matter
Deposits: PAYMENT_PAID (credit), PAYMENT_CANCELED, PAYMENT_FAILED (duplicate slip). An invoice that just expires sends nothing. Withdrawals: WITHDRAWAL_COMPLETED, WITHDRAWAL_COMPLETED_PARTIALLY, WITHDRAWAL_REJECT. WITHDRAWAL_PARTIALLY_FUNDED is progress only.
Changing the URL locks withdrawals
Changing the webhook URL blocks withdrawals for 24 hours. Set the final URL before go-live.
Checklist before go-live
- Signature verified over
datawith the webhook secret, constant-time compare, timestamp within 5 minutes - Replies 2xx within 10 seconds, heavy work done afterwards
- Same webhook sent twice → credited once
- PAYMENT_PAID after PAYMENT_CANCELED → order ends up paid
- Endpoint returns 500 → the reconciliation job still closes the order
- Amounts parsed as decimals, not floats
- Withdrawals closed from outcome.result, not from PARTIALLY_FUNDED
