How to Query Real-Time Queue Metrics via Genesys Cloud Statistics API
What You Will Build
- This tutorial builds a script that retrieves real-time queue statistics, specifically waiting call counts and available agent counts, for a specific queue in Genesys Cloud.
- The solution uses the Genesys Cloud Statistics API (
/api/v2/analytics/queues/details/query) with the Python SDK. - The code is written in Python 3.9+ using the
genesyscloudpackage.
Prerequisites
- OAuth Client: A Public or Confidential OAuth client with the
analytics:statistics:viewscope. - SDK Version:
genesyscloudPython SDK version 160.0.0 or later. - Runtime: Python 3.9 or higher.
- Dependencies:
genesyscloudlibrary installed via pip.
pip install genesyscloud
Authentication Setup
Genesys Cloud uses OAuth 2.0 for authentication. For real-time statistics, a short-lived access token is sufficient, but for production scripts, you must handle token expiration. The Python SDK provides a PureCloudPlatformClientV2 instance that manages the token lifecycle automatically if configured correctly.
You must configure the client with your environment URL, client ID, and client secret. The SDK supports both Public Key (PKCE) and Confidential Client flows. For server-side scripts, the Confidential Client flow is standard.
import os
from purecloudplatformclientv2 import PureCloudPlatformClientV2, Configuration
def init_platform_client() -> PureCloudPlatformClientV2:
"""
Initializes the Genesys Cloud Platform Client with OAuth2 credentials.
Returns:
PureCloudPlatformClientV2: The authenticated client instance.
"""
# Load credentials from environment variables for security
client_id = os.getenv("GENESYS_CLIENT_ID")
client_secret = os.getenv("GENESYS_CLIENT_SECRET")
env_url = os.getenv("GENESYS_ENVIRONMENT", "us-east-1.my.genesys.cloud")
if not client_id or not client_secret:
raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET must be set.")
# Create the configuration object
config = Configuration(
host=f"https://{env_url}",
client_id=client_id,
client_secret=client_secret
)
# Initialize the platform client
# The client will automatically handle token acquisition and refresh
return PureCloudPlatformClientV2(config)
# Initialize the client at module level or within main
platform_client = init_platform_client()
The Configuration object stores the credentials. When you make an API call, the SDK checks if a valid token exists. If not, it performs the OAuth client credentials grant flow to obtain one. The token is cached in memory for the duration of the session.
Implementation
Step 1: Construct the Query Request Body
The Statistics API does not use simple GET parameters for filtering. Instead, it uses a POST endpoint with a JSON body that defines the query. This body must include:
interval: For real-time data, userealtime.dateFromanddateTo: Even forrealtime, these are required. They define the window for aggregated metrics if requested, but forrealtimemode, they are largely ignored by the engine, yet mandatory for schema validation.view: The metric set to retrieve. For queues, usequeue.entities: A list of queue IDs or names you want to query.groupBy: How to aggregate the data. Usuallyentity(per queue) ornone(total).
The required OAuth scope for this operation is analytics:statistics:view.
from purecloudplatformclientv2.rest import ApiException
import json
def build_query_request(queue_ids: list[str]) -> dict:
"""
Builds the JSON payload for the /api/v2/analytics/queues/details/query endpoint.
Args:
queue_ids: List of Queue IDs to query.
Returns:
dict: The request body for the statistics query.
"""
# For real-time queries, the interval must be 'realtime'
# dateFrom and dateTo are required fields even for real-time queries
# Use ISO 8601 format with timezone offset
request_body = {
"interval": "realtime",
"dateFrom": "2023-01-01T00:00:00.000Z",
"dateTo": "2023-01-01T01:00:00.000Z",
"view": "queue",
"groupBy": ["entity"],
"entities": [
{"id": q_id} for q_id in queue_ids
],
# Optional: Filter by specific metric types if you want to reduce payload size
# However, for 'queue' view, most useful metrics are included by default
}
return request_body
Step 2: Execute the API Call
You must use the AnalyticsApi from the SDK. The method is post_analytics_queues_details_query. This method accepts the request body defined in Step 1.
You must handle potential errors:
- 401 Unauthorized: Token is invalid or expired. The SDK usually retries, but if it fails, check your client secrets.
- 403 Forbidden: The OAuth client lacks the
analytics:statistics:viewscope. - 429 Too Many Requests: You have exceeded the rate limit. Implement exponential backoff.
- 400 Bad Request: The JSON body is malformed or invalid.
from purecloudplatformclientv2 import AnalyticsApi
import time
def get_realtime_queue_stats(queue_ids: list[str], retries: int = 3) -> dict:
"""
Fetches real-time statistics for a list of queues.
Args:
queue_ids: List of Queue IDs.
retries: Number of retry attempts for 429 errors.
Returns:
dict: The response body containing queue metrics.
"""
analytics_api = AnalyticsApi(platform_client)
request_body = build_query_request(queue_ids)
attempt = 0
while attempt < retries:
try:
# Post the query to the Analytics API
response = analytics_api.post_analytics_queues_details_query(body=request_body)
# Log success
print(f"Successfully retrieved data for {len(queue_ids)} queues.")
return response
except ApiException as e:
print(f"API Call failed with status: {e.status}")
print(f"Reason: {e.reason}")
print(f"Error body: {e.body}")
# Handle Rate Limiting (429)
if e.status == 429:
wait_time = 2 ** attempt # Exponential backoff: 1s, 2s, 4s
print(f"Rate limited. Retrying in {wait_time} seconds...")
time.sleep(wait_time)
attempt += 1
else:
# For other errors, re-raise immediately
raise
raise Exception("Max retries exceeded for 429 Too Many Requests.")
Step 3: Parse the Response for Waiting Count and Available Agents
The response from /api/v2/analytics/queues/details/query is a complex nested object. It contains an entities array, where each item represents a queue. Inside each queue entity, there is a metrics object.
The key metrics you need are:
waitingCount: The number of interactions currently waiting in the queue.availableCount: The number of agents logged in and available to take calls for this queue.smalltalkCount: Agents on hold after a call.wrapupCount: Agents in wrap-up state.
The metrics object contains keys for different interaction types (e.g., call, callback, chat). For voice queues, you typically look at call.
def extract_queue_metrics(response: dict) -> dict:
"""
Parses the API response to extract waiting count and available agents.
Args:
response: The raw response from post_analytics_queues_details_query.
Returns:
dict: A simplified dictionary with queue IDs as keys and metrics as values.
"""
results = {}
# Check if response has entities
if not hasattr(response, 'entities') or response.entities is None:
print("No entities found in response.")
return results
for entity in response.entities:
# entity.id is the Queue ID
queue_id = entity.id
queue_name = entity.name
# Initialize metrics for this queue
queue_metrics = {
"queueId": queue_id,
"queueName": queue_name,
"waitingCount": 0,
"availableCount": 0,
"wrapupCount": 0,
"smalltalkCount": 0
}
# Check if metrics exist for this entity
if hasattr(entity, 'metrics') and entity.metrics:
metrics = entity.metrics
# We focus on 'call' metrics for voice queues
if 'call' in metrics:
call_metrics = metrics['call']
# Extract waiting count
if 'waitingCount' in call_metrics:
queue_metrics['waitingCount'] = call_metrics['waitingCount']
# Extract available agent count
if 'availableCount' in call_metrics:
queue_metrics['availableCount'] = call_metrics['availableCount']
# Extract wrapup count
if 'wrapupCount' in call_metrics:
queue_metrics['wrapupCount'] = call_metrics['wrapupCount']
# Extract smalltalk count
if 'smalltalkCount' in call_metrics:
queue_metrics['smalltalkCount'] = call_metrics['smalltalkCount']
results[queue_id] = queue_metrics
return results
Complete Working Example
This script combines authentication, query construction, API execution, and response parsing into a single runnable module. Replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with actual values or set the environment variables.
import os
import sys
import time
from purecloudplatformclientv2 import PureCloudPlatformClientV2, Configuration, AnalyticsApi
from purecloudplatformclientv2.rest import ApiException
def init_platform_client() -> PureCloudPlatformClientV2:
"""Initializes the Genesys Cloud Platform Client."""
client_id = os.getenv("GENESYS_CLIENT_ID")
client_secret = os.getenv("GENESYS_CLIENT_SECRET")
env_url = os.getenv("GENESYS_ENVIRONMENT", "us-east-1.my.genesys.cloud")
if not client_id or not client_secret:
raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET must be set.")
config = Configuration(
host=f"https://{env_url}",
client_id=client_id,
client_secret=client_secret
)
return PureCloudPlatformClientV2(config)
def get_realtime_queue_stats(queue_ids: list[str], platform_client: PureCloudPlatformClientV2, retries: int = 3) -> dict:
"""Fetches real-time statistics for a list of queues."""
analytics_api = AnalyticsApi(platform_client)
# Build the request body
request_body = {
"interval": "realtime",
"dateFrom": "2023-01-01T00:00:00.000Z",
"dateTo": "2023-01-01T01:00:00.000Z",
"view": "queue",
"groupBy": ["entity"],
"entities": [{"id": q_id} for q_id in queue_ids]
}
attempt = 0
while attempt < retries:
try:
response = analytics_api.post_analytics_queues_details_query(body=request_body)
return response
except ApiException as e:
if e.status == 429:
wait_time = 2 ** attempt
print(f"Rate limited. Retrying in {wait_time} seconds...")
time.sleep(wait_time)
attempt += 1
else:
raise
def extract_queue_metrics(response: dict) -> dict:
"""Parses the API response to extract waiting count and available agents."""
results = {}
if not hasattr(response, 'entities') or response.entities is None:
return results
for entity in response.entities:
queue_id = entity.id
queue_name = entity.name
queue_metrics = {
"queueId": queue_id,
"queueName": queue_name,
"waitingCount": 0,
"availableCount": 0
}
if hasattr(entity, 'metrics') and entity.metrics and 'call' in entity.metrics:
call_metrics = entity.metrics['call']
queue_metrics['waitingCount'] = call_metrics.get('waitingCount', 0)
queue_metrics['availableCount'] = call_metrics.get('availableCount', 0)
results[queue_id] = queue_metrics
return results
def main():
# 1. Initialize Client
try:
client = init_platform_client()
except Exception as e:
print(f"Failed to initialize client: {e}")
sys.exit(1)
# 2. Define Queue IDs (Replace with actual IDs from your environment)
# You can get these via the Platform API: GET /api/v2/queues
target_queue_ids = [
"12345678-1234-1234-1234-123456789012",
"87654321-4321-4321-4321-210987654321"
]
# 3. Fetch Data
try:
response = get_realtime_queue_stats(target_queue_ids, client)
except ApiException as e:
print(f"API Error: {e}")
sys.exit(1)
# 4. Parse and Display Results
metrics = extract_queue_metrics(response)
print("\n--- Real-Time Queue Statistics ---")
for q_id, data in metrics.items():
print(f"Queue: {data['queueName']} (ID: {data['queueId']})")
print(f" Waiting Calls: {data['waitingCount']}")
print(f" Available Agents: {data['availableCount']}")
print("-" * 30)
if __name__ == "__main__":
main()
Common Errors & Debugging
Error: 403 Forbidden
Cause: The OAuth client does not have the analytics:statistics:view scope.
Fix: Go to the Genesys Cloud Admin Console → Settings → Integrations → OAuth Clients. Select your client, edit it, and ensure analytics:statistics:view is checked under the Scopes section. Save and re-generate the token.
Error: 429 Too Many Requests
Cause: The Analytics API has strict rate limits, especially for realtime queries which hit the live data store.
Fix: Implement exponential backoff as shown in the get_realtime_queue_stats function. Do not poll faster than once every 10-15 seconds for real-time data unless you have negotiated higher limits with Genesys Support.
Error: Empty Entities List
Cause: The queue IDs provided do not exist, or the OAuth client does not have access to those queues (security profiles).
Fix: Verify the queue IDs using GET /api/v2/queues/{id}. Ensure the OAuth client’s associated security profile has Queue: View permissions.
Error: Metrics Missing call Key
Cause: The queue is not configured for voice calls, or no call metrics are available in the current real-time snapshot.
Fix: Check the view parameter. If you are querying a chat queue, look for chat in the metrics object instead of call. Ensure the queue actually has interactions routed to it.