Payout Webhooks
The Payout webhook allows you to receive real-time notifications about the status of your payout transactions. You can configure your webhook URL in the dashboard under Dev Settings.
Webhook Configuration
- Go to your dashboard
- Click on "Dev Settings" tab
- Find the "Webhook Configuration" section
- Enter your webhook URL
- Save the configuration
Webhook Payload
When a payout transaction status changes, you'll receive a POST request to your configured webhook URL with the following payload:
{
"type": "payout",
"timestamp": "2024-03-20T10:30:00Z",
"data": {
"order_id": "987654321098765",
"status": "SUCCESS",
"beneficiary_name": "Jason Stathom",
"account_number": "390000000003",
"amount": "99",
"utr": "UTR24031545789",
"timestamp": "2024-03-20T10:29:45Z",
"wallet_balance": {
"available": 5000.00,
"on_hold": 100.00
}
}
}Payload Fields
| Field | Type | Description |
|---|---|---|
| type | string | Always "payout" for payout webhooks |
| timestamp | string | ISO 8601 timestamp of when the webhook was sent |
| data.order_id | string | Your merchant order ID for the payout |
| data.status | string | Transaction status (SUCCESS, FAILED, PENDING) |
| data.beneficiary_name | string | Name of the beneficiary |
| data.account_number | string | Beneficiary's account number |
| data.amount | string | Amount of the payout |
| data.utr | string | UTR number for successful transactions |
| data.timestamp | string | ISO 8601 timestamp of the transaction |
| data.wallet_balance.available | number | Available balance in wallet |
| data.wallet_balance.on_hold | number | Amount on hold in wallet |
Headers
Each webhook request includes the following headers:
| Header | Value |
|---|---|
| Content-Type | application/json |
| X-Webhook-Source | PayVanta |
Response
Your webhook endpoint should return a 2xx status code to acknowledge receipt of the webhook. Any other status code will be considered a failure, and we may retry the webhook delivery.
Retry Policy
If your webhook endpoint fails to respond with a 2xx status code, we will retry the webhook delivery with the following schedule:
- First retry: 1 minute after initial failure
- Second retry: 5 minutes after first retry
- Third retry: 15 minutes after second retry
- Fourth retry: 30 minutes after third retry
Security
To ensure the webhook is coming from PayVanta:
- Verify the
X-Webhook-Sourceheader is set to "PayVanta" - Implement IP whitelisting for PayVanta's webhook servers
- Use HTTPS for your webhook endpoint
Example Implementation
const express = require('express');
const app = express();
app.post('/webhook', (req, res) => {
// Verify webhook source
if (req.headers['x-webhook-source'] !== 'PayVanta') {
return res.status(401).json({ error: 'Invalid webhook source' });
}
const { type, timestamp, data } = req.body;
// Handle payout webhook
if (type === 'payout') {
console.log('Received payout webhook:', {
orderId: data.order_id,
status: data.status,
amount: data.amount,
utr: data.utr,
walletBalance: data.wallet_balance
});
// Process the webhook data
// Update your database, notify users, etc.
}
// Always return 200 to acknowledge receipt
res.status(200).send('Webhook received');
});
app.listen(3000, () => {
console.log('Webhook server listening on port 3000');
});Testing Webhooks
You can test your webhook configuration using the "Test Webhook" button in the Dev Settings tab. This will send a test payload to your configured webhook URL.
Best Practices
- Always respond quickly to webhook requests (within 5 seconds)
- Implement idempotency to handle duplicate webhooks
- Log all webhook requests for debugging
- Use HTTPS for your webhook endpoint
- Implement proper error handling
- Store webhook data in your database for record-keeping
- Update your system's transaction status based on webhook notifications
- Monitor wallet balance changes through webhook notifications