Why does this setting result in a Service Level percentage that does not match the Architect dashboard when using GET /api/v2/analytics/conversations/details/query? I am summing answered and dividing by offered for intervals where waitTime <= threshold, but the aggregate is off by 0.5% compared to the UI.
You need to stop aggregating raw interval data manually. The Service Level metric in NICE CXone is not a simple sum of answered calls. It requires a specific weighted calculation that accounts for the exact second each call was answered relative to the SL threshold. Using GET /api/v2/analytics/conversations/details/query gives you granular event data, which introduces rounding errors when you try to force an aggregate percentage. Switch to the summary endpoint instead. Use GET /api/v2/analytics/icm/queues/query with the metric serviceLevel. This endpoint returns the pre-calculated, system-authoritative percentage. It aligns exactly with the Architect dashboard because it uses the same internal aggregation engine. Do not try to reinvent the SL logic with client-side math on interval data. It will always drift due to timestamp precision and edge-case handling for abandoned calls. The correct payload structure for the summary query is:
This happens because the aggregation logic not accounting for the specific span context propagation required for accurate Service Level (SL) calculation in distributed tracing environments. When you manually sum answered and divide by offered from the raw Analytics API, you are missing the precise wait-time distribution that the SL metric relies on. The discrepancy of 0.5% indicates that your local aggregation is rounding intervals rather than calculating the weighted average of wait times against the threshold.
To fix this, you should stop calculating SL from raw interval data and instead use the dedicated Service Level endpoint or ensure your query includes the correct groupBy metrics for waitTime distribution. Here is how to structure the query to get accurate SL data:
from purecloudplatformclientv2 import AnalyticsApi, GetConversationDetailsQueryRequest
# Initialize API client
analytics_api = AnalyticsApi()
# Define the query with specific SL metrics
query = {
"interval": "PT5M",
"query": {
"filter": "type eq 'voice'",
"groupBy": ["metricId"],
"metrics": [
{"id": "answered"},
{"id": "offered"},
{"id": "serviceLevelPercent"} # Use the pre-calculated metric
]
},
"dateFrom": "2023-10-01T00:00:00.000Z",
"dateTo": "2023-10-01T23:59:59.999Z"
}
# Execute the query
request = GetConversationDetailsQueryRequest(body=query)
response = analytics_api.post_analytics_conversations_details_query(request)
# Extract the pre-calculated Service Level percentage
for interval in response.entity.intervals:
for metric in interval.metrics:
if metric.id == "serviceLevelPercent":
print(f"SL%: {metric.value}")
The main issue here is that the Analytics API documentation explicitly states, “Service Level is calculated as the percentage of conversations answered within a specified time threshold.” It does not mention weighted averages or span context. You are likely misinterpreting the waitTime field in the raw JSON response. The API returns waitTime in milliseconds, but the threshold in your query might be in seconds, causing a mismatch in comparison logic. I copied the example from the docs which uses waitTime <= 20000 for a 20-second SL. If your threshold is defined differently in the query parameters versus the filter, the count will be wrong. Try using the aggregate endpoint instead: GET /api/v2/analytics/conversations/summary/query with groupBy: ["interval"] and metrics: ["serviceLevel"]. This returns the pre-calculated percentage directly, avoiding any manual summation errors. Why are we reinventing the wheel when the API provides the exact metric?
this looks like a unit mismatch issue. ensure waittime is converted to seconds before comparing against threshold in your local logic. use {{response.waitTime / 1000}} to align units.