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.

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.

On this page