Just noticed that the Service Level percentage derived from raw interval data does not match the dashboard metric. I am pulling data from /api/v2/analytics/conversations/details/summary with a granularity of hour. The goal is to calculate the percentage of calls answered within 20 seconds using the raw response objects rather than relying on pre-aggregated metrics.
My current logic iterates through the intervals and sums the waitTime where answerTime is less than 20000 milliseconds. I then divide this by the total offerCount. However, the resulting percentage is significantly lower than the official SLA report. The endpoint returns a JSON payload containing metrics arrays for each interval.
Is the offerCount metric inclusive of abandoned calls in this context? Or should I be using handledCount instead? I suspect the denominator is skewed by calls that were never answered, but the documentation is ambiguous about which metric represents the true ‘offered’ population for SLA calculations.
This is typically caused by the fundamental difference between how the Analytics API aggregates interval data versus how the dashboard calculates real-time service level. The /api/v2/analytics/conversations/details/summary endpoint returns aggregated metrics per interval, but it does not provide the raw waitTime for every individual call within that hour. You are trying to reconstruct a precise percentage from bucketed averages, which introduces significant rounding errors and loses the granular timing data required for an exact SLA calculation.
To get the actual service level percentage, you must query the specific report designed for this metric. Use the /api/v2/analytics/queues/details endpoint with the report type queue/conversation/metrics. This returns the percentWithinServiceLevel field directly, which is calculated server-side using the precise threshold defined in your queue settings. This avoids the mathematical drift inherent in client-side summation of interval summaries.
Here is the correct payload structure for the request. Ensure your date range aligns exactly with the dashboard view.
You should probably look at at the waitTime distribution buckets instead of trying to reverse-engineer the percentage from aggregated averages. The summary endpoint gives you totals, but losing the individual call granularity is exactly why your math is off. Coming from Five9, I initially tried the same logic and got burned by the rounding errors in the hourly buckets.
Instead, use the /api/v2/analytics/conversations/details/summary endpoint but request the waitTime grouping. This returns a histogram of calls per wait-time bucket. You can sum the calls in the 0-20s buckets and divide by total answered calls. It’s not perfect real-time, but it’s accurate for historical reporting.
{
"groupings": ["waitTime"],
"interval": "PT1H"
}
Check the waitTime bucket boundaries in the response
Verify OAuth scopes include analytics:conversation:view
Compare against /api/v2/analytics/conversations/summary for baseline metrics
It depends, but generally you need to weight the count by the wait time distribution. Aggregated averages hide the tail. Use the Python SDK to fetch the distribution buckets and sum the counts where the upper bound is less than your SL threshold. This aligns with the dashboard logic.
# Sum counts from distribution buckets <= SL threshold
Note: Verify your OAuth scopes include analytics:report:read.
How I usually solve this is by bypassing the summary endpoint entirely and fetching the raw distribution buckets via platformClient.AnalyticsApi.getConversationDetailsSummary with includeDistribution=true. This aligns with the dashboard logic by using weighted counts from the waitTimeDistribution array rather than reverse-engineering averages.