Pagination
Cursor-based, opaque, stable. Don't compute offsets.
Sellvik list endpoints use cursor pagination. The cursor is an opaque string; treat it as a token, not a value to parse.
Shape
Every paged response looks like:
{
"items": [/* … up to `limit` rows … */],
"nextCursor": "eyJpZCI6...","
}items— the page of resources.nextCursor— pass to the next request'scursorquery parameter.nullwhen there are no more pages.
Walking a list
cursor=""
while :; do
resp=$(curl -s "https://api.sellvik.app/api/v1/store/products?limit=50&cursor=$cursor" \
-H "X-Sellvik-Key: <publishable-key>")
echo "$resp" | jq '.items'
cursor=$(echo "$resp" | jq -r '.nextCursor // empty')
[ -z "$cursor" ] && break
doneTypeScript:
let cursor: string | undefined
do {
const { data } = await sellvik.GET("/api/v1/store/products", {
params: { query: { limit: 50, cursor } },
})
for (const product of data!.items) yield product
cursor = data!.nextCursor ?? undefined
} while (cursor)Limits
The limit query parameter accepts integers from 1 to 100. If you
omit it, the server picks 20.
We never page-trim silently. If you ask for 100 and there are only 7, you get
7 plus nextCursor: null — not 100 padded with anything.
What can go wrong
- Computing offsets from
limit × page. The server does not guarantee stable ordering across pages without a cursor — items added between pages can shift the apparent order. Use the cursor. - Caching cursors across deploys. Cursors are opaque and the encoding may change between API versions. They're stable within v1. Don't store them in a database that outlives a request.
- Mutating during iteration. If your iteration also writes to the same
collection (e.g. importing products and then walking them), you may visit
the new rows or you may skip them. Filter on
createdAtif you need determinism.
When endpoints don't paginate
A small number of endpoints return everything in one response — typically
when the natural cardinality is bounded (e.g. a shop's category tree). When
this is the case the response is a plain { "items": [...] } with no
nextCursor field. The OpenAPI spec is authoritative; if a nextCursor
isn't in the response schema, there's no pagination on that route.