The UK left the EU's PSD2 regime when it exited the Single Market. Since then, the two frameworks have diverged — not dramatically, but enough to catch fintech teams who assume a single integration approach works across both. This article documents the concrete API-level differences that matter when you are building for both markets, or evaluating whether a UK Open Banking integration ports cleanly to the EU.
Two standards bodies, two specifications
The UK operates under the Open Banking Implementation Entity (OBIE) standard — now maintained by the Open Banking Limited (OBL) following OBIE's restructuring in 2023. The technical specification is the UK Open Banking Read/Write API Specification, currently at v3.1.x.
The EU operates under Berlin Group's NextGenPSD2 XS2A (Access to Account) specification, currently at v1.3.8. Member states implement NextGenPSD2 — but the degree of compliance varies. France, Germany, and the Netherlands have generally high ASPSP compliance. Some Southern European markets have ASPSPs whose implementations are nominally NextGenPSD2-compliant but diverge on extension fields and error handling.
There is no official shared test harness between OBIE and Berlin Group. You maintain separate sandbox environments for each regime.
Consent model: intent objects vs resource creation
This is the most architecturally significant difference.
Under UK OBIE, consent initiation uses a two-step pattern. You first create a consent resource (an "intent object") by making a POST request to the ASPSP's consent endpoint. The ASPSP returns an intent ID. You then redirect the PSU to the authorisation endpoint, passing the intent ID as the request JWT parameter. This approach means the consent terms are committed to the ASPSP's system before the user sees the bank's UI.
POST /open-banking/v3.1/aisp/account-access-consents HTTP/1.1
Authorization: Bearer <client_credentials_token>
Content-Type: application/json
{
"Data": {
"Permissions": ["ReadAccountsDetail","ReadTransactionsDetail"],
"ExpirationDateTime": "2026-04-15T00:00:00+00:00",
"TransactionFromDateTime": "2026-01-01T00:00:00+00:00"
},
"Risk": {}
}
Under Berlin Group NextGenPSD2, the pattern is different. You initiate consent in a single step, passing permissions and PSU details in the body of the consent creation call. The ASPSP returns a consentId and an _links object containing the SCA authorisation redirect URL. There is no separate intent object step.
POST /v1/consents HTTP/1.1
PSU-IP-Address: 192.168.1.1
TPP-Redirect-URI: https://app.example.com/callback
Content-Type: application/json
{
"access": {
"accounts": [{"iban": "DE12345678901234567890"}],
"balances": [{"iban": "DE12345678901234567890"}],
"transactions": [{"iban": "DE12345678901234567890"}]
},
"recurringIndicator": true,
"validUntil": "2026-04-15",
"frequencyPerDay": 4
}
The practical implication: your consent flow state machine looks different for each regime. UK OBIE requires you to store and present the intent ID. Berlin Group requires you to handle the _links.scaRedirect URL that arrives in the consent creation response.
Transaction data schema differences
Both specifications define transaction objects, but the field names, nesting, and optionality differ.
Amount representation
UK OBIE: "Amount": {"Amount": "42.50", "Currency": "GBP"} — amount as a string, always positive, with a separate CreditDebitIndicator field ("Credit" or "Debit").
Berlin Group: "transactionAmount": {"amount": "-42.50", "currency": "EUR"} — amount as a string, signed (negative for debits). Some ASPSPs return unsigned amounts with a separate creditDebitIndicator; both representations are technically compliant with the spec.
If you are building a normalisation layer, you must handle both signed-amount and unsigned-with-indicator patterns from EU banks, and convert OBIE's always-positive amount + indicator into a consistent signed value.
Transaction identifiers
OBIE mandates a TransactionId field for completed transactions. Berlin Group has transactionId as optional — ASPSPs may omit it. Some German banks return a entryReference instead. For deduplication logic in your transaction store, you cannot rely on a consistent primary identifier field across EU banks; you need a composite key strategy (amount + valueDate + creditorName or similar).
Merchant information
OBIE includes MerchantDetails as an optional object with MerchantName and MerchantCategoryCode. Berlin Group's spec includes creditorName and remittanceInformationUnstructured — but merchant category codes are not standardised. Card transaction enrichment (merchant name normalisation, category classification) requires a separate enrichment layer on top of raw bank data in both regimes.
Account and IBAN handling
UK accounts use sort code and account number, expressed as either a SortCodeAccountNumber scheme or as an IBAN (where applicable — not all UK accounts have IBANs). The UK OBIE schema uses SchemeName + Identification to represent account identifiers:
{
"SchemeName": "UK.OBIE.SortCodeAccountNumber",
"Identification": "20000212345678",
"Name": "Example Account"
}
Berlin Group uses IBAN as the primary account identifier. This is straightforward for most EU markets but creates a mismatch when processing payments: a UK Faster Payments instruction needs a sort code and account number, while a SEPA Credit Transfer or SEPA Instant Credit Transfer needs an IBAN and BIC. Your payment initiation layer must resolve the correct scheme for each target bank.
Error handling and HTTP status codes
UK OBIE defines a structured error response format under OBErrorResponse1:
{
"Code": "400 BadRequest",
"Errors": [
{
"ErrorCode": "UK.OBIE.Field.Missing",
"Message": "The field ExpirationDateTime is required.",
"Path": "Data.ExpirationDateTime"
}
]
}
Berlin Group uses a different structure with tppMessages:
{
"tppMessages": [
{
"category": "ERROR",
"code": "FORMAT_ERROR",
"text": "Value of validUntil is not a valid date."
}
]
}
Neither format is reliably consistent across all ASPSPs. UK banks often add non-standard fields; some EU banks return plain-text error bodies for certain failure conditions. Defensive parsing — treating the error body as potentially malformed — is the only reliable approach.
Regulatory divergence: what to watch
The EU is working on PSD3 and the Payment Services Regulation (PSR), which will replace PSD2 directives with a directly applicable regulation — removing some of the member-state implementation variation. PSD3 is expected to require more standardised ASPSP APIs, dedicated open banking interfaces, and clearer TPP rights on fallback mechanisms.
The UK's PSR (Payment Systems Regulator) and FCA are pursuing their own open banking roadmap under the Joint Regulatory Oversight Committee (JROC) framework, targeting an "open banking entity" that takes over from OBL with a broader mandate including variable recurring payments (VRPs) beyond sweeping.
The two regimes will not converge on a single technical standard in the near term. Building for both markets means maintaining two integration paths — or using an aggregator that normalises the difference behind a single API contract.
What a normalised API covers
When building directly against ASPSPs, the difference between OBIE and Berlin Group is the API surface visible to your application. Through an aggregation layer, the intent-object creation, _links navigation, signed amount vs indicator, and tppMessages error format are all resolved before the response reaches your code. What you receive is a consistent account object, a consistent transaction object, and a consistent error schema — regardless of whether the upstream bank is a UK ASPSP or a Berlin Group implementation in Germany or the Netherlands.
This does not mean the abstraction is lossless. Some ASPSP-specific features — notably trusted beneficiary management and bank-specific transaction metadata — may be unavailable through a normalisation layer that targets the lowest common denominator. Evaluate what your product actually needs from the raw bank data before deciding how much of the ASPSP-specific surface to abstract away.