Pagination & filtering
Cursor-based pagination, how to load all pages, and filtering lists.
Keyset (cursor) pagination
List endpoints — products, categories' products, orders, search — use cursor
pagination, not page numbers. Each response carries a nextCursor:
{
data: [ /* items */ ],
nextCursor: "2026-01-01T12:00:00.000Z", // opaque — pass it back as-is
hasMore: true,
}To get the next page, pass nextCursor back as cursor:
let cursor: string | undefined;
const all = [];
do {
const { data, error } = await storekit.products.list({ limit: 50, cursor });
if (error) throw error;
all.push(...data.data);
cursor = data.hasMore ? data.nextCursor ?? undefined : undefined;
} while (cursor);Shortcut: listAll()
For products, the SDK can do this loop for you:
const { data: products } = await storekit.products.listAll({ categorySlug: "shoes" });Use it for build-time generation (e.g. generateStaticParams), not for
user-facing infinite scroll where you want one page at a time.
- Default
limitis 20; the maximum is 100. - Treat
nextCursoras opaque — don't parse or construct it. - Stop when
hasMoreisfalse.
Filtering
Products
await storekit.products.list({
categorySlug: "footwear", // includes the whole subtree of that category
tagSlug: "new-arrivals",
limit: 24,
});categorySlug expands to the full category subtree, so filtering by a
parent category returns products in its children too.
Search
await storekit.search({
q: "running shoes",
categorySlug: "footwear",
inStock: true,
limit: 20,
});Search responses also include facets (category counts, price range, in/out-of-stock counts) you can use to build filter UI:
{
results: [ /* products */ ],
facets: {
categories: [{ slug, name, count }],
priceRange: { min, max },
inStock: 42, outOfStock: 3,
},
nextCursor, hasMore, total,
}Categories are flat + parentId
categories.list() returns a flat array where each category has a
parentId. Build the tree client-side:
const { data } = await storekit.categories.list();
const roots = data.filter((c) => !c.parentId);
const childrenOf = (id) => data.filter((c) => c.parentId === id);