Pagination
Every list endpoint takes the same two parameters:
| Parameter | Default | Max |
|---|---|---|
page |
1 | — |
limit |
25 | 100 |
And returns the same envelope alongside its items:
{
"templates": [ ... ],
"page": 1,
"limit": 25,
"total": 63,
"totalPage": 3,
"hasMore": true
}
Loop on hasMore rather than comparing page to totalPage yourself:
let page = 1;
const all = [];
for (;;) {
const { data } = await mailstein.templates.list({ page, limit: 100 });
all.push(...data.templates);
if (!data.hasMore) break;
page++;
}
Cursors, for one endpoint
GET /v1/webhooks/{id}/attempts is cursor-paginated instead:
{ "attempts": [ ... ], "nextCursor": "cmsm9pt1b0017vseua7veqnqi" }
Pass it back as ?cursor=. nextCursor is null at the end.
The difference is not an oversight. Delivery attempts arrive continuously, so page 2 of a page-numbered list describes different rows every time you ask — you would see some twice and miss others. A cursor keeps its place while the list grows underneath it.
The same is true of anything else that grows quickly, so expect more endpoints to move to cursors rather than fewer.
Something here wrong or missing? It is generated from the running API —
tell us and we will fix the source.