Failed Payment Recovery — Direct Debit → Pay by Bank

Failed Payment Recovery — Direct Debit → Pay by Bank

What you're building: When a Direct Debit collection fails, your system detects the failure, assesses the reason, and recovers the payment — either by retrying the DD or by switching to Pay by Bank for instant settlement. This guide covers the orchestration logic for that recovery flow.


Who is this guide for?

You are a developer building payment recovery into your collections integration. You've either already set up recurring collections (using the Recurring Collections guide) or you have an existing DD integration and need to add failure handling.

Your industry: Lending (term loans, BNPL, invoice finance), subscription/SaaS, utilities, insurance, property management, or any business where a failed collection means revenue risk or churn.

What this guide adds: The API Reference documents the individual endpoints. The Recurring Collections guide covers the happy path. This guide covers what happens when things go wrong — and how to recover automatically using Modulr's multi-rail capability.

Common search terms for this pattern: failed payment recovery, dunning automation, Direct Debit to Open Banking fallback, rail-switching, payment retry flow, ARUDD handling, multi-rail collections recovery, failed DD retry, PIS fallback, Pay By Bank, pay-now link, instant payment recovery, collection failure handling.


What you'll be able to do after this guide

  • Detect a failed DD collection via webhook or polling
  • Assess the ARUDD failure reason code and determine if it's recoverable
  • Decide whether to retry the DD or switch to Pay by Bank
  • Send a dunning message with an instant pay-now link
  • Initiate a Pay by Bank (PIS) recovery payment
  • Monitor recovery and resume normal collections
  • Understand when a mandate needs to be re-established

What this guide does NOT cover: Setting up Direct Debit mandates and collection schedules from scratch. For that, start with the Recurring Collections guide.


Prerequisites

You should have already completed the Recurring Collections guide, or have an equivalent DD integration in place. Specifically, you need:

PrerequisiteWhere to set it up
Modulr account and API accessAPI Reference · Authentication · Sandbox Access
DD service enabled (SUN assigned)What is DD Collections
Active mandates and collection schedulesRecurring Collections guide or Setting up Mandates + Starting Collections
Collection monitoring via webhooksNotifications guide · DD Collection Status webhook

Additionally for this guide:

What you needWhyWhere to set it up
PIS enabled on your Modulr accountTo initiate Pay by Bank payments as a recovery methodPIS Overview · Getting Started with PIS
Your redirect URL registeredPIS requires a URL to return the customer to after bank authenticationSet up during PIS onboarding
Customer communication channelYou need to send dunning messages (email, SMS, in-app) with a pay-now linkYour responsibility — Modulr provides the payment link, not the messaging

The pattern at a glance

  1. Detect the failure — Via webhook or polling
  2. Assess the failure reason — Check the ARUDD reason code
  3. Decide: retry DD or switch to PIS — Based on the failure reason and mandate status
  4. Notify your customer (dunning) — Send a message with the appropriate next step
  5. Retry via Direct Debit (optional, if appropriate) — One-off collection on the same mandate
  6. Fall back to Pay by Bank — Generate and send an Open Banking payment link
  7. Monitor recovery — Track whether the retry or PIS payment succeeded
  8. Confirm recovery and resume — Update your ledger, resume normal collections

The core concept: rail-switching

Direct Debit is a pull payment — you instruct the payer's bank to debit their account. Pay by Bank (PIS) is a push payment — the payer authorises an immediate transfer from their banking app.

When the pull fails, you switch to push. This is the most common recovery pattern in UK collections because:

  • Speed: PIS settles in seconds via Faster Payments, vs. 3+ working days for a DD retry
  • Certainty: PIS is irrevocable once completed — no ARUDD-equivalent rejection window
  • Customer choice: The customer can pay from any bank account they hold — not just the one the DD was set up on. If the failure was due to insufficient funds, the customer may have money available in a different account
  • Customer experience: A pay-now link gives the customer agency, rather than waiting for another pull attempt
  • Cost: A successful PIS recovery avoids the cost of repeated failed DD attempts

ARUDD failure reason codes

The table below uses normalised recovery categories. In the Modulr webhook payload, use RejectionCode and map the actual Bacs values to your internal recovery logic.

Reason CodeBacs CodeDescriptionDD Retry Possible?Mandate StatusRecommended Action
REFER_TO_PAYER0The paying bank is not in a position to pay the DD (e.g. insufficient funds)MaybeMandate may still be ACTIVE — check before retryingContact the customer before taking any action. May indicate a dispute, query, or insufficient funds. The scheme recommends giving at least 5 working days' notice before re-presenting.
INSTRUCTION_CANCELLED1Payer cancelled the DD mandate at their bankNoMandate is no longer ACTIVE — it must be re-created if the customer agreesSend Pay by Bank link for the immediate payment. Contact customer to discuss re-establishing the mandate for future collections.
PAYER_DECEASED2The account holder is deceasedNoN/ADo not retry. Follow your internal deceased-customer process.
ACCOUNT_TRANSFERRED3Account transferred to a new bank or building societyNoMandate no longer valid at the original bankSend Pay by Bank link. Request updated bank details. Set up a new mandate at the new bank.
NO_ACCOUNT5Account number not recognised at the paying bank, or wrong account typeNoMandate may be invalidCheck details. May indicate a data entry error at mandate setup — PNV (see Recurring Collections guide) would have caught this.
NO_INSTRUCTION6No matching mandate found at the payer's bankNoMandate may need to be re-lodgedCheck mandate status via API. Contact Modulr support if unexpected. May need to create a new mandate.
AMOUNT_NOT_YET_DUE8Payer states the debit date is before the due date, or the DDI was lodged less than 2 working days agoNo (resubmit on the correct date)Mandate is still ACTIVECheck your collection scheduling — you may have submitted too early after lodgement. Reschedule for the correct date.
SERVICE_USER_DIFFERSAIdentity of service user doesn't match the DDINoMandate may need investigationContact Modulr support — this may indicate a SUN configuration issue.
ACCOUNT_CLOSEDBPayer's bank account has been closedNoMandate is effectively dead — a new mandate will be needed if the customer provides new bank detailsSend Pay by Bank link. Request updated bank details. Set up a new mandate for future collections.

A note on code 0 — Refer to Payer: This is by far the most common ARUDD return code you'll encounter. It covers insufficient funds, blocked accounts, and any other situation where the paying bank can't process the debit but doesn't give a specific reason. In practice, the majority of code 0 returns are insufficient funds. Because the Bacs scheme doesn't break this down further, your dunning messaging should assume insufficient funds as the default while leaving room for the customer to tell you otherwise. Code 0 is the only code where representation is straightforward — the mandate stays active, and you can re-present using POST /collection/{collectionId}/represent within the one-month window (max 3 retries). For all other codes, the mandate is either dead or the situation requires investigation before any further action.

Important — mandate implications: When a DD fails due to ACCOUNT_CLOSED or INSTRUCTION_CANCELLED, the mandate is no longer usable. You cannot retry the DD on the same mandate. To resume DD collections in the future, you need to create a new mandate (see Create Mandate), which takes 3 working days to lodge. In the meantime, Pay by Bank is your only collection option for that customer.


Step 1: Detect the Failure

What you're doing: Finding out that a DD collection didn't go through, identifying which customer, and routing it to your recovery workflow.

When failures happen in the Bacs cycle:

DayWhat happensRecovery relevance
Day 3Payer's bank debits the customer (or rejects the collection and generates an ARUDD)Failure originates here
Day 4Modulr receives the ARUDD file from the scheme. DD Collection Status webhook fires (10:15 AM, 12:15 PM, 2:15 PM).Your system detects the failure here
Day 5For unpaid collections: Modulr debits the funds back from your account and returns them to the paying bank. Collection status is FAILED. Late ARUDD returns (rare) may arrive on Day 5 instead of Day 4.Late failures surface

How to detect — Option A: Webhook (recommended)

Subscribe to the DD Collection Status webhook to track collection lifecycle changes — this is where you'll see statuses move to FAILED or REPRESENTABLE. Additionally, subscribe to the Unpaid Collection webhook which fires when an ARUDD is generated for an unpaid collection, and the PayIn webhook to confirm when funds land. Configure webhooks via the Notifications guide.

How to detect — Option B: Polling

GET /collections?mandateId={mandateId}&status=FAILED

Sample response:

{
  "content": [
    {
      "id": "COL-2026-05-001",
      "mandateId": "M21ABC123",
      "amount": 250.00,
      "status": "FAILED",
      "failureReason": "INSUFFICIENT_FUNDS",
      "scheduledDate": "2026-05-01",
      "reference": "LOAN-RPY-0142"
    }
  ]
}

What to do with this: Extract the failureReason and route to Step 2.


Step 2: Assess the Failure Reason

What you're doing: Looking at the ARUDD reason code and deciding your recovery strategy.

This is a decision point, not an API call. Your system logic should branch here:

IF failureReason is recoverable (INSUFFICIENT_FUNDS):
    → Mandate is still active
    → Optionally retry DD (Step 5) — but note funds are unlikely to be
      available days later if they weren't available before
    → If you skip the retry (or the retry also fails), fall back to
      Pay by Bank (Step 6)
    → Notify customer accordingly (Step 4)

IF failureReason is terminal (ACCOUNT_CLOSED, INSTRUCTION_CANCELLED,
                              NO_VALID_INSTRUCTION):
    → Mandate is no longer usable for DD
    → ONLY option for immediate recovery: Pay by Bank (Step 6)
    → Notify customer (Step 4) — include request for updated details
    → Begin new mandate setup process for future collections

IF failureReason is REFER_TO_PAYER:
    → Contact the customer first — do not retry or send PIS until you understand the issue

IF failureReason is PAYER_DECEASED:
    → Follow internal process. Do not attempt recovery.

Important — choose DD retry OR Pay by Bank, not both at the same time. Once a represented collection has entered the Bacs cycle, cancellation may not be possible. Avoid sending a Pay by Bank link and representing the same collection at the same time, because this can lead to double collection.

The recommended approach: For recoverable failures, you may optionally attempt a DD retry first — though bear in mind that if the customer didn't have the funds on the original collection date, they may not have them a few days later either. If you skip the DD retry, or the retry also fails, fall back to Pay by Bank. Pay by Bank via Open Banking gives the customer the option to pay from any bank account they hold, which is a key advantage — the funds may well be available in a different account.


Step 3: Decide — Retry or Switch

Can I retry the DD?

  • Is the failure reason recoverable? (INSUFFICIENT_FUNDS or confirmed REFER_TO_PAYER)
  • Is the mandate still ACTIVE? (Check via GET /mandates/{mandateId} — see Get Mandate)
  • Have I exceeded my retry limit? (Your business rule — typically 1–3 retries)
  • Is there a reasonable expectation the funds will be available? (e.g. the customer's payday falls between the original failure and the retry date)

Should I switch to Pay by Bank?

  • If DD retry is not possible (terminal failure, mandate dead, retry limit exceeded) — PIS is your recovery option
  • If you chose to skip DD retry — PIS is the natural next step
  • If DD retry also failed — PIS is the fallback
  • PIS doesn't require an active DD mandate — essential when the mandate has been cancelled or the account has closed
  • PIS lets the customer pay from a different bank account — useful when funds weren't available in the original DD account

Does the mandate need to be re-established?

  • ACCOUNT_CLOSED: Yes — you need new bank details from the customer and a new mandate
  • INSTRUCTION_CANCELLED: Yes — the customer cancelled the DD at their bank. You need to set up a new mandate if they agree to reinstate it (see Create Mandate)
  • NO_VALID_INSTRUCTION: Possibly — check the mandate status and contact Modulr support
  • INSUFFICIENT_FUNDS: No — mandate is still active, can be reused

The recommended sequence:

  1. Detect failure
  2. Assess reason code and mandate status
  3. For recoverable failures: Optionally retry DD (Step 5) — particularly if there's reason to believe funds will be available (e.g. upcoming payday). Notify the customer that you'll retry (Step 4).
  4. If you skip the DD retry, or the retry also fails → send a Pay by Bank link (Step 6). Notify the customer with the link (Step 4).
  5. If PIS succeeds → confirm and resume (Step 8)
  6. For terminal failures: Go straight to Pay by Bank (Step 6) and begin new mandate setup for future collections

Step 4: Notify Your Customer (Dunning)

What you're doing: Telling your customer their payment failed and giving them a way to pay. A well-timed message with a Pay by Bank link can recover the payment the same day.

Modulr does not send dunning messages — you send them from your own system using services like SendGrid, Twilio, WhatsApp Business API, or your in-app messaging.

What to include: What failed (amount, date, DD reference), what happens next, a Pay by Bank link for instant payment (if applicable at this stage), and your contact details.

Tailor the message to the failure reason and your chosen recovery path:

Failure reasonRecommended messaging
INSUFFICIENT_FUNDS (with DD retry)"Your payment was unsuccessful. We'll retry by Direct Debit in a few days. If you'd prefer to pay now, use the link below to pay instantly from any bank account."
INSUFFICIENT_FUNDS (skipping DD retry)"Your payment was unsuccessful. Pay now instantly via the link below — you can pay from any bank account you hold."
ACCOUNT_CLOSED"We couldn't reach your bank account. Please pay now using the link below and contact us to update your payment details."
INSTRUCTION_CANCELLED"Your Direct Debit has been cancelled. Please pay now using the link below — we'll be in touch about setting up a new instruction for future payments."

Example email (insufficient funds — DD retry path):

Dear Jane,

Your monthly repayment of £250.00 due on 1 May 2026 was unsuccessful. This can happen when there aren't enough funds available at the time we collect.

We'll retry your Direct Debit in a few days. If you'd prefer to pay now, you can pay instantly from any bank account using this link:

Pay now: [Pay by Bank link] — takes 30 seconds via your banking app.

Direct Debit reference: LOAN-2026-00142

Questions? Contact us at [email protected].

UI considerations for your dunning messages: Make the Pay by Bank link the most prominent element in the message — above the fold in emails, the primary CTA in push notifications. Recovery rate correlates directly with how easy it is for the customer to find and tap the link. Consider offering the link via multiple channels simultaneously (email + SMS + in-app) to maximise reach.

Timing: Immediately after failure detection. Speed matters — the sooner you notify, the higher the recovery rate.


Step 5: Retry via Direct Debit

This step is optional. It's most useful when you have reason to believe funds will be available in the original account shortly (e.g. the customer's payday is imminent). If you don't expect the funds to be there, skipping straight to Pay by Bank (Step 6) may be a better use of time.

Representment is not the same as creating a new one-off collection. If the failed collection is marked as representable, use the represent endpoint to resubmit that same collection. If you create a new one-off collection schedule instead, treat it as a new Direct Debit collection and ensure the required customer notice rules are followed.

Only do this if:

  • The failure reason is recoverable — the collection status is REPRESENTABLE (not all failures are eligible for retry)
  • The mandate is still ACTIVE
  • You haven't exceeded your retry limit
  • You have NOT already sent a Pay by Bank link that could result in double-collection

Scheme rules on retries: Under the Bacs Direct Debit scheme, re-presentation of an unpaid collection may only continue for one month from the date of the original collection attempt. Given the 3-day Bacs cycle, this means a practical maximum of 3 retries within that window. If payment has not been made within one month, you must make other arrangements directly with the payer — this is where Pay by Bank (Step 6) becomes essential. See Starting Collections for the full scheme representment rules.

What you're doing: Re-submitting a failed collection that has a REPRESENTABLE status. Use the dedicated represent endpoint — this resubmits the original collection through the Bacs cycle rather than creating a new one.

Important: Once submitted, a Direct Debit collection cannot be cancelled. Make sure the customer hasn't already paid via Pay by Bank before submitting the retry.

API call: POST /collection/{collectionId}/represent — see Represent Collection.

Collection status flow: ProcessingRepresentable (if eligible for retry) → Represented (after calling /collection/{collectionId}/represent) → Success or Failed (after the Bacs cycle completes).

Practical guidance:

  • Check the collection status is REPRESENTABLE before attempting — not all failures are eligible. The DD Collection Status webhook will tell you.
  • For representment, the original collection is resubmitted — do not assume you can change the reference. Track retry attempt count, recovery status, and any Pay by Bank fallback state in your own system.
  • Allow 3–5 working days from the original failure to give the customer time (e.g. next payday)
  • No additional advance notice is required for re-presentations, but the scheme recommends it — particularly if the failure reason was REFER_TO_PAYER
  • Track your retry count per collection — if you hit 3 retries or one month from the original attempt, stop and switch to Pay by Bank

Step 6: Fall Back to Pay by Bank (PIS)

What you're doing: Generating an instant payment link via Open Banking that the customer clicks to authorise a bank transfer from their banking app. This is the rail-switch — from pull (DD) to push (PIS).


Why Open Banking matters here: The customer isn't limited to the bank account the DD was set up on. When they click the Pay by Bank link, they choose which bank to pay from. This is a key advantage for recovery — if the failure was due to insufficient funds, the customer may have money available in a different account. They see their bank options and select the one that works.

Scheme compliance — Open Banking / PIS regulatory requirements:

Pay by Bank operates under the Open Banking framework, regulated by the FCA. Your customer-facing PIS screens must comply with the following requirements:

  • Explicit consent: The customer must give explicit, informed consent before any payment is initiated. The consent screen must clearly display the payee name, amount, payment reference, and the bank they are paying from.
  • Redirect transparency: Before redirecting the customer to their bank, you must clearly state that they are being securely redirected and that their banking credentials will not be shared with you or any third party.
  • TPP disclosure: As the payment is initiated via a regulated Third Party Provider (Modulr), your screens should include the required regulatory disclosures.
  • Terms and privacy: Links to Modulr's terms and conditions and the privacy policy must be accessible from the consent screen.

TPP Disclosure

By continuing you are permitting our partner Modulr FS Limited to initiate a payment from your bank account and also agree to their terms and conditions and privacy policy.

Important: All customer-facing Pay by Bank screens and communications — including bank selection pages, consent screens, redirect pages, and confirmation screens — must be reviewed and approved by Modulr before you go live. Submit your designs early in the implementation process to avoid delays.

For full PIS setup and endpoint documentation, see Getting Started with PIS and Supported Banks.

1. Get the list of supported banks:

GET /aspsps

See the ASPSP API reference. You'll typically cache this list and present it in your payment UI.

Your customer-facing UI — bank selection

The example above shows a bank selection screen. The customer chooses which bank to pay from — they aren't limited to the DD account.

Your bank selection UI should:

  • Present the full list of supported banks retrieved from GET /aspsps, displayed with bank logos for easy recognition
  • Inform the customer they'll be securely redirected to their bank to complete the payment
  • Include a "bank not shown?" option — consider offering your bank details for a manual transfer if the customer's bank isn't on the list
  • Use Modulr's API to retrieve the bank list dynamically rather than hardcoding — the supported bank list is updated as new banks are onboarded

2. Initiate the Pay by Bank payment:

POST /pis/payments

See the PIS API reference.

Sample request (recovering a failed loan repayment):

{
  "aspspId": "ob-lloyds",
  "amount": 250.00,
  "currency": "GBP",
  "payee": {
    "name": "Your Business Ltd",
    "accountNumber": "12345678",
    "sortCode": "040004"
  },
  "reference": "LOAN-RPY-0142-PIS",
  "redirectUrl": "https://yourbusiness.com/payment-complete"
}

Consent and redirect screens

The consent screen example above shows the payment details the customer reviews before being redirected — payee name, payment reference, amount, and the selected bank. The customer must explicitly consent before the redirect.

Your consent screen must clearly display:

  • Payee account name
  • Payment reference
  • Payment amount and currency
  • The name of the bank the customer selected
  • A redirect notice (e.g. "You'll be securely redirected to your bank to complete the payment")
  • The Modulr consent text and links to terms and conditions / privacy policy (as provided to you during PIS onboarding)

Redirect handling: When the customer is redirected to their bank, consider showing a brief loading or redirect screen with reassuring messaging (e.g. "We're securely taking you to your bank. Your security details won't be shared with us."). Research shows this improves completion rates by giving the customer a sense of control during the handoff.

Sample response:

{
  "id": "PIS-2026-05-001",
  "status": "CREATED",
  "authorisationUrl": "https://ob-lloyds.example.com/authorise?payment=PIS-2026-05-001",
  "amount": 250.00
}

The authorisationUrl is the pay-now link. Embed it in your dunning email/SMS from Step 4. The customer clicks it → selects their bank → authenticates → payment completes.

What to know:

  • Funds settle via Faster Payments — typically within seconds
  • PIS is irrevocable once completed — no rejection window like DD
  • The customer can choose any supported bank — they aren't locked to the DD account
  • Use a distinct reference suffix (e.g. -PIS) for reconciliation

Step 7: Monitor Recovery

What you're doing: Checking whether the recovery payment has succeeded.

For DD retry: GET /collections and the DD Collection Status webhook, same as your normal collection monitoring.

For Pay by Bank: GET /pis/payments/{paymentId} — see the PIS API reference. Subscribe to PIS status webhooks via the PIS documentation.

PIS statuses: CreatedAuthorisedCompleted / Failed / Rejected

Confirmation screen

The example above shows a payment confirmation screen with the transaction reference, payment reference, and payment status. Your system should verify the payment status via the Modulr API or webhook — do not rely on the redirect status alone, as it can be tampered with.

Your confirmation screen should display the transaction reference, payment reference, payment status, and the date and time. In rare cases, a bank may process the payment initiation successfully but subsequently block the outbound payment itself — always confirm via the API.

If DD retry succeeded: Move to Step 8. Do not also send a Pay by Bank link — the payment is recovered.

If DD retry failed (or you skipped it): Send the customer a Pay by Bank link (Step 6). The customer can pay from any bank account they hold.

If PIS succeeded: Move to Step 8. Do not submit a DD retry — you'll double-collect.

If PIS also failed or the customer didn't act: Contact the customer directly. If the mandate is no longer usable, you'll need to discuss alternative payment or setting up a new mandate.

Timing: DD retry = Days 1–5 of the Bacs cycle. PIS = same day (usually minutes).


Step 8: Confirm Recovery and Resume

What you're doing: The recovery payment succeeded. Close the loop.

  1. Update your ledger — mark the original failed collection as recovered
  2. Record which rail recovered the payment — this data helps optimise your recovery strategy over time
  3. Resume normal collections — if the mandate is still active, the existing collection schedule continues automatically for future payments
  4. If the mandate was cancelled or the account closed — you'll need to set up a new mandate with the customer's updated details before DD collections can resume. In the meantime, consider using PIS or VRP for the next payment(s).

Other recovery options

The DD retry → Pay by Bank flow is the primary recovery pattern covered in this guide. Depending on your use case, other options are available:

VRP (Variable Recurring Payments): If the customer has an active VRP consent, you can initiate a recovery payment instantly without needing the customer to click a link each time. VRP can serve as both a primary collection method (replacing DD) and a recovery rail. Currently available for eligible use cases including unsecured lending, with commercial VRP expanding coverage soon. See Getting Started with VRP.

Push payment to your collection account: The customer can send a manual bank transfer to your Modulr account. This is the simplest option but relies on the customer getting the details right. You can also create dedicated named accounts per customer via POST /customers/{customerId}/accounts to simplify reconciliation — more detail on this in a future one-off payments guide.

Adjusting the collection schedule: If a customer is repeatedly failing to meet the full amount, reducing the collection amount or adjusting the frequency may be an option worth considering alongside your recovery flow.

Recovery reporting: Tracking recovery rates by failure reason code and recovery rail will help you refine your dunning timing, messaging, and approach over time.


API reference — endpoints used in this guide

StepActionEndpointMethodAPI Reference
1Check for failed collections/collectionsGETDD Collection Status webhook
1Webhook: collection failedDD Collection Webhook
2Check mandate status/mandates/{id}GETGet Mandate
5Represent unpaid collection/collection/{collectionId}/representPOSTRepresent Collections
6aGet supported banks/aspspsGETSupported ASPSPs
6bInitiate Pay by Bank/pis/paymentsPOSTPIS API Reference
7Check PIS payment status/pis/payments/{id}GETGet PIS Details

Bacs timing — recovery context

DayWhat happensRecovery relevance
Day 3Payer's bank rejects the collectionFailure detected — notify customer, optionally retry DD or send PIS link
Day 5–6ARUDD rejection window closesLate failures surface — funds already credited may be reversed

If you detect a failure on Day 3 and the mandate is still active, you can choose to retry DD (adding another 3-day cycle) or send a Pay by Bank link for immediate recovery. If using PIS, the customer can pay within minutes from any bank account they hold.


Previous: Set Up Recurring CollectionsIndex: Collecting Payments with Modulr