The EventBridge integration is firing v2.analytics.conversation.aggregate events, but the JSON payload is way deeper than the docs suggest.
I’m hitting the endpoint to fetch the raw event data and the structure looks like this:
{
"id": "conv-123",
"metrics": {
"hold-time": {
"value": 15000
},
"queue-time": {
"value": 3000
}
},
"wrap-up-code": null
}
The problem is the dynamic keys inside metrics. When I try to map this in the Data Action to a static schema, it bombs because hold-time might not exist on every event type.
Is there a specific endpoint or filter I should use to flatten this before it hits the consumer? Or am I supposed to write a custom parser in the webhook handler to iterate over the metrics object keys? The standard GET request for the analytics report gives a flat list, but the event stream is nested and sparse.
Trying to avoid a 400 error on the downstream DB insert.
The docs for the aggregate API are notoriously sparse on the actual JSON structure. You’re seeing that because metrics isn’t a fixed object. It’s a dictionary where the keys are dynamic metric names. In C#, trying to deserialize this into a static class with properties like HoldTime will fail or leave you with nulls if the key names don’t match exactly.
You need to handle it as a Dictionary<string, MetricValue>. Here is how I do it in my Azure Functions. I use a wrapper class for the root, but the metrics part is always a dictionary.
public class ConversationAggregateEvent
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("metrics")]
public Dictionary<string, MetricData> Metrics { get; set; }
[JsonPropertyName("wrap-up-code")]
public string WrapUpCode { get; set; }
}
public class MetricData
{
[JsonPropertyName("value")]
public long Value { get; set; }
// Sometimes there's a 'unit' field too, depends on the metric
[JsonPropertyName("unit")]
public string Unit { get; set; }
}
When the event hits, you just iterate through the Metrics dictionary.
if (eventPayload.Metrics != null)
{
if (eventPayload.Metrics.TryGetValue("hold-time", out var holdMetric))
{
Console.WriteLine($"Hold time: {holdMetric.Value}ms");
}
}
Don’t try to map it to a rigid structure. The platform adds new metrics or changes keys occasionally. Keeping it as a dictionary saves you from breaking your integration every time Genesys pushes an update. Also, watch out for null values in the dictionary. The API returns the key even if the value is null or missing, so always check for nulls before accessing .Value.
It’s annoying, but it’s the only way to stay safe.