Pagination
Page through large result sets with cursors, offsets, or page numbers.
A single POST /v1/jobs/search returns at most your plan's page size: Free 25, Builder and Growth 100, Scale and Business 500. To retrieve more, paginate.
Cursor pagination (recommended)
Each response includes metadata.next_cursor. Pass it back as cursor to get the next page. When next_cursor is null, you've reached the end.
The request also accepts the cursor as next_cursor. A null cursor is treated as no cursor.
import requests
URL = "https://api.jobspipe.dev/v1/jobs/search"
HEADERS = {"Authorization": "Bearer jp_live_your_key_here"}
cursor, all_jobs = None, []
while True:
body = {"job_title_or": ["software engineer"], "limit": 100}
if cursor:
body["cursor"] = cursor
page = requests.post(URL, headers=HEADERS, json=body).json()
all_jobs.extend(page["data"])
cursor = page["metadata"].get("next_cursor")
if not cursor:
break
print(f"fetched {len(all_jobs)} jobs")const URL = "https://api.jobspipe.dev/v1/jobs/search";
const headers = {
Authorization: "Bearer jp_live_your_key_here",
"Content-Type": "application/json",
};
let cursor = null;
const all = [];
do {
const body = { job_title_or: ["software engineer"], limit: 100 };
if (cursor) body.cursor = cursor;
const page = await fetch(URL, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then((r) => r.json());
all.push(...page.data);
cursor = page.metadata.next_cursor;
} while (cursor);
console.log(`fetched ${all.length} jobs`);Offset & page pagination
If you prefer numeric paging, use offset (results to skip) or page (page index) instead of cursor:
{ "job_title_or": ["software engineer"], "limit": 100, "offset": 100 }Prefer cursors for large result sets: offsets shift as new jobs arrive.
Total counts
metadata.total_results is null unless you set include_total_results: true. Counting makes the request slightly slower.
Ordering
Results come back newest first, by posted date. The order is fixed, which keeps the cursor stable. order_by accepts only that order:
{ "order_by": [{ "field": "posted_at", "desc": true }] }date_posted is accepted as a synonym for posted_at, and omitting desc means newest first.
Any other order (ascending, a second sort key, or another field such as discovered_at) is rejected with 400. Sort client-side, or narrow with posted_at_gte / posted_at_lte.