Payments Collection Quickstart#

Collect rent payments through cards, open banking, and direct debit (BACS/SEPA/ACH). CasaPay handles payment routing, mandate management, and reconciliation.

Step 1: Create a Customer#

curl https://api.casapay.com/v1/customers \
  -H "Authorization: Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Doe",
    "email": "jane.doe@example.com"
  }'

Step 2: Create a PaymentAgreement#

A PaymentAgreement onboards the tenant into aggregated collection. CasaPay generates an onboarding URL where the tenant sets up their preferred payment method:

curl https://api.casapay.com/v1/payment_agreements \
  -H "Authorization: Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant": "cus_123456789",
    "entity": "ent_456def",
    "payment_methods_available": ["card", "open_banking", "direct_debit"],
    "metadata": {
      "property_id": "prop_456",
      "unit": "4B"
    }
  }'
{
  "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
}

Send the onboarding_url to the tenant via email, SMS, or your tenant portal. Once they complete onboarding, the agreement moves to active.

Step 3: Create a PaymentRequest#

When rent is due, create a PaymentRequest against the active agreement. CasaPay charges the tenant's preferred method, handles retries, and falls back to alternatives if needed:

curl https://api.casapay.com/v1/payment_requests \
  -H "Authorization: Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_agreement": "pa_abc123",
    "amount": 120000,
    "currency": "eur",
    "description": "Rent — February 2025",
    "metadata": {
      "property_id": "prop_456",
      "period": "2025-02"
    }
  }'
{
  "id": "preq_abc123",
  "object": "payment_request",
  "payment_agreement": "pa_abc123",
  "amount": 120000,
  "currency": "eur",
  "status": "pending",
  "created": 1706140800
}

Step 4: Handle the Result#

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

  switch (event.type) {
    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;
  }

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

That's it!

One agreement per tenant, one request per rent period. CasaPay handles method selection, mandates, retries, and fallback logic. See Aggregated Collection for the full reference.


Alternative: Custom Integration#

Need full control over payment routing, method selection, and retry logic? Use custom integration with PaymentIntents — you manage the checkout experience and CasaPay processes the charges.

# Create a PaymentIntent
curl https://api.casapay.com/v1/payment_intents \
  -H "Authorization: Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 120000,
    "currency": "eur",
    "customer": "cus_123456789",
    "payment_method_types": ["card", "open_banking", "direct_debit"],
    "description": "Rent payment — February 2025"
  }'
{
  "id": "pi_1a2b3c4d",
  "object": "payment_intent",
  "amount": 120000,
  "currency": "eur",
  "status": "requires_payment_method",
  "client_secret": "pi_1a2b3c4d_secret_xyz789"
}

Then confirm on the client side using the client_secret and handle payment_intent.succeeded / payment_intent.payment_failed webhooks.

Learn more about PaymentIntents