{✦} Stylumia Developers

Pagination & filtering

Cursor pagination

/v1/catalog is the one paginated endpoint here — the complete filtered set. It uses opaque cursors, not page numbers or offsets:

Parameter Default Max Notes
limit 100 500 Rows per page
cursor none Opaque — from a previous response's pagination.next_cursor

Take next_cursor exactly as returned and send it back exactly as received. Never construct one by hand, decode it, or edit it — its internal shape is not part of the contract and can change without notice.

has_more

pagination.has_more tells you whether another page exists. When it's false, next_cursor is null and you're done.

Stable ordering

Rows are ordered by sku within the filters you requested, and that ordering doesn't shift under you mid-walk — a page can't be reshuffled by data arriving between your requests.

Filters

The same six filters apply identically on /v1/sample, /v1/catalog, and /v1/coverage — all optional:

Parameter Format
retailer retailer slug
category category slug
department department slug
rcd one or more retailer:category:department triples, comma-separated — shorthand for the three above
start_date ISO 8601 (YYYY-MM-DD)
end_date ISO 8601 (YYYY-MM-DD)

start_date/end_date bound crawl_date, not the retailer's own change date — see The Product object. A wrong retailer, category, or department value fails with valid_options naming the real ones — see Error handling.

Invalid cursor

A cursor that's expired, malformed, or wasn't issued by this API returns invalid_cursor (400, not retryable). There's exactly one recovery: restart the walk from page one, without a cursor parameter. Don't try to repair a bad cursor — it isn't decodable in a way that's meaningful to you.

A two-request walk

curl "https://api.stylumia.com/v1/catalog?retailer=home_depot&category=power_tools&limit=2" \
  -H "Authorization: Bearer $STYLUMIA_KEY"
  # Never commit your key — see /docs/key-security
{
  "data": [
    { "product_id": "prd_5741354fa5d111f0a1ce7bcc", "sku": "1003097550", "retailer": "home_depot", "category": "power_tools", "...": "..." },
    { "product_id": "prd_9a3fddc7f5ec69b5913b5614", "sku": "1003097557", "retailer": "home_depot", "category": "power_tools", "...": "..." }
  ],
  "pagination": { "limit": 2, "total_matching": 6, "next_cursor": "eyJvIjogMn0=", "has_more": true },
  "meta": {
    "request_id": "req_1a2b3c9f7e0d452186af",
    "resolved": { "retailer": "home_depot", "category": "power_tools", "department": null, "rcd": null, "start_date": null, "end_date": null },
    "coverage": { "combinations": 1, "matching_rows": 6, "corpus_rows": 2361, "earliest_date": "2026-06-14", "latest_date": "2026-08-14" }
  }
}

pagination.limit and pagination.total_matching only appear on /v1/catalogtotal_matching is the size of the whole filtered set, not just this page. Take next_cursor and send it back — with the same filters, not just the cursor:

curl "https://api.stylumia.com/v1/catalog?retailer=home_depot&category=power_tools&limit=2&cursor=eyJvIjogMn0=" \
  -H "Authorization: Bearer $STYLUMIA_KEY"
  # Never commit your key — see /docs/key-security

The cursor only tracks your position in the result set — it decodes to an offset, nothing more — it doesn't remember which filters produced it. Drop or change a filter between calls and you'll walk a different set of rows from wherever the cursor left off, silently, not as an error. Keep retailer, category, department, rcd, start_date, and end_date identical across a whole walk.

View as markdown