Leads API

Manage leads in your Ledly account. Create, retrieve, update, and delete leads programmatically.

Base URL: https://api.ledly.io/api

Authentication: Bearer Token (see Authentication)


List Leads

Retrieve a paginated list of leads with optional filtering.

Endpoint: GET /api/leads

Query Parameters

ParameterTypeDescriptionDefault
pageintegerPage number1
limitintegerItems per page (max 100)20
sortBystringSort fieldcreated_at
sortOrderstringasc or descdesc
statusstringFilter by status-
sourcestringFilter by source-
vendor_idstringFilter by vendor-
programstringFilter by program-
start_datestringFilter created after (ISO 8601)-
end_datestringFilter created before (ISO 8601)-
searchstringSearch email, name, phone-

Request

curl -H "Authorization: Bearer your_token" \
  "https://api.ledly.io/api/leads?page=1&limit=20&status=active&sortBy=created_at&sortOrder=desc"

Response (200 OK)

{
  "data": [
    {
      "id": "lead_abc123",
      "email": "[email protected]",
      "first_name": "John",
      "last_name": "Doe",
      "phone": "+15551234567",
      "status": "active",
      "source": "website",
      "vendor_id": "vendor_xyz",
      "program": "MBA",
      "program_interest": "MBA Online",
      "ip_address": "203.0.113.42",
      "user_agent": "Mozilla/5.0...",
      "utm_source": "google",
      "utm_medium": "cpc",
      "utm_campaign": "spring-enrollment",
      "custom_fields": {
        "preferred_start": "Fall 2025",
        "years_experience": 5
      },
      "enrichment_data": {
        "state": "California",
        "city": "San Francisco"
      },
      "created_at": "2024-12-25T10:30:00Z",
      "updated_at": "2024-12-25T10:30:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 150,
    "totalPages": 8
  }
}

Get Lead by ID

Retrieve details for a specific lead.

Endpoint: GET /api/leads/:id

Request

curl -H "Authorization: Bearer your_token" \
  https://api.ledly.io/api/leads/lead_abc123

Response (200 OK)

{
  "data": {
    "id": "lead_abc123",
    "email": "[email protected]",
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+15551234567",
    "status": "active",
    "source": "website",
    "vendor_id": "vendor_xyz",
    "vendor_name": "Web Form Integration",
    "program": "MBA",
    "program_interest": "MBA Online",
    "ip_address": "203.0.113.42",
    "user_agent": "Mozilla/5.0...",
    "landing_page": "https://example.com/mba",
    "referrer": "https://google.com",
    "utm_source": "google",
    "utm_medium": "cpc",
    "utm_campaign": "spring-enrollment",
    "utm_term": "online mba",
    "utm_content": "ad-variant-a",
    "custom_fields": {
      "preferred_start": "Fall 2025",
      "years_experience": 5,
      "education_level": "Bachelor's"
    },
    "enrichment_data": {
      "state": "California",
      "city": "San Francisco",
      "zip_code": "94102"
    },
    "validation_status": "validated",
    "duplicate_of": null,
    "crm_sync_status": "synced",
    "crm_id": "00Q1234567890ABC",
    "crm_synced_at": "2024-12-25T10:31:00Z",
    "created_at": "2024-12-25T10:30:00Z",
    "updated_at": "2024-12-25T10:30:00Z",
    "deleted_at": null
  }
}

Error (404 Not Found)

{
  "error": {
    "code": "LEAD_NOT_FOUND",
    "message": "Lead with ID 'lead_abc123' not found"
  }
}

Create Lead

Create a new lead manually (typically used for imports or manual entry).

Endpoint: POST /api/leads

For vendor lead submission, use the Lead Ingestion API instead.

Request

curl -X POST https://api.ledly.io/api/leads \
  -H "Authorization: Bearer your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "first_name": "Jane",
    "last_name": "Smith",
    "phone": "+15559876543",
    "program": "Nursing",
    "source": "referral",
    "custom_fields": {
      "preferred_start": "Spring 2025",
      "referrer_name": "John Doe"
    }
  }'

Request Body

FieldTypeRequiredDescription
emailstringYesLead’s email address
first_namestringNoFirst name
last_namestringNoLast name
phonestringNoPhone number
programstringNoProgram of interest
program_intereststringNoDetailed program interest
sourcestringNoLead source
vendor_idstringNoVendor ID
utm_sourcestringNoUTM source
utm_mediumstringNoUTM medium
utm_campaignstringNoUTM campaign
utm_termstringNoUTM term
utm_contentstringNoUTM content
custom_fieldsobjectNoCustom field values

Response (201 Created)

{
  "data": {
    "id": "lead_xyz789",
    "email": "[email protected]",
    "first_name": "Jane",
    "last_name": "Smith",
    "phone": "+15559876543",
    "status": "active",
    "program": "Nursing",
    "source": "referral",
    "custom_fields": {
      "preferred_start": "Spring 2025",
      "referrer_name": "John Doe"
    },
    "created_at": "2024-12-25T11:00:00Z",
    "updated_at": "2024-12-25T11:00:00Z"
  }
}

Error (400 Bad Request)

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format"
      },
      {
        "field": "phone",
        "message": "Invalid phone number"
      }
    ]
  }
}

Error (409 Conflict)

{
  "error": {
    "code": "DUPLICATE_LEAD",
    "message": "A lead with this email already exists",
    "duplicate_of": "lead_existing123"
  }
}

Update Lead

Update an existing lead’s information.

Endpoint: PATCH /api/leads/:id

Request

curl -X PATCH https://api.ledly.io/api/leads/lead_abc123 \
  -H "Authorization: Bearer your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+15551111111",
    "program": "MBA Executive",
    "custom_fields": {
      "preferred_start": "Fall 2025",
      "notes": "Updated contact information"
    }
  }'

Response (200 OK)

{
  "data": {
    "id": "lead_abc123",
    "email": "[email protected]",
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+15551111111",
    "program": "MBA Executive",
    "custom_fields": {
      "preferred_start": "Fall 2025",
      "notes": "Updated contact information"
    },
    "updated_at": "2024-12-25T12:00:00Z"
  }
}
⚠️

Partial updates are supported. Only include fields you want to change.


Delete Lead

Soft delete a lead (marked as deleted but retained in database).

Endpoint: DELETE /api/leads/:id

Request

curl -X DELETE https://api.ledly.io/api/leads/lead_abc123 \
  -H "Authorization: Bearer your_token"

Response (204 No Content)


Get Lead Activity

Retrieve the activity log for a lead showing all processing steps, enrichments, and CRM sync events.

Endpoint: GET /api/leads/:id/activity

Request

curl -H "Authorization: Bearer your_token" \
  https://api.ledly.io/api/leads/lead_abc123/activity

Response (200 OK)

{
  "data": [
    {
      "id": "activity_1",
      "event": "lead.created",
      "timestamp": "2024-12-25T10:30:00Z",
      "description": "Lead received from vendor 'Web Form'",
      "metadata": {
        "vendor_id": "vendor_xyz",
        "ip_address": "203.0.113.42"
      }
    },
    {
      "id": "activity_2",
      "event": "lead.validated",
      "timestamp": "2024-12-25T10:30:01Z",
      "description": "Lead passed validation",
      "metadata": {
        "validation_rules": ["email_format", "phone_format"]
      }
    },
    {
      "id": "activity_3",
      "event": "lead.enriched",
      "timestamp": "2024-12-25T10:30:02Z",
      "description": "Enrichment rule 'Set Default Program' applied",
      "metadata": {
        "rule_id": "rule_456",
        "changes": {
          "program": "MBA"
        }
      }
    },
    {
      "id": "activity_4",
      "event": "lead.crm_synced",
      "timestamp": "2024-12-25T10:31:00Z",
      "description": "Synced to Salesforce",
      "metadata": {
        "crm_type": "salesforce",
        "crm_id": "00Q1234567890ABC"
      }
    }
  ]
}

Bulk Update Leads

Update multiple leads in a single request.

Endpoint: POST /api/leads/bulk-update

Request

curl -X POST https://api.ledly.io/api/leads/bulk-update \
  -H "Authorization: Bearer your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "lead_ids": ["lead_1", "lead_2", "lead_3"],
    "updates": {
      "status": "contacted",
      "custom_fields": {
        "last_contact_date": "2024-12-25"
      }
    }
  }'

Response (200 OK)

{
  "success": true,
  "updated": 3,
  "failed": 0,
  "results": [
    { "id": "lead_1", "success": true },
    { "id": "lead_2", "success": true },
    { "id": "lead_3", "success": true }
  ]
}

Maximum 100 leads per bulk update request.


Bulk Delete Leads

Delete multiple leads in a single request.

Endpoint: POST /api/leads/bulk-delete

Request

curl -X POST https://api.ledly.io/api/leads/bulk-delete \
  -H "Authorization: Bearer your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "lead_ids": ["lead_1", "lead_2", "lead_3"]
  }'

Response (200 OK)

{
  "success": true,
  "deleted": 3,
  "failed": 0
}

Lead Statuses

StatusDescription
newNewly received, not yet processed
activeValid and active lead
contactedLead has been contacted
qualifiedLead is qualified for program
convertedLead converted to student
rejectedLead rejected by validation rules
duplicateDuplicate of another lead
archivedArchived for record-keeping

Advanced Filtering

Date Range Filtering

Filter by creation date:

GET /api/leads?start_date=2024-12-01T00:00:00Z&end_date=2024-12-31T23:59:59Z

Search across email, name, and phone:

Multiple Filters

Combine multiple filters:

GET /api/leads?status=active&program=MBA&source=website&sortBy=created_at&sortOrder=desc

Export Leads

Export filtered leads to CSV.

Endpoint: POST /api/leads/export

Request

curl -X POST https://api.ledly.io/api/leads/export \
  -H "Authorization: Bearer your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "csv",
    "filters": {
      "status": "active",
      "start_date": "2024-12-01T00:00:00Z"
    },
    "fields": ["email", "first_name", "last_name", "phone", "program", "created_at"]
  }'

Response (200 OK)

{
  "export_id": "export_abc123",
  "status": "processing",
  "download_url": null,
  "estimated_completion": "2024-12-25T12:05:00Z"
}

Check export status:

GET /api/exports/export_abc123

Response when ready:

{
  "export_id": "export_abc123",
  "status": "completed",
  "download_url": "https://api.ledly.io/exports/export_abc123/download",
  "expires_at": "2024-12-26T12:00:00Z",
  "row_count": 1500
}
⚠️

Export downloads expire after 24 hours. Large exports are processed asynchronously.


Webhooks

Subscribe to lead events via webhooks. See Webhooks API for configuration.

Available Events:

EventDescription
lead.createdNew lead received
lead.updatedLead information updated
lead.deletedLead deleted
lead.validatedLead passed validation
lead.rejectedLead rejected by rules
lead.duplicateDuplicate lead detected
lead.crm_syncedLead synced to CRM

Rate Limits

OperationLimit
List leads100 requests/minute
Get lead200 requests/minute
Create lead50 requests/minute
Update lead100 requests/minute
Bulk operations20 requests/minute
Export10 requests/minute

Error Codes

CodeHTTP StatusDescription
LEAD_NOT_FOUND404Lead does not exist
VALIDATION_ERROR400Invalid input data
DUPLICATE_LEAD409Lead already exists
INSUFFICIENT_PERMISSIONS403User lacks permission
RATE_LIMIT_EXCEEDED429Too many requests

Examples

Complete Lead Management Flow

// 1. Create a lead
const createResponse = await fetch('https://api.ledly.io/api/leads', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer your_token',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    email: '[email protected]',
    first_name: 'John',
    last_name: 'Doe',
    program: 'MBA'
  })
});
 
const { data: lead } = await createResponse.json();
 
// 2. Update the lead
await fetch(`https://api.ledly.io/api/leads/${lead.id}`, {
  method: 'PATCH',
  headers: {
    'Authorization': 'Bearer your_token',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    status: 'contacted',
    custom_fields: {
      contact_date: '2024-12-25'
    }
  })
});
 
// 3. Get activity log
const activityResponse = await fetch(
  `https://api.ledly.io/api/leads/${lead.id}/activity`,
  {
    headers: { 'Authorization': 'Bearer your_token' }
  }
);
 
const { data: activities } = await activityResponse.json();
console.log(activities);