curl --request POST \
--url https://api.parallellabs.app/api/v0/leads/people-search \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"companyId": "<string>",
"filters": {},
"query": "<string>",
"page": 1,
"pageSize": 25,
"cursor": "<string>"
}
'import requests
url = "https://api.parallellabs.app/api/v0/leads/people-search"
payload = {
"companyId": "<string>",
"filters": {},
"query": "<string>",
"page": 1,
"pageSize": 25,
"cursor": "<string>"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
companyId: '<string>',
filters: {},
query: '<string>',
page: 1,
pageSize: 25,
cursor: '<string>'
})
};
fetch('https://api.parallellabs.app/api/v0/leads/people-search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.parallellabs.app/api/v0/leads/people-search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'companyId' => '<string>',
'filters' => [
],
'query' => '<string>',
'page' => 1,
'pageSize' => 25,
'cursor' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.parallellabs.app/api/v0/leads/people-search"
payload := strings.NewReader("{\n \"companyId\": \"<string>\",\n \"filters\": {},\n \"query\": \"<string>\",\n \"page\": 1,\n \"pageSize\": 25,\n \"cursor\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.parallellabs.app/api/v0/leads/people-search")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"companyId\": \"<string>\",\n \"filters\": {},\n \"query\": \"<string>\",\n \"page\": 1,\n \"pageSize\": 25,\n \"cursor\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.parallellabs.app/api/v0/leads/people-search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"companyId\": \"<string>\",\n \"filters\": {},\n \"query\": \"<string>\",\n \"page\": 1,\n \"pageSize\": 25,\n \"cursor\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"items": [
{}
],
"total": 123,
"page": 123,
"pageSize": 123,
"creditCost": 123,
"nextCursor": "<string>",
"filters": {}
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}Search the professional people database by filters or a plain-language description.
Send either query (AI search, below) or filters. For filters, get
field names and enum values from leads_listFieldOptions first; at least
one positive filter is required (exclusions alone are rejected).
Returns basic profiles (name, title, company, location, linkedinUrl) plus
the total match count — no emails or phones. To page, send the same
filters, companyId and pageSize with page+1 and the previous nextCursor;
nextCursor null means the last page. Free: searching requires at least 1
data credit or remaining data-credit window capacity but never spends it.
To get contact details, import the results into a smart list or export
them.
AI search: send query (a description such as “engineers in New York at
software companies with more than 500 employees”) instead of filters — no
leads_listFieldOptions call needed. AI picks the filters (using AI
credits), the search runs, and the response’s filters shows what was
searched — page on with those filters and nextCursor.
curl --request POST \
--url https://api.parallellabs.app/api/v0/leads/people-search \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"companyId": "<string>",
"filters": {},
"query": "<string>",
"page": 1,
"pageSize": 25,
"cursor": "<string>"
}
'import requests
url = "https://api.parallellabs.app/api/v0/leads/people-search"
payload = {
"companyId": "<string>",
"filters": {},
"query": "<string>",
"page": 1,
"pageSize": 25,
"cursor": "<string>"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
companyId: '<string>',
filters: {},
query: '<string>',
page: 1,
pageSize: 25,
cursor: '<string>'
})
};
fetch('https://api.parallellabs.app/api/v0/leads/people-search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.parallellabs.app/api/v0/leads/people-search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'companyId' => '<string>',
'filters' => [
],
'query' => '<string>',
'page' => 1,
'pageSize' => 25,
'cursor' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.parallellabs.app/api/v0/leads/people-search"
payload := strings.NewReader("{\n \"companyId\": \"<string>\",\n \"filters\": {},\n \"query\": \"<string>\",\n \"page\": 1,\n \"pageSize\": 25,\n \"cursor\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.parallellabs.app/api/v0/leads/people-search")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"companyId\": \"<string>\",\n \"filters\": {},\n \"query\": \"<string>\",\n \"page\": 1,\n \"pageSize\": 25,\n \"cursor\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.parallellabs.app/api/v0/leads/people-search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"companyId\": \"<string>\",\n \"filters\": {},\n \"query\": \"<string>\",\n \"page\": 1,\n \"pageSize\": 25,\n \"cursor\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"items": [
{}
],
"total": 123,
"page": 123,
"pageSize": 123,
"creditCost": 123,
"nextCursor": "<string>",
"filters": {}
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}Authorizations
Company API key - scoped to a specific company. Generate from the Integrations page in your dashboard.
Body
Company ID for access and any applicable data-credit charges
Person and company filters keyed by the camelCase field names from leads_listFieldOptions, e.g. {"title": ["Head of Marketing"], "seniority": ["Director"], "companyDomain": ["acme.com"], "employeeRange": ["51-200"], "country": ["US"]}. Text and enum filters take a list of values (any value matches); different filters must all match. Enum values must come from leads_listFieldOptions; countries are two-letter codes. Number filters take a single number. At least one positive (non-exclude) filter is required. Send filters or query, not both.
AI search: a plain-language description of the people to find, e.g. "engineers in New York at software companies with more than 500 employees". Turned into filters by AI (uses AI credits), then searched. Page 1 only; the response returns the filters used, so request later pages with those filters and nextCursor.
1-based page number. Page 1 needs no cursor; later pages need the previous response's nextCursor.
Results per page: 5, 10, 25, 50. Default: 25.
nextCursor from the previous response. Required for page > 1; keep filters, companyId and pageSize unchanged.
Response
Paginated people database matches
Matching people: name, title, company, location, linkedinUrl and other profile fields, as text. No emails or phones. Pass items back unchanged as rows to import or export them.
Total people matching the filters
Always zero; people search is free. Importing costs one data credit per record and enriches emails.
Continuation cursor; null means the end of the results
The normalized filters that were searched. For an AI search, these are the filters it chose; send them with nextCursor for later pages.

