Protocol translation is the easy part and it is what most integration guides stop at. The problems that actually decide whether an integration holds up are about uncertainty: what an idempotency key is for, why a timeout tells you nothing about whether the money moved, and which reconciliations you cannot skip. Build a translation layer so the core's quirks never reach your domain model, then spend your design effort on the failure cases rather than the happy path.
Search for a guide to this and you will find vendor documentation for one specific platform, or an overview that stops at "expose REST APIs". Neither helps much on day one of a real programme, because the first discovery is almost always the same: the integration surface is not one thing, and nobody internally has a complete picture of it.
What you are actually integrating with
A core banking system that has been running for fifteen years has accumulated layers. In practice the surface is usually a mixture:
- Published REST APIs for whatever was modernised most recently — often balances and customer data.
- Older SOAP services underneath, sometimes the only route to an operation the REST layer does not cover.
- An enterprise service bus in the middle, configured by people who have since left, applying transformations nobody has fully documented.
- Overnight batch for some operations, which quietly sets the latency floor for anything that depends on them.
- Occasionally a screen, where a capability exists only in a terminal interface and the "API" someone mentioned is a scraper.
Planning as though this is a modern API estate is the single most common source of slippage. The first deliverable of any serious programme is an honest map: for each operation you need, what exposes it, through which protocol, at what latency, and whether it is real-time or batch.
The translation layer is the architecture
The one decision that pays for itself fastest is putting a translation boundary between your application and the core — an anti-corruption layer, in the usual phrasing.
It terminates the modern protocols your application speaks — HTTPS, OAuth 2.0, mTLS — and converts payloads into whatever the core actually understands. More importantly, it stops the core's naming, field quirks and limitations from leaking into your domain model.
That last point is what makes it worth the cost. When the core is upgraded, replaced, or when a second core arrives through an acquisition, the change lands in one layer instead of in every consumer. Teams that let the app call the core directly save time in month two and pay it back with interest in year two.
The problem that defines this work
Here is the scenario every banking integration has to answer, and the one that separates a working system from a demo.
Your application sends a transfer request. The connection times out. Did the money move?
Idempotency, concretely
The pattern is short to describe and easy to get subtly wrong:
- Generate the key and persist it before the outbound call. Not after, not in memory. If your process dies between generating and sending, you still need to know the key existed.
- Send the same key on every retry of the same logical operation.
- The core returns the original result for a repeated key rather than executing a second transfer.
- Reconcile later where the response was ambiguous.
If the core does not support idempotency keys — and plenty do not — you need the equivalent on your side: a durable record of in-flight operations keyed by your own reference, plus a status query you can call to resolve them. The work does not disappear because the core lacks the feature; it just moves to you.
On timeouts, one practical refinement: use tiered windows rather than a single global value. An authorisation that should answer in under a second does not deserve the same timeout as a settlement operation that legitimately takes longer. A single generous timeout makes fast failures slow; a single aggressive one makes slow successes look like failures.
Reconciliation: three comparisons
The principle underneath all of this is worth stating plainly: an API success response confirms only what that API contract defines. It is not proof that money settled, and it is not proof that two systems agree.
So three reconciliations, run on a schedule, not on demand:
- Application requests against core records. Every transfer your app believes it made should exist in the core, exactly once.
- Gateway status against your ledger. Where a payment gateway sits in the path, its view and yours must agree.
- Incoming batch files against internal records. The overnight file is authoritative about things your real-time calls may have missed.
Build the reconciliation job in the first phase, not after the first incident. It is the thing that tells you your integration is wrong before a customer does.
Where ISO 20022 fits, and where it does not
ISO 20022 matters where the rails require it — payments and interbank messaging — rather than for internal account operations. Where it applies, it is normally spoken by the translation layer rather than by your application.
One caveat worth knowing before you design around it: ISO 20022 assumes a correspondent-banking model, with intermediary institutions and multi-day settlement cycles. That fits traditional payment flows well and instant or peer-to-peer rails considerably less well. Check that the standard matches the rail before you commit to it as the internal format.
What to prove first
Before any feature work, prove the hardest call path end to end in a real sandbox. Not the balance enquiry — the money movement, including its failure cases.
- Get a genuine integration environment. This routinely takes longer than anyone plans for, and it gates everything else.
- Execute one real transfer through the full path.
- Deliberately time it out and resolve the ambiguity with a status query.
- Retry with the same idempotency key and confirm nothing moves twice.
- Run the reconciliation and confirm all three views agree.
A programme that can do those five things has removed most of its real risk. A programme that has built forty screens and not done them has removed none of it.
Questions we get asked
What does core banking integration actually involve?
Rarely a single clean API. A typical bank exposes some published REST, older SOAP underneath, an ESB in the middle, certain operations only as overnight batch, and occasionally a capability that exists solely as a screen. Integration means presenting all of that to your application as one coherent, versioned interface.
What is an anti-corruption layer?
A translation boundary between your application and the core. It terminates HTTPS, OAuth 2.0 and mTLS, converts payloads to what the core understands, and stops the core's quirks leaking into your domain model — so a future core upgrade is a change in one layer, not a rewrite.
Why does a payment need an idempotency key?
Because networks fail after a request is sent but before a response arrives, and a blind retry can move money twice. Generate and persist the key before the call, send the same key on every retry, and have the core return the original result rather than executing a second transfer.
What should happen when a call times out?
Treat it as unknown, not failed. A timeout says the response did not arrive; it says nothing about what the core did. Query the transaction status by key or reference, establish what actually happened, and only then retry, reverse or report.
What reconciliations do we need?
Three: application requests against core records, gateway status against your ledger, and incoming batch files against internal records. An API success confirms only what that contract defines — not that money settled or that two systems agree.
Do we need ISO 20022?
Only where the rails require it — payments and interbank messaging rather than internal account operations — and usually spoken by the translation layer rather than your app. Note it assumes correspondent banking with intermediaries and multi-day settlement, which suits instant rails poorly.
On Oracle estates this work usually runs through OBDX, where the adapter layer is the integration seam. If you are starting, the first week is best spent mapping what the core exposes rather than designing screens — that is where we begin every banking engagement.