Skip to main content
POST
/
v1
/
campaigns
/
:id
/
leads
Add Leads to Campaign
curl --request POST \
  --url https://api.example.com/v1/campaigns/:id/leads
import requests

url = "https://api.example.com/v1/campaigns/:id/leads"

response = requests.post(url)

print(response.text)
const options = {method: 'POST'};

fetch('https://api.example.com/v1/campaigns/:id/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.example.com/v1/campaigns/:id/leads",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);

$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.example.com/v1/campaigns/:id/leads"

req, _ := http.NewRequest("POST", url, nil)

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.example.com/v1/campaigns/:id/leads")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.example.com/v1/campaigns/:id/leads")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body

Add Leads to a Campaign

Adds one or more leads to a campaign for calling. If a lead with the same phone or email already exists, it will be linked to the campaign. Otherwise, a new lead is created automatically. This is the primary endpoint for Clay, Zapier, and other automation tool integrations.

Request

POST /v1/campaigns/:id/leads

Path Parameters

ParameterTypeRequiredDescription
iduuidYesThe campaign ID to add leads to

Body Parameters

ParameterTypeRequiredDescription
leadsarrayYesArray of lead objects to add
leads[].phonestringConditionalPhone in E.164 format (required if no email or lead_id)
leads[].emailstringConditionalEmail address (required if no phone or lead_id)
leads[].lead_iduuidConditionalExisting lead ID (use if lead already exists)
leads[].first_namestringNoFirst name
leads[].last_namestringNoLast name
leads[].company_namestringNoCompany name
leads[].titlestringNoJob title
leads[].linkedin_urlstringNoLinkedIn profile URL
Each lead in the array must include at least one of: phone, email, or lead_id. The API automatically deduplicates leads based on phone number or email within your workspace.

Example

curl -X POST \
  "https://kdjmltmhxvvmiuehafgl.supabase.co/functions/v1/api-gateway/v1/campaigns/c1d2e3f4-.../leads" \
  -H "Authorization: Bearer rchd_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "leads": [
      {
        "first_name": "Marie",
        "last_name": "Dupont",
        "phone": "+33698765432",
        "company_name": "TechCo",
        "title": "Head of Sales"
      },
      {
        "first_name": "Pierre",
        "last_name": "Martin",
        "phone": "+33612345678",
        "email": "pierre@startup.io"
      }
    ]
  }'
const campaignId = "c1d2e3f4-...";
const response = await fetch(
  `https://kdjmltmhxvvmiuehafgl.supabase.co/functions/v1/api-gateway/v1/campaigns/${campaignId}/leads`,
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer rchd_live_xxxxxxxxxxxx",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      leads: [
        {
          first_name: "Marie",
          last_name: "Dupont",
          phone: "+33698765432",
          company_name: "TechCo",
          title: "Head of Sales"
        },
        {
          first_name: "Pierre",
          last_name: "Martin",
          phone: "+33612345678",
          email: "pierre@startup.io"
        }
      ]
    })
  }
);
const data = await response.json();
import requests

campaign_id = "c1d2e3f4-..."
response = requests.post(
    f"https://kdjmltmhxvvmiuehafgl.supabase.co/functions/v1/api-gateway/v1/campaigns/{campaign_id}/leads",
    headers={
        "Authorization": "Bearer rchd_live_xxxxxxxxxxxx",
        "Content-Type": "application/json"
    },
    json={
        "leads": [
            {
                "first_name": "Marie",
                "last_name": "Dupont",
                "phone": "+33698765432",
                "company_name": "TechCo",
                "title": "Head of Sales"
            },
            {
                "first_name": "Pierre",
                "last_name": "Martin",
                "phone": "+33612345678",
                "email": "pierre@startup.io"
            }
        ]
    }
)
data = response.json()

Response

{
  "data": {
    "campaign_id": "c1d2e3f4-...",
    "results": [
      {
        "lead_id": "new-lead-uuid-1",
        "status": "added"
      },
      {
        "lead_id": "existing-lead-uuid",
        "status": "already_in_campaign"
      }
    ]
  }
}

Result Statuses

StatusDescription
addedLead was successfully added to the campaign
already_in_campaignLead was already in the campaign (no duplicate created)
If a lead object is missing all three identifiers (phone, email, lead_id), it will be skipped and an error will be returned in the results array for that entry.