Cursor-based Pagination
The most common pagination type. The API returns a cursor/token pointing to the next page.
When to Use
- API returns a
cursor,next_cursor,starting_after, or similar token - API returns a
has_moreboolean - Response includes a link to the next page as a token value
Configuration
{
enabled: true,
type: "cursor",
paramsLocation: "query",
params: {
cursorParam: "cursor",
limitParam: "limit",
defaultLimit: 100
},
response: {
nextCursorPath: "meta.next_cursor",
hasMorePath: "meta.has_more",
dataArrayPath: "data"
},
stopCondition: {
type: "cursor_empty"
}
}
Example: Stripe API
API Behavior
Request:
GET /v1/customers?limit=100
GET /v1/customers?limit=100&starting_after=cus_abc123
Response:
{
"object": "list",
"data": [
{ "id": "cus_abc123", "email": "a@example.com" },
{ "id": "cus_def456", "email": "b@example.com" }
],
"has_more": true,
"url": "/v1/customers"
}
Configuration
{
type: "cursor",
params: {
cursorParam: "starting_after",
limitParam: "limit",
defaultLimit: 100
},
response: {
nextCursorPath: "data[-1].id",
hasMorePath: "has_more",
dataArrayPath: "data"
},
stopCondition: {
type: "boolean_flag",
flagPath: "has_more",
flagValue: false
}
}
Note: Stripe uses the last item's ID as the cursor, hence data[-1].id.
Example: Slack API
API Behavior
Request:
GET /users.list?limit=200
GET /users.list?limit=200&cursor=dXNlcjpVMDYxTkZUVDI=
Response:
{
"ok": true,
"members": [
{ "id": "U061NFTT2", "name": "alice" },
{ "id": "U061NFTT3", "name": "bob" }
],
"response_metadata": {
"next_cursor": "dXNlcjpVMDYxTkZUVDI="
}
}
Configuration
{
type: "cursor",
params: {
cursorParam: "cursor",
limitParam: "limit",
defaultLimit: 200
},
response: {
nextCursorPath: "response_metadata.next_cursor",
dataArrayPath: "members"
},
stopCondition: {
type: "cursor_empty"
}
}
Common Cursor Parameter Names
| API | Parameter |
|---|---|
| Stripe | starting_after |
| Slack | cursor |
pagination_token | |
after | |
| Generic | cursor, next |
Stop Conditions for Cursor
Empty Cursor (Most Common)
Stop when cursor is null, empty string, or missing:
{
stopCondition: {
type: "cursor_empty"
}
}
Boolean Flag
Stop when a field equals a specific value:
{
stopCondition: {
type: "boolean_flag",
flagPath: "has_more",
flagValue: false
}
}
Troubleshooting
Cursor Not Changing
Symptoms: Same data retrieved repeatedly
Check:
- Cursor path is correct
- Cursor is being sent in requests
- API is receiving cursor parameter
Pagination Stops Early
Symptoms: Missing data
Check:
- Stop condition not triggering prematurely
- Cursor path returns actual cursor value
has_morepath is correct
Infinite Loop
Symptoms: Pagination never stops
Check:
- Stop condition is configured
- Cursor eventually becomes empty/null
- Compare API docs for expected behavior