Skip to main content
Documentation

Guide

Pagination

Two paging models, on purpose: an opaque keyset cursor on the REST resources, and an exact remaining count on the capability lists.

The REST resource routes page by keyset cursor. Read meta.next_cursor from a page and send it back as ?cursor= to get the next one; when it comes back null, you have reached the end.

  • The cursor is opaque. It encodes a composite position, not a timestamp. Do not parse it, build one, or compare two — just hand it back.
  • Page size is 25 by default, 100 at most. Out-of-range and unparseable values are clamped or fall back rather than erroring.
  • New rows never shift your page. Paging walks backwards from a fixed point, so an import landing mid-sync cannot make you skip or repeat a record.
  • Webhook subscriptions are not paginated — that list is capped at 10 per shop and returns no meta block.

A capability that can return a partial answer declares a truncation contract, and its response carries an exact count of what it did NOT return — omitted, with 0 as a real answer meaning you have all of them — plus the way to get the rest.

Silent truncation is the most dangerous thing a read can do to an agent

A person who gets 25 of 300 customers sees a page control and knows. A model gets an array, has no page control to look at, and answers the owner's question confidently and wrongly about a book it has seen a twelfth of. So a list capability may not return a bare capped array: it says how much it withheld, every time, and its operating contract tells the model what to do about it.

A cursor is right for a machine walking an entire table in order, which is what a nightly sync does. An exact remaining count is right for an agent asking a narrow question and then answering a shop owner out loud. Both surfaces read the same rows through the same mapper, so the records are identical either way.