Analytics API: 400 Bad Request on POST /api/v2/analytics/conversations/aggregates with custom group-by

We are trying to build a custom interval report for our agent desktop extension. The goal is to show agents their average handle time broken down by skill group in real time. We have been using the Embeddable Client App SDK for the UI, but we need to pull the data from the Analytics API directly.

The endpoint is POST /api/v2/analytics/conversations/aggregates. We constructed the JSON payload based on the documentation. It looks like this:

{
 "dateFrom": "2023-10-01T00:00:00.000Z",
 "dateTo": "2023-10-01T23:59:59.999Z",
 "groupBy": ["wrapUpCode", "skill"],
 "metrics": ["handled", "talk"],
 "interval": "PT1H"
}

When we send this request, we get a 400 Bad Request. The error message says Invalid groupBy value: skill. This is confusing because skill is listed as a valid dimension in the schema for conversation aggregates. We tried using skillId instead, but that also failed with the same error.

We checked the OAuth token. It has the analytics:report:view scope. The token works fine for other endpoints like getting user details. We also verified the date range. It is valid and within the last 30 days.

The documentation says that some dimensions require specific filters. We tried adding a filter for conversationType equal to voice. The request still fails. We are using the JavaScript SDK to make the call. The code looks like this:

const response = await platformClient.analytics.postAnalyticsConversationsAggregates(payload);

The error occurs before we even get a response object. It throws a validation error. We are stuck on this for two days. The team needs this report for the next sprint review. We don’t understand why skill is invalid. Is there a specific format required for the groupBy array? Or is the skill dimension only available for certain report types? We tried looking at the Swagger UI example. It shows queue as a groupBy value. That works fine. But skill does not.

We also noticed that the wrapUpCode dimension works when used alone. So the issue seems to be with combining wrapUpCode and skill. Or maybe skill itself is not supported in this specific endpoint version. We are using the latest version of the SDK.

Any ideas on what we are missing? The error message is not very helpful. It just says invalid value. We need to know the correct syntax. We have tried every combination we can think of. The documentation is not clear on the dependencies between dimensions. We are going to try removing the interval field next. But that seems unrelated.

We are running out of options here. The deadline is tomorrow. We need this working. Please help.

The issue is likely the groupBy array. The Analytics Aggregates API is strict about which dimensions you can use together. You can’t just pick any attribute. For AHT by skill, you need routing.skillGroup.name. Also, make sure your date range isn’t too wide. If you ask for real-time data, keep the window small, like last 60 minutes.

Here is a working payload structure. Notice the interval is set to PT1H and the groupBy matches the metric.

{
 "dateFrom": "2023-10-27T10:00:00.000Z",
 "dateTo": "2023-10-27T11:00:00.000Z",
 "interval": "PT1H",
 "metricTypes": ["conversation"],
 "metrics": ["avgHandleTime"],
 "groupBy": ["routing.skillGroup.name"],
 "entity": {
 "type": "queue",
 "id": "your-queue-id-here"
 }
}

Check the entity type too. If you leave it out, it pulls global data, which might cause a 400 if permissions are tight. Try scoping it to a specific queue ID first.

The 400 usually hits because the SDK doesn’t like raw strings in the groupBy array when you’re using C#. You need to use the specific enum values or the exact field path strings defined in the model. Also, mixing interval with certain groupBy dimensions throws a validation error if the grain doesn’t match.

I hit this exact wall last week. The fix is to ensure you’re using the PostAnalyticsConversationsAggregatesRequest object correctly and not bypassing the model. Here’s how I structure it in the .NET SDK:

var request = new PostAnalyticsConversationsAggregatesRequest
{
 GroupBy = new List<string> { "routing.skillGroup.name" },
 Metrics = new List<string> { "conversation.handled.duration" },
 Interval = "PT5M", // Must match the grain
 DateFrom = DateTime.UtcNow.AddHours(-1).ToString("o"),
 DateTo = DateTime.UtcNow.ToString("o")
};

var result = await analyticsApi.PostAnalyticsConversationsAggregates(request);

Check your Interval duration. If you group by skill, you can’t have an interval that’s too granular for the data volume. It’ll reject the request silently until you hit the size limit.