Aggregated Events#
CasaPay sends webhook events for all aggregated collection lifecycle changes. Subscribe to these events to track tenant onboarding, payment processing, and collection results.
Event types#
| Event | Description |
|---|---|
payment_agreement.created | A new PaymentAgreement was created |
payment_agreement.activated | Tenant completed onboarding, agreement is active |
payment_agreement.suspended | Agreement suspended (method failed, mandate cancelled) |
payment_agreement.cancelled | Agreement was cancelled |
payment_request.created | A new PaymentRequest was created |
payment_request.processing | CasaPay is actively collecting payment |
payment_request.succeeded | Payment collected successfully |
payment_request.failed | All collection attempts exhausted |
payment_request.retrying | Collection attempt failed, retry scheduled |
payment_agreement.created#
Triggered when a new PaymentAgreement is created.
{
"id": "evt_pa_created_001",
"object": "event",
"type": "payment_agreement.created",
"data": {
"object": {
"id": "pa_abc123",
"object": "payment_agreement",
"tenant": "cus_123456789",
"entity": "ent_456def",
"status": "pending_onboarding",
"onboarding_url": "https://pay.casapay.com/onboard/pa_abc123",
"payment_methods_available": ["card", "open_banking", "direct_debit"],
"created": 1706140800
}
},
"created": 1706140800,
"livemode": true
}payment_agreement.activated#
Triggered when a tenant completes onboarding and the agreement becomes active.
{
"id": "evt_pa_activated_001",
"object": "event",
"type": "payment_agreement.activated",
"data": {
"object": {
"id": "pa_abc123",
"object": "payment_agreement",
"tenant": "cus_123456789",
"entity": "ent_456def",
"status": "active",
"preferred_method": "direct_debit",
"mandate": "md_xyz789",
"created": 1706140800
}
},
"created": 1706227200,
"livemode": true
}payment_agreement.suspended#
Triggered when an agreement is suspended due to a permanent method failure.
{
"id": "evt_pa_suspended_001",
"object": "event",
"type": "payment_agreement.suspended",
"data": {
"object": {
"id": "pa_abc123",
"object": "payment_agreement",
"status": "suspended",
"preferred_method": "direct_debit",
"mandate": "md_xyz789"
}
},
"created": 1709251200,
"livemode": true
}payment_agreement.cancelled#
Triggered when a PaymentAgreement is cancelled.
{
"id": "evt_pa_cancelled_001",
"object": "event",
"type": "payment_agreement.cancelled",
"data": {
"object": {
"id": "pa_abc123",
"object": "payment_agreement",
"status": "cancelled"
}
},
"created": 1709337600,
"livemode": true
}payment_request.created#
Triggered when a new PaymentRequest is created.
{
"id": "evt_preq_created_001",
"object": "event",
"type": "payment_request.created",
"data": {
"object": {
"id": "preq_abc123",
"object": "payment_request",
"payment_agreement": "pa_abc123",
"amount": 120000,
"currency": "eur",
"description": "Rent — March 2025",
"status": "pending",
"created": 1709251200
}
},
"created": 1709251200,
"livemode": true
}payment_request.processing#
Triggered when CasaPay begins actively collecting the payment.
{
"id": "evt_preq_processing_001",
"object": "event",
"type": "payment_request.processing",
"data": {
"object": {
"id": "preq_abc123",
"object": "payment_request",
"payment_agreement": "pa_abc123",
"amount": 120000,
"currency": "eur",
"status": "processing",
"payment_method_used": "direct_debit",
"attempts": 1
}
},
"created": 1709251260,
"livemode": true
}payment_request.succeeded#
Triggered when payment is collected successfully.
{
"id": "evt_preq_succeeded_001",
"object": "event",
"type": "payment_request.succeeded",
"data": {
"object": {
"id": "preq_abc123",
"object": "payment_request",
"payment_agreement": "pa_abc123",
"amount": 120000,
"currency": "eur",
"status": "succeeded",
"payment_method_used": "direct_debit",
"attempts": 1,
"metadata": {
"property_id": "prop_456",
"period": "2025-03"
}
}
},
"created": 1709337600,
"livemode": true
}payment_request.failed#
Triggered when all collection attempts are exhausted and the payment was not collected.
{
"id": "evt_preq_failed_001",
"object": "event",
"type": "payment_request.failed",
"data": {
"object": {
"id": "preq_def456",
"object": "payment_request",
"payment_agreement": "pa_def456",
"amount": 95000,
"currency": "eur",
"status": "failed",
"payment_method_used": "card",
"failure_reason": "insufficient_funds",
"attempts": 3
}
},
"created": 1709596800,
"livemode": true
}Failure reasons#
| Code | Description |
|---|---|
insufficient_funds | Tenant's account has insufficient funds |
card_declined | Card was declined by the issuer |
mandate_cancelled | Direct debit mandate has been cancelled |
account_closed | Tenant's bank account has been closed |
authentication_required | Payment requires additional authentication |
expired_method | Payment method has expired |
payment_request.retrying#
Triggered when a collection attempt fails but a retry is scheduled.
{
"id": "evt_preq_retrying_001",
"object": "event",
"type": "payment_request.retrying",
"data": {
"object": {
"id": "preq_def456",
"object": "payment_request",
"payment_agreement": "pa_def456",
"amount": 95000,
"currency": "eur",
"status": "processing",
"payment_method_used": "direct_debit",
"failure_reason": "insufficient_funds",
"attempts": 1,
"next_retry_at": 1709337600
}
},
"created": 1709251200,
"livemode": true
}Handling aggregated events#
app.post('/webhooks/casapay', async (req, res) => {
const event = req.body;
switch (event.type) {
case 'payment_agreement.activated':
await markTenantOnboarded(event.data.object.tenant);
break;
case 'payment_agreement.suspended':
await notifyOperator(event.data.object);
break;
case 'payment_request.succeeded':
const request = event.data.object;
await markRentPaid(request.metadata.property_id, request.metadata.period);
break;
case 'payment_request.failed':
await escalateFailedPayment(event.data.object);
break;
case 'payment_request.retrying':
await logRetryAttempt(event.data.object);
break;
}
res.status(200).send();
});