Pagination helpers for Xero API endpoints.
Xero returns 100 items per page (fixed). Endpoints supporting pagination: Invoices, Contacts, Bank Transactions, Manual Journals, Purchase Orders, Payments.
Usage
# Lazy stream (recommended — memory-efficient)
Xero.Accounting.Invoices.stream(token, tenant_id)
|> Stream.filter(&(&1["Status"] == "AUTHORISED"))
|> Enum.to_list()
# Fetch all pages at once (caution with large datasets)
{:ok, all} = Xero.Paginator.fetch_all(
fn opts -> Xero.Accounting.Contacts.list(token, tenant_id, opts) end,
key: "Contacts"
)
# Single page
{:ok, page} = Xero.Paginator.fetch_page(fetch_fn, page: 2)High-Volume Threshold
Xero rejects GET requests that require processing more than 100k records
(HTTP 400). Use if_modified_since:, where:, and summary_only: true
to reduce the working set before paginating.
Summary
Types
@type fetch_fn() :: (keyword() -> {:ok, term()} | {:error, Xero.Error.t()})
Functions
@spec fetch_all( fetch_fn(), keyword() ) :: {:ok, list()} | {:error, Xero.Error.t()}
Fetches all pages and returns a flat list.
Options
:key— if the fetch_fn returns a map, extract items at this string key:start_page— page to begin at (default 1)
@spec fetch_page( fetch_fn(), keyword() ) :: {:ok, term()} | {:error, Xero.Error.t()}
Fetches a single page.
@spec page_size() :: 100
Returns the fixed Xero page size (100).
@spec stream( fetch_fn(), keyword() ) :: Enumerable.t()
Returns a lazy Stream that fetches pages on demand.
fetch_fn receives [page: integer()] and must return
{:ok, list()} or {:error, Error.t()}.