Bank redirects
The customer leaves your checkout, authenticates at their own bank, approves the payment, and comes back. Strong bank authentication means the money is guaranteed once approved — and there is no chargeback rail. In markets like the Netherlands and Belgium, these methods outsell cards.
The redirect methods
| Method | payment_method | Region |
|---|---|---|
| iDEAL | ideal | Netherlands |
| Bancontact | bancontact | Belgium |
| EPS | eps | Austria |
| Przelewy24 | p24 | Poland |
| FPX | fpx | Malaysia |
| Trustly | trustly | Europe + Nordics |
All six are account-to-account push payments dressed in a scheme: the customer instructs their own bank to pay you. Trustly is the multi-market one — a single method id covering bank login across much of Europe and the Nordics. Currencies per method are in the catalog.
The redirect round-trip
Two properties of this flow shape your integration:
- The webhook is the source of truth. The customer's browser coming back to
return_urlproves nothing — they can close the tab at the bank, the redirect can be lost, or it can arrive before the bank's confirmation. Fulfill onpayment.succeeded, and make the return page read state your webhook handler wrote. The API integration guide shows the pattern. - Approval is usually seconds, but not always. Most banks confirm while the customer is still in the flow. A few confirm minutes later — treat
requires_action→succeededas asynchronous, never as a same-request answer.
Creating a redirect payment
return_url is required — there is always a redirect to come back from:
curl https://api.finscale.dev/v1/payments \
-H "Authorization: Bearer sk_test_51FinscaleDemo…" \
-H "Idempotency-Key: idem_ord_9f21_0716" \
-H "Content-Type: application/json" \
-d '{
"amount": 4900,
"currency": "EUR",
"payment_method": "ideal",
"reference": "ord_9f21_0716",
"customer": { "email": "anna@example.com" },
"return_url": "https://shop.example.com/checkout/return"
}'
{
"id": "pay_8Q2mX4nT1cVb",
"object": "payment",
"amount": 4900,
"currency": "EUR",
"status": "requires_action",
"payment_method": "ideal",
"reference": "ord_9f21_0716",
"provider": "prov_eu_acq_01",
"next_action": {
"type": "redirect",
"url": "https://pay.finscale.dev/r/8Q2mX4nT"
},
"created_at": "2026-07-16T09:24:31Z",
"livemode": false
}
Send the customer to next_action.url. Bank selection (for methods that need it, like iDEAL and Przelewy24) happens on the Finscale-hosted page — you don't build a bank picker.
What comes back
After approval, payment_method_details records which bank paid and the tail of the paying account — useful for support and for matching refunds later:
{
"payment_method_details": {
"ideal": {
"bank": "demo_bank_nl",
"iban_last4": "3401"
}
}
}
The shape is keyed by method id — ideal: { bank, iban_last4 } here; equivalents for the other five carry the same idea.
Refunds — and no chargebacks
Refunds work the standard way: POST /v1/refunds with the payment id, full or partial. Under the hood the refund travels as a credit transfer back to the account that paid — Finscale captured it during the flow, so there is nothing to collect from the customer. Refunds are pending until the transfer lands, typically one to two business days; subscribe to refund.succeeded. See Refunds.
Settlement timing
The bank's approval is a guarantee, not yet cash: the scheme moves the funds to Finscale within a business day, and they join your unified payout on the standard T+2 schedule alongside your card and wallet volume — one payout per currency, one settlement report to reconcile.
Error scenarios
| Scenario | What the API does |
|---|---|
| Customer abandons at the bank | The payment stays requires_action until the redirect session expires, then moves to failed and payment.failed fires. Sessions are single-use — a restarted checkout is a new payment. |
| Bank refuses the payment | payment.failed with a normalized failure_code — most commonly insufficient_funds. Bank refusals are final: no failover, because the answer came from the customer's bank, not from a provider. |
| Method/currency mismatch | 400 invalid_request_error with currency_not_supported — e.g. ideal with a non-EUR currency. |
return_url missing | 400 invalid_request_error at create — redirect methods require it. |
| Provider degraded | Routing happens before the customer is redirected, so a failing provider is skipped transparently — see Provider health & failover. |
Related
- Payment methods overview — families, payload shapes, full catalog
- Real-time payments — the app-and-QR cousins of these rails
- API integration — the redirect round-trip in code
- Webhooks — signature checks and delivery semantics
- Method catalog on finscale.dev — regions and currencies