Return transactions and statements newest-first
Neither specification says which end of history a transactions or statements response starts from. A TPP holding page 1 cannot tell whether it is this month’s activity or activity from two years ago, and has no way to ask for the other one. This proposal makes descending date order — newest first — a requirement on both endpoints at V2.2, for every LFI including those already live. Whether TPPs should later be able to request ascending order is asked, not answered.
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 — and the answers matter more than the tally: they decide whether the transition treatment holds and whether a sort control follows in a later version.
Nothing says which end of history a page starts from
GET /accounts/{AccountId}/transactions and GET /accounts/{AccountId}/statements both return a list that can run to thousands of records across a mandated two years of history. Neither the TPP-facing standard nor the Ozone Connect specification says what order that list arrives in, and neither offers a parameter to ask for one.
# Today — neither specification constrains the order
# TPP-facing (uae-account-information-openapi.yaml)
GET /accounts/{AccountId}/transactions?fromBookingDateTime=...&toBookingDateTime=...
GET /accounts/{AccountId}/statements?fromStatementDate=...&toStatementDate=...
# Ozone Connect (uae-ozone-connect-bank-data-sharing-openapi.yaml)
GET /accounts/{accountId}/transactions?fromBookingDateTime=...&page=1&page-size=100
"Return all transactions for the account, filtered on date range parameters
as required."
# No sort parameter. No ordering statement. A TPP holding page 1 has no way to
# know whether it is this month's activity or activity from two years ago — and
# no way to ask for the other one.The only ordering rule that exists anywhere is ours, not the specification’s: the Pagination article requires an LFI to return records in a deterministic order so that paging is stable across successive page requests. Deterministic is not a direction. An LFI returning oldest-first and an LFI returning newest-first are both conformant today, and a TPP integrating with both gets two different answers to the same question.
The consequences land entirely on the TPP, and they are not small. It cannot treat page 1 as recent activity, so the common case — showing a customer what has just happened on their account — requires pulling every page of the filtered set and sorting client-side before anything can be displayed. It cannot bound work by asking for the last fifty transactions. And because the difference is invisible until it meets a second LFI, it is the kind of assumption that survives the sandbox and fails in production — surfacing as a mis-ordered account view rather than an error anyone can catch.
The related weakness is stability. Both endpoints filter on a date field that is not unique: transactions share a bookingDateTime routinely, and statements carry an OpeningDate that is a date, not a timestamp. If an LFI orders on that field alone, two records that tie can be returned in either order on either request — so walking pages can hand a TPP the same record twice and never show it another. That is permitted by “deterministic” only on a generous reading of it.
Newest first, on both endpoints, from V2.2
Transactions and statements MUST be returned in descending date order — newest first. The ordering applies to the filtered result set and is applied before pagination, so the first page always carries the most recent records the query matched.
# Proposed — one direction, defined for both endpoints
GET /accounts/{accountId}/transactions
order by bookingDateTime DESC # MUST — newest first
transactionId DESC # SHOULD — stable tiebreaker
GET /accounts/{accountId}/statements
order by openingDate DESC # MUST — newest first
statementId DESC # SHOULD — stable tiebreaker
# Applied to the FILTERED result set, before it is paged. Page 1 therefore
# always carries the most recent records the query matched.Descending is chosen because it serves the common case without a client-side pass. Account aggregation, spending views, notifications, and the “what happened recently” question that most TPP journeys open with all read backwards from today — and it is the direction a customer already sees in every banking app they use. Under pagination the direction decides which page holds the answer: newest-first puts it on page 1, oldest-first puts it on the last page the TPP can only reach by fetching all of them.
The requirement applies to every LFI at V2.2, including those already live. No grace period is proposed. Ordering is a property of the query that already serves these endpoints rather than of the data model, so for most implementations this is a sort clause and a regression test — and the cost of leaving it unspecified compounds with every LFI and TPP that joins. Whether that reading holds for LFIs who have already built is the first question attached to this vote, and a clear answer to the contrary is the thing that would reopen it.
This proposal does not introduce a way to request ascending order. A direction control — a request header or query parameter carrying asc / desc — is a reasonable thing to want and a different thing to specify: it doubles what an LFI must implement and test, and it is only worth defining if LFIs can support it and TPPs would use it. Both are asked in section 06. If the answers point that way, a control follows as its own proposal against a later version, with descending remaining the default.
What “newest first” means, precisely
An ordering rule is only worth having if two LFIs reading it independently produce the same sequence, so the key, the tiebreaker, and the interaction with filtering and paging all have to be pinned down.
- Transactions MUST be ordered by
bookingDateTime, descending. This is the field the existingfromBookingDateTime/toBookingDateTimefilters already act on, so filtering, ordering, and paging all address the same value. - Statements MUST be ordered by
OpeningDate, descending — the start of the statement period. Again this is the field thefromStatementDate/toStatementDatefilters act on.StatementDate(when the statement was issued) andClosingDateare deliberately not used: ordering on a field the filters do not use would let a statement fall inside the requested range and outside the expected position. - A stable, unique tiebreaker SHOULD be applied —
transactionIdfor transactions,StatementIdfor statements — so that records sharing a date hold a fixed relative position across requests. Without one, ties can be returned in either order on either request, and walking pages can duplicate a record on one page while dropping it from another. It is a SHOULD rather than a MUST because an LFI whose ledger already guarantees a total order by other means satisfies the intent; what matters is that ties never move. - Ordering is applied to the filtered result set, before pagination. This extends the existing rule that filtering is applied first and pagination to the filtered set; ordering sits between them.
totalRecordsandtotalPagesare unaffected. - The order does not vary with the request. Date filters,
page,page-size, and theo3-fx-transactionsheader narrow which records are returned; none of them change the direction they are returned in. - The API Hub passes the LFI’s order through unchanged. It converts the LFI’s
metainto the TPP-facingLinksenvelope and does not re-sort, so the order the TPP observes is the order Ozone Connect produced. The requirement therefore has to be met at the LFI; there is no Hub-side correction. - No sort control is introduced. Neither specification gains a sort parameter or header under this proposal. The order is fixed, and a TPP that needs ascending reverses it itself.
- Other list endpoints are out of scope.
/beneficiaries,/direct-debits,/scheduled-payments,/standing-orders,/products,/accountsand/accounts/{accountId}/customerare unaffected and remain subject only to the existing deterministic-order rule. They are small, optionally paginated, and mostly carry no obvious date to sort on.
Insurance Data Sharing is not covered by this proposal. If the ecosystem wants the same treatment for policy-level history, it should be raised separately rather than folded in here, where the endpoints, filters, and pagination behaviour are different.
What changes
No schema changes, no new fields, no new parameters. Four endpoint descriptions, the documentation that describes them, and a conformance check.
In the bank data sharing specification, state the ordering requirement on GET /accounts/{accountId}/transactions and GET /accounts/{accountId}/statements — the key, the direction, the tiebreaker, and that ordering precedes pagination. This is the normative home of the rule, because this is the surface the LFI implements. Targets V2.2.
Mirror the statement on the TPP-facing GET /accounts/{AccountId}/transactions and GET /accounts/{AccountId}/statements in the account information specification, so a TPP reading only the standard knows what it can rely on without inferring it from the LFI-facing spec. No request or response schema changes.
Tighten the ordering line in the Pagination article and the LFI Bank Data Sharing — Pagination guide from “deterministic” to “deterministic and descending”, with the tiebreaker and the duplicate-record failure it prevents spelled out. Add the guarantee to the TPP Data Sharing API guide so it is stated where TPPs read, and record the change as an errata entry.
Add a Data Sharing check that walks a multi-page transactions query and asserts the order is descending across the page boundary, and that re-requesting a page returns the same records in the same positions. This is what makes the requirement enforceable rather than aspirational — and it is a check that “deterministic” on its own could never support.
A sort clause for most LFIs — but not, necessarily, for all
For an LFI serving these endpoints from a query against a ledger or transaction store, this is an ORDER BY, a tiebreaker column, and a regression test that walks two pages. That is the expectation this proposal is written on, and it is why no grace period is offered.
It is not universally true. An LFI serving transactions from a cache, a materialised feed, or an event log built forwards in time may find that reversing the order means reversing how that feed is built or indexed — a different size of change, and one that has to be scheduled rather than absorbed. An LFI whose statement records are keyed by issue date rather than OpeningDate has a mapping to make on top. Nobody outside those LFIs can size this, which is exactly why it is the first question attached to the vote.
For a TPP, conforming costs nothing — the guarantee only adds something to rely on. The cost falls on the TPP that wanted the other direction: reconciliation and running-balance work reads forwards, and reversing a paginated response means holding the whole filtered set before processing can start. That is a real cost, and section 06 asks who carries it.
A vote in favour is a statement that your institution would conform to this — an LFI that it would return newest-first at V2.2 without a transition period, a TPP that it would build against a fixed descending order. Answering the questions matters more than the tally: a For vote with “this is a two-line change for us” and a For vote with “this rebuilds our feed” mean different things, and the second is what would change the proposal.
Three questions, asked with the vote
These appear as optional boxes when you confirm your vote. Answer the ones addressed to you — every voter sees all three. The vote decides descending order; these answers decide whether the transition holds and whether a direction control follows.
Would newest-first ordering change your implementation, and what work would it involve?
This is the question that decides whether the requirement is a one-line sort clause or a change to how a feed is built. If a meaningful number of live LFIs answer that it is structural, the transition treatment below is the part to revisit.
Does newest-first work for your use cases, or do you need to request ascending order?
Descending suits the common case — showing recent activity. Reconciliation and running-balance reconstruction read oldest-first, and under pagination that means collecting every page before processing. We need to know whether that cost is real for anyone.
Could you support a TPP-requested asc/desc sort control, or is a fixed descending order materially easier?
A control is only worth specifying if LFIs can implement it. If descending-only is materially easier, that settles it — and the answers to the TPP question tell us what we are asking TPPs to give up.
What a defined order buys
- ✓TPPs can rely on the order for the first time. “Show me this customer’s recent activity” becomes the first page of the response rather than a full pull-and-sort of the filtered set.
- ✓Removes a silent interop difference. Ordering is the kind of assumption a TPP makes against one LFI in the sandbox and only discovers is wrong against another in production — where it surfaces as a mis-ordered account view, not an error.
- ✓Newest-first matches how account activity is read almost everywhere else — banking apps, card statements, the account views TPPs are building. It is the direction the common case wants.
- ✓Cheapest to fix now. Ordering is set by the query that already serves these endpoints, so for most LFIs this is a sort clause and a regression test — and only a handful of LFIs are live to change.
- ✓Tightens pagination stability at the same time. The tiebreaker guidance addresses a real failure: rows sharing a date can shuffle between page requests, so a record appears twice on one page and never on another.
- ✓Makes conformance testable. A functional check can assert newest-first across a multi-page query; “deterministic” alone is hard to test meaningfully.
What it costs
- ×It is a behaviour change for any LFI already live that returns oldest-first, and this proposal gives them no grace period — they conform at V2.2 with everyone else.
- ×Consumers that read forwards — reconciliation, ledger replay, reconstructing a running balance — must reverse the order themselves, and under pagination that means collecting the whole filtered set before they can start. The cost of the choice lands on that use case.
- ×If the consultation says a sort control is wanted, LFIs implement ordering twice: a fixed descending order now, and a direction control in a later version.
- ×The statement ordering key is less self-evident than the transaction one. An LFI that thinks of a statement by its issue date (StatementDate) rather than the start of its period (OpeningDate) has a mapping to make, even though the date filters already act on OpeningDate.
- ×It settles direction without settling choice. A TPP that wants ascending has no way to ask for it until a later proposal, and this one deliberately does not answer that.
