---
title: "Page lists with cursors · Agent Wranglers"
url: https://agentwranglers.se/playbook/api-design/lists/cursor-pagination
updated: 2026-10-20
licence: "All rights reserved"
---

# Page lists with cursors

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Lists](https://agentwranglers.se/playbook/api-design/lists)
- Rule: Return every list that can grow past one page in pages, and point to the next page with an opaque cursor, not a page number.
- How: Return the items and a `nextCursor`, or a `Link` header with `rel="next"` as RFC 8288 defines. Build the cursor from a unique sort key, such as the creation time plus the ID. Encode it, for example as base64url, and validate it on the way back in. Offsets skip or repeat items when rows are added during paging. The database side is in the data playbook's [keyset pagination](https://agentwranglers.se/playbook/data/queries-and-indexes/keyset-pagination).
- Check: Create items while a test pages through a list. Every item appears exactly once, and the last page has no next cursor. A tampered cursor gets 400.

Example:

```http
GET /orders?limit=50&cursor=b3JkXzhmMms HTTP/1.1

HTTP/1.1 200 OK
Link: </orders?limit=50&cursor=b3JkXzlhMXo>; rel="next"

{ "items": [ ... ], "nextCursor": "b3JkXzlhMXo" }
```

```js
const encodeCursor = row => Buffer.from(JSON.stringify([row.createdAt, row.id])).toString('base64url')
const decodeCursor = cursor => JSON.parse(Buffer.from(cursor, 'base64url').toString())
```

```python
import base64, json

def encode_cursor(row) -> str:
    return base64.urlsafe_b64encode(json.dumps([row.created_at, row.id]).encode()).decode()

def decode_cursor(cursor: str) -> list:
    return json.loads(base64.urlsafe_b64decode(cursor))
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers api design playbook: https://agentwranglers.se/playbook/api-design/lists/cursor-pagination`.

- Next: [Cap the page size](https://agentwranglers.se/playbook/api-design/lists/page-size-limit)
- [Lists](https://agentwranglers.se/playbook/api-design/lists)
