Skip to main content

Run an outbound dialer campaign live

You launched a dialer campaign with Launch an outbound dialer campaign. This guide is what you run on during the live phase — the /voice/dialer/[id] console you land on when you click into an active campaign, what each widget measures, when to pause or abort, and how callbacks and DNC sync stay honored while calls are in flight. All endpoints used below are on the Dialer API surface.

1. Not to be confused with a campaign journey — the dialer “create” wizard

Orbit has two outbound-campaign surfaces that use the word “campaign.” Choosing the wrong one is the most common onboarding mistake.
  • A campaign journey (Build, simulate, and launch a campaign journey) is a bulk pusher for message-style content — SMS, email, voice broadcasts, and multi-step journeys. It originates a fixed wave of sends, then advances per-event. There is no agent-pacing math and no per-contact dialing — it’s an event-driven batch flow (type: "journey").
  • The dialer campaign (/voice/dialer) is a live, agent-ready pacing surface. It claims contacts one tick at a time, answers each leg with a person or a voice agent, and re-claims on disposition. Its wizard collects pacing, abandon-ceiling, caller-ID, and script fields because those knobs exist only on a live pacing engine.
Open /voice/dialer in the dashboard; the New campaign button opens the dialer CreateCampaignDialog. A journey lives under /campaigns; the two are never cross-linked. If you intended a bulk message-style send, cancel here — the dialer wizard’s pacing knobs (pacing_ratio, max_abandon_rate) only make sense for a live pacing engine.

2. Live-run console layout — what each widget meters

The campaign detail page at /voice/dialer/[id] (reached from the dialer list or created from the dialog) is a wallboard for the run. The page polls live stats every 10 seconds while the campaign is active or paused; polling stops when the campaign is completed or aborted. The header carries the campaign name, its status badge (draft / active / paused / completed / aborted), and the mode badge (Preview / Progressive / Predictive / Agentless). The action buttons below them change with lifecycle — see “Pause / Abort” below.

Stats strip — per-contact status

The stats strip reads the campaign’s contact-status breakdown as of the last stats fetch (visible right after GET /dialer/campaigns/:id/stats). The tiles that matter:
  • Total / Pending / Dialing / Connected / Failed / DNC blocked / Timezone blocked / Exhausted / Callback scheduled / Wrong number / Archived — per-contact status buckets, with a Total tile showing a + suffix when the scan is bounded (contacts_count_capped=true), so the count is a floor, not a runaway exact total.
  • Voicemail (24h) / No answer (24h) — short-window outcome counters, read from `last_24h.
The donut at the bottom of the contact-progress card is the sum of dialing + connected + failed + dnc + exhausted against Total — the “dialed” share. Pending and DNC / TCPA blocked are rendered beneath it with their own counts.

Call outcomes — last 24 hours

The “Call outcomes” table aggregates dialer_call_attempts by outcome over the trailing 24 hours: connected, no_answer, busy, voicemail, AMD detected, and abandoned, with the average handle time (avg_handle_time_seconds) as a footer when set. An empty table reads “No calls yet.”

Post-call AI sentiment + per-attempt score

Two read-outs sit below the outcomes table — GET /dialer/campaigns/:id/sentiment (four-way sentiment tally; positive / neutral / negative / pending) and GET /dialer/campaigns/:id/attempts/:attemptId/outcome-scoring (single-attempt: sentiment, 0–100 composite score, warm/engaged/neutral/cold/voicemail label, next best action, agent disposition). analyzed:false is the normal zero state — the outcome-intelligence analyzer is tenant opt-in and async.

Caller-ID coverage (local presence)

GET /dialer/campaigns/:id/callerId_coverage aggregates the lead phone numbers against the campaign’s caller-ID pool and the caller_id_strategy (npa_match or fixed) and reports the under-covered destination NPAs (area codes) the pool should add to improve local-presence answer rates. This is a read-only aggregate; no calls originate from it.

3. Pause, resume, and abort — the lifecycle during a run

The action bar shows the lifecycle controls appropriate to the current status. Every transition goes through PATCH /dialer/campaigns/:id (dialer:write scope).
  • Activate — visible only on drafts with ≥1 contact. Sends {"status":"active"}. The back-end flips draft → active; the pacing scheduler starts claiming.
  • Pause (active) — {"status":"paused"}. Pacing stops claiming new contacts; in-flight legs complete.
  • Resume (paused) — {"status":"active"} when correcting a trip.
  • Abort{"status":"aborted"}. The abort is terminal: after it the campaign cannot be reactivated under FCC Telemarketing Sales Rule (TSR), 47 C.F.R. § 64.1200(a)(7), and the page replaces its action buttons with a banner and a “Create new campaign” link. Abort on drafts is a safe discard (no calls in flight).
  • Delete campaign (overflow menu) — a soft delete. Pending contacts archive; connected/failed/DNC terminal rows stay for TCPA-dispute defense. If any contact is still in flight (409 DIALER_CAMPAIGN_IN_FLIGHT) the dialog shows the count and asks you to pause first.
  • Dispatch batch (voice-agent campaigns only) — fires one batch through a bound voice agent when dispatch_mode='voice_agent'; see “Voice agent vs human dispatch” below.
A 409 CAMPAIGN_ABORTED from a re-activate attempt means you aborted earlier; create a new campaign instead — the status is terminal by design. The mutated status is validated by the back-end and the UI renders an inline error on the detail page so the click doesn’t silently land.

4. Dispositions and wrap-up codes during the live run

Every answered-or-completed attempt must land a disposition — otherwise the contact stays pending and the return-eligibility guard reclaims it. Agents post to POST /dialer/campaigns/:id/dispositions (scope dialer:write). The canonical route matrix on dialer dispositions maps the string to a contact status: z.string() on the disposition caps input at 100 characters. For an inbound queue that routes a human agent through wrap-up, see wrap-up codes.

5. Callback honoring and DNC sync

A callback disposition is not just a note — callback_scheduled_at writes next_attempt_at on the contact, and the pacing claim re-picks the contact at that ISO moment (clamped by pacing). The Callback scheduled tile on the stats strip counts these rows so you can see pending callbacks before they fire. A dnc / do_not_call disposition inserts the phone onto the tenant do-not-call list (dnc_list) with source dialer_disposition. Every future pacing tick across every campaign blocks at the DNC gate — first-write wins, so a phone already suppressed by SMS STOP or carrier feed cannot be overwritten on conflict. The audit log fires dialer.dnc_added alongside dialer.disposition_submitted.

6. Live-console API hooks — script the same views

Everything the console shows is a standard GET /api/v1/dialer/... read with scope dialer:read; writes require dialer:write. All responses are wrapped in the standard envelope ({ data, meta, request } — errors return { error: { code, message, details? } }).

Live batch metering

The response carries the same fields the console renders; the full schema is on Dialer API:
Polar a dashboard of these — the same widget the console polls. last_30m.abandon_rate_30m is the rolling 30-minute abandonment rate the pacing engine enforces against max_abandon_rate; it trips to aborted on the live side.

Lifecycle via PATCH

Accepts draft|active|paused|aborted transitions; only aborted → * is rejected with 409 CAMPAIGN_ABORTED.

Post a disposition from a script

The response echoes the routed status, and DNC callbacks get callback_scheduled_at stamped onto the contact’s next_attempt_at.

Voice agent vs human dispatch

A campaign routes answered legs to either a human agent (dispatch_mode='human', the default) or a bound AI voice agent (dispatch_mode='voice_agent'). The batch-dispatch endpoint only exists for the latter; for human-dispatch campaigns the console surfaces a 409 WRONG_DISPATCH_MODE and hides the Dispatch-batch button.
A 503 SOFTSWITCH_UNHEALTHY trip resets claimed rows back to pending before any leg is attempted, and a per-batch TCPA audit row lands in public.audit_logs as dialer.batch_dispatch. The Preview-mode agent workspace (Open agent view on the detail page) polls GET /dialer/next-call for the next pending contact and directly fires POST /dialer/dial; progressive and predictive campaigns auto-dial server-side and return 204 from next-call.

See also