Webhooks notify your server when events happen — user KYC status changes, card transactions, and collateral updates.
Setup
Configure your webhook endpoint using the Set Webhook endpoint. You’ll receive a webhookSecret (prefixed whsec_) that you’ll use to verify webhook signatures.
Events
KYC Events
| Event | Description |
|---|
user.kyc.pending | User KYC submission received, under review |
user.kyc.approved | User KYC approved — user can now create cards |
user.kyc.denied | User KYC denied |
user.kyc.needsVerification | Additional verification required from the user |
user.kyc.manualReview | KYC submitted for manual review |
Transaction Events
| Event | Description |
|---|
transaction.authorized | Card transaction authorized |
transaction.declined | Card transaction declined |
transaction.reversed | Card transaction reversed |
transaction.settled | Card transaction settled (final) |
Collateral Events
| Event | Description |
|---|
collateral.received | Collateral deposit received |
collateral.settled | Collateral deposit settled |
All webhooks are delivered as POST requests with a JSON body:
{
"event": "user.kyc.approved",
"timestamp": "2025-01-15T10:30:00.000Z",
"data": {
"serviceId": "acme-rain-user-abc123def456ghi",
"partnerId": "acme",
"status": "approved",
"details": {}
}
}
Signature Verification
Every webhook includes an X-Webhook-Signature header containing an HMAC-SHA256 hex digest. Always verify this signature before processing the webhook.
const crypto = require('crypto');
function verifyWebhook(req, webhookSecret) {
const signature = req.headers['x-webhook-signature'];
const payload = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', webhookSecret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Retry Policy
If your endpoint doesn’t respond with a 2xx status code, the webhook is retried with exponential backoff:
| Attempt | Delay |
|---|
| 1st retry | 5 minutes |
| 2nd retry | 30 minutes |
| 3rd retry | 2 hours |
After 3 failed retries, the webhook is marked as failed. All webhook deliveries (successful and failed) are logged for debugging.
Your webhook endpoint must respond within 30 seconds. Long-running processing should be handled asynchronously after acknowledging the webhook with a 200 response.