Pagination
How Subscriby list endpoints return data and how to iterate over large result sets.
Every list endpoint returns a data array wrapped in a meta + links envelope. Pagination is page-based, capped at 100 rows per request.
Response shape
{
"data": [
{ "id": "prj_...", "name": "Research Premium" },
{ "id": "prj_...", "name": "Weekend Studio" }
],
"links": {
"first": "https://api.subscriby.net/v1/projects?page=1",
"last": "https://api.subscriby.net/v1/projects?page=4",
"prev": null,
"next": "https://api.subscriby.net/v1/projects?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 4,
"per_page": 25,
"to": 25,
"total": 92
}
}data is ordered by created_at descending (newest first) on every collection endpoint.
The per_page and page parameters
Every collection endpoint accepts:
per_page— number of rows in the response (default25, max100).limitis accepted as an alias on every list that once documented it.page— 1-based page index (default1).
curl "https://api.subscriby.net/v1/projects?per_page=50&page=2" \
-H "Authorization: Bearer sbt_live_..."If per_page is omitted, endpoint-specific defaults apply:
| Endpoint | Default per_page | Notes |
|---|---|---|
GET /v1/projects | 25 | |
GET /v1/projects/{project}/plans | 25 | |
GET /v1/projects/{project}/resources | 25 | |
GET /v1/projects/{project}/members | 25 | Accepts a status filter. |
GET /v1/projects/{project}/payment-methods | 25 | |
GET /v1/projects/{project}/plans/{plan}/access-codes | 50 | Accepts a status filter (unredeemed / redeemed / expired). |
GET /v1/subscriptions | 25 | Accepts status and plan_id filters. |
GET /v1/groups | 25 | |
GET /v1/roles | 25 | |
GET /v1/tokens | 25 | |
GET /v1/webhook-endpoints | 25 | |
GET /v1/webhook-events | 3 (max 10) | Used primarily by the Zapier "sample" UX. |
Requesting per_page above the cap (100) clamps to the maximum silently.
Requesting a page past the last page returns an empty data array with
meta.total still populated, so a polling loop can detect the end without
guessing.
Iterating across pages
async function fetchAllProjects(token: string) {
const all = [];
let page = 1;
while (true) {
const url = `https://api.subscriby.net/v1/projects?per_page=100&page=${page}`;
const res = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
const body = await res.json();
all.push(...body.data);
if (body.meta.current_page >= body.meta.last_page) break;
page += 1;
}
return all;
}For very large historical pulls (years of payment / subscription history) prefer streaming over webhooks instead of polling — see Webhook endpoints.
Filtering before paginating
Combine per_page with the resource-specific filters to avoid pagination loops on large tenants:
curl "https://api.subscriby.net/v1/subscriptions?status=active&per_page=100" \
-H "Authorization: Bearer sbt_live_..."Cursor pagination
The REST API does not expose cursors today. The one exception is the MCP list_transactions tool, which uses keyset pagination internally because creators routinely query entire years of payment history. REST callers that need the same data should filter by date range or use MCP directly.
Related
- Rate limiting — how hard you can poll.
- Webhook endpoints — streaming alternative to polling.
How is this guide?