Skip to content

API Reference ​

Generated from DialerDigital/core commit bbb8e373d900 — spec openapi/dialer-v1.yaml v0.151.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.

Español

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).. 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 on code (machine-readable), never on message.
  • 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 carries gate (which gate refused) and decision_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 carry Retry-After: whole seconds until a retry can succeed. The quota also carries X-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 carries Retry-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 ​

ResourceEndpointsDescription
Skip trace3Skip tracing (F0): a measured vendor lookup behind a per-tenant monthly cap with a hard cut. No invoice line yet.
Identity29Authenticated tenant, account settings.
Auth21Dashboard 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).
Sso11SAML 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 access4Platform-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.
Users6Dashboard user accounts (email + password; disabled, never deleted).
API keys7Per-tenant API keys (sha256 at rest; plaintext shown once).
Widgets11Embeddable agent-widget lifecycle — ddw_ browser tokens + the origin allowlist.
Click to call7Click-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.
Campaigns28Campaign CRUD, lifecycle, manual dial, rewind.
Debts & leads10Bulk lead import, debt detail, per-debt CDR, defense packet.
Consumers1Debtor card by consumer_ref: debts, DNC / cease-and-desist, Reg F counter and next permitted window, derived from the append-only sources.
Debt lists10Reusable lists of debts, associated with campaigns.
Import mappings8CSV import templates (column -> field mapping and parse options), versioned append-only per tenant.
Qm16Quality-management scoring forms, versioned append-only per tenant. Writes need the qm_enabled flag.
Insights3Anomaly evidence of the insights evaluator: 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 analytics3Product analytics and NPS inside the console, our own and with no third party: 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 scripts4Collection-notice script library: immutable versions per tenant, approved by a sealed event.
Segment filters7Saved segmentation filters (the criteria of GET /v1/debts with a name), versioned append-only per tenant. Behind the debt_segmentation_enabled flag.
Call attempts (CDR)4Append-only CDR query + typed dispositions.
Callbacks5Consumer-agreed redial appointments.
Disposition rules5The 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.
Dispositions1The dialer.v1.Disposition contract set in REST spelling: the lowercase value, its enum name and number.
Promises to pay2Promise-to-pay pipeline.
Agents & seats23Seat roster, presence, softphone checkin/checkout.
Wfm1Workforce 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.
Academy3In-app Academy training records — the auditable constancia (who completed what and when), append-only and per agent.
Supervision4Supervisor audio (listen/whisper/barge/takeover), evidence-first.
Calls18Live-call control verbs (hold/unhold/mute/unmute/hangup), evidence-first.
Transfer destinations5The tenant's registry of the external numbers a live call may be transferred to.
Rewind segments4Named sets of rewind filters a supervisor saves per tenant and re-uses (the filters, never a list of accounts).
Stats & usage9Operational counters, blocked-dial rollups, usage metering.
Billing10Invoiceable line items.
Reports10Packaged compliance artifacts.
Compliance8Suppression 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)14DID registry, CDR-computed health, launch checklist and carrier tickets.
Support5Support tickets with a number and a first-response target by plan level.
Carriers (SIP trunks)8SIP trunk registry (BYOC/house) + SBC provisioning.
SMS13Gated one-off SMS send + unified ledger.
SMS providers5Per-tenant/region SMS routing registry.
Messaging1010DLC brand and campaign registration through the SMS provider, and the numbers of an approved campaign. Provider fees land on the balance at cost.
Email6Debtor email addresses with provenance, the suppression ledger (read) and the email ledger (read).
Email providers5Per-tenant/region email provider registry (SMTP / log).
Email templates6Per-tenant e-mail templates (static subject + body with typed variables), append-only versions, account_admin approval and retirement.
Sms templates8Per-tenant SMS templates with typed variables, approval and the "templates only" setting.
Webhooks9Outbound webhooks for CRMs: the tenant's endpoint registry, its subscribed events and the signing secret (shown once; rotation with a window).
Inbound routes6Inbound DID routing + SBC provisioning.
Inbound ivr menus4The 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 queues15The 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>.
Recordings23Call-recording evidence: retention-locked metadata, signed playback, legal hold, bulk export, per-tenant policy.
Voice ai26AI voice agents: builder + versioned policy, live conversations, transcripts/outcomes, supervisor takeover, the per-tenant AI-dialing kill-switch and today's metrics.
Ws1
Webhook endpoints3Provider-facing, signature-authenticated (no bearer).

Nothing in these docs is legal advice — always confirm compliance posture with your own counsel.