Sellvik / developers
Concepts

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's cursor query parameter. null when 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
done

TypeScript:

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 createdAt if 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.

On this page