Guide
Webhooks
Fiatsend sends real-time notifications to your server when withdrawal statuses change. Instead of polling the API, register a webhook URL and we'll push updates to you.
How It Works
- Register a webhook endpoint via
POST /v1/webhooks
- Fiatsend sends a
POST request to your URL whenever a subscribed event occurs
- Your server verifies the signature and processes the event
- Respond with a
2xx status code to acknowledge receipt
Retry Policy
If your endpoint returns a non-2xx status or times out (30s), Fiatsend retries with exponential backoff: 1 min, 5 min, 30 min, 2 hr, 24 hr. After 5 failed attempts, the webhook is marked as failed.
Webhook Payload
{
"event": "withdrawal.completed",
"timestamp": "2026-03-21T06:59:42Z",
"data": {
"withdrawal_id": "wd_9f8e7d6c5b4a",
"status": "completed",
"amount": "50.00",
"currency": "USDC",
"ghs_amount": "750.00",
"fx_rate": "15.00",
"fee": "0.50",
"recipient_phone": "+233241234567",
"mobile_network": "MTN",
"reference_id": "deel-txn-abc123",
"on_chain_tx_hash": "0x1234abcd...",
"mobile_money_reference": "MOMO-REF-456789",
"completed_at": "2026-03-21T06:59:42Z"
}
}
Signature Verification
Every webhook request includes an X-Fiatsend-Signature header containing an HMAC-SHA256 signature of the request body, computed using your webhook secret. Always verify this signature before processing events.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express middleware example
app.post('/webhooks/fiatsend', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-fiatsend-signature'];
const isValid = verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET);
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(req.body);
switch (event.event) {
case 'withdrawal.completed':
// Mark payout as complete in your system
break;
case 'withdrawal.failed':
// Handle failure, notify user
break;
}
res.status(200).json({ received: true });
});
Event Types
| Event | Description |
withdrawal.pending | Withdrawal request received, awaiting processing |
withdrawal.processing | On-chain transaction submitted, mobile money transfer initiated |
withdrawal.completed | Funds successfully delivered to mobile money wallet |
withdrawal.failed | Transaction failed โ funds returned to source |