Node.js Lambda function failing to parse Genesys Cloud routing event webhook payload

Having trouble getting a simple Node.js Lambda function to process the routing event webhooks from Genesys Cloud. The setup is straightforward. We have a queue configured to send events to an HTTP target, and that target points to our API Gateway endpoint which triggers the Lambda. The goal is to log basic call metadata like the conversation ID and queue name for adherence tracking.

The Lambda is deployed and the API Gateway logs show a 200 OK response from Genesys Cloud, so the handshake seems fine. But inside the Lambda, the event object structure isn’t what I expected based on the documentation. The payload comes in wrapped in the API Gateway proxy integration format, but the actual Genesys event data is nested deep inside event.body. When I try to parse it, I’m hitting a type error because event.body is a string, not an object. I’ve tried using JSON.parse(event.body), but then I can’t access the conversationId field directly. It seems to be buried under a data object or something similar.

Here is the current handler code. It crashes on the second console.log because parsedBody is undefined or the path is wrong.

exports.handler = async (event) => {
 console.log('Raw event:', JSON.stringify(event));
 
 // Attempting to parse the body
 let body;
 try {
 body = JSON.parse(event.body);
 } catch (e) {
 console.error('Parse error:', e);
 return { statusCode: 500, body: 'Invalid JSON' };
 }

 console.log('Parsed body:', body);
 
 // This line throws: Cannot read property 'conversationId' of undefined
 const convId = body.data.conversationId;
 
 return {
 statusCode: 200,
 body: JSON.stringify({ received: convId })
 };
};

The raw event log shows the body is a stringified JSON object. Is there a specific field name I should be looking for in the parsed body to get the conversation details? The docs are a bit vague on the exact nesting level for routing events versus other event types. I’ve checked the webhook configuration in Genesys Cloud and it’s set to send the full event payload. Not sure if the API Gateway is stripping headers or modifying the structure. Any ideas on how to correctly extract the conversation ID from this specific event type?

// C# equivalent check
var body = await request.Content.ReadAsStringAsync();
var data = JsonSerializer.Deserialize(body);
Console.WriteLine(data.ConversationId);


Are you verifying the `Content-Type` header? Sometimes API Gateway strips it or changes the format. In C# I use `ReadAsStringAsync` then deserialize. Node might be choking on the stream if you're not handling it right. Check the raw payload first.

The 200 OK just means GC got a response, it doesn’t mean the payload parsed. Check the Lambda CloudWatch logs to see if event.body is a string you need to JSON.parse first.

API Gateway often proxies the body as a raw string, so accessing properties directly will return undefined. Parse it before touching the data object.