Pagination

How to walk any collection with an opaque cursor, and how to keep a copy of it up to date.

Every list in this API is read the same way: you walk a collection page by page, deliveries included.

GET /v1/restaurants/{restaurantId}/collections/{collection}/records
  ?limit=100
  &cursor=eyJpZCI6…
ParameterRequiredRules
limitno1 to 100. Defaults to 50.
cursornoThe nextCursor of the previous page, verbatim.

The answer is { "data": [...], "nextCursor": string | null }.

No time range

There is no from and no to. A record changes in place (a correction, a tombstone), so you walk the collection and reconcile rather than asking for a window of it. To read one week of deliveries, walk deliveries and keep the records whose data.timestamp falls inside the week.

Ordering

Oldest change first: ascending by sequence, the position of each record's latest change in the stream. Compare two sequence values; do not do arithmetic on one.

Walking the pages

nextCursor is null on the last page and a string otherwise. Pass it back untouched: it is an opaque position, not a document to parse, and its internals will change without notice.

async function* records({ apiKey, restaurantId, collection }) {
  const base = `https://api.backresto.com/v1/restaurants/${restaurantId}/collections/${collection}/records`;
  let cursor = null;

  do {
    const url = new URL(base);
    url.searchParams.set('limit', '100');
    if (cursor !== null) {
      url.searchParams.set('cursor', cursor);
    }

    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${apiKey}` }
    });
    if (!response.ok) {
      throw new Error(`BackResto ${response.status}`);
    }

    const page = await response.json();
    yield* page.data;
    cursor = page.nextCursor;
  } while (cursor !== null);
}

A walk is a consistent snapshot. The first page pins the position of the stream, and every later page is answered as of that same position. Records written while you are paging do not shift the pages under you. You see them on your next walk.

The cursor is bound to the restaurant, the collection and the limit. Change the page size mid-walk and it answers 400: pick a limit, keep it for the whole walk.

Keeping a copy up to date

There is no since parameter today. A refresh is another walk, and you reconcile with what you already hold:

  • Key on id within a collection, and overwrite when the sequence you receive is higher than the one you stored.
  • Honour tombstones. deleted: true is the delete instruction; applying it is the only way your copy stops diverging.
  • Expect late arrivals. A device that was offline during service uploads when it reconnects, so a record can appear after a walk that would have covered its data.timestamp. Report on capturedAt, sync on receivedAt.

An empty page is not proof that nothing happened. See the note on completeness.

Last updated 2026-09-29.