Get a campaign's statistics
Returns the campaign’s aggregated performance on one of two bases, told apart by range in the response:
- All-time (no
dateFrom/dateTo): lifetime counters served from a projection refreshed in the background —updated_attells you how fresh they are, andrangeis null.call_durationsis included only whenincludeDurations=true(it is the one read whose cost grows with the campaign). - Ranged (
dateFromanddateToboth set): counters aggregated at request time over the half-open window[dateFrom, dateTo).rangeechoes the resolved window,updated_atis null, and durations are always included (includeDurationsis ignored).
A date-only dateTo (YYYY-MM-DD) names a calendar day and is served inclusive of it — the exclusive end moves to the following UTC midnight, so equal date-only bounds are a valid one-day window. There is no limit on the window’s length; the only bound is the 13-month event retention horizon on dateFrom. Supplying only one bound, an empty window, or a dateFrom past the horizon is a 422.
The membership-state blocks (contact_states*, pending_by_category, open_assignments) always describe the campaign’s current state — a window does not narrow them. Unknown query parameters are rejected with 400 rather than ignored. A campaign that has never been dialed returns zeroed counters, not 404.
Authorizations
HTTP Basic Authentication. Use your API Access Key ID as the username and your API Access Key Secret as the password. Generate keys in the CloudTalk Dashboard under Account -> Settings -> API Keys (https://dashboard.cloudtalk.io/menu/account/settings/API-keys).
Path Parameters
Dialer campaign ID.
^[1-9][0-9]*$Query Parameters
Inclusive lower bound of the statistics window (ISO 8601). Requires dateTo. Must not be older than the 13-month event retention horizon.
Exclusive upper bound of the statistics window (ISO 8601). Requires dateFrom. A date-only value is served inclusive of that day.
Set to true to include the call_durations block on an all-time read. Ignored on a ranged read, which always carries durations. Only the literal strings true and false are accepted — anything else is a 400.
Response
The campaign's statistics.
Aggregated campaign performance. range tells the basis apart: null means all-time (cumulative over the campaign's lifetime, updated_at set), non-null means the counters cover exactly that window (updated_at null). The membership-state blocks always describe the campaign's current state regardless of any window.
Campaign ID the statistics belong to.
"42"
Contact counts per campaign-membership state.
Per-state count of contacts that have at least one phone number — a breakout of contact_states, not a filter.
Per-state count of contacts already attempted at least once — a breakout of contact_states, not a filter. Subtract it from contact_states for the never-attempted counts.
Breakout of contact_states.pending by waterfall category — the four sum exactly to the pending total. Includes non-dialable pending contacts, so it is not an available-to-dial count.
Contacts that were members of the campaign at the window's end (on an all-time read: the full current membership).
165
Contacts currently held by agents. Always a current-state count, never narrowed by the window.
3
Calls placed.
240
Calls answered.
150
total_answered / total_dialed, in the range 0–1.
0.625
Calls dispositioned as rescheduled.
12
Calls dropped before an agent could take them.
3
Calls that received a disposition.
96
Calls dispositioned with a positive outcome.
30
num_conversions / num_dispositioned, in the range 0–1.
0.3125
Attempts that reached a human.
130
Attempts that reached a voicemail.
15
Attempts that reached another machine (IVR, queue, tone).
5
Attempts split by whether they were the contact's first attempt or a repeat.
Distinct contacts dialed inside the window. Ranged-only — null on every all-time response.
null
Distinct contacts that answered. Never null; an all-time read counts contacts whose first answer is on record, a ranged read counts distinct answered contacts inside the window.
112
Duration aggregate over the calls the basis covers; all values are whole seconds. Null means the block is not on the response — an all-time read without includeDurations=true, or a failed-open duration lookup. An all-zero block is a real answer: the window's calls simply carry no recorded duration yet (calls can trail the dialed count — duration records lag the dial). Zero and null must be treated as different states.
Per-tag disposition counts.
Freshness of the all-time projection (ISO 8601, UTC). Null on every ranged response, and null on an all-time response whose projection has not materialized yet.
"2026-08-04T11:40:00.000Z"
The resolved statistics window — the field that tells you which basis the counters are on: null on an all-time response, set on a ranged one. to is exclusive; a date-only dateTo is echoed here already advanced to the following UTC midnight, so the echo may not equal the request literally.