docs

Pagination

Pagination is essential for working with larger data sets, where it is not feasible to fetch all data in a single call.

All top-level API resources that return a list of items always include pagination information in the response. Whether an endpoint also accepts pagination parameters on the request is documented per endpoint. If you paginate past the available items, the API returns an empty list.

The Storefront API offers three ways to paginate:

Choosing a method

MethodBest forCan jump to arbitrary page?Subject to the 500,000-item window?
Page-basedUI pagination, "page X of Y" navigationYesYes
Offset-basedSequential reads with a changing batch sizeNo (sequential)Yes
Product-ID-basedFull exports / iterating over all products at scaleNo (sequential)No

Maximum result window. For page-based and offset-based pagination, you cannot reach beyond the first 500,000 items: page * perPage and offset + limit must each stay at or below 500000. To extract product sets larger than this - or simply for better performance on deep pagination - use product-ID-based pagination, which is not bound by this limit.

Page-based (page, perPage) and offset-based (offset, limit) parameters are mutually exclusive. Combining them in a single request returns a 400 validation error. See Error handling.

Page-based Pagination

All endpoints use page-based pagination by default when you don't specify otherwise.

ParameterDetails
page

The page you want to retrieve items for.

Type: Integer
Default: 1
Minimum: 1
Maximum: 500000 / perPage (e.g. 5000 when perPage=100)

perPage

How many items you want to retrieve per page.

Keep this value the same between requests to avoid duplicates or missing items.

Type: Integer
Default: 100
Minimum: 1
Maximum: 1000


For the /v1/products endpoint, use a perPage of at most 250, or at most 100 when including siblings.

Every paginated response includes a pagination object:

Response FieldDetails
currentThe number of items returned on the current page.

This equals perPage unless there are fewer items left. For example, if you request the last page and only 10 items remain, current is 10.

Type: Integer
totalThe total number of items available for this resource, regardless of pagination.

Type: Integer
perPageThe perPage value that was applied to the request.

Type: Integer
pageThe page that was applied to the request.

Type: Integer
firstThe first page. Always 1.

Type: Integer
prevThe previous page you can request. If you are on the first page, this is 1.

Type: Integer
nextThe next page you can request. If you are on the last page, this equals the value in page.

Type: Integer
lastThe last page you can request, derived from total and perPage. When there are no items, this is 1.

Type: Integer

Offset-based Pagination

Offset-based pagination gives you more flexibility, because the number of items you retrieve per call can vary.

Set offset to the number of items you have already retrieved, and adjust limit as needed while iterating.

ParameterDetails
limit

The maximum number of items to return.

Type: Integer
Default: 100
Minimum: 1
Maximum: 1000

offset

The position from which to start returning items. Set it to the total number of items retrieved so far.

Example: when retrieving products in chunks of 250, increase offset by 250 after each request.

Type: Integer
Default: 0
Minimum: 0
Maximum: 500000 - limit

Offset-based pagination is a REST API feature. The typed @scayle/storefront-api client always paginates by page (pagination: { page, perPage }), so use a direct REST request for offset/limit, or use page-based or product-ID-based pagination with the SDK.

Offset-based responses return only the total count:

Response FieldDetails
total

The total number of items for this resource.

Once offset reaches or exceeds total, you have reached the end of the data and further requests return an empty list.

Type: Integer

Product-ID-based Pagination

Product-ID-based pagination is only available on the /v1/products endpoint. Use it whenever you iterate over large amounts of products. For example, an export, or a script that processes every product in a shop.

Instead of requesting pages, you use the ID of the last product you received as a cursor for the next request. This is far more performant than page-based or offset-based pagination for large data sets, and it is not bound by the 500,000-item window that otherwise limits /v1/products.

ParameterDetails
minProductId

Only products with an ID greater than or equal to this value are returned.

Type: Integer
Default: none

page

The page you want to retrieve items for.

Type: Integer
Default: 1
Minimum: 1
Maximum: 500000 / perPage (e.g. 5000 when perPage=100)

perPage

How many items you want to retrieve per page.

Keep this value the same between requests to avoid duplicates or missing items.

Type: Integer
Default: 100
Minimum: 1
Maximum: 1000


Use a perPage of at most 250, or at most 100 when including siblings.

To reliably iterate over every product, sort by product ID ascending so the cursor advances predictably:

  1. Start with an initial request using minProductId=0, sort=id, and sortDir=asc.
  2. Take the ID of the last product in the response and use that ID + 1 as the minProductId of the next request.
  3. Repeat until a request returns an empty list. You have now retrieved every product in the shop.

Product ID is the Storefront API's default sort field, so the TypeScript example only needs to set the direction. sort: { direction: 'asc' } gives you ID-ascending order out of the box, fully typed and with no extra configuration. Just keep the request free of a search term, as that switches the default to relevance sorting.

Because it walks the data by ID rather than by position, product-ID-based pagination stays consistent even if products are added or removed while you iterate, unlike page/offset pagination, where inserts and deletes can shift items between pages.

Error handling

Invalid pagination parameters return a 400 response with a details array describing each violation:

Common causes:

SituationResult
Mixing page/perPage with offset/limit in the same request400 "Can't use both offset-based and page-based pagination in the same request"
perPage outside 11000, or not an integer400 "perPage must be between 1 and 1000", or "Unable to parse integer from perPage"
limit outside 11000400 "The limit parameter must be an integer between 1 and 1000"
page * perPage exceeds 500000, or page not an integer400 "page must be between 1 and {n}", where {n} is 500000 / perPage rounded down (e.g. "...and 5000" at the default perPage=100); or "Unable to parse integer from page"
offset + limit exceeds 500000400 "The offset parameter must be an integer between 0 and {n}", where {n} is 500000 - limit (e.g. "...and 499900" at limit=100)
Paginating past the available items (but within the window)200 with an empty list, not an error