Core Concepts
Pagination
2 min read
Renidly list endpoints use opaque cursors. Fetch the next page by sending back the cursor we returned — no offset math required.
First page
Call any list endpoint with an optional limit (default 25, max 100):
GET /api/v2/person/activities?handle=jane-doe&limit=25The response
{
"success": true,
"statusCode": 200,
"message": "Activities retrieved",
"errors": null,
"data": {
"items": [ /* page of results */ ],
"nextCursor": "eyJvZmZzZXQiOjI1fQ==",
"hasMore": true,
"count": 25
}
}Three fields drive pagination:
items— the page of records.nextCursor— opaque string. Pass it back on the next call as?cursor=….hasMore— boolean.falsemeans you've reached the end.
Subsequent pages
GET /api/v2/person/activities?handle=jane-doe&limit=25&cursor=eyJvZmZzZXQiOjI1fQ==Iterating safely
The canonical loop is a generator over pages until hasMore is false. Doing it this way means your worker only holds one page in memory at a time and naturally respects rate limits — you can't over-fetch.
async function* paginate(handle: string) {
let cursor: string | undefined;
do {
const url = new URL("https://renidly.com/api/v2/person/activities");
url.searchParams.set("handle", handle);
url.searchParams.set("limit", "50");
if (cursor) url.searchParams.set("cursor", cursor);
const body = await fetch(url, {
headers: { "X-renidly-apikey": process.env.RENIDLY_API_KEY! },
}).then(r => r.json());
if (!body.success) throw new Error(body.message);
yield body.data.items;
cursor = body.data.hasMore ? body.data.nextCursor : undefined;
} while (cursor);
}
for await (const page of paginate("jane-doe")) {
console.log(page.length);
}When to use start instead
A few legacy endpoints still accept an offset-style start parameter alongside cursor. New integrations should always use cursor — it survives schema changes and avoids the off-by-one problems offsets create when the underlying list shifts.