DEV Community

EkLine.io
EkLine.io

Posted on • Originally published at ekline.io

An Open Banking API Is a Contract. Your Docs Are the Contract Surface.

Strip the acronyms off open banking and what you have is a small, boring promise.

A bank says to a third-party app: if you bring me a customer who agreed to share their data, I will hand you that data in a predictable shape, through a predictable door, using a predictable key, and I will tell you in a predictable way when something goes wrong.

Four predictable things. That is the whole deal.

When all four hold, an app can read a customer's transactions and tell them they spend too much on coffee. When even one of them slips, calls still return 200, dashboards stay green, and the data flowing through is quietly wrong. The contract has broken silently, and the only place it can break is in the documentation that was supposed to describe the contract.

This post is about the four predictabilities, where they leak, and why your docs are the only place to catch the leak before a regulator does.

The Contract, in Four Parts

Part 1: a predictable SHAPE for the data
Part 2: a predictable PERMISSION flow
Part 3: a predictable AUTHORIZATION credential
Part 4: a predictable ERROR vocabulary
Enter fullscreen mode Exit fullscreen mode

That is the entire open banking contract from a developer's point of view.

The UK Open Banking Standard and the PSD2 RTS in the EU both encode the same four parts in different words. Your bank's docs are how you, the developer building on top of the bank, learn what shape, what flow, what credential, and what error codes the bank chose inside the room the regulation gave it.

When the docs and the running API agree, the contract holds. When they disagree, here is what breaks.

Drift 1: The Shape Drifts

Documented response has 12 fields. Production now returns 14.

// Documented
{
  "transaction_id": "...",
  "amount": "...",
  "currency": "...",
  "booked_at": "...",
  "description": "...",
  "counterparty": { ... }
  // ... 6 more documented fields
}

// Production today
{
  "transaction_id": "...",
  "amount": "...",
  "currency": "...",
  "booked_at": "...",
  "description": "...",
  "counterparty": { ... },
  "merchant_category_code": "5814",   // NEW, undocumented
  "scheme_id": "FPS-2026-..."         // NEW, undocumented
  // ... 6 more documented fields
}
Enter fullscreen mode Exit fullscreen mode

The app reading this ignores the two unknown fields. It still works. But the budgeting category it shows the customer is now derived from a heuristic the app wrote two years ago, when the actual merchant category code is sitting unused in the response. The app cannot use what the docs do not say is there.

Drift 2: The Permission Drifts

Docs list 5 consent scopes. Production added a 6th, required for the standing-orders endpoint.

The app requests the documented 5. The bank's authorization server returns a token. The token works for the four endpoints the app uses. The standing-orders endpoint returns a 200 with an empty array.

The app interprets "empty" as "this customer has no standing orders." The customer has six. They call support to ask why their rent payment is missing.

Empty data and missing-permission data look identical to a client unless the docs say otherwise. The docs were the only place the new scope could have been announced.

Drift 3: The Credential Drifts

Docs describe OAuth 2 with bearer tokens. Production migrated higher-value endpoints to mutual TLS.

GET /accounts/{id}/balance       → bearer token works
POST /payments                   → mTLS required, bearer token = TLS handshake error
Enter fullscreen mode Exit fullscreen mode

The app, holding only a bearer token, can read balances fine. The first time the customer initiates a payment, it fails with a TLS error the app never expected. The on-call engineer spends two hours hunting a network problem that does not exist. The actual problem is that the docs described one credential and production now requires two.

Drift 4: The Errors Drift

Docs say 429 Too Many Requests means "you are sending requests too fast."

Production has started returning 429 for a second case: "the customer revoked consent in the last 60 seconds and our consent cache is still warm."

# What the docs imply
if response.status == 429:
    sleep(retry_after)
    retry()
Enter fullscreen mode Exit fullscreen mode

Three retries later, the bank's actual rate limiter trips and bans the app's IP for an hour. One customer revoked consent. Now the app cannot serve any of its customers using that bank, because 429 grew a second meaning the docs never described.

Why the Docs Are the Only Place to Catch This

A test environment catches a broken endpoint. Monitoring catches an outage. A regulator catches a serious incident, eventually.

None of them catch silent contract drift. Silent drift looks identical to a healthy system from every observation point except one: a developer reading the docs and finding they describe a different system than the one answering when called.

The Postman 2025 State of the API Report found 55% of teams cite documentation gaps as their top collaboration challenge. In open banking, "collaboration" includes the regulator. The FCA and EBA both require documented behavior to match production behavior, because a third-party app cannot comply with rules it cannot read.

Three Rules That Follow

If the docs are the contract surface, then changes to the API are changes to the contract, and:

  1. The schema in the docs is the schema in production. Generated reference docs are not a nice-to-have in this niche. Hand-edited reference is a contract risk.
  2. Every consent scope and every error code is documented before it is enforced. If a scope becomes required Tuesday, the docs say so Monday.
  3. Deprecations ship with a date and an alternative. Silent deprecations are silent contract breaks.

That is the whole post in three lines.

The One-Sentence Version

An open banking API is a four-part contract, the docs are the contract, and when the two disagree the only people who notice are the customers calling support to ask why their money looks wrong.


EkLine checks every doc change against the live spec, the consent model, and the published error catalog so the contract surface stays honest.

Top comments (0)