Flexible bank transfer reconciliation (Beta)
This feature is in beta.
Virtual IBANs and the Unmatched Credit Transfer API are currently available to a limited set of merchants in the Netherlands, Belgium, France, and Germany. Contact us or your account/sales manager to request early access.
General information
By default, Mollie automatically matches incoming bank transfers to open payments using the payment reference and amount. This works well for straightforward cases — but bank transfers are inherently uncontrolled: customers may forget the reference, mistype the amount, or send a single transfer covering multiple invoices.
The Flexible Reconciliation feature gives you programmatic control over these edge cases. It combines two things:
- Virtual IBANs (vIBANs) — a dedicated IBAN assigned to your Mollie profile, so every incoming transfer is unambiguously routed to you. The vIBAN is in your profile's name and is compliant with the latest Verification of Payee regulation: a green checkmark will be displayed on the consumer's bank app flagging that the virtual IBAN corresponds to the correct profile
- Unmatched Credit Transfer API — when automatic matching fails, Mollie notifies you via webhook and lets you decide: match the funds to one or more payments, or return them to the sender
This is especially useful for platforms, billing software, and B2B merchants who deal with partial payments, combined invoices, or customers who routinely omit payment references.
How it works
Step 1: Share your virtual IBAN with customers
Once provisioned, your virtual IBAN is unique to your Mollie profile. Display it on your invoices, order confirmations, and checkout pages as the payment destination.
Unlike a standard SEPA bank transfer payment where each order gets a unique reference, with vIBANs the IBAN itself identifies you — all transfers land in one place, and Mollie (or you, via the API) handles routing.
Tip: Still include a payment reference in your instructions. This maximises the chance of automatic matching and reduces the number of unmatched transfers you need to handle.
Step 2: Create open payments (standard flow)
Create a payment via the Create payment endpoint with method:banktransfer, status will remain as open.
curl -X POST https://api.mollie.com/v2/payments \
-H "Authorization: Bearer live_xxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"amount": { "currency": "EUR", "value": "120.00" },
"description": "Invoice INV-2024-0099",
"redirectUrl": "https://example.com/order/INV-2024-0099",
"method": "banktransfer"
}'When the customer pays correctly (right reference, right amount), Mollie matches and settles automatically — no
further action needed.
Step 3: Receive the webhook for unmatched transfers
When a transfer cannot be matched automatically, Mollie sends a webhook event to your endpoint.
Event type: unmatched-credit-transfer.received
The embedded entity gives you everything you need to make a reconciliation decision: the sender's account details, the amount, and any remittance information they included.
Step 4: Fetch the unmatched credit transfer
Use the entityId from the webhook to retrieve the unmatched credit transfer resource via the Get unmatched credit transfer endpoint.
curl https://api.mollie.com/v2/unmatched-credit-transfers/uct_abcDEFghij123456789 \
-H "Authorization: Bearer live_xxxxxxxxxxxxxxx" You can also use the List unmatched credit transfers endpoint to retrieves a list of unmatched credit transfers for your profile.
Step 5: Resolve the transfer
Once you receive the unmatched-credit-transfer.received webhook, you have up to 2 days to resolve the transfer. If 2 days pass, the transfer will be returned to the sender.
You cannot match an unmatched transfer to a payment with a different amount by adjusting the payment amount. The total of thepaymentIdsyou provide must exactly equal the amount of the unmatched credit transfer.
Once you've identified what the funds are for, take one of two actions.
Option A: Match the funds to one or more payments
Use this when you can identify the payment(s) the customer intended to pay. You can match to an existing open payment, or — for maximum flexibility — create a new payment first and then immediately match the unmatched funds to it.
Matching to a payment:
curl -X POST https://api.mollie.com/v2/unmatched-credit-transfers/uct_abcDEFghij123456789/match \
-H "Authorization: Bearer live_xxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d "paymentIds": ["tr_PaymentToken"]"Matching to multiple payments (e.g. a customer paying two invoices in one transfer):
curl -X POST https://api.mollie.com/v2/unmatched-credit-transfers/uct_abcDEFghij123456789/match \
-H "Authorization: Bearer live_xxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"paymentIds": ["tr_PaymentToken1","tr_PaymentToken2"]
}'The action is processed asynchronously. Mollie will send an unmatched-credit-transfer.matched webhook once the funds are settled against the payments you specified.
Option B: Return the funds to the sender
Use this when you cannot identify the customer or the funds don't correspond to any open invoice, and you want to
refund them.
curl -X POST https://api.mollie.com/v2/unmatched-credit-transfers/uct_abcDEFghij123456789/return \
-H "Authorization: Bearer live_xxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{}'Mollie will send an unmatched-credit-transfer.returned webhook once the return is processed.
Status reference
| Status | Description |
|---|---|
received | The credit transfer has been received but not yet matched or returned. |
matched | The credit transfer has been matched to one or more payments. |
returned | The credit transfer has been returned to the sender. |
expired | The credit transfer has expired without being matched or returned. |
Webhook events
| Event type | Triggered when |
|---|---|
unmatched-credit-transfer.received | A new unmatched credit transfer is created (matching failed) |
unmatched-credit-transfer.matched | The transfer is successfully matched and settled to payment(s) |
unmatched-credit-transfer.returned | The transfer has been returned to the sender. |
unmatched-credit-transfer.expired | The transfer expired without a resolution being applied |
Updated about 3 hours ago