Overview
The Dev API currently uses two pagination models:- Cursor-based pagination for most resource lists
- Page-based pagination for operational lists where page navigation is clearer
- Cursor-Based
- Page-Based
Use cursor-based pagination for feed-style lists like products, invoices, orders, customers, and subscriptions.
Response:
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Number of items per page (1-100) |
cursor | string | - | Cursor from previous response |
Basic Usage
First Request
Next Page
Use thenext_cursor from the previous response:Final Page
When there are no more items:Code Examples
Fetch All Pages
Async Generator (Streaming)
TypeScript
Filtering with Pagination
Filters work alongside pagination:Cursor-Based Endpoints
| Endpoint | Default Limit | Max Limit |
|---|---|---|
GET /products | 50 | 100 |
GET /invoices | 50 | 100 |
GET /customers | 50 | 100 |
GET /coupons | 50 | 100 |
GET /subscriptions | 50 | 100 |
GET /reviews | 50 | 100 |
GET /tickets | 50 | 100 |
GET /webhooks | 50 | 100 |
GET /blacklist | 50 | 100 |
Best Practices
Use Reasonable Limits
Fetching for a UI? 20-25 items is plenty. Background sync job? Crank it to 100. Larger limits increase response time.
Don't Store Cursors
Cursors are meant for immediate sequential use. They expire after 24 hours and become invalid if the underlying data changes significantly.
Handle Empty Results
An empty
data array with has_more: false is valid - no items match your query.Respect Rate Limits
When fetching all pages, add delays between requests to avoid rate limiting.