Add leads to campaign
curl --request POST \
--url https://api.sendpilot.ai/v1/leads \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"campaignId": "cmobr5lei0000u1h02ezf5itt",
"leads": [
{
"linkedinUrl": "https://www.linkedin.com/in/johndoe/",
"firstName": "John",
"lastName": "Doe",
"company": "Acme Corp",
"title": "VP of Engineering",
"industry": "SaaS",
"region": "EMEA"
}
]
}
'import requests
url = "https://api.sendpilot.ai/v1/leads"
payload = {
"campaignId": "cmobr5lei0000u1h02ezf5itt",
"leads": [
{
"linkedinUrl": "https://www.linkedin.com/in/johndoe/",
"firstName": "John",
"lastName": "Doe",
"company": "Acme Corp",
"title": "VP of Engineering",
"industry": "SaaS",
"region": "EMEA"
}
]
}
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({
campaignId: 'cmobr5lei0000u1h02ezf5itt',
leads: [
{
linkedinUrl: 'https://www.linkedin.com/in/johndoe/',
firstName: 'John',
lastName: 'Doe',
company: 'Acme Corp',
title: 'VP of Engineering',
industry: 'SaaS',
region: 'EMEA'
}
]
})
};
fetch('https://api.sendpilot.ai/v1/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.sendpilot.ai/v1/leads",
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([
'campaignId' => 'cmobr5lei0000u1h02ezf5itt',
'leads' => [
[
'linkedinUrl' => 'https://www.linkedin.com/in/johndoe/',
'firstName' => 'John',
'lastName' => 'Doe',
'company' => 'Acme Corp',
'title' => 'VP of Engineering',
'industry' => 'SaaS',
'region' => 'EMEA'
]
]
]),
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/leads"
payload := strings.NewReader("{\n \"campaignId\": \"cmobr5lei0000u1h02ezf5itt\",\n \"leads\": [\n {\n \"linkedinUrl\": \"https://www.linkedin.com/in/johndoe/\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"company\": \"Acme Corp\",\n \"title\": \"VP of Engineering\",\n \"industry\": \"SaaS\",\n \"region\": \"EMEA\"\n }\n ]\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/leads")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"campaignId\": \"cmobr5lei0000u1h02ezf5itt\",\n \"leads\": [\n {\n \"linkedinUrl\": \"https://www.linkedin.com/in/johndoe/\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"company\": \"Acme Corp\",\n \"title\": \"VP of Engineering\",\n \"industry\": \"SaaS\",\n \"region\": \"EMEA\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sendpilot.ai/v1/leads")
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 \"campaignId\": \"cmobr5lei0000u1h02ezf5itt\",\n \"leads\": [\n {\n \"linkedinUrl\": \"https://www.linkedin.com/in/johndoe/\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"company\": \"Acme Corp\",\n \"title\": \"VP of Engineering\",\n \"industry\": \"SaaS\",\n \"region\": \"EMEA\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"leadsAdded": 10,
"duplicatesSkipped": 2,
"invalidEntries": 0,
"errors": [
{}
]
}Leads
Add Leads
Import 1–1,000 profiles into an existing campaign, with duplicate and validation results.
POST
/
v1
/
leads
Add leads to campaign
curl --request POST \
--url https://api.sendpilot.ai/v1/leads \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"campaignId": "cmobr5lei0000u1h02ezf5itt",
"leads": [
{
"linkedinUrl": "https://www.linkedin.com/in/johndoe/",
"firstName": "John",
"lastName": "Doe",
"company": "Acme Corp",
"title": "VP of Engineering",
"industry": "SaaS",
"region": "EMEA"
}
]
}
'import requests
url = "https://api.sendpilot.ai/v1/leads"
payload = {
"campaignId": "cmobr5lei0000u1h02ezf5itt",
"leads": [
{
"linkedinUrl": "https://www.linkedin.com/in/johndoe/",
"firstName": "John",
"lastName": "Doe",
"company": "Acme Corp",
"title": "VP of Engineering",
"industry": "SaaS",
"region": "EMEA"
}
]
}
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({
campaignId: 'cmobr5lei0000u1h02ezf5itt',
leads: [
{
linkedinUrl: 'https://www.linkedin.com/in/johndoe/',
firstName: 'John',
lastName: 'Doe',
company: 'Acme Corp',
title: 'VP of Engineering',
industry: 'SaaS',
region: 'EMEA'
}
]
})
};
fetch('https://api.sendpilot.ai/v1/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.sendpilot.ai/v1/leads",
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([
'campaignId' => 'cmobr5lei0000u1h02ezf5itt',
'leads' => [
[
'linkedinUrl' => 'https://www.linkedin.com/in/johndoe/',
'firstName' => 'John',
'lastName' => 'Doe',
'company' => 'Acme Corp',
'title' => 'VP of Engineering',
'industry' => 'SaaS',
'region' => 'EMEA'
]
]
]),
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/leads"
payload := strings.NewReader("{\n \"campaignId\": \"cmobr5lei0000u1h02ezf5itt\",\n \"leads\": [\n {\n \"linkedinUrl\": \"https://www.linkedin.com/in/johndoe/\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"company\": \"Acme Corp\",\n \"title\": \"VP of Engineering\",\n \"industry\": \"SaaS\",\n \"region\": \"EMEA\"\n }\n ]\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/leads")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"campaignId\": \"cmobr5lei0000u1h02ezf5itt\",\n \"leads\": [\n {\n \"linkedinUrl\": \"https://www.linkedin.com/in/johndoe/\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"company\": \"Acme Corp\",\n \"title\": \"VP of Engineering\",\n \"industry\": \"SaaS\",\n \"region\": \"EMEA\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sendpilot.ai/v1/leads")
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 \"campaignId\": \"cmobr5lei0000u1h02ezf5itt\",\n \"leads\": [\n {\n \"linkedinUrl\": \"https://www.linkedin.com/in/johndoe/\",\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"company\": \"Acme Corp\",\n \"title\": \"VP of Engineering\",\n \"industry\": \"SaaS\",\n \"region\": \"EMEA\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"leadsAdded": 10,
"duplicatesSkipped": 2,
"invalidEntries": 0,
"errors": [
{}
]
}Requires
This REST request imports immediately when accepted. Campaign state determines subsequent outreach; use the dashboard to review the sequence. Send an Idempotency-Key when retrying an import.
leads:write, plus inbox:send when importing into a running campaign. The REST limit is 1–1,000 leads per request. MCP add_leads has separate 500-lead draft and 50-lead approval limits; those are not the REST limit.
Only linkedinUrl is required on each lead. Existing campaign duplicates are skipped; inspect leadsAdded, duplicatesSkipped, invalidEntries and any per-entry errors in the response.
Dynamic/custom fields
REST accepts custom fields as flat properties besidelinkedinUrl, such as industry or icebreaker. MCP instead uses the nested custom_fields argument. Keep the interfaces distinct.
{
"campaignId": "CAMPAIGN_ID",
"leads": [{
"linkedinUrl": "https://www.linkedin.com/in/PROFILE_ID",
"firstName": "Alex",
"company": "Example company",
"icebreaker": "We met at the conference"
}]
}
Authorizations
API key for authentication (prefix: sp_live_ or sp_test_)
Body
application/json
Campaign ID to add leads to
Example:
"cmobr5lei0000u1h02ezf5itt"
Array of leads (1 to 1000 per request) - only linkedinUrl required, all other fields are dynamic
Required array length:
1 - 1000 elementsShow child attributes
Show child attributes
Example:
[
{
"linkedinUrl": "https://www.linkedin.com/in/johndoe/",
"firstName": "John",
"lastName": "Doe",
"company": "Acme Corp",
"title": "VP of Engineering",
"industry": "SaaS",
"region": "EMEA"
}
]
Response
Leads added successfully