curl --request GET \
--url https://api.naturalead.ai/api/leads \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.naturalead.ai/api/leads"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.naturalead.ai/api/leads', 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.naturalead.ai/api/leads",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"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"
"net/http"
"io"
)
func main() {
url := "https://api.naturalead.ai/api/leads"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.naturalead.ai/api/leads")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.naturalead.ai/api/leads")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body[
{
"id": 123,
"name": "<string>",
"phone": "<string>",
"email": "",
"status": "new",
"accountId": "<string>",
"source": "api",
"tags": [
"<string>"
],
"assignedAgentId": "<string>",
"abTestId": "<string>",
"agentAssignedBy": "auto",
"customFields": {},
"lastContactedAt": "2023-11-07T05:31:56Z",
"importBatchId": "<string>",
"externalId": "<string>",
"currentStage": {
"name": "<string>",
"index": 123,
"total": 123,
"conversationId": "<string>",
"conversationStatus": "<string>",
"agentConfigId": "<string>",
"agentName": "<string>"
},
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z"
}
]{
"error": "<string>"
}List Leads
Returns leads for the account.
Campaign preview mode — when statuses, tags, and/or channel
are provided, returns { leads, total } without pagination metadata.
List / sync mode — when page, limit, search, status,
sortBy, updatedAfter, and/or updatedBefore are provided, returns
a paginated { leads, total, page, limit } payload. Lead updatedAt
is bumped when conversation activity occurs, so
updatedAfter is suitable for incremental CRM sync waterfalls.
Without those query params, returns a plain array of all leads.
Requires leads:view permission.
curl --request GET \
--url https://api.naturalead.ai/api/leads \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.naturalead.ai/api/leads"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.naturalead.ai/api/leads', 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.naturalead.ai/api/leads",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"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"
"net/http"
"io"
)
func main() {
url := "https://api.naturalead.ai/api/leads"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.naturalead.ai/api/leads")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.naturalead.ai/api/leads")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body[
{
"id": 123,
"name": "<string>",
"phone": "<string>",
"email": "",
"status": "new",
"accountId": "<string>",
"source": "api",
"tags": [
"<string>"
],
"assignedAgentId": "<string>",
"abTestId": "<string>",
"agentAssignedBy": "auto",
"customFields": {},
"lastContactedAt": "2023-11-07T05:31:56Z",
"importBatchId": "<string>",
"externalId": "<string>",
"currentStage": {
"name": "<string>",
"index": 123,
"total": 123,
"conversationId": "<string>",
"conversationStatus": "<string>",
"agentConfigId": "<string>",
"agentName": "<string>"
},
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z"
}
]{
"error": "<string>"
}Authorizations
API key prefixed with nl_live_ or nl_test_
Query Parameters
Comma-separated outreach statuses to filter by (new, contacted)
"new,contacted"
Comma-separated list of tags to filter by
"vip,hot"
Channel to filter by
Page number (list / sync mode)
x >= 1Page size. Campaign preview mode default 50; list / sync mode default 25.
x <= 100Search name, phone, or email (list / sync mode)
Single outreach status filter (new or contacted)
Outreach I/O state for the lead — whether Naturalead has performed contact
yet. This is not journey position. Journey position lives on the
conversation as currentStage / currentStageName.
new, contacted Sort field (list / sync mode)
id, name, status, createdAt, updatedAt asc, desc Return only records with updatedAt strictly after this timestamp.
Accepts ISO 8601 (2026-06-01T00:00:00Z) or Unix epoch (seconds or
milliseconds). Use for incremental sync; lead updatedAt is also
bumped when related conversations change.
"2026-06-01T00:00:00Z"
Return only records with updatedAt strictly before this timestamp.
Same formats as updatedAfter.
"2026-07-01T00:00:00Z"
Response
Without filters: a plain array of leads. With list/preview filters: a paginated or preview object.
- object[]
- object
Sequential, account-scoped identifier
Unique per account
Outreach I/O state for the lead — whether Naturalead has performed contact
yet. This is not journey position. Journey position lives on the
conversation as currentStage / currentStageName.
new, contacted ObjectId reference to AgentConfig
ObjectId reference to AbTest
manual, ab_test, auto Key-value string map of custom fields
Show child attributes
Show child attributes
Present on list responses enriched with the latest conversation stage
Show child attributes
Show child attributes
Last modification time. Also bumped when related conversation
activity occurs, so incremental polls with updatedAfter see
conversation changes.