Appearance
API Reference
Generated from
DialerDigital/corecommit0fc18008b3c8— specopenapi/dialer-v1.yamlv0.134.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.
Compliance-first outbound dialer control plane — the authenticated /v1 surface.
Formal reference of the /v1 control-plane API served by Dialer.API.Router (Bandit, port 4000). Source of truth: lib/dialer/api/v1_router.ex (tenant surface), lib/dialer/api/admin_router.ex (platform-admin surface), lib/dialer/api/auth_router.ex (dashboard login and password recovery — the only unauthenticated /v1 surface) and lib/dialer/api/sms_webhook_router.ex (public SMS webhooks, described under webhooks). CI enforces tools/check_openapi_drift.py: every route in the routers must appear here (method + path) and vice versa, and info.version must equal the @version in mix.exs.
Conventions
- JSON in / JSON out. Request bodies above 8 MiB are rejected.
- Errors always use the envelope
{"error": {"code": "...", "message": "..."}}. Branch oncode(machine-readable), never onmessage. - Every response carries
X-Request-ID(yours is propagated when sane). - Timestamps are RFC 3339 / ISO-8601 (UTC). Times of day are
HH:MM:SS. - Decimal fields (pacing ratios, thresholds) are rendered as JSON strings.
Multi-tenancy and 404 semantics
Every route runs with the tenant resolved from the bearer key; all data access flows through Postgres row-level security (RLS). The API never accepts a tenant id from path, query or body. Cross-tenant ids read as 404 not_found because RLS returns zero rows — existence is never leaked (no 403 for foreign ids), and malformed (non-UUID) ids are the same 404.
Rate limits (per API key, per person)
Every dd_ API key has its own request quota on /v1: two keys of the same tenant never share a budget. It is a sliding allowance (GCRA), per node, with a burst of one minute's worth. The default is generous and a per-tenant operator setting (api_key_requests_per_minute) adjusts it. The console (ddu_) and agent (ddw_) lanes are counted too, with the same algorithm and their own setting (session_requests_per_minute): the bucket belongs to the person (the agent, else the user), not to the session, so logging in again does not buy a fresh budget, and another person of the same tenant is unaffected. Every response to a counted request carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; over the quota the answer is 429 rate_limited with Retry-After and the request is not processed. Exempt: POST /v1/calls/{call_id}/hangup, webhooks and health routes. A request refused by the quota is not counted again, so waiting Retry-After seconds is always enough.
Canonical errors
401 unauthorized— missing/unknown/revoked API key.403 forbidden— suspended tenant.404 not_found— unknown, malformed or cross-tenant id (RLS; see above).422 compliance_blocked— the compliance engine refused the operation; the body carriesgate(which gate refused) anddecision_id(citable against the audit chain). Do NOT retry unchanged — the block is evidence, not an error.429 rate_limited— the per-API-key request quota (below), or one of the fixed-window request brakes (login, second factor, widget tokens, call control, dispositions, invitations). These carryRetry-After: whole seconds until a retry can succeed. The quota also carriesX-RateLimit-*.429 sms_spend_cap_exceeded— month-to-date SMS budget brake; retryable only after a cap raise or the month rollover.429 throttled— rate brake; retry later with backoff. Neither carriesRetry-After: the engine does not know when capacity returns, and a made-up number is worse than none.502 provider_error/502 dial_error/502 sbc_error— an upstream (SMS provider, switch, SIP edge) rejected the operation.
Out of scope here (documented in API.md): GET /healthz (no auth), GET /v1/ws websocket live floor (upgrades before this pipeline; auth via an ephemeral one-shot ?ticket= minted by POST /v1/ws/ticket, never a long-lived bearer), and GET /metrics (Prometheus, port 9568).
Resources
| Resource | Endpoints | Description |
|---|---|---|
| Skip trace | 3 | Skip tracing (F0): a measured vendor lookup behind a per-tenant monthly cap with a hard cut. No invoice line yet. |
| Identity | 22 | Authenticated tenant, account settings. |
| Auth | 16 | Dashboard login (email + password -> a revocable ddu_ session; sha256 at rest, plaintext shown once) and password recovery (a one-shot, expiring link — the request half never reveals whether an address has an account). |
| Sso | 11 | SAML 2.0 single sign-on per tenant: the tenant's identity-provider configuration (loaded by an account_admin, audited append-only) and the service-provider metadata its IdP admin needs. SP-initiated only; a person must already exist in the tenant (no just-in-time provisioning). |
| Support access | 4 | Platform-support access (ADR 225): the customer's consent (a grant with a reason and a fixed expiry, one live per tenant, revoked at will) and the append-only trail of it. account_admin only, except the banner. |
| Users | 6 | Dashboard user accounts (email + password; disabled, never deleted). |
| API keys | 4 | Per-tenant API keys (sha256 at rest; plaintext shown once). |
| Widgets | 11 | Embeddable agent-widget lifecycle — ddw_ browser tokens + the origin allowlist. |
| Click to call | 7 | Click-to-call for the customer's website (ADR 220): the console mints/revokes a PUBLISHABLE ddc_ site key, and the visitor's browser uses it to read the form's config and to leave a call request. Gated by click_to_call_enabled. |
| Campaigns | 28 | Campaign CRUD, lifecycle, manual dial, rewind. |
| Debts & leads | 10 | Bulk lead import, debt detail, per-debt CDR, defense packet. |
| Consumers | 1 | Debtor card by consumer_ref: debts, DNC / cease-and-desist, Reg F counter and next permitted window, derived from the append-only sources. |
| Debt lists | 10 | Reusable lists of debts, associated with campaigns (ADR #162). |
| Import mappings | 8 | CSV import templates (column -> field mapping and parse options), versioned append-only per tenant. |
| Qm | 16 | Quality-management scoring forms (ADR #217), versioned append-only per tenant. Writes need the qm_enabled flag. |
| Insights | 3 | Anomaly evidence of the insights evaluator (core#1983): contact, abandon, cost, gate-block and media-timeout series, each anomaly with its series and threshold. Always on; insights_anomaly_k only tunes the sensitivity. |
| Product analytics | 3 | Product analytics and NPS inside the console, our own and with no third party (macro-tasks#876): usage events as keys of a closed catalog, and the NPS question for account administrators. Always on; it never carries a consumer's data. |
| Disclosure scripts | 4 | Collection-notice script library (ADR #219): immutable versions per tenant, approved by a sealed event. |
| Segment filters | 7 | Saved segmentation filters (the criteria of GET /v1/debts with a name), versioned append-only per tenant. Behind the debt_segmentation_enabled flag (ADR #221). |
| Call attempts (CDR) | 4 | Append-only CDR query + typed dispositions. |
| Callbacks | 5 | Consumer-agreed redial appointments. |
| Disposition rules | 5 | The tenant's retry policy by call outcome (R10): reschedule or suppress a debt after a given disposition. It can only postpone or close a debt; every dial still runs the compliance gates at originate time. |
| Dispositions | 1 | The dialer.v1.Disposition contract set in REST spelling: the lowercase value, its enum name and number. |
| Promises to pay | 2 | Promise-to-pay pipeline. |
| Agents & seats | 20 | Seat roster, presence, softphone checkin/checkout. |
| Wfm | 1 | Workforce management: the per-interval coverage of a day (forecast from the CDR, agents required by Erlang C against the tenant's service target, agents planned in R11 shifts). A derived read; nothing is persisted. |
| Academy | 3 | In-app Academy training records — the auditable constancia (who completed what and when), append-only and per agent. |
| Supervision | 4 | Supervisor audio (listen/whisper/barge/takeover), evidence-first. |
| Calls | 13 | Live-call control verbs (hold/unhold/mute/unmute/hangup), evidence-first. |
| Transfer destinations | 5 | The tenant's registry of the external numbers a live call may be transferred to. |
| Rewind segments | 4 | Named sets of rewind filters a supervisor saves per tenant and re-uses (the filters, never a list of accounts). |
| Stats & usage | 9 | Operational counters, blocked-dial rollups, usage metering. |
| Billing | 9 | Invoiceable line items. |
| Reports | 10 | Packaged compliance artifacts. |
| Compliance | 5 | Suppression data the tenant owns (its internal do-not-call list, uploaded as CSV into the same list the pre-dial gate reads) and the audit-chain citation: resolving a decision_id into its sealed link plus the integrity verdict over it. |
| DIDs (caller IDs) | 11 | DID registry, CDR-computed health, launch checklist and carrier tickets. |
| Carriers (SIP trunks) | 8 | SIP trunk registry (BYOC/house) + SBC provisioning. |
| SMS | 12 | Gated one-off SMS send + unified ledger. |
| SMS providers | 5 | Per-tenant/region SMS routing registry. |
| 6 | Debtor email addresses with provenance, the suppression ledger (read) and the email ledger (read). | |
| Email providers | 5 | Per-tenant/region email provider registry (SMTP / log). |
| Email templates | 6 | Per-tenant e-mail templates (static subject + body with typed variables), append-only versions, account_admin approval and retirement. |
| Sms templates | 8 | Per-tenant SMS templates with typed variables, approval and the "templates only" setting. |
| Webhooks | 8 | Outbound webhooks for CRMs: the tenant's endpoint registry, its subscribed events and the signing secret (shown once; rotation with a window). |
| Inbound routes | 6 | Inbound DID routing + SBC provisioning. |
| Inbound ivr menus | 4 | The tenant's inbound IVR menus: published versions, append-only history, rendered to audio when published. An inbound route with dest_type: ivr runs one of them. |
| Inbound queues | 15 | The tenant's inbound queues: created with a name, an optional overflow to another of its queues, retired when nothing uses them. A route with dest_type: queue names one in queue_id; an inbound IVR menu names one as queue:<id>. |
| Recordings | 23 | Call-recording evidence: retention-locked metadata, signed playback, legal hold, bulk export, per-tenant policy. |
| Voice ai | 25 | AI voice agents: builder + versioned policy, live conversations, transcripts/outcomes, supervisor takeover, the per-tenant AI-dialing kill-switch and today's metrics. |
| Ws | 1 | |
| Webhook endpoints | 3 | Provider-facing, signature-authenticated (no bearer). |