Learn how to paginate through list results using cursor-based pagination.
All filter endpoints in the MVMNT API use cursor-based pagination to efficiently retrieve large result sets. Pagination is consistent across all resource types (orders, vendors, carriers, customers, etc.).
Filter endpoints use POST requests with pagination parameters in the request body:
POST /v1/vendors/filter
Content-Type: application/json
{
"filter": { ... },
"pageSize": 50,
"cursor": null
}All paginated responses return a consistent structure:
{
"data": [
{ "id": "...", "name": "..." },
{ "id": "...", "name": "..." }
],
"pageInfo": {
"pageSize": 50,
"hasNextPage": true,
"hasPreviousPage": false,
"endCursor": "eyJpZCI6IjU1MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCJ9"
}
}Type: Integer Default: 50 Range: 1 - 250 Description: Number of results to return per page
{
"pageSize": 100
}Type: String (nullable) Default: null Description: Opaque cursor token from previous response's pageInfo.endCursor
{
"cursor": "eyJpZCI6IjU1MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCJ9"
}First page: Omit cursor or set to null Subsequent pages: Use endCursor from previous response
The pageInfo object in every response provides pagination metadata:
| Field | Type | Description |
|---|---|---|
pageSize | integer | Number of items in current page |
hasNextPage | boolean | Whether more results are available |
hasPreviousPage | boolean | Whether previous page exists |
endCursor | string | Cursor for next page (null if no next page) |
curl -X POST https://api.mvmnt.io/v1/vendors/filter \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"status": { "equalTo": "ACTIVE" }
},
"pageSize": 50
}'Response:
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"friendlyId": "V100001",
"name": "ABC Warehouse",
"status": "ACTIVE"
},
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"friendlyId": "V100002",
"name": "XYZ Storage",
"status": "ACTIVE"
}
// ... 48 more results
],
"pageInfo": {
"pageSize": 50,
"hasNextPage": true,
"hasPreviousPage": false,
"endCursor": "eyJpZCI6IjY2MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMSJ9"
}
}Use endCursor from the previous response:
curl -X POST https://api.mvmnt.io/v1/vendors/filter \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"status": { "equalTo": "ACTIVE" }
},
"pageSize": 50,
"cursor": "eyJpZCI6IjY2MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMSJ9"
}'When hasNextPage is false, you've reached the end:
{
"data": [
// ... remaining results
],
"pageInfo": {
"pageSize": 50,
"hasNextPage": false,
"hasPreviousPage": true,
"endCursor": null
}
}- Use maximum page size for batch processing: Set
pageSize: 250when fetching all results - Store cursor tokens temporarily: Only valid for the current query, don't persist long-term
- Handle hasNextPage correctly: Always check
hasNextPageinstead of checking if data is empty - Preserve filter criteria: Use identical filter on all pages of a query
- Implement retry logic: Network failures can occur during pagination
- Don't use offset-based pagination: MVMNT uses cursor-based pagination, not
pagenumbers - Don't modify filters mid-pagination: Using different filters with the same cursor produces undefined results
- Don't persist cursors: Cursors may expire or become invalid over time
- Don't assume page size matches result count: Last page may have fewer results
- Don't paginate unnecessarily: If you need all results, fetch them in one efficient loop
Problem: data array is empty but no error
Possible Causes:
- Filter criteria matches no records
- All matching records are deleted (see Soft Deletes)
Solutions:
- Verify filter criteria
- Check if records exist using less restrictive filters
- Include deleted records if needed (see Filtering)
Problem: API returns error: "Invalid cursor"
Possible Causes:
- Cursor from a different query (different filter/sort)
- Cursor expired (very old cursor)
- Malformed cursor string
Solutions:
- Always use cursor from the same filter query
- Don't persist cursors - start fresh queries with
cursor: null - Ensure cursor is passed as-is without modification
Problem: Same record appears in multiple pages
Possible Causes:
- Records were created/modified during pagination
- Using cursors from different queries
Solutions:
- Accept eventual consistency for real-time data
- Deduplicate results by ID on client side
- For consistent snapshots, consider using timestamps in filters
Problem: Receiving different number of results than requested
Possible Causes:
- Last page has fewer results
pageSizeexceeds maximum (250)- Some records filtered out after query
Solutions:
- Check
pageInfo.hasNextPageinstead of counting results - Ensure
pageSizeis between 1-250 - This behavior is normal and expected
- Filtering - Learn how to filter results before pagination
- Soft Deletes - Understand how deleted records affect pagination
- API Reference - See pagination on specific endpoints