FlowKit

Connecting GoCardless to n8n: automating SEPA direct debit and failed-payment tracking

Published 30 August 2026 · 7 min read

A SEPA direct debit fails, and the first visible alert sometimes only surfaces three weeks later, at the monthly accounting reconciliation — far too late to follow up with the customer before the subscription turns into a chronic unpaid balance. Unlike a card payment, a failed SEPA direct debit is rarely fixed by simply resubmitting the transaction: you first need to know whether it's a one-off insufficient-funds issue (the next collection attempt has a real chance of succeeding) or a cancelled mandate (no further attempt will ever go through). The GoCardless API exposes this distinction through real-time webhooks — enough to build an n8n pipeline that reacts to the actual nature of the incident, instead of firing off a generic follow-up blind.

Why automate instead of checking the dashboard

The GoCardless dashboard does list every payment and its status, but you have to open it to find out — nothing surfaces on its own to the team handling customer relations or accounting. A subscription whose direct debit silently fails often keeps delivering the service for weeks, until someone notices the gap. That's exactly the kind of delay an event-driven workflow fixes, instead of a manual dashboard check — the same principle covered in our guide on Stripe payment follow-ups via webhook, except that SEPA failure mechanics (insufficient funds, cancelled mandate, bank rejection) differ enough from a card decline to deserve their own pipeline.

Generating an access token

No partner process is required for internal use. From the GoCardless dashboard: Account settings → Developers → Create access token. A sandbox environment (api-sandbox.gocardless.com) exists alongside live (api.gocardless.com): always start in sandbox to test the pipeline with fake collections before wiring up the real account — GoCardless provides test scenarios that deliberately trigger each type of failure.

Authenticating n8n against the API

There's no native GoCardless node in n8n for the payments API — careful not to confuse it with the n8n-nodes-gocardless-bad package findable under Community Nodes, which actually targets the "GoCardless Bank Account Data" API (formerly Nordigen, a separate open banking service acquired by GoCardless, but with its own API and its own account-aggregation use case). To manage collections, mandates, and refunds, the HTTP Request node consumes the REST API directly:

  • Create a Generic Credential Type → Header Auth credential in n8n with the Authorization header set to Bearer <your_token>.
  • Every request must also carry a GoCardless-Version header naming a released API version (for example 2015-07-06, the reference version documented by GoCardless) — omitting it returns an error, unlike most REST APIs where versioning is optional.

Listening for events in real time instead of polling

GoCardless delivers events via webhooks: a single POST request can bundle up to 250 events, each carrying a resource_type (payments, mandates, subscriptions…), an action (failed, cancelled, confirmed…), and details on the cause. Three events cover most of a failed-payment tracking pipeline:

  • payments.failed — a single collection failed (most often insufficient funds). GoCardless typically retries on its own schedule; the mandate itself stays valid.
  • payments.charged_back — the customer disputed the collection with their bank after letting it go through, a more serious signal than a plain failure since it involves an active claim.
  • mandates.cancelled or mandates.failed — the collection authorization itself no longer exists (cancelled by the customer, closed account, invalid IBAN). No further collection attempt will succeed until a new mandate has been signed — retrying against the old mandate wastes time.

An n8n Webhook node receives these raw POSTs; as with any publicly exposed webhook, see our n8n webhook security guide for HTTPS exposure and general best practices before going further.

Verifying the signature before processing anything

Every GoCardless webhook request carries a Webhook-Signature header, computed as HMAC-SHA256 over the raw request body using your endpoint's secret (generated when the webhook is configured in the dashboard). A Code node recomputes this HMAC on the n8n side and compares it against the received header — no base64 involved, the secret is used verbatim as the HMAC key. If the comparison fails, the workflow must stop before reading the payload's contents: that's the only guarantee the event genuinely came from GoCardless rather than a third party that guessed the endpoint URL. A single request can carry several events in the same events array, which is why a Split Out node right after verification, splitting each event out for individual handling, is worth adding.

Routing by the nature of the incident

Once the signature is verified and events are split out, a Switch node routes based on resource_type and action:

  1. payments.failed → check how many attempts have already been made on this collection (retry_if_possible in the GoCardless response indicates whether an automatic retry is scheduled); if so, notify without urgency; if not (GoCardless's own retry window is exhausted), trigger a customer follow-up with a link to update bank details.
  2. payments.charged_back → priority alert to accounting, since this case usually needs a documented manual response rather than an automatic follow-up.
  3. mandates.cancelled or mandates.failed → suspend access to the relevant service (if the subscription warrants it) and send a mandate re-signing link rather than a standard payment reminder — the two messages differ in both content and urgency.

This pattern of routing by incident type before choosing an action mirrors the one already covered for error handling with n8n's Error Workflow: a dedicated branch per failure type beats a generic catch-all that treats everything the same way.

Logging every event

A dedicated Supabase table — GoCardless payment or mandate ID, event type, date, action taken — answers "why was this customer followed up with?" in seconds, without reopening the GoCardless dashboard. Our n8n ↔ Supabase connection guide covers setting up this kind of table, on the same principle as the GDPR audit trail already described for other sensitive flows: one row per event, timestamped server-side, never rewritten afterward. Since GoCardless retries webhook delivery if your endpoint doesn't respond quickly, add a uniqueness constraint on the event ID to avoid processing it twice — the same webhook idempotence mechanism already needed for Stripe applies here identically.

What research says about automated anomaly detection in banking data

Beyond simple routing by event type, a failed-payment pipeline running for several months builds up a history that can reveal patterns finer than a single isolated failure — a mandate that fails and then suspiciously reactivates, a cluster of rejections in a short window. A 2025 study by Preciado Martínez, Reier Forradellas, Garay Gallastegui, and Náñez Alonso, published in Cogent Business & Management ("Comparative analysis of machine learning models for the detection of fraudulent banking transactions," see on Google Scholar), compared several models on 565,000 real bank transfers: a Random Forest model reached 95.79% accuracy detecting fraudulent transactions, against near-perfect accuracy on legitimate ones. The same logic — a model trained on logged history rather than an arbitrary fixed threshold — applies to a mature GoCardless pipeline: once a few hundred events have accumulated in Supabase, an AI node fed on that history can propose a per-customer risk score instead of a simple failure count.

Common pitfalls

  • Treating every failure as insufficient funds. A cancelled mandate (mandates.cancelled) is never fixed by another collection attempt — only a new authorization signed by the customer resolves it.
  • Forgetting the GoCardless-Version header. An HTTP Request without it fails immediately, unlike most REST APIs where versioning is implicit.
  • Confusing the two GoCardless APIs. The community node available on npm targets open banking (account aggregation), not SEPA direct debits — check which API a third-party package actually covers before installing it.
  • Only testing against live. The GoCardless sandbox simulates every failure type (insufficient funds, refused mandate, closed account) risk-free, on the same principle as testing n8n webhooks locally.

Summary

A SEPA failed payment that surfaces three weeks too late costs more than a follow-up sent within the hour — and a follow-up sent at the wrong moment, against an already-cancelled mandate, is worse than useless. By wiring n8n into GoCardless webhooks instead of a manual dashboard check, every incident triggers the response that actually matches its nature the moment it happens. If your priority is tracing this kind of financial flow with a demonstrable audit trail, the Compliance & Audit Pack (€149) already ships the Supabase schema and reusable follow-up workflows for the logging piece. The AI Inbox Pack (€79) rounds things out on the incoming-email side of payment disputes, and the Complete FlowKit Bundle (€269 instead of €347 bought separately) brings all three packs together to cover the full financial workflow.

FAQ

Frequently asked questions

Is there a native n8n node for GoCardless?

No, not for the GoCardless payments API. The only package findable on npm under that name actually targets the "GoCardless Bank Account Data" API (formerly Nordigen, a separate open banking service acquired by GoCardless but with its own distinct API). To manage SEPA direct debits, mandates, and refunds, you need the n8n HTTP Request node against GoCardless's public, documented REST API.

Do I need a paid GoCardless account to use the API?

No: a standard account is enough, with an access token generated from the dashboard (Account settings → Developers → Create access token). A separate sandbox environment (api-sandbox.gocardless.com) lets you test webhooks and API calls without touching real direct debits before going live.

How do I tell a one-off failed payment apart from a mandate that's permanently lost?

These are two different webhook events: `payments.failed` signals a single failed collection (usually insufficient funds), typically followed by an automatic retry on GoCardless's own schedule; `mandates.cancelled` or `mandates.failed` signals that the collection authorization itself no longer exists (cancelled by the customer or the bank), making any further collection attempt pointless until a new mandate has been signed.

Bundle FlowKit Complet

€269