Skip to content
API v1 preview — endpoints and fields may change before general availability.

Pagination

How do I page through results with next_cursor?

View .md

Every list in the API is paged with an opaque cursor. Each page returns next_cursor. Send it back to get the next page. When next_cursor is null, you have the last page.

Endpoint Send the cursor as Page size
POST /v1/jobs/search cursor in the JSON body limit, 1 to 100, default 25
GET /v1/searches/{id} cursor query parameter limit, 1 to 100, default 100
GET /v1/watches cursor query parameter Set by the server
GET /v1/billing/ledger cursor query parameter Set by the server
GET /v1/events since query parameter limit, 1 to 100, default 100

Treat the cursor as an opaque string, for example cur_8fJ2kQ. Do not parse it or build one yourself.

For POST /v1/jobs/search, send the same body on every page and add cursor. Keep filters, waterfall and limit unchanged, so each page continues the same result set.

Terminal window
# Page 1
curl https://api.betterjobs.cc/v1/jobs/search \
-H "Authorization: Bearer $BETTERJOBS_API_KEY" \
-H "BetterJobs-Version: 2026-10-01" \
-H "Content-Type: application/json" \
-d '{
"filters": { "title_or": ["Head of RevOps"], "country_code_or": ["DE", "AT", "CH"], "posted_within_days": 7 },
"limit": 100
}'
# Page 2: same body plus the next_cursor from page 1
curl https://api.betterjobs.cc/v1/jobs/search \
-H "Authorization: Bearer $BETTERJOBS_API_KEY" \
-H "BetterJobs-Version: 2026-10-01" \
-H "Content-Type: application/json" \
-d '{
"filters": { "title_or": ["Head of RevOps"], "country_code_or": ["DE", "AT", "CH"], "posted_within_days": 7 },
"limit": 100,
"cursor": "cur_8fJ2kQ"
}'

Each page is billed like any search: 1 credit per unique job on that page that you have not paid for before. Jobs you already paid for, duplicates and empty pages are free. metadata.credits_charged on each page tells you what that page cost. See Credits and billing.

waterfall.max_credits caps one request, so it caps one page. To cap a whole run, bound the number of pages, as the examples above do, or add up metadata.credits_charged and stop at your budget.

A synchronous search returns at most 100 jobs per page. For a backfill or market sizing run, use an async search instead. It collects up to 10,000 jobs in the background, and reading its pages with GET /v1/searches/{id} is free.

GET /v1/events returns events oldest first. Store the next_cursor from the last page you processed, then pass it as since on your next call to resume where you stopped. Omit since to start from the oldest retained event. This makes the feed a reliable backup for missed webhooks. See Webhooks and Sync patterns.