{
  "object": "doc",
  "title": "How does pagination work?",
  "description": "Opaque cursors, limits and iterating all results.",
  "section": "Concepts",
  "url": "https://cart-route.com/docs/pagination",
  "updated": "2026-09-23",
  "prev": "https://cart-route.com/docs/idempotency",
  "next": "https://cart-route.com/docs/pages-as-json",
  "text": "Search returns at most `limit` products (1 to 25, default 10) and a `next_cursor`. Pass that value back as `cursor`, unchanged and with the same other parameters, to get the next page. On the last page `next_cursor` is `null`. Each page is a separate metered call.\n\n## How do I fetch the next page?\n\n```\ncurl \"https://cart-route.com/api/v1/search?q=laptop&limit=5\" -H \"Authorization: Bearer $CARTROUTE_API_KEY\"\n# ... \"next_cursor\": \"eyJvIjo1fQ\", \"links\": {\"next\": \"https://cart-route.com/api/v1/search?q=laptop&cursor=eyJvIjo1fQ\"}\n\ncurl \"https://cart-route.com/api/v1/search?q=laptop&limit=5&cursor=eyJvIjo1fQ\" -H \"Authorization: Bearer $CARTROUTE_API_KEY\"\n```\n\n## How do I iterate every page?\n\n```\nimport os\nimport requests\n\ndef search_all(q, **filters):\n    params = {\"q\": q, \"limit\": 25, **filters}\n    headers = {\"Authorization\": f\"Bearer {os.environ['CARTROUTE_API_KEY']}\"}\n    while True:\n        body = requests.get(\"https://cart-route.com/api/v1/search\", params=params, headers=headers, timeout=15).json()\n        yield from body[\"results\"]\n        if not body.get(\"next_cursor\"):\n            return\n        params[\"cursor\"] = body[\"next_cursor\"]\n```\n\n## Should I paginate at all?\n\nUsually not. Results are ranked, so the first page holds the best matches; an agent answering \"where should I buy X\" rarely needs more than 5. Narrow the query or add filters before paging, which costs fewer credits than paging through broad results.\n\n## What makes a cursor invalid?\n\nEditing it, or using a value from another source. An invalid cursor returns `422 validation_error` with `param: \"cursor\"` and is not charged. Cursors do not expire, but results can shift between pages as prices change, because ranking is recomputed on every call."
}