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.
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.
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 — 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.- 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
5xxpart-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
pageandpage-sizeat Ozone Connect, and the Hub converts the LFI’smetainto a TPP-facingLinksenvelope (see Pagination — LFI meta to TPP Links). Products, the other public-data API, already requiresLinksandMeta.TotalPagesonGET /products. ATMs are the exception. - V2.2 is the point to fix it. Adding
Linksto a response defined withadditionalProperties: falsechanges its shape, so it belongs in a new version rather than an errata.
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 — 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.
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.
- The API Hub MUST send
pageandpage-sizeon every request to Ozone ConnectGET /atm.pageis 1-indexed and defaults to1;page-sizedefaults to100, 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
pageandpage-size, and MUST NOT return the full estate in place of a page. There is nopaginated: falseoption for ATMs. - The order MUST be stable. The LFI MUST order its ATMs by
ATMIdascending, and SHOULD useLFIBrandIdascending 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. metaMUST describe the full estate.TotalRecordsis the number of ATMs across all pages.TotalPagesisceil(TotalRecords / page-size).LastUpdatedDateTimeis 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 emptydataarray withTotalRecordsandTotalPagesof0, as in Bank Data Sharing. It MUST NOT return404. - The TPP-facing response MUST carry
LinksandMeta.TotalPages.Links.Selfis always present;First,Prev,NextandLastare present when they apply.Meta.TotalRecordsandMeta.LastUpdatedDateTimeare kept. - The TPP request does not change. No TPP-facing query parameters are added to the request definition. The
pagevalue 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 setpage-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.
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.
- LFI — paginate
GET /atm. Acceptpageandpage-size, order the estate byATMId, return the requested slice, and addTotalPagestometa. - API Hub — send the parameters and build the links. Send
pageandpage-sizeto Ozone Connect, and convert the LFI’smetaintoLinksandMeta.TotalPageson the TPP response, as it does for Bank Data Sharing. - TPP — follow
Links.Next. A TPP that needs the whole estate loops onLinks.Nextuntil it is absent. The first request is unchanged.
uae-atm-openapi.yamlAdd 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.
uae-ozone-connect-bank-open-data-openapi.yamlAdd 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.
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.
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.
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.
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.
- V2.1 is unchanged. A TPP calling
/open-finance/atm/v2.1/atmskeeps receiving the full estate in one response, withoutLinks, 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.
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.
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.
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.
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.
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.
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.
