Pagination
Offset-based pagination, response envelope, and how to iterate through pages.
List endpoints use offset-based pagination. Two query parameters drive it, and every paginated response carries the same envelope so you can iterate without endpoint-specific logic.
Query parameters
| Parameter | Type | Default | Bounds |
|---|---|---|---|
limit | integer | 20 | 1–1000 |
offset | integer | 0 | ≥ 0 |
Note: Merchant list endpoints such as transactions, invoices, customers, emails, and payment-methods allow
limitup to1000. A few endpoints differ — most notablyGET /v2/usage(default100, max500),GET /v2/billing(default50, max100), andGET /v2/autoprocessing-forecast(max100). Always check the per-operation schema in the OpenAPI spec for the authoritative bounds.
Response envelope
{
"data": [ /* items */ ],
"pagination": {
"limit": 20,
"offset": 0,
"hasMore": true,
"nextOffset": 20,
"prevOffset": null
}
}| Field | Type | Description |
|---|---|---|
limit | integer | Page size used for this response. |
offset | integer | Current offset. |
hasMore | boolean | Whether more results exist beyond this page. |
nextOffset | integer | null | Offset to fetch the next page, or null if this is the last page. |
prevOffset | integer | null | Offset for the previous page, or null if this is the first page. |
Many merchant list endpoints also include pagination.total (count of matching items across all pages):
GET /v2/invoicesGET /v2/customersGET /v2/payment-methodsGET /v2/transactionsGET /v2/emailsGET /v2/usersGET /v2/autoprocessing-forecast
Per-operation schemas in the OpenAPI spec are authoritative.
Example: first page
GET https://api.benjipays.com/v2/transactions?limit=20&offset=0
x-api-key: YOUR_API_KEY{
"data": [
{ "id": "txn_abc123", "status": "approved" }
],
"pagination": {
"total": 150,
"limit": 20,
"offset": 0,
"hasMore": true,
"nextOffset": 20,
"prevOffset": null
}
}Example: next page
GET https://api.benjipays.com/v2/transactions?limit=20&offset=20
x-api-key: YOUR_API_KEY{
"data": [ /* ... 20 items starting from offset 20 */ ],
"pagination": {
"total": 150,
"limit": 20,
"offset": 20,
"hasMore": true,
"nextOffset": 40,
"prevOffset": 0
}
}Example: last page
{
"data": [ /* ... remaining items (less than `limit`) */ ],
"pagination": {
"total": 150,
"limit": 20,
"offset": 140,
"hasMore": false,
"nextOffset": null,
"prevOffset": 120
}
}Iterating through all pages
async function fetchAllTransactions(apiKey) {
const all = [];
let offset = 0;
const limit = 20;
let hasMore = true;
while (hasMore) {
const response = await fetch(
`https://api.benjipays.com/v2/transactions?limit=${limit}&offset=${offset}`,
{ headers: { 'x-api-key': apiKey } }
);
const body = await response.json();
all.push(...body.data);
hasMore = body.pagination.hasMore;
offset = body.pagination.nextOffset ?? offset + limit;
}
return all;
}Best practices
- Use
hasMoreto decide whether to fetch another page; don't infer it fromdata.length. - Use
nextOffsetfrom the response rather than recomputing it. - Pick a
limitclose to your actual rendering / processing batch size. - Respect rate limits when iterating — pace your requests so you don't burst through your quota.
- An empty
dataarray withhasMore: falseis the end of the list, not an error.
Updated 25 days ago
