Speed to lead
When you send a lead with POST /leads, it goes straight into its campaign’s dial queue. A call_now lead goes to the front, so a lead from your web form can be on the phone within seconds.
curl -X POST 'https://v2-api.callview.ai/api/v1/external/leads' \ -u "$CALLVIEW_KEY_ID:$CALLVIEW_SECRET" \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: crm-10442-create' \ -d '{ "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "external_id": "crm-10442", "phone": "+12125557812", "name": "Dana Smith", "fields": { "roof_age": "12" }, "consent": { "source": "web_form", "agreed_at": "2026-10-06T16:58:02Z", "url": "https://example.com/quote" }, "call_now": true }'external_id is your own ID for the lead. Send it every time: it stops repeats, and you can look the lead up by it later. fields are your own fields, and the campaign’s script can use them.
The checks
Section titled “The checks”Before anything is stored, the lead is checked in this order. The first one that fails is your answer, and nothing is saved.
| Check | If it fails |
|---|---|
| The campaign exists and isn’t finished | 404 not_found or 409 campaign_closed |
The phone is a US or Canadian number, +1 and 10 digits |
400 invalid_phone |
| Not a premium-rate or international number | 422 number_not_allowed (see Money guards) |
| Not on your Do Not Call list | 422 on_dnc_list |
| Not a number the campaign retired after repeated failed calls | 422 number_retired |
Not already in the campaign (same external_id, or same phone) |
409 duplicate_lead, with lead_id naming the one that exists |
| Consent is there, if the campaign asks for it | 422 consent_required |
| The campaign has fewer than 5,000 API leads waiting | 429 queue_full, with Retry-After |
Numbers in the 555-0100 to 555-0199 range are made up, so they fail as invalid_phone (in test mode, the magic numbers are the exception).
Add "dry_run": true to run every check and get the answer without saving anything. It’s handy for testing a form.
The answer
Section titled “The answer”201 means the lead was accepted. status tells you what happens next:
status |
What it means |
|---|---|
dialing |
A line is free. It’s being called now. place_in_line is 0. |
queued |
Waiting for a free line. place_in_line is 1 when it’s next, and estimated_wait_seconds is a rough guess. |
scheduled |
It can’t be called yet. scheduled_for says when (UTC) and scheduled_reason says why: outside_calling_hours, or recent_contact_cooldown when another of your campaigns called the number in the last 24 hours. Reading the lead later (GET /leads/{id}, lead events) gives the same reason while that time stands, and can also say next_dial_time (CallView moved its next try, say for a retry wait) or retry_after_outcome (the last call ended in an outcome it tries again after, like no answer). |
held |
Kept, but nothing is dialing: held_reason is campaign_paused, campaign_not_started or spend_cap_reached. It’s called once the hold lifts. |
{ "data": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "external_id": "crm-10442", "status": "queued", "call_now": true, "place_in_line": 1, "estimated_wait_seconds": 20, "scheduled_for": null, "scheduled_reason": null, "held_reason": null, "dry_run": false, "livemode": true }}The place and the wait are estimates, made from the campaign’s free lines and its recent call lengths.
Call now
Section titled “Call now”With call_now: true the lead jumps ahead of the campaign’s other leads. Among call_now leads, the oldest goes first, so none keeps slipping back when many arrive at once. Leave call_now out and the campaign’s own setting decides.
call_now never goes past the campaign’s lines. If the campaign has 5 lines and all 5 are on calls, your lead waits for the first one to free up. That’s why the queue exists: the limit is phone lines, not the API.
To call an existing lead again right away, use POST /calls with its lead_id or external_id. Each lead can be called this way 3 times in 24 hours (429 call_limit_reached after that).
Late leads
Section titled “Late leads”If a call_now lead is still waiting 15 minutes after it arrived (each campaign can change that number), it’s still called, but we mark it late: "late": true on the lead, and a lead.late event goes to your webhook. Use it to warn someone, or to follow up another way.
The 5,000-lead limit
Section titled “The 5,000-lead limit”Each campaign holds at most 5,000 API leads waiting to be called. Past that you get 429 queue_full with Retry-After (in seconds). Nothing is lost: send the lead again later. Leads you load into the campaign in the app don’t count toward this.
Repeats
Section titled “Repeats”The same external_id, or the same phone, in the same campaign within 30 days is a duplicate: 409 duplicate_lead, and error.lead_id is the lead you already have. Each campaign can change the 30 days.
After that window, sending the lead again puts the existing lead back in the queue. You get 200 with "requeued": true and the same id.
Many leads at once
Section titled “Many leads at once”POST /leads/batch takes up to 60 leads. Each one gets the same checks and its own result, in the order you sent them, and one bad lead doesn’t stop the rest:
{ "data": { "succeeded": 1, "failed": 1, "dry_run": false, "results": [ { "index": 0, "ok": true, "lead": { "id": "2b8e4c1d-9f3a-4b7e-8c21-6a5d4e3f2b10", "status": "queued", "...": "..." } }, { "index": 1, "ok": false, "error": { "code": "duplicate_lead", "message": "...", "param": "external_id", "lead_id": "..." } } ] }}Every lead in a batch counts toward your 60 new leads a minute.
Following the lead
Section titled “Following the lead”GET /leads/{id}orGET /leads?external_id=crm-10442says where it is:new,queued,scheduled,held,dialing,on_call,callback_scheduled,doneorout_of_queue, with its last 10 calls.- The events tell you as it happens:
lead.createdandlead.queuedright away, thencall.started,call.answered,lead.interested,handover.acceptedandcall.completed. See Events. PATCH /leads/{id}changes the name, email, address, fields or consent. The phone can’t change: add a new lead instead.POST /leads/{id}/opt_outstops all calls to the number and adds it to your Do Not Call list.