Unable to validate zoom webhook through api gateway

Hi everyone,

I’m running into an issue with Zoom webhook validation and I’m hoping someone can clarify what’s happening.

  • When I expose my service using ngrok, Zoom’s webhook URL validation (endpoint.url_validation) works fine.

  • But when I put the same service behind my API Gateway (Express.js gateway forwarding requests to microservices), Zoom responds with “validation failed”.

Here’s some context:

  • My Sessions service has express.json() enabled globally, and I can’t disable it for just this route.

  • For webhook signature validation, I’m building the message like this:

const message = `v0:${req.headers['x-zm-request-timestamp']}:${JSON.stringify(req.body)}`;

  • This works with ngrok directly, but fails when the request goes through my gateway.

My guess: the gateway or express.json() is modifying the body (parsing and re-stringifying), so the payload is no longer byte-for-byte identical to what Zoom sent. This would explain why signature validation fails.

Questions:

  1. Is my understanding correct that Zoom requires the exact raw request body for signature and URL validation?

  2. If so, what’s the best practice for handling this in an Express.js microservices setup where express.json() is already in use globally?

    • Should I capture the raw body using the verify option in express.json()?

    • Or should I route Zoom’s webhook through express.raw({ type: "application/json" }) at the gateway and then forward it untouched?

Any guidance or confirmation would be really helpful. Thanks!