Paging, events and as-of reads
How to read long lists, follow every change in order, and see data as it was at a given time.
Lists: limit and offset
Most lists answer one page at a time. Send limit for the page size and offset for how many to skip:
curl -X GET 'https://inventory.getmanifold.io/items?limit=50&offset=100' \
-H "Authorization: Bearer $MANIFOLD_TOKEN"{
"items": [ … 50 items … ],
"total": 128,
"limit": 50,
"offset": 100
}total counts every match across all pages, with your filters applied. Ask for the next
page with offset plus limit, and stop once offset reaches total.
Each list's page in the reference gives its largest limit and what it does when you
leave limit out. Some lists then answer a default page, such as 50; others answer every
match.
A few lists answer a bare array, with no total. Stop when a page comes
back shorter than limit. These are:
GET /orderson fulfillment: newest first,limit100 by default and at most 1000.GET /orders/countgives the total for the same filters.GET /importsandGET /imports/{jobId}/failureson import and export.- Every service's
GET /events, which pages bysince(below).
Each list's page in the reference shows its answer, so you can see which shape it has.
Logs that grow: before and next
A log that grows while you read it, such as a SKU's activity or the webhook delivery log, is newest first and paged with before. An offset would shift every time a new entry landed.
curl -X GET 'https://inventory.getmanifold.io/items/WIDGET-BLUE/events?limit=100&before=1031' \
-H "Authorization: Bearer $MANIFOLD_TOKEN"{
"events": [ … 100 entries, newest first … ],
"next": 931
}Each page carries next: the sequence of the oldest entry on the page. Send it back as before for the older page, which starts below it. Pass it on as it came rather than
working one out. The last page has no next.
Events: every change, in order
Each service keeps a record of every change it made for the organization, as facts it never edits
or deletes (see Facts and the journal). Each fact has a sequence, counting up within one service for one organization. GET /events reads them, oldest first:
curl -X GET 'https://inventory.getmanifold.io/events?since=1042&limit=500' \
-H "Authorization: Bearer $MANIFOLD_TOKEN"[
{
"_tag": "inventory.stock-dispatched",
"eventId": "evt_01a1615a-c0e0-7d38-a94d-ee5249f39be3",
"txId": "tx_01a1615a-c0e0-7de2-b618-5b6075c9f4c7",
"tenantId": "org_019cadd3-7f48-7813-b601-1d0e5ec31353",
"sequence": 1042,
"occurredAt": "2026-10-22T02:05:00.000Z",
"source": "inventory-manager",
"version": 1,
"actor": {
"_tag": "user",
"id": "usr_019cadd3-7fc0-792b-bb42-1992ef490f3b"
},
"correlationId": "req_01a1615a-c0e0-756f-be6c-4dc5e8f50d4d",
"payload": {
"sku": "WIDGET-BLUE",
"locationId": "loc_019cadd3-8330-7e12-aa44-2cd5f05da74a",
"quantity": 2,
"orderId": "ord_01a1612f-7ea8-705d-b799-e8d57826848d",
"reference": "dsp_309cca80-6f93-1b13-35a3-a6c100d3dd4d"
}
}
]since is inclusive: a page starts at that sequence. limit is 500 by
default, and at most 5000. To read every fact exactly once, start from since=0 the
first time, then ask again from the last fact's sequence plus one, until a page comes
back shorter than limit:
const base = "https://inventory.getmanifold.io";
const headers = { Authorization: `Bearer ${process.env.MANIFOLD_TOKEN}` };
// since is inclusive: a page starts at that sequence.
let since = 1042; // where you stopped last time; 0 on the first run
for (;;) {
const res = await fetch(`${base}/events?since=${since}&limit=500`, { headers });
if (!res.ok) throw new Error(`events: ${res.status}`);
const page = await res.json();
for (const fact of page) handle(fact);
if (page.length < 500) break;
since = page[page.length - 1].sequence + 1;
}
// Store `since`: next time, start from it.Store the cursor and start from it next time. Each service has its own sequence and its own /events, and each needs the scopes that read what it records; the operation's page
says which.
Inventory also pushes its facts as they happen, over GET /events/stream (Server-Sent Events). It is best effort: a slow reader loses its oldest messages. After a gap or a
dropped connection, reconnect and read /events from the last sequence you
saw plus one.
The record at a moment
GET /events/head?at= answers the last sequence the service had recorded
at that moment. There is no sequence if it had recorded nothing yet.
curl -X GET 'https://inventory.getmanifold.io/events/head?at=2026-10-22T03%3A00%3A00.000Z' \
-H "Authorization: Bearer $MANIFOLD_TOKEN"{
"at": "2026-10-22T03:00:00.000Z",
"sequence": 1042
}Then replay up to that sequence with upTo, beside since. upTo is inclusive: the replay ends at that sequence, so you get the record exactly as it
stood then.
curl -X GET 'https://inventory.getmanifold.io/events?since=0&upTo=1042' \
-H "Authorization: Bearer $MANIFOLD_TOKEN"Heads taken at the same at from several services describe the same moment.
As-of reads
Add x-manifold-as-of with a past moment to a GET, and the service answers
as it would have at that moment:
curl -X GET 'https://inventory.getmanifold.io/items/WIDGET-BLUE' \
-H "Authorization: Bearer $MANIFOLD_TOKEN" \
-H 'x-manifold-as-of: 2026-10-22T03:00:00.000Z'- Where it works: inventory, fulfillment, purchasing and CRM. Other services ignore the header and answer as of now.
- The answer carries
x-manifold-as-of-sequence: the sequence the service read up to. It is absent if the service had recorded nothing by then. - Reads only. A write with a past moment in the header is refused
409AsOfIsReadOnly. An as-of read changes nothing and sends nothing. - A missing or invalid token is refused
401Unauthorizedbefore anything else. - A moment that is not a time is refused
400AsOfInvalid. A moment that is now or later is answered as of now. - Details from another service in the answer, such as a location's name next to an old order, are as they are now.
- A person whose data was erased stays erased at every moment, even before the erasure.
Your scopes apply as they do now. In the admin, a past moment shows as a bar reading Viewing as of the moment, with Back to now.
Reference
GET /items: a list withlimitandoffset.GET /items/{sku}/events: a log withbefore.GET /eventsandGET /events/head: inventory's record. Most services have the same pair.- Page through the order book, arranged your way.