← All proposals
OFP-016 DraftMedium

Paginate the ATM API

GET /atms returns an LFI’s entire ATM estate in one response, with no Links and no way to ask for a slice. This proposal brings ATMs into line with Bank Data Sharing and Products: from V2.2, every LFI MUST paginate its Ozone Connect GET /atm on page and page-size, and the API Hub returns the standard Links envelope and Meta.TotalPages to the TPP. The TPP’s first request does not change.

Proposed by
Nebras
Author
Thomas Catchpole
Target
V2.2
Opened
21 Oct 2026
Closes
4 Nov 2026
Decision

Cast your vote

Sign in with the Trust Framework to vote — For, Against, or Abstain — recorded in the open with your reasoning. Your organisation and name come from your directory profile, and each person may vote once. Three questions are attached to this vote — set out in section 06 below. The first asks LFIs how large their ATM estates are and whether they can paginate by V2.2; the second asks TPPs how they consume ATM data today; the third asks both whether TPP-controlled page sizes or filters are wanted later.

§ BallotOFP-016Closes 4 Nov 2026 ·
Where do you stand?
Pick a stance to add your name & a comment.
0%
in favour
0
votes cast
0
For
0
Against
0
Abstain
Voting not yet open
Voting opens 21 Oct 2026
The proposal
01 · Background

A list endpoint with no pages

The ATM API publishes an LFI’s ATM network to TPPs: each record carries the ATM’s location, opening hours, supported services, currencies, accessibility features and fees. The TPP calls GET /atms on the API Hub, and the Hub proxies the request to the LFI’s Ozone Connect GET /atm endpoint.

Neither side of that call can ask for less than everything. Ozone Connect GET /atm takes no query parameters, and the TPP-facing response (AEReadAtms1) has only Data and Meta, with Meta carrying LastUpdatedDateTime and TotalRecords. There is no Links object and no TotalPages. Every call returns every ATM:

Today — the whole estate on every call
# Today — one call, the whole estate, no way to ask for less
GET /open-finance/atm/v2.2/atms

  API Hub -> Ozone Connect   GET /atm          # no query parameters
  Ozone Connect -> API Hub   200 { "data": [ ...every ATM... ],
                                   "meta": { "LastUpdatedDateTime": "2026-10-20T00:00:00Z",
                                             "TotalRecords": 1240 } }

200
{
  "Data": [ { "ATMId": "ATM-0001", ... }, ... { "ATMId": "ATM-1240", ... } ],
  "Meta": { "LastUpdatedDateTime": "2026-10-20T00:00:00Z", "TotalRecords": 1240 }
}
# No Links. No TotalPages. Every record, in one payload, on every call.
Why this needs changing
  • The response has no upper bound. Its size is set by the LFI’s ATM estate, not by the standard. Each record is large (opening hours per day, service and currency arrays, a full postal address and geolocation), so a large network produces a large payload. That payload grows as the network grows, and every hop — Ozone Connect, the API Hub and the TPP — has to carry it in one go.
  • A failure costs the whole estate. A timeout or a 5xx part-way through cannot be resumed. The only retry is to request every ATM again.
  • It is out of step with the rest of the standard. Bank Data Sharing lists are paginated on page and page-size at Ozone Connect, and the Hub converts the LFI’s meta into a TPP-facing Links envelope (see Pagination — LFI meta to TPP Links). Products, the other public-data API, already requires Links and Meta.TotalPages on GET /products. ATMs are the exception.
  • V2.2 is the point to fix it. Adding Links to a response defined with additionalProperties: false changes its shape, so it belongs in a new version rather than an errata.
02 · Recommendation

Use the Data Sharing pagination model for ATMs

At Ozone Connect, pagination is page-based and mandatory. The API Hub sends page and page-size on every call to GET /atm. The LFI returns that slice of its estate, in a stable order, and adds TotalPages to the meta it already returns.

For the TPP, pagination is link-based. The Hub converts the LFI’s meta into the same Links envelope (Self, First, Prev, Next, Last) and Meta.TotalPages that Products and Account Information already return. The TPP’s first request is unchanged. To read the whole estate, the TPP follows Links.Next until it is absent.

Proposed — page 1 of 13, with a link to page 2
# Proposed — same first request, a bounded page, and a link to the next one
GET /open-finance/atm/v2.2/atms

  API Hub -> Ozone Connect   GET /atm?page=1&page-size=100
  Ozone Connect -> API Hub   200 { "data": [ ...ATMs 1-100... ],
                                   "meta": { "LastUpdatedDateTime": "2026-10-20T00:00:00Z",
                                             "TotalRecords": 1240, "TotalPages": 13 } }

200
{
  "Data": [ { "ATMId": "ATM-0001", ... }, ... { "ATMId": "ATM-0100", ... } ],
  "Links": {
    "Self":  "https://rs1.bank.apihub.openfinance.ae/open-finance/atm/v2.2/atms?page=1",
    "First": "https://rs1.bank.apihub.openfinance.ae/open-finance/atm/v2.2/atms?page=1",
    "Next":  "https://rs1.bank.apihub.openfinance.ae/open-finance/atm/v2.2/atms?page=2",
    "Last":  "https://rs1.bank.apihub.openfinance.ae/open-finance/atm/v2.2/atms?page=13"
  },
  "Meta": { "LastUpdatedDateTime": "2026-10-20T00:00:00Z", "TotalRecords": 1240, "TotalPages": 13 }
}
# The TPP follows Links.Next until it is absent.

This is the pattern LFIs already implement for Bank Data Sharing and the API Hub already operates. The only differences are that pagination is required here, not optional, and that ATMs are ordered by identifier rather than by date.

03 · Scope and behaviour

The rules

The rules follow the Bank Data Sharing pagination guide wherever they can. The ordering rule is new, because ATMs have no natural date to order by.

Proposed rules
  • The API Hub MUST send page and page-size on every request to Ozone Connect GET /atm. page is 1-indexed and defaults to 1; page-size defaults to 100, in line with the Operating Guidelines default used for Bank Data Sharing.
  • The LFI MUST paginate. It MUST return only the records for the requested page and page-size, and MUST NOT return the full estate in place of a page. There is no paginated: false option for ATMs.
  • The order MUST be stable. The LFI MUST order its ATMs by ATMId ascending, and SHOULD use LFIBrandId ascending as a tiebreaker. It MUST apply this order before cutting the page, so that the same ATM does not move between pages while a TPP is reading them.
  • meta MUST describe the full estate. TotalRecords is the number of ATMs across all pages. TotalPages is ceil(TotalRecords / page-size). LastUpdatedDateTime is the time the estate’s data was last updated, and is the same on every page.
  • Empty results return 200. An LFI with no ATMs returns an empty data array with TotalRecords and TotalPages of 0, as in Bank Data Sharing. It MUST NOT return 404.
  • The TPP-facing response MUST carry Links and Meta.TotalPages. Links.Self is always present; First, Prev, Next and Last are present when they apply. Meta.TotalRecords and Meta.LastUpdatedDateTime are kept.
  • The TPP request does not change. No TPP-facing query parameters are added to the request definition. The page value in the Hub’s links is set by the Hub, and the TPP MUST treat each link as opaque and follow it as given. The TPP cannot set page-size.
  • Out of scope: filtering and delta retrieval. This proposal adds no filters by location, service or LastUpdatedDateTime. Question 03 asks whether those are wanted in a later proposal.
04 · Technical changes

What changes

Two schema changes in the standard, two parameters in Ozone Connect, and a meta-to-Links conversion at the Hub that already exists for Data Sharing.

Who implements what
  • LFI — paginate GET /atm. Accept page and page-size, order the estate by ATMId, return the requested slice, and add TotalPages to meta.
  • API Hub — send the parameters and build the links. Send page and page-size to Ozone Connect, and convert the LFI’s meta into Links and Meta.TotalPages on the TPP response, as it does for Bank Data Sharing.
  • TPP — follow Links.Next. A TPP that needs the whole estate loops on Links.Next until it is absent. The first request is unchanged.
01 · Standards specification — uae-atm-openapi.yaml

Add a required Links property to AEReadAtms1, using the same Links schema as uae-product-openapi.yaml (Self required; First, Prev, Next, Last optional). Add a required TotalPages to AEReadAtmsMeta1, alongside the existing LastUpdatedDateTime and TotalRecords. Update the GET /atms description to state that results are paginated and the TPP follows Links.Next. The per-ATM Links.FeesUri object inside each Data item is unrelated and does not change. Targets V2.2.

02 · Ozone Connect — uae-ozone-connect-bank-open-data-openapi.yaml

Add required page and page-size query parameters to GET /atm, defined as in the Bank Data Sharing Ozone Connect spec (integer, defaults 1 and 100). Add a required TotalPages to the ATM meta (UAEATMAPI.AEReadAtmsMeta1), in the PascalCase that object already uses. Add the ordering and full-estate meta rules to the endpoint description.

03 · API Hub

Send page and page-size on every GET /atm call, and apply the meta-to-Links conversion used for Bank Data Sharing to the V2.2 ATM response. Calls to the V2.1 base path keep the V2.1 contract.

04 · Documentation

Write the LFI ATM requirements page, which is currently a placeholder, covering pagination and ordering. Update the LFI and TPP ATM API Guides with the request, the response and a worked page walk. Add ATMs to the Pagination knowledge-base article, and record the change in the version changelog.

05 · Functional certification

Add an ATM scenario that walks every page of the LFI’s estate. It asserts that TotalPages and TotalRecords are consistent, that no page exceeds page-size, that each ATMId appears exactly once across the walk, and that the order is the same when the walk is repeated.

05 · Rollout

A V2.2 change, with V2.1 left as it is

The response shape changes, so the change lands with the version. TPPs opt in by moving to V2.2.

How it lands
  • V2.1 is unchanged. A TPP calling /open-finance/atm/v2.1/atms keeps receiving the full estate in one response, without Links, for as long as V2.1 is supported.
  • LFIs conform by V2.2. Pagination is a V2.2 conformance requirement for every LFI that offers the ATM API, and is tested in functional certification.
  • TPPs move when they move to V2.2. The migration is a loop on Links.Next. The TPP ATM API Guide will state plainly that the first page is not the whole estate, because that is the one way this change can go wrong without anything failing.
06 · Questions

Three questions, asked with the vote

These appear as optional boxes when you confirm your vote. The first sizes the work for LFIs, the second the migration for TPPs, and the third decides whether a follow-up proposal is needed.

01 · LFIs

How many ATM records does your Ozone Connect GET /atm return today, and how large and how slow is that response? Can you honour page and page-size, in a stable order, by V2.2?

This sizes the problem and the build. The case for pagination rests on how large ATM estates are and how quickly they are growing; the answers also tell us whether a mandatory requirement at V2.2 is realistic for every LFI, or whether some need longer.

02 · TPPs

How do you consume GET /atms today — a periodic full sync, on-demand lookups, or something else? Would following Links.Next until it is absent cause you any difficulty?

Pagination changes what a single call returns. A TPP that reads only the first response would silently hold the first 100 ATMs. The answers tell us how many integrations are affected and how much the TPP guide needs to say about walking pages.

03 · TPPs and LFIs

Is a fixed page size of 100, set by the API Hub, right for ATM data — or should TPPs be able to set page-size, or filter the estate (for example by LastUpdatedDateTime), in a later version?

This proposal deliberately adds no TPP-facing query parameters, so it matches Bank Data Sharing and stays small. If there is demand for client-chosen page sizes or a change feed, that is a separate proposal; the answers tell us whether to write it.

07 · Pros

What pagination buys

  • ✓Responses are bounded. The size of one GET /atms response no longer grows with the LFI’s ATM estate, which protects the API Hub, the LFI, and the TPP from payloads that only get larger.
  • ✓One pagination model across the standard. ATMs adopt the page / page-size contract LFIs already implement for Bank Data Sharing and the Links envelope TPPs already parse for Products and Account Information.
  • ✓Mandatory pagination is predictable. Because every LFI paginates, a TPP writes one loop that works against every bank, instead of handling some that page and some that do not.
  • ✓A failure costs one page, not the whole estate. A timeout or 5xx part-way through is retried for the page that failed, not by fetching every ATM again.
  • ✓The TPP request does not change. The first call to GET /atms is the same unparameterised request it is today; the TPP only has to follow Links.Next.
  • ✓TotalRecords and LastUpdatedDateTime are kept, so a TPP that checks the estate’s freshness or size before syncing can keep doing so from page 1.
08 · Cons

What it costs

  • ×Every LFI has to build it. Ozone Connect GET /atm takes no query parameters today, so each LFI must add page and page-size handling, a stable order, and TotalPages.
  • ×It is breaking for TPPs at V2.2. A TPP that reads Data from the first response and stops will silently hold only the first page of ATMs. Nothing in the response fails; the data is just incomplete.
  • ×More calls for the same data. A full sync of a large estate becomes several requests instead of one, each with its own token check, its own latency, and its own entry in reporting.
  • ×Pages can drift during a walk. If an LFI adds or removes an ATM between page requests, a TPP walking the estate can miss or repeat a record. A stable order narrows this, but does not remove it.
  • ×It does not help a TPP that only wants what has changed. A full sync still fetches every page; delta retrieval is left for a later proposal.