Genesys Cloud webhook payload parsing in Node Lambda

Trying to parse the resource field from a Genesys Cloud queue updated webhook in a Node.js Lambda. The event object looks nested and I can’t find the doc for the exact path. Here’s what I’m seeing in CloudWatch logs.

const event = {
 "resource": {
 "id": "123",
 "name": "Queue A"
 }
}
console.log(event.body.resource.id)

Getting undefined. The payload is actually in the body string, right? Just need to know how to extract the queue ID without erroring out.

The payload is a string, not an object. Lambda sends the body as a raw JSON string, so you have to parse it first.

const body = JSON.parse(event.body);
const queueId = body.resource?.id;

Also, check the Content-Type header on the webhook subscription in Genesys. If it’s set to application/x-www-form-urlencoded, the body won’t be JSON. Make sure it’s application/json.

If you’re still getting undefined, dump the raw event.body to CloudWatch before parsing. Sometimes there’s a BOM or extra whitespace that trips up strict parsers.

The JSON.parse approach works, but it’s fragile if you’re dealing with high-volume queues. I’ve seen Lambda time out when the payload gets too large or the encoding shifts unexpectedly.

Instead of parsing the body string inside the handler, try using the application/json content type strictly in the Genesys Cloud webhook subscription. If you’re using the REST Proxy pattern in to trigger this, you can map the resource.id directly before sending it out. That way, the Lambda receives a clean object.

Here’s a safer Node.js pattern that handles both string and object bodies, plus validates the schema:

exports.handler = async (event) => {
 let parsedBody;
 try {
 // Handle both stringified JSON and direct objects
 parsedBody = typeof event.body === 'string' 
 ? JSON.parse(event.body) 
 : event.body;
 } catch (e) {
 console.error("Failed to parse webhook body", e);
 return { statusCode: 400, body: "Invalid JSON" };
 }

 // Validate expected structure
 if (!parsedBody?.resource?.id) {
 console.warn("Missing resource.id in payload");
 return { statusCode: 400, body: "Missing queue ID" };
 }

 const queueId = parsedBody.resource.id;
 console.log(`Processing queue update for: ${queueId}`);
 
 // Your logic here
 return { statusCode: 200, body: "OK" };
};

Also, double-check the webhook subscription in Genesys. If you’re using a shared flow to trigger this, make sure the REST action isn’t overriding the content-type header. I’ve had issues where the header defaults to text/plain and the Lambda handler chokes on it.

One more thing: if you’re using Terraform to manage these webhooks, ensure the content_type field is explicitly set to application/json in the resource block. Otherwise, drift can happen if the API defaults change.

resource "genesyscloud_routing_webhook" "queue_update" {
 name = "Queue Update Handler"
 enabled = true
 content_type = "application/json"
 url = aws_lambda_function.queue_handler.invoke_arn
 // ... other config
}

This setup keeps the parsing logic tight and avoids runtime errors from malformed payloads.