The official @trackserps/sdk client includes built-in async iterators for automatic pagination. You do not need to manually parse or pass cursors:
SDK Async Pagination
import { TrackSERPs } from "@trackserps/sdk";
const client = new TrackSERPs({ apiKey: "ts_live_..." });
// Method 1: Async iterator (iterates across all pages automatically)
for await (const keyword of client.keywords.list("proj_abc123")) {
console.log(keyword.phrase, keyword.devices);
}
// Method 2: Fetch all items directly with .all()
const allProjects = await client.projects.list().all();
console.log(`Loaded ${allProjects.length} total projects across all pages`);
// Method 3: Page-by-page iteration
for await (const page of client.projects.list().pages()) {
console.log(`Page returned ${page.projects.length} projects. Next cursor: ${page.next_cursor}`);
}
Manual Pagination Example (Vanilla Fetch)
If you are consuming the raw REST API directly, pass next_cursor into subsequent requests as ?cursor=:
Manual Cursor Loop
async function fetchAllKeywords(projectId, apiKey) {
let cursor = null;
const allKeywords = [];
do {
const url = new URL(`https://api.trackserps.com/v1/projects/${projectId}/keywords`);
url.searchParams.set("limit", "100");
if (cursor) {
url.searchParams.set("cursor", cursor);
}
const response = await fetch(url.toString(), {
headers: {
Authorization: `Bearer ${apiKey}`,
Accept: "application/json",
},
});
if (!response.ok) {
throw new Error(`Failed to fetch keywords: ${response.statusText}`);
}
const data = await response.json();
allKeywords.push(...data.keywords);
cursor = data.next_cursor; // null on the final page
} while (cursor);
return allKeywords;
}