Create a lead extraction campaign
curl --request POST \
--url https://api.sendpilot.ai/v1/lead-extractor/campaigns \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "<string>",
"urls": [
"<string>"
],
"limit": 2,
"sender_id": "sender_123",
"webhook_url": "https://my-app.example.com/webhooks/sendpilot"
}
'import requests
url = "https://api.sendpilot.ai/v1/lead-extractor/campaigns"
payload = {
"name": "<string>",
"urls": ["<string>"],
"limit": 2,
"sender_id": "sender_123",
"webhook_url": "https://my-app.example.com/webhooks/sendpilot"
}
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({
name: '<string>',
urls: ['<string>'],
limit: 2,
sender_id: 'sender_123',
webhook_url: 'https://my-app.example.com/webhooks/sendpilot'
})
};
fetch('https://api.sendpilot.ai/v1/lead-extractor/campaigns', 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.sendpilot.ai/v1/lead-extractor/campaigns",
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([
'name' => '<string>',
'urls' => [
'<string>'
],
'limit' => 2,
'sender_id' => 'sender_123',
'webhook_url' => 'https://my-app.example.com/webhooks/sendpilot'
]),
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.sendpilot.ai/v1/lead-extractor/campaigns"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"urls\": [\n \"<string>\"\n ],\n \"limit\": 2,\n \"sender_id\": \"sender_123\",\n \"webhook_url\": \"https://my-app.example.com/webhooks/sendpilot\"\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.sendpilot.ai/v1/lead-extractor/campaigns")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"urls\": [\n \"<string>\"\n ],\n \"limit\": 2,\n \"sender_id\": \"sender_123\",\n \"webhook_url\": \"https://my-app.example.com/webhooks/sendpilot\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sendpilot.ai/v1/lead-extractor/campaigns")
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 \"name\": \"<string>\",\n \"urls\": [\n \"<string>\"\n ],\n \"limit\": 2,\n \"sender_id\": \"sender_123\",\n \"webhook_url\": \"https://my-app.example.com/webhooks/sendpilot\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"name": "<string>",
"status": "<string>",
"created_at": "<string>",
"estimated_credits": 123
}Lead Extractor
Start Lead Extraction
Start an extraction job from LinkedIn or Sales Navigator search URLs.
POST
/
v1
/
lead-extractor
/
campaigns
Create a lead extraction campaign
curl --request POST \
--url https://api.sendpilot.ai/v1/lead-extractor/campaigns \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "<string>",
"urls": [
"<string>"
],
"limit": 2,
"sender_id": "sender_123",
"webhook_url": "https://my-app.example.com/webhooks/sendpilot"
}
'import requests
url = "https://api.sendpilot.ai/v1/lead-extractor/campaigns"
payload = {
"name": "<string>",
"urls": ["<string>"],
"limit": 2,
"sender_id": "sender_123",
"webhook_url": "https://my-app.example.com/webhooks/sendpilot"
}
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({
name: '<string>',
urls: ['<string>'],
limit: 2,
sender_id: 'sender_123',
webhook_url: 'https://my-app.example.com/webhooks/sendpilot'
})
};
fetch('https://api.sendpilot.ai/v1/lead-extractor/campaigns', 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.sendpilot.ai/v1/lead-extractor/campaigns",
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([
'name' => '<string>',
'urls' => [
'<string>'
],
'limit' => 2,
'sender_id' => 'sender_123',
'webhook_url' => 'https://my-app.example.com/webhooks/sendpilot'
]),
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.sendpilot.ai/v1/lead-extractor/campaigns"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"urls\": [\n \"<string>\"\n ],\n \"limit\": 2,\n \"sender_id\": \"sender_123\",\n \"webhook_url\": \"https://my-app.example.com/webhooks/sendpilot\"\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.sendpilot.ai/v1/lead-extractor/campaigns")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"urls\": [\n \"<string>\"\n ],\n \"limit\": 2,\n \"sender_id\": \"sender_123\",\n \"webhook_url\": \"https://my-app.example.com/webhooks/sendpilot\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sendpilot.ai/v1/lead-extractor/campaigns")
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 \"name\": \"<string>\",\n \"urls\": [\n \"<string>\"\n ],\n \"limit\": 2,\n \"sender_id\": \"sender_123\",\n \"webhook_url\": \"https://my-app.example.com/webhooks/sendpilot\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"name": "<string>",
"status": "<string>",
"created_at": "<string>",
"estimated_credits": 123
}Requires
Use an Idempotency-Key to avoid duplicate paid jobs on retries. An identical request (same URLs,
lead_sourcing:run and the creator’s ALLOW_LEAD_EXTRACTION workspace permission. Supply name, HTTPS search urls, url_type, mode, limit, and sender_id.
url_type:linkedin_searchorsales_navigator.mode:extraction_onlyorwith_enrichment.limit: at least 1; REST is capped by available credits rather than MCP’s separate 2,000-lead tool maximum.sender_id: the LinkedIn account the extraction runs on. Use anidfrom List Senders or asenderIdfrom Sender Quotas. The account must belong to the workspace and be active. To spread extractions across accounts, pass a differentsender_idper request.webhook_url: optional public HTTPS completion destination.
id identifies the extraction job. Despite the URL’s campaigns segment, this does not create an outreach sequence. Poll job status, then read its leads.
Sender errors, returned before any credits are reserved:
| Status | code | Meaning |
|---|---|---|
| 400 | — | sender_id is missing or empty. |
| 404 | SENDER_NOT_FOUND | No sender with that id in this workspace. |
| 400 | SENDER_NOT_ACTIVE | The sender exists but is paused, disconnected or otherwise not active; the message includes its current status. |
| 400 | NO_LINKEDIN_ACCOUNT | The sender has no connected LinkedIn account. |
url_type, mode and limit) within about two minutes of another returns 409 DUPLICATE_CAMPAIGN_REQUEST with the original job’s campaign_id, even if it names a different sender_id.Authorizations
API key for authentication (prefix: sp_live_ or sp_test_)
Body
application/json
Campaign name
Search URLs (LinkedIn or Sales Navigator). Must be HTTPS.
Type of URLs provided
Available options:
linkedin_search, sales_navigator Extraction mode
Available options:
extraction_only, with_enrichment Maximum leads to extract (no hard limit - capped by available credits)
Required range:
x >= 1ID of the LinkedIn account (sender) to run the extraction on. Get it from GET /v1/senders/quotas or GET /v1/inbox/senders.
Example:
"sender_123"
HTTPS URL to receive a completion notification. Must be a public host.
Example:
"https://my-app.example.com/webhooks/sendpilot"