Push leads from your CRM into an agent-dialer campaign while it runs. Each lead can carry your own record ID (external_id) and any custom_fields; agents see the fields, and both come back in results and webhook events, so your CRM never needs to store Edesy IDs. Numbers on your DNC list and duplicates are suppressed automatically.
Request#
curl -X POST https://voice-api.edesy.in/v1/campaigns/{id}/leads \
-H "Authorization: Bearer $EDESY_KEY" \
-H "Content-Type: application/json" \
-d '{
"leads": [
{
"phone_number": "+9198XXXXXXXX",
"name": "Asha Rao",
"external_id": "crm-lead-77812",
"consent_source": "website_form",
"consent_timestamp": "2026-10-27T18:04:00Z",
"custom_fields": { "city": "Pune", "product": "Home loan", "loan_amount": 2500000 }
}
]
}'
| Field | Type | Required | Description |
|---|---|---|---|
leads |
array | Required | One or more leads |
leads[].phone_number |
string | Required | Number to call |
leads[].name |
string | Optional | Shown to the agent |
leads[].external_id |
string | Optional | Your CRM's record ID. Returned on results and webhooks |
leads[].custom_fields |
object | Optional | Any attributes. Shown to the agent and returned verbatim |
leads[].consent_source, leads[].consent_timestamp |
string | Optional | Where and when consent was given |
Response#
{
"data": {
"contacts_added": 1,
"total_rows": 1,
"suppressed_dnc": 0,
"suppressed_duplicate": 0,
"invalid": 0,
"invalid_samples": [],
"consent_timestamp_unparsed": 0
}
}
Rules#
- The campaign must be an agent-dialer campaign (created with
queue_id). For broadcast campaigns, use POST/v1/campaigns/{id}/contacts. - Leads can be added while the campaign is draft, scheduled, running or paused, but not after it is completed or stopped.
- An empty
leadsarray returns400.
Getting results back into your CRM#
Create a webhook subscription and you receive, for each lead:
| Event | When |
|---|---|
call.answered |
The lead picked up |
call.completed |
The call ended, with status, duration_sec, sip_status and answered_by |
recording.ready |
The recording is playable |
disposition.submitted |
The agent submitted a wrap-up code, with disposition and agent |
Each event's data carries your external_id and custom_fields, so you can update the lead directly.
{
"event": "disposition.submitted",
"timestamp": "2026-10-28T11:20:31Z",
"data": {
"call_sid": "CA_6f1c2d3e-0000-4000-8000-000000000000",
"external_id": "crm-lead-77812",
"campaign_id": "...",
"contact_id": "...",
"to": "+9198XXXXXXXX",
"direction": "outbound",
"agent": { "id": "...", "name": "Priya" },
"disposition": { "id": "...", "name": "Interested", "is_terminal": true, "notes": "Call back Friday" },
"custom_fields": { "city": "Pune", "product": "Home loan", "loan_amount": 2500000 }
}
}