Callback Request
One time. Any matching skill. Nobody dials it early.
A callback is a time-gated pool lead. CRM sends callback_scheduled_at. When due, any idle agent whose skills include form_type and whose priority_ids allow the lead’s priority_id (empty = all) may claim it. Master has no agent_id pin. Field shapes are in the API reference.
End-to-end flow
The row sits as Callback until the time is due. Claim starts when any matching-skill agent is panel-active, ready, and AMI idle.
- POST callback_scheduled_at on a callback priority, or unhold a disposed row
- Store Callback (skill pool, no employee pin)
- Wait until the time is due (and inside working hours when
outbound_obey_work_hours = 1) - Any idle agent with matching form_type claims it
- Progressive: AMI to that desk. Predictive: customer first, then skill bridge
Push
callback_scheduled_at is only for priority_id 1, 2, or 3 on POST. Extra keys such as agent_id are rejected. Tickets already on priority_id 8 use PUT /api/escalated-tickets to Close or Callback Schedule. Disposed rows come back with POST /api/unholdDialerData (always priority 3, now+1h or next work_start).
| Body | Result |
|---|---|
| Time on priority 1, 2, or 3 | Stored. dial_status = Callback. |
| Time on any other priority | 400 callback_scheduled_at is only allowed for callback priorities |
agent_id present | 400 extra field rejected |
Accepted times: 2026-08-20 15:30:00 or ISO-8601, including past datetimes (due immediately). Rejected: date-only. Other priority_id values cannot send a time on this POST.
curl -sS -X POST https://YOUR_HOST/api/leads \
-H "Authorization: Bearer YOUR_WS_SECRET" \
-H "Content-Type: application/json" \
-d '{
"oli_id": "OLI124",
"phone_number": "9876543211",
"client_name": "B",
"form_type": "GST",
"priority_id": 3,
"callback_scheduled_at": "2026-08-20 15:30:00"
}'
Wait until due
Both engines skip a lead while callback_scheduled_at is in the future. Until then the row stays unreserved. When the time is null or <= NOW(), it can be claimed as soon as a matching agent is ready. Only when dialer_config.outbound_obey_work_hours = 1 is it also held to work_start–work_end. After a later Not Connected, the pattern-bucket scheduler resumes.
Any matching skill
Claim requires
form_type in that agent’s skills and priority_id in their allowlist (empty = all).Master has no
agent_id. Any matching idle agent may take it.Panel active, presence ready, AMI idle, wrap finished. If nobody matching is free, the lead waits.
Progressive vs Predictive
| Progressive | Predictive | |
|---|---|---|
| When claimed | Next in that agent’s skill claimNextLead queue | When any matching agent is idle, via claimNextForPool |
| Overdial pool | Skill-matched like other leads | In the pool when due. Bridged to a free skilled agent |
| Originate | AMI to the claiming extension | Customer first, then Bridge to a skilled extension |
| If agent busy after answer | N/A (agent-first) | Hold until a skilled agent is free, or Abandoned if the customer hangs up |
Hangup and retry
| Outcome | Status | Next |
|---|---|---|
Talked (ANSWER) | Received | Never |
| No answer / busy / congestion | Not Connected | retry_pattern + retry_seconds |
call_count reaches max_tries | Disposed | Final Disposal until unhold or redial |
| Reject / customer cancel | Rejected | Never |
| Customer left while waiting | Abandoned | retry_seconds (or keep existing next_retry_at) |
Failed originate restores the previous status and clears reserve without incrementing call_count or touching first_attempt_at / last_attempt_at (those are stamped only at a real dial), and retries after RELEASE_RETRY_MS (default 60s). Received / Rejected / Disposed are not claimed by the engines; socket redial can reopen them (call_type = redial). CRM unholdDialerData returns Disposed to Callback priority 3. Not Connected uses dialer_config.retry_pattern (currently [4,4,3,2,1,1,1,1,1,1,1]), same-day retry_seconds (3600), window work_start–work_end, until max_tries (20). Leftover in the current bucket carries to the next working day. Abandoned is not on that cycle — it keeps a future next_retry_at, otherwise waits retry_seconds. A due callback_scheduled_at still waits for working hours. Redial NC does not bump call_count or send RNR mail. Auto-dial Not Connected also sends RNR mail if isRnrSent is still 0. Claim order: due Callback, then Pending, then Abandoned, then Not Connected.