maesn
Product insight

Every result set, one way to page it

Systems paginate in incompatible ways, some by page number, some by cursor, each with its own quirks. Maesn puts one limit and page parameter in front of all of them, and adds the filters that let you pull only what changed.

Four ways to pageone result set
Page-basedcount pages first
Page-based, minus onelast page errors
Cursor-basedbookmark, no total
Max count in the URLparse it out
maesn pages it
One pagination, every system
GET /invoices?limit=50&page=1
Trusted by winning software teams
HubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinProvetHeroHolviLanes & PlanesHubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinProvetHeroHolviLanes & Planes
The concept

What is unified pagination and filtering

Normalizing the shape of the data is one problem. Controlling the shape of the result set is a separate one: which records come back, in what order, which ones are filtered out and how many arrive at a time. Two systems can return an identical invoice object and still disagree completely on how you walk through ten thousand of them.

Unified pagination and filtering is the layer that settles that. One paging scheme, one set of filter parameters and one way to order results, applied across every system, so the loop you write for the first integration is the loop that works for all of them. It sits alongside the common data model rather than inside it: the model settles what a record looks like, this settles which records you get.

The problem

Two paradigms, and a variant per system

Paging is not one problem with one solution. It is two incompatible models, each with per-system oddities on top, and you meet all of them the first time you try to read a full list.

Page-based

You count and request numbered pages.

  1. 1Ask how many pages there are
  2. 2Request page 1, 2, 3 in a loop
  3. 3Stop one page early, the last errors
  4. 4Some return the max count in the URL
Cursor-based

You follow a bookmark until it runs out.

  1. 1Ask for the first batch
  2. 2Read the cursor out of the response
  3. 3Send it back to get the next batch
  4. 4You never learn the total

Two incompatible paradigms, plus a variant per system. Build against them directly and every integration needs its own paging loop.

How Maesn handles it

Two parameters, predictable results

You send limit and page. Maesn translates that into whatever the target system actually needs and hands back a consistent page of normalized records.

limit
How many per page

Accepts 5, 10, 20, 50 or 100, so a page size is always a valid, predictable number.

page
Which page to return

Starts at 1 and counts up, with no pre-query and no off-by-one at the end of the set.

One pagination everywhere

Page-based schemes, cursor bookmarks and their per-system variants all sit behind the same two query parameters.

Delta with lastModified

Pass the timestamp of your last fetch and receive only the objects that are new or changed since then.

Filters where they matter

Beyond lastModified there is status on invoices, plus filters built for a specific system's gaps, on the same unified endpoints.

Ordering you control

Order invoices, bills and booking proposals by date, number or created and updated timestamps, ascending or descending.

fetch-invoices.ts
const res = await axios.get(url, {
params: { limit: 50, page: 1 },
headers: {
'X-API-KEY': apiKey,
'X-ACCOUNT-KEY': accountKey
}
});
The delta filter

Pull what changed, not everything again

The filter most integrations end up living on is lastModified. You store the timestamp of your last successful fetch, pass it on the next request, and receive only the objects that are new or changed since then. A nightly reconciliation over a customer's full ledger becomes a request that returns a handful of records.

It is built on nearly every schema and endpoint, which is what makes it usable as a general strategy rather than a special case. The practical rule that goes with it: poll at the lowest frequency that still keeps your data fresh enough. Polling every minute for something that changes once a day is wasted traffic and cost, and Maesn paces requests to each target system anyway through asynchronous processing. Where you need to react the moment something changes rather than on a schedule, unified webhooks push the event to you instead, and many integrations run both: webhooks for immediacy, a periodic delta poll as the safety net.

Your last fetch: Jan 15, 09:30
inv_8836Jan 14, 08:12
inv_8837Jan 14, 16:40
inv_8841Jan 15, 10:05
inv_8842Jan 15, 11:37

Illustrative. Grey objects were already in your database.

maesn returns the delta
Only what changed
GET /invoices?lastModified=2026-01-15T09:30:00

You get the two objects that are new or changed since your timestamp, not the whole ledger again.

Filtering and ordering

Filters built for what each system lacks

Some filters exist across the board, others exist because one system has a gap worth closing. Both live on the same unified endpoints, so using them costs you no per-system code.

sevdesk

·Contacts
number

Search contacts by their contact number, covering both customers and suppliers in the same filter.

sevdesk integration

Lexware Office

·Contacts
name, email

Filter contacts by name or by email address, so you can match a record you already hold.

Lexware Office integration

Sage Active

·Invoices
paymentStatus

Sage Active has no paid or partially paid state in its regular invoice status, so payment status is its own filter.

Sage Active integration

BuchhaltungsButler

·Bills
billDateFrom

Return only bills whose bill date falls after the value you pass, filtered in the request itself.

BuchhaltungsButler integration
orderFieldplusorderDirasASCorDESC
InvoicesinvoiceDate · invoiceNumber · createdDate · updatedDate
BillsbillDate · billNumber · createdDate · updatedDate
Booking proposalsbookingProposalDate · number · createdDate · updatedDate

Not every resource supports all three of filtering, ordering and pagination, and Maesn does not claim otherwise. The capability has to exist somewhere underneath, so support is documented per endpoint in the API reference. You can see what a given endpoint offers before you build against it, which is the honest version of a unified layer: consistent where consistency is possible, transparent about the edges.

Why it matters

One loop, every system

Building it yourself
  • Write a paging loop per system
  • Handle cursors and page counts
  • Work around the failing last page
  • Re-pull everything to find changes
With Maesn
  • One limit and page everywhere
  • Cursors and counts handled for you
  • No off-by-one to work around
  • Pull only what changed since

Reading a full list sounds like the simplest thing an integration does, and it is where a surprising amount of time disappears: a paging loop per system, a workaround for the page that errors, and a full re-read every night because there is no reliable way to ask what changed. Because you page and filter through Maesn rather than against each system, that work happens once. The same two parameters and the same delta filter carry over to every integration you add, including the ones Maesn adds after you have shipped, and the customer connects once for all of it.

Unified Pagination & Filtering FAQ

Common questions

Through two query parameters: limit and page. The limit parameter sets how many resources come back per page and accepts 5, 10, 20, 50 or 100. The page parameter selects the page and starts at 1. That is the same on every system, whether the underlying API is page-based or cursor-based.

Build once on the Unified API.

See how unified pagination and filtering works for your integration, or dive into the technical reference.