Node.js Lambda: Genesys Cloud Webhook payload parsing fails on nested conversation data

How do you handle the event structure when Genesys Cloud sends a conversation.updated webhook to a Node.js Lambda function? I’m trying to parse the payload to trigger a screen pop in my custom agent desktop widget, but the data isn’t landing where I expect it.

Here’s the setup. I’ve got a simple Lambda function listening on an API Gateway endpoint. The webhook is configured to send conversation.updated events. When I test it with the built-in webhook tester in Genesys Cloud, the payload looks fine. But when the real event hits, the body in the Lambda handler is sometimes a string and sometimes a parsed object, depending on how API Gateway is configured. I’ve tried setting the Lambda integration type to Lambda Proxy Integration, which usually gives me a consistent event.body string.

The issue is with the JSON structure inside that body. I’m using JSON.parse(event.body) to get the object. Then I try to access eventObject.conversationId. That works. But when I try to dig into the data array to find the participant status, it’s null.

exports.handler = async (event) => {
 const payload = JSON.parse(event.body);
 console.log('Raw Payload Keys:', Object.keys(payload));
 const convId = payload.conversationId;
 const data = payload.data;
 // data is undefined here for production events
 return {
 statusCode: 200,
 body: JSON.stringify({ received: true, convId: convId })
 };
};

In the test event, payload.data is an array of changes. In production logs, payload only has conversationId, eventType, and timestamp. The actual change details are missing. Is Genesys Cloud sending different payloads for different event types? Or is API Gateway truncating the body? I’ve checked the x-amzn-remapped-content-length header, but that’s not even present.

I need to know if I should be expecting the full conversation object or just the delta. The docs are vague on what exactly is inside the webhook body for conversation.updated. If I need the full state, do I have to make a separate API call to /api/v2/conversations/{id} inside the Lambda? That feels like overkill for a simple status update. What am I missing in the payload parsing logic?