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.

priority_id 1, 2, 3 callback_scheduled_at Skill pool when due retry_pattern after no-answer

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.

  1. POST callback_scheduled_at on a callback priority, or unhold a disposed row
  2. Store Callback (skill pool, no employee pin)
  3. Wait until the time is due (and inside working hours when outbound_obey_work_hours = 1)
  4. Any idle agent with matching form_type claims it
  5. 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).

BodyResult
Time on priority 1, 2, or 3Stored. dial_status = Callback.
Time on any other priority400 callback_scheduled_at is only allowed for callback priorities
agent_id present400 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

1
Skill + priority
Claim requires form_type in that agent’s skills and priority_id in their allowlist (empty = all).
2
No employee pin
Master has no agent_id. Any matching idle agent may take it.
3
Still eligible
Panel active, presence ready, AMI idle, wrap finished. If nobody matching is free, the lead waits.

Progressive vs Predictive

ProgressivePredictive
When claimedNext in that agent’s skill claimNextLead queueWhen any matching agent is idle, via claimNextForPool
Overdial poolSkill-matched like other leadsIn the pool when due. Bridged to a free skilled agent
OriginateAMI to the claiming extensionCustomer first, then Bridge to a skilled extension
If agent busy after answerN/A (agent-first)Hold until a skilled agent is free, or Abandoned if the customer hangs up

Hangup and retry

OutcomeStatusNext
Talked (ANSWER)ReceivedNever
No answer / busy / congestionNot Connectedretry_pattern + retry_seconds
call_count reaches max_triesDisposedFinal Disposal until unhold or redial
Reject / customer cancelRejectedNever
Customer left while waitingAbandonedretry_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.