curl --request GET \
--url https://{host}/api/v1/campaigns/{id}/stats \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://{host}/api/v1/campaigns/{id}/stats', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{host}/api/v1/campaigns/{id}/stats"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"abandon_rate": 123,
"abandoned": 123,
"answer_rate": 123,
"answered": 123,
"campaign_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"dialed": 123,
"done": 123,
"failed": 123,
"in_flight": 123,
"max_abandon_pct": "<string>",
"name": "<string>",
"pending": 123,
"scheduled": true,
"status": "<string>",
"suppressed": 123,
"total": 123,
"start_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}What a campaign is doing right now
Meant to be polled while a campaign runs. In flight is counted from leased contacts rather than from live channels: the dialer sets a campaign id as a channel variable, but the switch’s channel listing does not surface custom variables, so it cannot be filtered by campaign.
curl --request GET \
--url https://{host}/api/v1/campaigns/{id}/stats \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://{host}/api/v1/campaigns/{id}/stats', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{host}/api/v1/campaigns/{id}/stats"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"abandon_rate": 123,
"abandoned": 123,
"answer_rate": 123,
"answered": 123,
"campaign_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"dialed": 123,
"done": 123,
"failed": 123,
"in_flight": 123,
"max_abandon_pct": "<string>",
"name": "<string>",
"pending": 123,
"scheduled": true,
"status": "<string>",
"suppressed": 123,
"total": 123,
"start_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}Authorizations
Every request sends Authorization: Bearer <token>. The token is either a panel session (a JWT from /auth/login, 12 hours) or an API key ft_<id>_<secret>. An API key is accepted only from an address on its IP allowlist (403 ip_not_allowed otherwise; 403 ip_allowlist_required for an old key that has none), is limited to its rate per minute (429 rate_limited with Retry-After; X-RateLimit-Limit/Remaining/Reset on every response), and at most 60 call placements a minute.
Path Parameters
Response
OK
What a campaign is doing right now. The dialer's own counters come from the campaign row, because the pacer reads them every tick and an aggregate over call history would get slower exactly as a campaign got busier. Everything about the list is counted from the contact states.
Abandoned as a percentage of ANSWERED calls, not of everything dialled -- the denominator a regulator measures, and the one the pacer's governor uses.
Answered by a person who reached no agent. The figure max_abandon_pct governs.
Answered as a percentage of dialled.
Contacts currently leased to the dialer: a call has been placed and has not finished. Counted from the lease rather than from live channels, because show channels carries no campaign id.
The campaign's compliance ceiling, for comparison with abandon_rate.
Running, but its start time has not arrived. Not a status of its own -- it is the difference between dialling nothing because it is waiting and dialling nothing because something is wrong.
On the list and never dialled: do-not-call or blacklisted.