Pagination, filtering and sorting

List behavior is documented per endpoint. Some lists are paginated; others return every result in a single response.

ListsPagination
Jobs, applications, candidates, candidate notes, locations, pipeline templateslimit and cursor; response includes nextCursor
Contract types, employment types, remote regions, scorecardsAll matching records in one response

Fetch successive pages

On paginated endpoints, limit and cursor are URL query parameters. limit defaults to 10 and accepts 1–50. Omit cursor on your first request. For every later request, pass the previous response’s nextCursor unchanged, with the same filters and sort order. URL-encode the cursor rather than building the query by string concatenation.

curl --fail-with-body "https://api.join.com/v3/applications?jobId=4321&limit=50" \
  -H "Authorization: Bearer $JOIN_API_TOKEN" \
  -H "Join-Version: 2026-11-01"

For the next request, set JOIN_NEXT_CURSOR to the previous response’s nextCursor value. In the cURL example below, --get puts the --data-urlencode values in the URL query string, and --data-urlencode handles the encoding for you. The request remains a GET with no request body:

curl --fail-with-body --get "https://api.join.com/v3/applications" \
  -H "Authorization: Bearer $JOIN_API_TOKEN" \
  -H "Join-Version: 2026-11-01" \
  --data-urlencode "jobId=4321" \
  --data-urlencode "limit=50" \
  --data-urlencode "cursor=$JOIN_NEXT_CURSOR"

This produces a URL in the following form, with the cursor URL-encoded:

https://api.join.com/v3/applications?jobId=4321&limit=50&cursor=URL_ENCODED_CURSOR

URL_ENCODED_CURSOR is a placeholder. You can also put the query parameters directly in the URL, or use your HTTP client’s query-parameter option to encode the cursor for you.

Stop when nextCursor is null, including when data is empty. Cursors are opaque: do not decode, construct or reuse them for another query. If a cursor is invalid or expired, JOIN returns 400 cursor_invalid; restart the query and reconcile records by ID. Use nextCursor to determine when you have reached the end.

Filtering and ordering

Jobs, applications and candidates default to creation order, oldest first. Where supported, sort=createdAt selects that order and sort=-createdAt selects newest first. Other list endpoints document their fixed order.

Supplying q on the candidates list sorts results by relevance. Use sort only when browsing without q. Start with a fresh cursor when switching between browsing and searching.

Filters generally combine with AND. Multi-value filters document their own rules, such as repeated job statuses matching any supplied status. No matches is a successful empty list, not a 404.

For jobs, applications and candidates, createdAfter includes records at the timestamp and createdBefore selects records strictly before it. On jobs and applications, updatedAfter is also inclusive and updatedBefore is exclusive. Use the date filters listed for your endpoint. For periodic synchronization, reconcile overlapping results by ID and update time because multiple records can share a timestamp.