Skip to main content
GET
/
api
/
v1
/
leads
curl "https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads?campaignId=YOUR_CAMPAIGN_ID&limit=1000" \
  -H "x-api-key: YOUR_API_KEY"
curl "https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads?campaignId=YOUR_CAMPAIGN_ID&limit=1000&cursor=CURSOR_FROM_PREVIOUS" \
  -H "x-api-key: YOUR_API_KEY"
curl "https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads?campaignId=YOUR_CAMPAIGN_ID&status=raw" \
  -H "x-api-key: YOUR_API_KEY"
async function getAllLeads(campaignId, status) {
  const allLeads = [];
  let cursor = null;

  do {
    const params = new URLSearchParams({ campaignId, limit: '1000' });
    if (status) params.append('status', status);
    if (cursor) params.append('cursor', cursor);

    const response = await fetch(
      `https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads?${params}`,
      { headers: { 'x-api-key': 'YOUR_API_KEY' } }
    );

    const data = await response.json();
    allLeads.push(...data.data.leads);
    cursor = data.data.hasMore ? data.data.cursor : null;
  } while (cursor);

  return allLeads;
}
import requests

def get_all_leads(campaign_id, status=None):
    all_leads = []
    cursor = None

    while True:
        params = {'campaignId': campaign_id, 'limit': 1000}
        if status:
            params['status'] = status
        if cursor:
            params['cursor'] = cursor

        response = requests.get(
            'https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads',
            params=params,
            headers={'x-api-key': 'YOUR_API_KEY'}
        )

        data = response.json()['data']
        all_leads.extend(data['leads'])

        if not data['hasMore']:
            break
        cursor = data['cursor']

    return all_leads
{
  "success": true,
  "data": {
    "leads": [
      {
        "_id": "jh7abc123xyz",
        "campaignId": "YOUR_CAMPAIGN_ID",
        "phoneNumber": "+15555551234",
        "externalId": "CRM_12345",
        "metadata": {
          "name": "John Doe",
          "company": "Acme Corp"
        },
        "status": "raw",
        "scheduledFor": "2024-12-25T09:00:00Z",
        "priority": 10,
        "attempts": 0,
        "_creationTime": 1703520000000
      },
      {
        "_id": "jh7abc456def",
        "campaignId": "YOUR_CAMPAIGN_ID",
        "phoneNumber": "+15555555678",
        "externalId": "CRM_67890",
        "metadata": {
          "name": "Jane Smith",
          "company": "Tech Inc"
        },
        "status": "raw",
        "priority": 5,
        "attempts": 0,
        "_creationTime": 1703520100000
      }
    ],
    "count": 2,
    "cursor": "eyJwb3NpdGlvbiI6Mn0=",
    "hasMore": true
  },
  "error": null
}
{
  "success": false,
  "data": null,
  "error": "campaignId query parameter is required"
}
Endpoint Alias: You can also use /api/v1/records instead of /api/v1/leads. Both endpoints are functionally identical - use whichever naming convention fits your integration.

Authentication

x-api-key
string
required
Your API key with read or write scope

Query Parameters

campaignId
string
required
The ID of the campaign to list leads for
status
string
Filter leads by statusOptions:
  • raw - Never been called
  • attempting - Currently being called
  • exhausted - Max attempts reached
  • concluded - Successfully completed
limit
number
Maximum number of leads to return per request. Default: 1000, Max: 8000
cursor
string
Pagination cursor from a previous response. Use this to fetch the next page of results.

Response

success
boolean
Whether the request was successful
data
object
error
string | null
Error message if request failed
curl "https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads?campaignId=YOUR_CAMPAIGN_ID&limit=1000" \
  -H "x-api-key: YOUR_API_KEY"
curl "https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads?campaignId=YOUR_CAMPAIGN_ID&limit=1000&cursor=CURSOR_FROM_PREVIOUS" \
  -H "x-api-key: YOUR_API_KEY"
curl "https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads?campaignId=YOUR_CAMPAIGN_ID&status=raw" \
  -H "x-api-key: YOUR_API_KEY"
async function getAllLeads(campaignId, status) {
  const allLeads = [];
  let cursor = null;

  do {
    const params = new URLSearchParams({ campaignId, limit: '1000' });
    if (status) params.append('status', status);
    if (cursor) params.append('cursor', cursor);

    const response = await fetch(
      `https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads?${params}`,
      { headers: { 'x-api-key': 'YOUR_API_KEY' } }
    );

    const data = await response.json();
    allLeads.push(...data.data.leads);
    cursor = data.data.hasMore ? data.data.cursor : null;
  } while (cursor);

  return allLeads;
}
import requests

def get_all_leads(campaign_id, status=None):
    all_leads = []
    cursor = None

    while True:
        params = {'campaignId': campaign_id, 'limit': 1000}
        if status:
            params['status'] = status
        if cursor:
            params['cursor'] = cursor

        response = requests.get(
            'https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads',
            params=params,
            headers={'x-api-key': 'YOUR_API_KEY'}
        )

        data = response.json()['data']
        all_leads.extend(data['leads'])

        if not data['hasMore']:
            break
        cursor = data['cursor']

    return all_leads
{
  "success": true,
  "data": {
    "leads": [
      {
        "_id": "jh7abc123xyz",
        "campaignId": "YOUR_CAMPAIGN_ID",
        "phoneNumber": "+15555551234",
        "externalId": "CRM_12345",
        "metadata": {
          "name": "John Doe",
          "company": "Acme Corp"
        },
        "status": "raw",
        "scheduledFor": "2024-12-25T09:00:00Z",
        "priority": 10,
        "attempts": 0,
        "_creationTime": 1703520000000
      },
      {
        "_id": "jh7abc456def",
        "campaignId": "YOUR_CAMPAIGN_ID",
        "phoneNumber": "+15555555678",
        "externalId": "CRM_67890",
        "metadata": {
          "name": "Jane Smith",
          "company": "Tech Inc"
        },
        "status": "raw",
        "priority": 5,
        "attempts": 0,
        "_creationTime": 1703520100000
      }
    ],
    "count": 2,
    "cursor": "eyJwb3NpdGlvbiI6Mn0=",
    "hasMore": true
  },
  "error": null
}
{
  "success": false,
  "data": null,
  "error": "campaignId query parameter is required"
}

Lead Status Lifecycle

Status Meanings:
  • raw: Lead has never been called
  • attempting: Lead is currently in the calling queue
  • exhausted: Max call attempts reached without success
  • concluded: Call completed successfully

Common Errors

ErrorCauseSolution
campaignId query parameter is requiredMissing campaignIdAdd campaignId to query string
Invalid or inactive API keyWrong API keyCheck your API key
Campaign not found or access deniedWrong campaign or no accessVerify campaignId and API key scope

Usage Tips

Filtering: Use the status parameter to focus on specific subsets:
  • status=raw - See leads that haven’t been called yet
  • status=attempting - Monitor active calls
  • status=concluded - Review completed calls

Pagination

This endpoint supports cursor-based pagination for handling large datasets efficiently.
Limits:
  • Default: 1,000 leads per request
  • Maximum: 8,000 leads per request
For campaigns with more than 8,000 leads, use the cursor parameter to fetch additional pages.
Best Practice: When fetching all leads for large campaigns, loop through pages using the cursor until hasMore is false.