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#

  1. You configure a webhook endpoint in your Dashboard or via the API
  2. When an event occurs, CasaPay creates an Event object
  3. CasaPay sends an HTTP POST request with the event to your endpoint
  4. Your endpoint acknowledges receipt with a 2xx response

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:

ProductEvent Types
Tenant Verificationverification_session.created, .completed, .expired, verification_report.ready
Tenant Scoringscore_request.completed, score_report.ready
Invoicinginvoice.created, .finalized, .paid, .voided
Payments Collectionpayment_intent.created, .succeeded, .failed, charge.succeeded, .refunded
Payments Payoutspayout.created, .paid, .failed
Payments Guaranteeguarantee.activated, .claimed, .expired
Debt Collectioncollection_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.