Webhooks#
CasaPay uses webhooks to notify your application when events happen in your account. Webhooks are particularly useful for asynchronous events like when a payment succeeds, a verification completes, or a debt collection case is updated.
How Webhooks Work#
- You configure a webhook endpoint in your Dashboard or via the API
- When an event occurs, CasaPay creates an
Eventobject - CasaPay sends an HTTP POST request with the event to your endpoint
- Your endpoint acknowledges receipt with a
2xxresponse
Setting Up a Webhook Endpoint#
curl https://api.casapay.com/v1/webhook_endpoints \
-H "Authorization: Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/casapay",
"enabled_events": [
"payment_intent.succeeded",
"payment_intent.failed",
"verification_session.completed",
"invoice.paid"
]
}'Verifying Signatures#
CasaPay signs all webhook events with an HMAC-SHA256 signature. Verify this signature to confirm that events were sent by CasaPay, not by a third party.
The signature is included in the X-CasaPay-Signature header with the format:
t={timestamp},v1={signature}Verification Steps#
const crypto = require('crypto');
function verifyWebhookSignature(payload, header, secret) {
const [tPart, v1Part] = header.split(',');
const timestamp = tPart.split('=')[1];
const signature = v1Part.split('=')[1];
// Check timestamp tolerance (5 minutes)
const tolerance = 300;
const currentTime = Math.floor(Date.now() / 1000);
if (currentTime - parseInt(timestamp) > tolerance) {
throw new Error('Webhook timestamp too old');
}
// Compute expected signature
const signedPayload = `${timestamp}.${payload}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// Compare signatures
if (!crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
)) {
throw new Error('Webhook signature verification failed');
}
return JSON.parse(payload);
}Event Types#
Events are organized by product:
| Product | Event Types |
|---|---|
| Tenant Verification | verification_session.created, .completed, .expired, verification_report.ready |
| Tenant Scoring | score_request.completed, score_report.ready |
| Invoicing | invoice.created, .finalized, .paid, .voided |
| Payments Collection | payment_intent.created, .succeeded, .failed, charge.succeeded, .refunded |
| Payments Payouts | payout.created, .paid, .failed |
| Payments Guarantee | guarantee.activated, .claimed, .expired |
| Debt Collection | collection_case.created, .updated, .closed, debt_payment.created |
Retry Policy#
CasaPay attempts to deliver each webhook 3 times with exponential backoff:
- 1st retry: 5 minutes after failure
- 2nd retry: 30 minutes after first retry
- 3rd retry: 2 hours after second retry
After all retries are exhausted, the event is marked as failed and available in your Dashboard for manual inspection.
Respond quickly
Your endpoint must return a 2xx HTTP status code within 30 seconds of receiving the webhook. If your endpoint takes longer, CasaPay will consider the delivery failed and retry.