OpenAPI: Cursor-Based Pagination
Document cursor-based pagination for API endpoints. Covers cursor parameters, page size limits, response metadata with next/previous cursors, and hasMore flags.
Detailed Explanation
Documenting Cursor-Based Pagination in OpenAPI
Cursor-based pagination provides stable pagination that does not break when data is inserted or deleted. It is the preferred approach for high-volume APIs (used by Twitter, Stripe, Slack, and GitHub).
Query Parameters
parameters:
- name: cursor
in: query
schema:
type: string
description: Opaque cursor from the previous response's nextCursor field
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
description: Number of items per page (max 100)
Paginated Response Schema
components:
schemas:
PaginatedUsers:
type: object
required:
- data
- pagination
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
pagination:
type: object
required:
- hasMore
properties:
nextCursor:
type: string
description: Cursor for fetching the next page
previousCursor:
type: string
description: Cursor for fetching the previous page
hasMore:
type: boolean
description: Whether more results exist
totalCount:
type: integer
description: Total number of items (optional, may be expensive)
How Cursors Work
A cursor is typically a Base64-encoded identifier (like the last item's ID or a timestamp). Clients pass the cursor from one response to the next request. This approach avoids the "offset skip" problem where traditional offset pagination becomes slow on large datasets.
Comparison with Offset Pagination
| Feature | Cursor | Offset |
|---|---|---|
| Performance on large datasets | Consistent | Degrades |
| Stable with data changes | Yes | No (items shift) |
| Jump to arbitrary page | No | Yes |
| Implementation complexity | Higher | Lower |
Cursor pagination is better for feeds, activity logs, and any dataset that changes frequently. Offset pagination is simpler for small, static datasets.
Use Case
Designing a social media feed, activity stream, transaction history, or any API endpoint that returns large, frequently-updated collections where stable, performant pagination is critical.