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

  1. Configure your webhook URL in the dashboard
  2. Implement an endpoint to receive POST requests at that URL
  3. Verify webhook signatures for security
  4. 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

EventDescription
deposit.initiatedDeposit request created, awaiting payment
deposit.completedFunds received and credited to wallet
deposit.failedDeposit failed or was cancelled

Withdrawal Events

EventDescription
withdrawal.initiatedWithdrawal request submitted
withdrawal.completedFunds sent to recipient
withdrawal.failedWithdrawal failed

Transfer Events

EventDescription
transfer.completedTransfer completed successfully
transfer.failedTransfer failed

Bill Payment Events

EventDescription
bill.initiatedBill payment submitted
bill.completedBill paid successfully
bill.failedBill 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');
2
3function verifyWebhookSignature(payload, signature, secret) {
4 const expectedSignature = 'sha256=' + crypto
5 .createHmac('sha256', secret)
6 .update(JSON.stringify(payload))
7 .digest('hex');
8
9 return crypto.timingSafeEqual(
10 Buffer.from(signature),
11 Buffer.from(expectedSignature)
12 );
13}
14
15// Express.js example
16app.post('/webhooks/wasaapay', express.json(), (req, res) => {
17 const signature = req.body.signature;
18 const payload = req.body;
19
20 // Remove signature from payload for verification
21 delete payload.signature;
22
23 if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
24 return res.status(401).send('Invalid signature');
25 }
26
27 // Process the webhook
28 const { event, data } = req.body;
29
30 switch (event) {
31 case 'deposit.completed':
32 handleDepositCompleted(data);
33 break;
34 case 'withdrawal.completed':
35 handleWithdrawalCompleted(data);
36 break;
37 // ... handle other events
38 }
39
40 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.