Checkout flow#
This is the full lifecycle of a gateway payment, from your API call to money landing in your bank account.
Sequence#
Your backend CasaPay Tenant
| | |
|-- POST /sessions ------>| |
|<-- session_id + url ----| |
| | |
|-- redirect to gateway_url ------------------------->|
| | |
| |<-- step: verification ----| (if required)
| |<-- step: deposit_choice --| (if offered)
| |<-- step: payment ---------|
| | |
| |-- charge via EveryPay --->|
| |<-- settled ---------------|
| | |
| |-- redirect to success_url >|
|<-- webhook: session.completed |
| | |
| (payout scheduled to your IBAN) |1. Create the session#
You post the tenant, the amounts and your return URLs. Nothing is charged and no agreement exists yet - you get back a session_id and a gateway_url.
The agreement and invoice are created when the tenant pays, not when the session is created. A session that is never paid leaves no financial records behind.
2. Redirect the tenant#
Send the tenant to gateway_url exactly as returned. Do not construct it yourself.
Sessions created from POST /sessions expire (24 hours by default, see expires_at). Sessions created from the invoice endpoint never expire.
3. The step machine#
CasaPay decides which steps a session needs and exposes the current one as current_step:
| Step | Shown when |
|---|---|
verification | Your entity requires identity verification, or you set verification_required: true, and the tenant is not already verified. |
deposit_choice | deposit_mode is choice, so the tenant picks cash or guarantee. |
payment | Always, unless the balance due is zero. |
When the session finishes, current_step becomes null. Steps are skipped automatically when not needed - a returning verified tenant with a fixed deposit mode goes straight to payment.
4. Payment#
The tenant picks card or bank link and is redirected to EveryPay. CasaPay learns the result twice: once when the tenant's browser returns, and once via a server-to-server webhook. Both paths are idempotent and guarded by a row lock, so exactly one set of records is created no matter which arrives first or whether both do.
On success CasaPay:
- Creates the payment agreement, if the session did not already have one.
- Creates and marks the invoice paid.
- Splits a cash deposit off to the CasaPay deposit account, and rent to your entity.
- Activates the guarantee, if the tenant chose one.
- Schedules the operator payout.
- Sends
gateway.session.completed.
Do not rely on the redirect
success_url only loads if the tenant's browser comes back. They may close the tab, lose signal, or return late. The webhook is the authoritative signal - reconcile on it.
5. Payout#
Collected money sits with CasaPay and is paid out to your configured bank account on a schedule that depends on the agreement type:
| Agreement type | Payout timing |
|---|---|
payment_link | Once the tenant payment settles. |
ontime | On the invoice due date - even if the tenant is late. |
cover | Due date plus 30 days. |
A cash deposit is not paid to you. It goes to a segregated CasaPay deposit account and is returned or claimed at end of tenancy.
Track progress with payout_status on the invoice: pending to in_disbursement to settled.
Failure and cancellation#
- A failed payment attempt fires
gateway.payment.failedand leaves the session open. The tenant retries on the same URL. - An unpaid session past
expires_atbecomesexpired. - You can cancel an unpaid session at any time. A session whose payment completed can never be cancelled.
- If the invoice is settled or cancelled elsewhere, CasaPay auto-cancels the open sessions to prevent a double payment.