Webhooks
Webhooks allow you to receive real-time notifications when events happen in your WasaaPay integration. Configure a URL and we'll send HTTP POST requests with event data.
Setting Up Webhooks
- Configure your webhook URL in the dashboard
- Implement an endpoint to receive POST requests at that URL
- Verify webhook signatures for security
- Return a 200 status code to acknowledge receipt
Webhook Payload Structure
Webhook Payload
{"event": "deposit.completed","timestamp": "2024-01-15T10:30:45Z","partnerId": "partner_abc123","environment": "PRODUCTION","signature": "sha256=d4e5f6...","data": {// Event-specific data}}
Available Events
Deposit Events
| Event | Description |
|---|---|
deposit.initiated | Deposit request created, awaiting payment |
deposit.completed | Funds received and credited to wallet |
deposit.failed | Deposit failed or was cancelled |
Withdrawal Events
| Event | Description |
|---|---|
withdrawal.initiated | Withdrawal request submitted |
withdrawal.completed | Funds sent to recipient |
withdrawal.failed | Withdrawal failed |
Transfer Events
| Event | Description |
|---|---|
transfer.completed | Transfer completed successfully |
transfer.failed | Transfer failed |
Bill Payment Events
| Event | Description |
|---|---|
bill.initiated | Bill payment submitted |
bill.completed | Bill paid successfully |
bill.failed | Bill payment failed |
Verifying Signatures
All webhooks include a signature in the signature field. Verify this to ensure the request came from WasaaPay.
webhook-handler.js
1const crypto = require('crypto');23function verifyWebhookSignature(payload, signature, secret) {4 const expectedSignature = 'sha256=' + crypto5 .createHmac('sha256', secret)6 .update(JSON.stringify(payload))7 .digest('hex');89 return crypto.timingSafeEqual(10 Buffer.from(signature),11 Buffer.from(expectedSignature)12 );13}1415// Express.js example16app.post('/webhooks/wasaapay', express.json(), (req, res) => {17 const signature = req.body.signature;18 const payload = req.body;1920 // Remove signature from payload for verification21 delete payload.signature;2223 if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {24 return res.status(401).send('Invalid signature');25 }2627 // Process the webhook28 const { event, data } = req.body;2930 switch (event) {31 case 'deposit.completed':32 handleDepositCompleted(data);33 break;34 case 'withdrawal.completed':35 handleWithdrawalCompleted(data);36 break;37 // ... handle other events38 }3940 res.status(200).send('OK');41});
Retry Policy
If your endpoint doesn't return a 2xx status code, we'll retry the webhook with exponential backoff:
- 1st retry: 1 minute
- 2nd retry: 5 minutes
- 3rd retry: 30 minutes
- 4th retry: 2 hours
- 5th retry: 12 hours
After 5 failed attempts, the webhook is marked as failed.
Best Practices
- Always verify signatures to ensure webhooks are from WasaaPay
- Return 200 quickly - process webhooks asynchronously if needed
- Handle duplicates - use idempotency to prevent processing the same event twice
- Log webhook payloads for debugging and audit trails
- Test with sandbox before going live
Testing Webhooks
Use the dashboard to send test webhooks to your endpoint. You can also view webhook delivery history and retry failed deliveries.