Dialer Dispositions
When an agent submits a disposition on an outbound dial-attempt, the platform routes the contact’s lifecycle status based on a canonical mapping. The correct route is critical: ado_not_call disposition that’s mis-routed leaves the contact in the active pool, which creates a TCPA exposure (47 U.S.C. § 227(b)(3) carries a private right of action with 1,500 statutory damages per call).
This page documents the disposition matrix and the POST /campaigns/:id/dispositions endpoint that agents call to submit them.
Base path: /api/v1/dialer
Authentication: Clerk session (Authorization: Bearer <token>) or API key (X-API-Key).
Scope: dialer:write on every endpoint listed here.
Contact-status enum
dialer_list_contacts.status is the contact lifecycle. An agent disposition routes the contact to one of these statuses:
Disposition → status matrix
Disposition matching is case-insensitive and trim-stripped at the request boundary. Any disposition not listed below routes tofailed (PS-STATE_MACHINE-12), not connected — unmapped dispositions are deliberately excluded from connect-rate maths so a freeform or newly-added FE disposition cannot silently inflate the connect-rate KPI or pollute the TCPA per-attempt audit. The agent’s chosen string is still persisted verbatim on dialer_call_attempts.disposition; operators adding a new disposition should extend the matrix so it routes intentionally instead of defaulting to failed.
DNC writes are platform-wide per tenant. A
dnc disposition in Campaign A blocks future dials to the same phone in Campaign B, C, etc. on the same tenant — the DNC list is read by every pacing tick across every campaign in the tenant. Inserts are idempotent (UNIQUE on phone), so the first-write wins and existing entries’ source / reason are preserved.Submit disposition
POST /api/v1/dialer/campaigns/{id}/dispositionsdialer:write.
The
dialer_call_attempts.id returned when the dial leg was placed.Agent-selected disposition string. Matched case-insensitively against the matrix above. 1–100 chars.
Free-form agent notes. Max 2000 chars. Accepted but not currently persisted — the field is validated at the request boundary but is not yet written to the attempt (no storage column has landed). Treat it as a no-op until a future release adds persistence; do not rely on it surviving the request.
ISO-8601 timestamp with timezone offset. REQUIRED when disposition routes to
callback_scheduled (callback_later / callback). Must be strictly in the future and ≤90 days ahead.cURL
cURL
List campaigns
GET /api/v1/dialer/campaignsdialer:read.
Cursor-paginated. Returns campaigns excluding soft-deleted (status = 'deleted') rows.
Query parameters
Get next contact (preview mode)
GET /api/v1/dialer/next-call?campaign_id=dcmp_abcdialer:read.
Agent readiness endpoint for preview-mode campaigns. Atomically claims the next eligible contact (CTE + FOR UPDATE SKIP LOCKED) so two agents polling concurrently can never receive the same row. For progressive / predictive campaigns this endpoint returns 204 No Content — pacing is handled server-side by the scheduler.
Stale-claim recovery: A preview contact stuck in dialing for >5 minutes (agent abandoned the tab) is automatically re-claimable. Without this, abandoned previews would block the contact forever.
200 OK
progressive or predictive mode (pacing engine handles dial).
Errors
Soft-delete a campaign
DELETE /api/v1/dialer/campaigns/{id}dialer:write.
Soft-deletes the campaign. Pending contacts flip to archived; terminal contacts (connected / failed / dnc / exhausted / wrong_number) are left untouched as TCPA-dispute audit trail. All three updates (campaign, lists, contacts) commit in a single transaction.
Errors
FCC abandon-rate ceiling
max_abandon_rate is hard-capped at 0.03 (3%) per the FCC Telemarketing Sales Rule. Any POST or PATCH request that sends a value above this is rejected with 422 VALIDATION_ERROR. The scheduler also auto-flips campaigns to status: 'aborted' if the rolling 30-day abandon rate trips the ceiling — aborted is terminal and cannot be re-activated; create a new campaign after reviewing the abort reason.