Payment Events#

CasaPay sends webhook events for all payment lifecycle changes.

Event Types#

EventDescription
payment_intent.createdA new PaymentIntent was created
payment_intent.requires_actionPaymentIntent needs customer action
payment_intent.processingPayment is being processed
payment_intent.succeededPayment succeeded
payment_intent.payment_failedPayment attempt failed
payment_intent.canceledPaymentIntent was canceled
charge.succeededCharge was successful
charge.failedCharge failed
charge.refundedCharge was refunded
payment_method.attachedPayment method attached to customer
payment_method.detachedPayment method detached
mandate.createdDirect debit mandate created
mandate.activeMandate is active and ready for charges
mandate.cancelledMandate was cancelled
mandate.failedMandate setup failed
bank_authorisation.authorisedBank authorisation completed
bank_authorisation.failedBank authorisation failed
dispute.createdDispute was opened
dispute.updatedDispute status changed
dispute.wonDispute resolved in your favor
dispute.lostDispute resolved in tenant's favor

Event Object#

{
  "id": "evt_pay_abc123",
  "object": "event",
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_1a2b3c4d",
      "object": "payment_intent",
      "amount": 120000,
      "currency": "eur",
      "status": "succeeded",
      "customer": "cus_123456789",
      "payment_method": "pm_card_visa"
    }
  },
  "created": 1706140800
}

Handling Payment Events#

app.post('/webhooks/casapay', async (req, res) => {
  const event = req.body;

  switch (event.type) {
    case 'payment_intent.succeeded':
      await recordSuccessfulPayment(event.data.object);
      break;
    case 'payment_intent.payment_failed':
      await handleFailedPayment(event.data.object);
      break;
    case 'mandate.active':
      await enableRecurringPayments(event.data.object);
      break;
    case 'dispute.created':
      await alertDisputeTeam(event.data.object);
      break;
  }

  res.status(200).send();
});