Stats & usage
Generated from
DialerDigital/corecommit6e9f026f0a72— specopenapi/dialer-v1.yamlv0.36.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.
Operational counters, blocked-dial rollups, usage metering.
Endpoints
| Method | Path | Summary |
|---|---|---|
GET | /v1/stats/summary | Today's operational counters (UTC day) |
GET | /v1/stats/promises | PTP pipeline summary |
GET | /v1/stats/penetration | Person-level penetration analytics |
GET | /v1/stats/blocked | Durable blocked-dial rollup |
GET | /v1/stats/capacity | Tenant capacity ceilings + live usage (ADR |
GET | /v1/stats/ai-usage | Voice-AI minute metering (invoicing read) |
GET | /v1/stats/sms-usage | SMS segment metering (invoicing read) |
Today's operational counters (UTC day)
GET /v1/stats/summaryComputed from the append-only CDR + live seat registry — reconstructible truth, not cached state.
Responses
200
Today's counters.
| Field | Type | Required | Description |
|---|---|---|---|
date | string (date) | no | |
window | "utc_day" | no | |
calls_today | integer | no | |
connected_today | integer | no | |
connect_rate | number | no | |
agents_online | integer | no | |
agents_available | integer | no | |
campaigns_running | integer | no |
{
"date": "2026-07-05",
"window": "utc_day",
"calls_today": 412,
"connected_today": 67,
"connect_rate": 0.1626,
"agents_online": 5,
"agents_available": 3,
"campaigns_running": 2
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}PTP pipeline summary
GET /v1/stats/promisesCurrencies never sum together; kept_rate_30d is null when nothing resolved in the window.
Responses
200
Pipeline summary.
| Field | Type | Required | Description |
|---|---|---|---|
open | object | no | |
open.count | integer | no | |
open.amount_cents | object | no | Per-currency sums — currencies never sum together. |
kept_rate_30d | number | null | no | Over promises RESOLVED with promised_date in the last 30 days; null = none resolved. |
window_days | integer | no |
{
"open": {
"count": 4,
"amount_cents": {
"USD": 50000,
"MXN": 120000
}
},
"kept_rate_30d": 0.75,
"window_days": 30
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}Person-level penetration analytics
GET /v1/stats/penetrationPerson-level dedup (each debt counts once): attempted = at least one original attempt, reached = any non-failed disposition or conversation, effective_contact = answered_human or conversation. campaign_ids is required (max 100; campaign_id= also accepted).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
campaign_ids | query | string | yes | Comma-separated campaign UUIDs (max 100). |
from | query | string (date-time) | no | RFC 3339 lower bound (endpoint-specific field; default trailing 30 UTC days where noted). |
to | query | string (date-time) | no | RFC 3339 upper bound. |
Responses
200
Penetration totals + per-campaign rows.
| Field | Type | Required | Description |
|---|---|---|---|
totals | object (PenetrationRow) | no | |
totals.campaign_id | string (uuid) | null | no | |
totals.unique_accounts | integer | no | |
totals.unique_consumers | integer | no | |
totals.attempted | integer | no | |
totals.reached | integer | no | |
totals.effective_contact | integer | no | |
totals.attempted_pct | number | no | |
totals.reached_pct | number | no | |
totals.effective_contact_pct | number | no | |
by_campaign | array of PenetrationRow | no | |
by_campaign[].campaign_id | string (uuid) | null | no | |
by_campaign[].unique_accounts | integer | no | |
by_campaign[].unique_consumers | integer | no | |
by_campaign[].attempted | integer | no | |
by_campaign[].reached | integer | no | |
by_campaign[].effective_contact | integer | no | |
by_campaign[].attempted_pct | number | no | |
by_campaign[].reached_pct | number | no | |
by_campaign[].effective_contact_pct | number | no |
{
"totals": {
"campaign_id": null,
"unique_accounts": 4,
"unique_consumers": 4,
"attempted": 2,
"reached": 1,
"effective_contact": 1,
"attempted_pct": 50,
"reached_pct": 25,
"effective_contact_pct": 25
},
"by_campaign": [
{
"campaign_id": "3f2c1b0a-9d8e-4c7b-a6f5-4e3d2c1b0a99",
"unique_accounts": 4,
"unique_consumers": 4,
"attempted": 2,
"reached": 1,
"effective_contact": 1,
"attempted_pct": 50,
"reached_pct": 25,
"effective_contact_pct": 25
}
]
}400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}Durable blocked-dial rollup
GET /v1/stats/blockedReads the durable, APPEND-ONLY gate_blocks evidence: one row per (debt, gate, campaign, UTC day) the compliance engine REFUSED to dial. Every number is a count of distinct refusals, never an estimate. Defaults: trailing 30 UTC days.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from | query | string (date-time) | no | RFC 3339 lower bound (endpoint-specific field; default trailing 30 UTC days where noted). |
to | query | string (date-time) | no | RFC 3339 upper bound. |
campaign_id | query | string (uuid) | no |
Responses
200
Blocked-dial rollup.
| Field | Type | Required | Description |
|---|---|---|---|
from | string (date-time) | no | |
to | string (date-time) | no | |
campaign_id | string (uuid) | null | no | |
total | integer | no | |
by_gate | object | no | Keys are the ComplianceGate vocabulary. |
daily | array of object | no | |
daily[].date | string (date) | no | |
daily[].total | integer | no | |
daily[].by_gate | object | no |
{
"from": "2026-06-05T00:00:00Z",
"to": "2026-07-05T00:00:00Z",
"campaign_id": null,
"total": 5,
"by_gate": {
"quiet_hours": 4,
"dnc_listed": 1
},
"daily": [
{
"date": "2026-06-01",
"total": 3,
"by_gate": {
"quiet_hours": 2,
"dnc_listed": 1
}
}
]
}400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}Tenant capacity ceilings + live usage (ADR
GET /v1/stats/capacityThe tenant's admin-set capacity ceilings (max_cps, max_concurrent_channels; null = no ceiling) plus live usage read from the capacity gate. limits: null = the ceilings could not be read AND were never cached — the exact condition the gate fails CLOSED on; surfaced honestly, never fabricated as "unlimited".
supervision is a SECOND, independent ceiling (ADR #37): live-call supervision legs originate outside the dial choke point, so they are counted in their own quota. Neither lane can exhaust the other — the dialing floor can be at its ceiling while supervision still admits, and vice versa.
Responses
200
Capacity ceilings + live usage.
| Field | Type | Required | Description |
|---|---|---|---|
limits | object | null | no | Admin-set ceilings, or null when the gate fails closed (ceilings unreadable and never cached). Each ceiling is null when unset. |
channels_in_use | integer | no | |
dials_last_second | integer | no | |
supervision | object | no | The SECOND ceiling (ADR #37): concurrent live-call supervision sessions, counted and bounded separately from the dialing lane so neither can starve the other. limit is the deploy-time max_supervision_channels; in_use counts (call, supervisor) sessions, so a listen → barge switch on one call counts once. |
supervision.limit | integer | no | |
supervision.in_use | integer | no |
{
"limits": {
"max_cps": 10,
"max_concurrent_channels": 50
},
"channels_in_use": 3,
"dials_last_second": 2,
"supervision": {
"limit": 20,
"in_use": 1
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}Voice-AI minute metering (invoicing read)
GET /v1/stats/ai-usageOff the durable exactly-once ai_usage feed (one row per answered AI call, billed EXACTLY ONCE on call_uuid). Each row snapshots the per-minute rate it was metered under — changing the configured rate never reprices history. The window is half-open — from inclusive, to EXCLUSIVE — so a call answered exactly at a billing cut belongs to one period only (the one starting at that instant), never to both sides of the cut. ?format=csv (or Accept: text/csv) returns the billing artifact with its own X-Artifact-SHA256.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from | query | string (date-time) | no | RFC 3339 lower bound (endpoint-specific field; default trailing 30 UTC days where noted). |
to | query | string (date-time) | no | RFC 3339 upper bound. |
campaign_id | query | string (uuid) | no | |
format | query | csv | no | csv for the downloadable artifact (equivalent: Accept: text/csv). |
Responses
200
Metering stats (JSON) or the CSV billing artifact.
| Field | Type | Required | Description |
|---|---|---|---|
from | string (date-time) | no | |
to | string (date-time) | no | |
campaign_id | string (uuid) | null | no | |
minute_rate_usd | number | no | |
calls | integer | no | |
billable_seconds | integer | no | |
billable_minutes | number | no | |
estimated_cost_usd | number | no | |
daily | array of object | no | |
daily[].date | string (date) | no | |
daily[].calls | integer | no | |
daily[].billable_seconds | integer | no | |
daily[].billable_minutes | number | no | |
daily[].minute_rate_usd | number | no | |
daily[].estimated_cost_usd | number | no |
{
"from": "2026-06-05T00:00:00Z",
"to": "2026-07-05T00:00:00Z",
"campaign_id": null,
"minute_rate_usd": 0.25,
"calls": 3,
"billable_seconds": 270,
"billable_minutes": 4.5,
"estimated_cost_usd": 1.13,
"daily": [
{
"date": "2026-06-01",
"calls": 2,
"billable_seconds": 180,
"billable_minutes": 3,
"minute_rate_usd": 0.25,
"estimated_cost_usd": 0.75
}
]
}400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}SMS segment metering (invoicing read)
GET /v1/stats/sms-usageStraight off the unified ledger: sms_segment billable events, exactly-once at provider ACCEPT, each priced at its region-rate snapshot. JSON, or ?format=csv / Accept: text/csv for the billing artifact.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from | query | string (date-time) | no | RFC 3339 lower bound (endpoint-specific field; default trailing 30 UTC days where noted). |
to | query | string (date-time) | no | RFC 3339 upper bound. |
campaign_id | query | string (uuid) | no | |
format | query | csv | no | csv for the downloadable artifact (equivalent: Accept: text/csv). |
Responses
200
Metering stats (JSON) or the CSV billing artifact.
| Field | Type | Required | Description |
|---|---|---|---|
from | string (date-time) | no | |
to | string (date-time) | no | |
campaign_id | string (uuid) | null | no | |
segment_rates_usd | object | no | Per-region rate currently in force (what new sends will snapshot). |
messages | integer | no | |
segments | string | no | Decimal as string. |
amount_usd | string | no | Decimal as string. |
daily | array of object | no | |
daily[].date | string (date) | no | |
daily[].messages | integer | no | |
daily[].segments | string | no | |
daily[].segment_rate_usd | string | no | |
daily[].amount_usd | string | no |
{
"from": "2026-06-05T00:00:00Z",
"to": "2026-07-05T00:00:00Z",
"campaign_id": null,
"segment_rates_usd": {
"us": "0.0100",
"mx": "0.0300",
"eu": "0.0500"
},
"messages": 2,
"segments": "3",
"amount_usd": "0.03",
"daily": [
{
"date": "2026-07-01",
"messages": 2,
"segments": "3",
"segment_rate_usd": "0.0100",
"amount_usd": "0.03"
}
]
}400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}