Five years of PSD2 connectors: what the spec doesn't tell you

A bank tile connected to the Trex Pi mark by dashed data lines

PSD2 promised one API for every bank in Europe. What we got is one spec family and a few hundred interpretations of it. After five years of building and running account-information and payment-initiation connectors for clients across the Baltics, the pattern is clear: the first bank takes a week, the fifth takes a day, and then the next one unexpectedly takes a month.

The consent flow is where projects stall

The API calls are the easy part. The hard part is the consent lifecycle - how a customer authorizes your access, how long that authorization lives, and what happens when it expires at 03:00 on a Sunday.

  • Some banks issue 90-day consents and renew silently; others force full re-authentication.
  • Sandbox consent flows routinely differ from production ones. Budget for a second integration pass after go-live.
  • Error taxonomies are inconsistent: the same expired consent can surface as 401, 403, or - in one memorable case - a 200 with an empty transaction list.

That last one deserves emphasis: an empty response is not the same as a successful response. If your reconciliation depends on a transaction feed, treat "no transactions" as a condition to verify, not a fact to record.

What we standardize on

Every connector we ship now runs behind the same internal interface, with per-bank adapters kept deliberately thin. The same discipline applies on the payment-initiation side - one canonical payment object, mapped explicitly to each bank's dialect:

Mapping ERP payment fields to SEPA pain.001 XML elements

The adapter handles authentication quirks and pagination dialects; everything else - retries, idempotency, alerting, consent-expiry warnings - lives in the shared layer, written once and tested once.

If a bank integration needs custom retry logic, that logic belongs in the shared layer with a feature flag - never in the adapter. Adapters rot; shared layers get maintained.

The result is boring, and boring is the goal. A new bank is a new adapter, a fixture file recorded from its sandbox, and a checklist - not a new project.