Appearance
Fresh 2026
Pagination ​
Cursor-based pagination for list endpoints. Covers the next/previous cursor fields in responses and how to page through large result sets.
Overview ​
Any data you interact with via the Merge API is able to be paginated. Pagination is specified via the cursor and page_size query parameters. Ensure that all query parameters, aside from cursor and page_size, remain consistent across pagination to maintain the integrity of your data retrieval. The next and previous cursors are attached to paginated API responses. Their values inform the cursor where to point to next.
Query parameters ​
| Parameter | Type | Description |
|---|---|---|
cursor | String | Denotes the starting position in the data list from where a paginated API endpoint should return bulk data. Get this value from the next or previous property of any previous paginated response. When next or previous is null there are no more pages to paginate through. |
page_size | Integer | Limit on number of objects to return per request. Defaults to 30, maximum of 100. |
Sample HTTP request ​
Below is an sample request using pagination in HTTP. The page_size is set to 20, and the cursor is pointing to a value for the next page.
GET /api/ats/candidates?page_size=20&cursor=cD0yMDIxLTA3LTI4KzE5JTNBMzglM0EzNi42NzUxNTMlMkIwMCUzQTAw
X-Account-Token: {Linked Account Token Here}
Authorization: Bearer {Production API Key Here}Getting the cursor ​
In the response payload of an API request to a paginated endpoint, you can find next and previous cursors.
json
{
"next": "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw",
"previous": null,
"results": [
{...},
{...},
{...}
]
}Using the cursor ​
These cursors can be attached to future requests to paginated API endpoints to query the next (or previous) page of results, as demonstrated in the following code sample using the Merge SDK:
python
# See SDK docs for configuration information
import merge
from merge.client import Merge
merge_client = Merge(api_key="", account_token="")
cursor = ""
while cursor != None:
try:
next_employees_page = merge_client.hris.employees.list(next=cursor)
pprint(next_employees_page)
cursor = next_employees_page.next
except Exception as e:
print("Exception when calling EmployeesApi->employees_list: %s" % e)ruby
MergeATSClient.configure do |config|
# See SDK docs for configuration information
end
x_account_token = 'END_USER_ACCOUNT_TOKEN'
api_instance = MergeATSClient::CandidatesApi.new
begin
cursor = ''
while cursor
result = api_instance.candidates_list(x_account_token, { cursor: cursor })
cursor = result._next
puts result
end
rescue MergeATSClient::ApiError => e
puts "Exception when calling CandidatesApi->candidates_list: #{e}"
endjavascript
const getEmployees = (cursor) => {
apiInstance.employeesList(xAccountToken, { cursor: cursor }, (error, data) => {
if (error) {
console.error(error);
} else {
console.log(data);
if (data.next) {
getEmployees(data.next);
}
}
});
};
getEmployees(null);java
import merge_ats_client.ApiClient;
import merge_ats_client.ApiException;
import merge_ats_client.Configuration;
import merge_ats_client.api.CandidatesApi;
import merge_ats_client.auth.ApiKeyAuth;
import merge_ats_client.model.PaginatedCandidateList;
public class MergePagination {
public void paginateViaSDK() {
MergeApiClient mergeClient = MergeApiClient.builder()
.accountToken("ACCOUNT_TOKEN")
.apiKey("API_KEY")
.build();
String cursor = "";
while(cursor != null) {
try {
Candidate candidate = mergeClient.ats().candidates().list(
RequestOptions.builder()
.accountToken("OVERRIDE_ACCOUNT_TOKEN")
.cursor(cursor)
.build());
cursor = candidate.getNext();
} catch (ApiException e) {
System.out.println("Exception when calling CandidatesApi->candidate_list:" + e);
break;
}
}
}
}If you don't want to use the Merge SDK and want to form your own API requests instead, you can do so as illustrated below:
python
import requests
endpoint_url = "https://api.merge.dev/api/hris/companies"
headers = {"Accept": "application/json", "Authorization": "Bearer YOUR_API_KEY", "X-Account-Token": "END_USER_ACCOUNT_TOKEN"}
response = requests.request("GET", endpoint_url, headers=headers)
print(response.json()["results"])
cursor = response.json()["next"]
while cursor:
page_url = f"{endpoint_url}?cursor={cursor}"
response = requests.request("GET", page_url, headers=headers)
print(response.json()["results"])
cursor = response.json()["next"]ruby
require 'httparty'
require 'json'
cursor = ''
url = 'https://api.merge.dev/api/hris/companies'
headers = {
'Authorization' => "Bearer YOUR_API_KEY",
'X-Account-Token' => 'END_USER_ACCOUNT_TOKEN'
'Accept' => 'application/json',
}
while cursor:
query = {
'cursor' => cursor,
}
response = HTTParty.get(url, query: query, headers: headers)
cursor = JSON.parse(request.body)["next"]
endjavascript
const axios = require("axios");
async function getEmployees(cursor) {
const response = await axios.get("https://api.merge.dev/api/hris/employees" + (cursor ? "?cursor=" + cursor : ""), {
headers: {
Authorization: "Bearer YOUR_API_KEY",
"X-Account-Token": "END_USER_ACCESS_TOKEN",
},
});
console.log(response.data);
if (response.data.next) {
getEmployees(response.data.next);
}
}java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ManualPagination {
public void printAllCandidates() {
try {
HttpClient client = HttpClient.newHttpClient();
String cursor = fetchCandidate(client, null);
while (cursor != null) {
cursor = fetchCandidate(client, cursor);
}
} catch (IOException ioException) {
System.out.println("IO Exception occurred during manual pagination fetch: " + ioException);
} catch (InterruptedException interruptedException) {
System.out.println("Interruption Exception occurred during manual pagination fetch: " + interruptedException);
}
}
private String fetchCandidate(HttpClient client, String cursor) throws IOException, InterruptedException {
String endpointUrl = "https://api.merge.dev/api/ats/candidates";
endpointUrl = cursor != null ? String.format("%s?cursor=%s", endpointUrl, cursor) : endpointUrl;
URI uri = URI.create(endpointUrl);
HttpRequest request = HttpRequest.newBuilder(uri)
.header("Accept", "application/json")
.header("Authorization", String.format("Bearer %s", "YOUR_API_KEY"))
.header("X-Account-Token", "END_USER_ACCOUNT_TOKEN")
.build();
HttpResponse candidateResult = client.send(request, HttpResponse.BodyHandlers.ofString());
ObjectNode parsableData = new ObjectMapper().readValue(candidateResult.body(), ObjectNode.class);
System.out.println(parsableData.get("results").textValue());
return parsableData.get("next").textValue();
}
}