Deprecating /api/v2/routing/queue/{id}/users endpoints, replacing with alernatives

Category: API

Summary: Due to performance problems with the existing GET /routing/queue/{id}/users endpoint, the five endpoints using that path are being deprecated and replaced with alternatives at /routing/queue/{id}/members.

Context: With certain filters enabled, the GET /routing/queue/{id}/users implementation has to internally page through all members of a queue to prepare a response. When a queue has lots of members, this is not scalable and has led to performance issues including excessive memory usage and slow response times, which can have platform-wide effects. The chosen solution is to replace the entire set of existing endpoints with a new set.

GET /routing/queue/{id}/users :arrow_right: GET /routing/queue/{id}/members
POST /routing/queue/{id}/users :arrow_right: POST /routing/queue/{id}/members
PATCH /routing/queue/{id}/users :arrow_right: PATCH /routing/queue/{id}/members
PATCH /routing/queue/{id}/users/{id} :arrow_right: PATCH /routing/queue/{id}/members/{id}
DELETE /routing/queue/{id}/users/{id} :arrow_right: DELETE /routing/queue/{id}/members/{id}

Impact: The only change in the functionality of the endpoints is that GET /routing/queue/{id}/members no longer returns totals information -- the total, lastUri, and pageCount fields -- in its response. These fields will not be present at all in the new response. All other new endpoints function identically to what they replace.

Date of Change: Immediate. There is no current timeline for the removal of the deprecated endpoints.

References: AS-1563

We currently use the returned "totals" values to determine if we have agents available or not, so we can reroute the interaction or update the messaging the caller hears. The short version is "how many agents are members of the queue - how many are offqueue = X and if X=0, move the call somewhere else" - I cannot find another endpoint that gives such info - is there one that I am missing or another way to obtain this agent availability info within the context of a data action that can be run via inbound flow?

/api/v2/analytics/queues/observations/query with the metric oMemberUsers might be work for you if you only care about count and not the actual agent ids

Thank you Kevin.

While the announcement does not have a date for the users variant being removed from the platform, is it safe to assume that they will be removed at some point?

Yes, the deprecated resources will be removed at some point in the future. A separate announcement will be made when the removal is scheduled; there's no tentative date yet.

note that you can also just check the entities field to see if there are queue members matching a given set of search criteria. most uses of the totals field have been reported as just being to see if totals > 0 or not; checking entities for actual results has the same effect.

I've created 2 Call Data Actions to address this, 1 is safer but doesn't give much details, the other gives more detail but may get deprecated too...

Safer Method - using the /api/v2/routing/queues/{queueId}/members API, filtering by On Queue presence, this works in a similar way to retrieving the "total": value when it was /user, "total" as the total is just the total elements/objects in the returned "entities" array, it's what SethAtGenesys is refering to, now you are just doing your own count of how many elements/objects in that array. Config below.

Request:
{
"requestUrlTemplate": "/api/v2/routing/queues/{input.QUEUE_ID}/members?joined=true&presence=On%20Queue", "requestType": "GET", "headers": { "UserAgent": "PureCloudIntegrations/1.0", "Content-Type": "application/x-www-form-urlencoded" }, "requestTemplate": "{input.rawRequest}"
}

Response:

{
"translationMap": {
"OnQueueAgentCount": ".entities.size()" }, "translationMapDefaults": { "OnQueueAgentCount": "0" }, "successTemplate": "{\"OnQueueAgentCount\": {OnQueueAgentCount}}"
}

More detailed way but not as safe (API can break) - using the /api/v2/analytics/queues/observations/query API
You are retrieving some metrics for the queue, I use the “oActiveUsers” and “oUserRoutingStatuses”, you need to be careful though because if no agents are Activated on the queue (a member but deactivated by supervisor or themselves) then no “oUserRoutingStatuses” will be returned and if that is the only metric you are retrieving there will be no “Data” array and the Call Data Action will fail (depending how you write it). I included the “oActiveUsers” metric because it’s a constant, even if no agents are Activated on queue it will still show and return 0, the risk is that if Genesys changes the behavior of "oActiveUsers" to the same as “oUserRoutingStatuses” (not show if not used / 0) then the below Call Data Action will fail as the "data" array will not generate.

Running the API in Developer site as the below,
{
"filter": {
"type": "or",
"clauses": [
{
"type": "or",
"predicates": [
{
"type": "dimension",
"dimension": "queueId",
"operator": "matches",
"value": "ab1bfbda-34c1-4931-a108-56381a30769a"
}
]
}
]
},
"metrics": ["oActiveUsers","oUserRoutingStatuses"]
}

Will return
{
"results": [
{
"group": {
"queueId": "ab1bfbda-34c1-4931-a108-56381a30769a"
},
"data": [
{
"metric": "oActiveUsers",
"stats": {
"count": 3
}
},
{
"metric": "oUserRoutingStatuses",
"qualifier": "OFF_QUEUE",
"stats": {
"count": 3
}
}
]
}
]
}

Call Data Action config is as follows, this allows for 0 values and works if "metric": "oUserRoutingStatuses" doesn’t exist.
Request
{
"requestUrlTemplate": "/api/v2/analytics/queues/observations/query",
"requestType": "POST",
"headers": {},
"requestTemplate": "{"filter": {"type":"or","predicates": [{"dimension": "queueId","value": "${input.QUEUE_ID}"}]}, "metrics": ["oUserRoutingStatuses","oActiveUsers"]}"
}

Response:
{
"translationMap": {
"offqueue": ".results[0].data[?(@.qualifier==\"OFF_QUEUE\")].stats.count", "activeUsers": ".results[0].data[?(@.metric=="oActiveUsers")].stats.count",
"idle": ".results[0].data[?(@.qualifier==\"IDLE\")].stats.count", "interacting": ".results[0].data[?(@.qualifier=="INTERACTING")].stats.count"
},
"translationMapDefaults": {
"offqueue": "0",
"activeUsers": "0",
"idle": "0",
"interacting": "0"
},
"successTemplate": "{"activeUsers": {successTemplateUtils.firstFromArray(\"{activeUsers}", "0")},"interacting": {successTemplateUtils.firstFromArray(\"{interacting}", "0")},"idle": {successTemplateUtils.firstFromArray(\"{idle}", "0")},"offqueue": {successTemplateUtils.firstFromArray(\"{offqueue}", "0")}}"
}

2 Likes

For those accessing the totals property of this endpoint with data actions, there is a robust data action available on the AppFoundry that uses the alternative Analytics endpoints to access this information, and can optionally break down the user counts by routing status. The action is called "Get On Queue Agent Counts" and instructions are included in the package readme file.

Hi SCJohnson,

Thanks for the reference, I just downloaded those and imported the "Get On Queue Agents Counts" one, it is looking at results.data array and only using the "oOnQueueUsers".

The problem is that if there are no agents on queue and you're only looking at metric "oOnQueueUsers" then the data array doesn't get generated (doesn't exist in the returned results), whoever built that API though accommodated for that with the defaults "statuses": "["Error"]","counts": "[0]" (I've copied the configuration below for reference).

The other scenario is you have 2 agents On Queue, 1 is IDLE 1 is Interacting, the way this API is coded it returns a count of 2 , and Status Interacting because it only looks at the first status it matches not all statuses, so it would appear you have 2 agents interacting when there's actually only 1.

If you only care about the agent on queue count then this is fine, but there are better ways to get On Queue Agents.

{
"requestUrlTemplate": "/api/v2/analytics/queues/observations/query",
"requestType": "POST",
"headers": {
"UserAgent": "PureCloudIntegrations/1.0",
"Content-Type": "application/json"
},
"requestTemplate": "{\n "filter": {\n "type": "or",\n "predicates": [\n {\n "type": "dimension",\n "dimension": "queueId",\n "operator": "matches",\n "value": "${input.queueId}"\n }\n ]\n },\n "metrics": [\n "oOnQueueUsers"\n ]\n}"
}

{
"translationMap": {
"statuses": ".results[0].data..qualifier", "counts": ".results[0].data..stats.count"
},
"translationMapDefaults": {
"statuses": "["Error"]",
"counts": "[0]"
},
"successTemplate": "{"counts": {counts}, \"statuses\": {statuses}}"
}

Hi Nathan,
Regarding the first item, this is intentional and should not be problematic for the intended use case of the action. If no agents are on queue, the count returned by the data action should be zero.

Regarding the second item, this is actually not the case. The data action returns two parallel arrays, one with a list of routing statuses, and another with the corresponding list of counts per routing status. This provides you the flexibility to either get the total on-queue agent count (by summing the contents of the counts array) or by selecting specific routing statuses that are desired. In your above example, if 1 agent is idle and 1 agent is interacting, the statuses array will contain two entries: an entry for IDLE, and an entry for INTERACTING. In the counts array, the corresponding counts for those routing statuses are returned, so you would see each agent represented by the appropriate routing status. As a bonus, the parallel array design means that you will not need to re-publish this action in the scenario that routing statuses change in the future.

The readme.md file in the AppFoundry package contains examples on how to access this information from the action output within an Architect flow in a robust manner:

Example usage: output variables in the example are Flow.QueueCounts for the counts output, and Flow.StatusList for the statuses output

Check if there are any agents on queue: sum(Flow.QueueCounts) > 0

Get number of idle agents: If(FindFirst(Flow.StatusList, "IDLE") >= 0, GetAt(Flow.QueueCounts, FindFirst(Flow.StatusList, "IDLE")), 0)

Get number of interacting agents: If(FindFirst(Flow.StatusList, "INTERACTING") >= 0, GetAt(Flow.QueueCounts, FindFirst(Flow.StatusList, "INTERACTING")), 0)

Get number of not responding agents: If(FindFirst(Flow.StatusList, "NOT_RESPONDING") >= 0, GetAt(Flow.QueueCounts, FindFirst(Flow.StatusList, "NOT_RESPONDING")), 0)

Just retested it, the first did I did didn't show multiple statuses for some reason, it did the second time.

This is good way of doing it, but unless you need to know the statuses or do some more advanced routing, and all you need is to know how many agents are On Queue no matter their routing status then I much prefer the API /api/v2/routing/queues/{queueId}/members and do a count of the objects in the entities array, I feel this is less likely to change rather than the queue observations query, but who knows, which API I end up using with which customer will be dependant on what the customer needs in their architect flow.

Thanks for the help though, that repository is really useful.

Just noticed the firstUri/selfUri/previousUri that are returned still refer to the old queues/{queueId}/users endpoints:

GET /api/v2/routing/queues/93c4094c-4e9b-4a5f-992b-81c700f0ed9f/members?pageNumber=3

{
  "entities": [],
  "pageSize": 25,
  "pageNumber": 3,
  "firstUri": "/api/v2/routing/queues/93c4094c-4e9b-4a5f-992b-81c700f0ed9f/users?pageSize=25&pageNumber=1",
  "selfUri": "/api/v2/routing/queues/93c4094c-4e9b-4a5f-992b-81c700f0ed9f/users?pageSize=25&pageNumber=3",
  "previousUri": "/api/v2/routing/queues/93c4094c-4e9b-4a5f-992b-81c700f0ed9f/users?pageSize=25&pageNumber=2"
}

thanks for pointing that out Andrew! I'll work on a fix.

Seth

a fix for this issue has been applied and will be released with the next Public API release, which will be in a week or two. thanks again for pointing out the bug, Andrew.

/api/v2/analytics/queues/observations/query with the metric oMemberUsers might be work for you
good luck!

This topic was automatically closed 62 days after the last reply. New replies are no longer allowed.