curl --request POST \
--url https://api.parallellabs.app/api/v0/lead-searches/sales-navigator \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"searchMode": "url",
"searchUrl": "<string>",
"filters": {
"jobTitle": "<string>",
"location": "<string>",
"currentCompany": "<string>",
"school": "<string>",
"keywords": "<string>"
},
"maxResults": 50,
"companyId": "<string>"
}
'import requests
url = "https://api.parallellabs.app/api/v0/lead-searches/sales-navigator"
payload = {
"searchMode": "url",
"searchUrl": "<string>",
"filters": {
"jobTitle": "<string>",
"location": "<string>",
"currentCompany": "<string>",
"school": "<string>",
"keywords": "<string>"
},
"maxResults": 50,
"companyId": "<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({
searchMode: 'url',
searchUrl: '<string>',
filters: {
jobTitle: '<string>',
location: '<string>',
currentCompany: '<string>',
school: '<string>',
keywords: '<string>'
},
maxResults: 50,
companyId: '<string>'
})
};
fetch('https://api.parallellabs.app/api/v0/lead-searches/sales-navigator', 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/lead-searches/sales-navigator",
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([
'searchMode' => 'url',
'searchUrl' => '<string>',
'filters' => [
'jobTitle' => '<string>',
'location' => '<string>',
'currentCompany' => '<string>',
'school' => '<string>',
'keywords' => '<string>'
],
'maxResults' => 50,
'companyId' => '<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/lead-searches/sales-navigator"
payload := strings.NewReader("{\n \"searchMode\": \"url\",\n \"searchUrl\": \"<string>\",\n \"filters\": {\n \"jobTitle\": \"<string>\",\n \"location\": \"<string>\",\n \"currentCompany\": \"<string>\",\n \"school\": \"<string>\",\n \"keywords\": \"<string>\"\n },\n \"maxResults\": 50,\n \"companyId\": \"<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/lead-searches/sales-navigator")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"searchMode\": \"url\",\n \"searchUrl\": \"<string>\",\n \"filters\": {\n \"jobTitle\": \"<string>\",\n \"location\": \"<string>\",\n \"currentCompany\": \"<string>\",\n \"school\": \"<string>\",\n \"keywords\": \"<string>\"\n },\n \"maxResults\": 50,\n \"companyId\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.parallellabs.app/api/v0/lead-searches/sales-navigator")
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 \"searchMode\": \"url\",\n \"searchUrl\": \"<string>\",\n \"filters\": {\n \"jobTitle\": \"<string>\",\n \"location\": \"<string>\",\n \"currentCompany\": \"<string>\",\n \"school\": \"<string>\",\n \"keywords\": \"<string>\"\n },\n \"maxResults\": 50,\n \"companyId\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"status": "<string>",
"searchId": "<string>",
"dataCredits": 123,
"priorityFields": [
"<string>"
]
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}Start a Sales Navigator search. Returns immediately with a search id.
The search runs in the background — this does NOT return the leads. It
responds 202 with a searchId; poll GET /lead-searches/{searchId} until
its status is no longer “pending”, then read the leads from results.
A search takes minutes, because each matching profile is enriched
individually upstream.
Do not retry this endpoint while a search is pending. Every call starts
a new search and charges for it again; polling the id you already have is
free. If a call appears to time out, the search is still running — find it
in GET /lead-searches?source=sales_navigator rather than re-running it.
Nothing is written to a smart list: the caller reviews the results and adds
the ones it wants through POST /lists/{listId}/rows, which is what the
dashboard does once the user has picked rows.
The search is specified either by a Sales Navigator people-search URL
(searchMode “url”) or by structured filters — jobTitle, location,
currentCompany, school, keywords (searchMode “filters”). Each result is a
lead row (firstName, lastName, linkedinUrl, headline, positionTitle,
companyName, location, …) ready to be added to a list as-is.
No LinkedIn account or session cookie is required: the search is resolved from public profile data.
Costs 1 data credit per lead returned, charged when the search finishes — the same balance enrichment and People Search draw from. A search that matches nobody or fails is free, and principals with Audience Builder are not charged at all. Credits are checked against the requested ceiling before the search starts.
curl --request POST \
--url https://api.parallellabs.app/api/v0/lead-searches/sales-navigator \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"searchMode": "url",
"searchUrl": "<string>",
"filters": {
"jobTitle": "<string>",
"location": "<string>",
"currentCompany": "<string>",
"school": "<string>",
"keywords": "<string>"
},
"maxResults": 50,
"companyId": "<string>"
}
'import requests
url = "https://api.parallellabs.app/api/v0/lead-searches/sales-navigator"
payload = {
"searchMode": "url",
"searchUrl": "<string>",
"filters": {
"jobTitle": "<string>",
"location": "<string>",
"currentCompany": "<string>",
"school": "<string>",
"keywords": "<string>"
},
"maxResults": 50,
"companyId": "<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({
searchMode: 'url',
searchUrl: '<string>',
filters: {
jobTitle: '<string>',
location: '<string>',
currentCompany: '<string>',
school: '<string>',
keywords: '<string>'
},
maxResults: 50,
companyId: '<string>'
})
};
fetch('https://api.parallellabs.app/api/v0/lead-searches/sales-navigator', 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/lead-searches/sales-navigator",
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([
'searchMode' => 'url',
'searchUrl' => '<string>',
'filters' => [
'jobTitle' => '<string>',
'location' => '<string>',
'currentCompany' => '<string>',
'school' => '<string>',
'keywords' => '<string>'
],
'maxResults' => 50,
'companyId' => '<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/lead-searches/sales-navigator"
payload := strings.NewReader("{\n \"searchMode\": \"url\",\n \"searchUrl\": \"<string>\",\n \"filters\": {\n \"jobTitle\": \"<string>\",\n \"location\": \"<string>\",\n \"currentCompany\": \"<string>\",\n \"school\": \"<string>\",\n \"keywords\": \"<string>\"\n },\n \"maxResults\": 50,\n \"companyId\": \"<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/lead-searches/sales-navigator")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"searchMode\": \"url\",\n \"searchUrl\": \"<string>\",\n \"filters\": {\n \"jobTitle\": \"<string>\",\n \"location\": \"<string>\",\n \"currentCompany\": \"<string>\",\n \"school\": \"<string>\",\n \"keywords\": \"<string>\"\n },\n \"maxResults\": 50,\n \"companyId\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.parallellabs.app/api/v0/lead-searches/sales-navigator")
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 \"searchMode\": \"url\",\n \"searchUrl\": \"<string>\",\n \"filters\": {\n \"jobTitle\": \"<string>\",\n \"location\": \"<string>\",\n \"currentCompany\": \"<string>\",\n \"school\": \"<string>\",\n \"keywords\": \"<string>\"\n },\n \"maxResults\": 50,\n \"companyId\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"status": "<string>",
"searchId": "<string>",
"dataCredits": 123,
"priorityFields": [
"<string>"
]
}{
"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
Sales Navigator search to run
Request body for a Sales Navigator lead search. Either paste a Sales Navigator people-search URL (searchMode 'url') or supply structured filters (searchMode 'filters'). The search runs in the background: the response carries a searchId to poll, not the leads. Nothing is written to a smart list — once the search completes, add the leads you want with POST /lists/{listId}/rows. No LinkedIn account or session cookie is required. Costs 1 data credit per lead returned, charged when the search finishes — the same balance enrichment and People Search draw from; a search that matches nobody is free.
How the search is specified: 'url' to use searchUrl, 'filters' to use filters. Default: 'url'.
url, filters Full Sales Navigator people-search URL (a linkedin.com/sales/search/people… link). Required when searchMode is 'url'.
Structured search filters. Required when searchMode is 'filters' — at least one filter must be non-empty.
Show child attributes
Show child attributes
Maximum leads to return (1-500). Data credits are reserved against this ceiling but only the leads actually returned are charged. Default: 50.
Company ID that owns the list. Required when authenticating with a personal access key (pak_…) — the key is not tied to a specific company so the server cannot infer it. Required when authenticating with a company API key only if the key belongs to a user who has access to multiple companies; otherwise it defaults to the key's company. Optional for JWT (dashboard) auth — defaults to the user's active company.
Response
Search accepted — poll GET /lead-searches/{searchId} for results
A Sales Navigator search that has been accepted and is now running. The leads are NOT in this response: poll GET /lead-searches/{searchId} until its status is no longer 'pending', then read them from that response's results. Do not call the search endpoint again while a search is pending — each call runs and charges for a new search, while polling costs nothing.
Always 'pending' — the search has started and has not finished yet.
ID of the saved search. Poll GET /lead-searches/{searchId} with this to get the status and, once complete, the leads.
The billing principal's data credit balance. The search has not been charged yet — leads are charged when it finishes.
Field names to show first, in order, when rendering the results as a table.

