Skip to main content
Leads are the recipients of your cold email campaigns. ColdSend supports uploading leads via CSV, adding them individually, and tracking their engagement.

Lead Status

StatusDescription
PENDINGLead not yet contacted — eligible for sending
QUEUEDEmail task created, waiting to be sent
SENTInitial email successfully sent
OPENEDEmail was opened (tracking enabled)
REPLIEDLead replied to email
FAILEDEmail send failed
BOUNCEDEmail bounced after sending
UNSUBSCRIBEDLead unsubscribed
EXTERNALExternal/unsolicited incoming lead

Lead Upload via CSV

POST /api/public/v1/campaigns/{campaign_id}/leads Upload leads asynchronously via CSV file. The file must include an email column.
import requests
import json

campaign_id = "550e8400-e29b-41d4-a716-446655440000"

mapping = {
    "email": "Email",
    "first_name": "First Name",
    "last_name": "Last Name",
    "company": "Company"
}

with open("leads.csv", "rb") as f:
    response = requests.post(
        f"https://api.coldsend.pro/api/public/v1/campaigns/{campaign_id}/leads",
        headers={"X-API-Key": api_key},
        files={"file": f},
        data={"mapping": json.dumps(mapping)}
    )

print(response.json())

CSV Requirements

  • Must include an email column (required)
  • Additional supported columns: first_name, last_name, company
  • Custom columns are mapped automatically and available as {{custom_column_name}} in your email templates
  • Max CSV size: 50MB
  • Max leads per upload: 10,000

Upload Progress

The upload runs asynchronously. Check progress with:
response = requests.get(
    f"https://api.coldsend.pro/api/public/v1/campaigns/{campaign_id}/leads/upload/{job_id}",
    headers={"X-API-Key": api_key}
)

Manual Lead Addition

POST /api/public/v1/campaigns/{campaign_id}/leads/manual Add a single lead:
response = requests.post(
    f"{base_url}/api/public/v1/campaigns/{campaign_id}/leads/manual",
    headers={"X-API-Key": api_key},
    json={
        "email": "john.doe@example.com",
        "first_name": "John",
        "last_name": "Doe",
        "company": "Acme Inc"
    }
)

Listing Leads

GET /api/public/v1/campaigns/{campaign_id}/leads List leads with pagination and filtering:
response = requests.get(
    f"{base_url}/api/public/v1/campaigns/{campaign_id}/leads?status=PENDING&page=1&limit=20",
    headers={"X-API-Key": api_key}
)

Query Parameters

ParameterDescription
pagePage number (1-based, default: 1)
limitItems per page (1-100, default: 20)
statusFilter by status: PENDING, SENT, OPENED, REPLIED, BOUNCED, etc.
searchSearch by email or name

Deleting Leads

DELETE /api/public/v1/campaigns/{campaign_id}/leads Only PENDING leads (not yet sent) can be deleted:
response = requests.delete(
    f"{base_url}/api/public/v1/campaigns/{campaign_id}/leads",
    headers={"X-API-Key": api_key},
    json={
        "lead_ids": [
            "650e8400-e29b-41d4-a716-446655440000",
            "750e8400-e29b-41d4-a716-446655440001"
        ]
    }
)
Leads that have already received emails cannot be deleted. This ensures compliance and prevents data gaps in campaign analytics.

Get a Single Lead

GET /api/public/v1/campaigns/{campaign_id}/leads/{lead_id} Returns full lead data including email interaction history and any replies received from the lead.
lead_id = "650e8400-e29b-41d4-a716-446655440000"

response = requests.get(
    f"{base_url}/api/public/v1/campaigns/{campaign_id}/leads/{lead_id}",
    headers={"X-API-Key": api_key}
)
print(response.json())

Update a Lead

PUT /api/public/v1/campaigns/{campaign_id}/leads/{lead_id} Update mutable fields on a lead. Only the fields you provide are changed — custom_fields uses merge patch semantics: existing keys are preserved, keys you send are added or updated, and keys explicitly set to null are removed. Updatable fields: first_name, last_name, company, custom_fields.
response = requests.put(
    f"{base_url}/api/public/v1/campaigns/{campaign_id}/leads/{lead_id}",
    headers={"X-API-Key": api_key},
    json={
        "first_name": "Jane",
        "company": "New Corp",
        "custom_fields": {
            "industry": "SaaS",
            "old_field": None  # removes this key
        }
    }
)
Requires the leads:update scope.

Export Leads as CSV

GET /api/public/v1/campaigns/{campaign_id}/leads/export Downloads all leads for a campaign as a CSV file — bypasses pagination limits, so every lead is included in a single download. The exported columns are: email, first_name, last_name, company, status, custom_fields (JSON-encoded), created_at
response = requests.get(
    f"{base_url}/api/public/v1/campaigns/{campaign_id}/leads/export",
    headers={"X-API-Key": api_key}
)

with open("leads_export.csv", "wb") as f:
    f.write(response.content)
The response Content-Type is text/csv and the Content-Disposition header sets the suggested filename.
Use this endpoint to sync your ColdSend lead data into external CRMs, data warehouses, or spreadsheets without having to page through the list endpoint.

Next Steps

Create Campaign

Set up your campaign with lead mapping configuration.

Personalization

Use lead data in personalized email content.