# Unable to validate zoom webhook through api gateway

**URL:** <https://devforum.zoom.us/t/unable-to-validate-zoom-webhook-through-api-gateway/137273>\
**Category:** API and Webhooks\
**Created:** [September 11, 2025, 10:36am UTC](https://devforum.zoom.us/t/unable-to-validate-zoom-webhook-through-api-gateway/137273 "2025-09-11T10:36:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shivansh](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/shivansh/32/56599_2.png) [@Shivansh](https://devforum.zoom.us/u/Shivansh)\
**Post date:** [September 11, 2025, 10:36am UTC](https://devforum.zoom.us/t/unable-to-validate-zoom-webhook-through-api-gateway/137273/1 "2025-09-11T10:36:47Z")

</div>

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:

```auto
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?

Any guidance or confirmation would be really helpful. Thanks!

---

<div class="post-metadata">

**Author:** ![gianni.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/gianni.zoom/32/32523_2.png) [@gianni.zoom](https://devforum.zoom.us/u/gianni.zoom)\
**Post date:** [September 17, 2025, 10:55pm UTC](https://devforum.zoom.us/t/unable-to-validate-zoom-webhook-through-api-gateway/137273/2 "2025-09-17T22:55:53Z")

</div>

> [@Shivansh](#):
>
> - For webhook signature validation, I’m building the message like this:
> 
> ```auto
> const message = `v0:${req.headers['x-zm-request-timestamp']}:${JSON.stringify(req.body)}`;
> 
> ```

Based on this I believe you may be mixing up [webhook verification](https://developers.zoom.us/docs/api/webhooks/#verify-webhook-events) and webhook validation. Webhook [validation](https://developers.zoom.us/docs/api/webhooks/#validate-your-webhook-endpoint) involves implementing the challenge-response check flow which includes hashing the plainToken sent by Zoom, creating the response JSON object and responding to Zoom servers within 3 seconds with the JSON object:

**Webhook endpoint validation** (`endpoint.url_validation` event)

- Happens once when you register your webhook.

- You must **echo back Zoom’s `plainToken`** as an `encryptedToken`.

- This does **not** involve HMAC verification or raw body concerns.

- If validation fails, it usually means the app didn’t return the JSON response in the exact format Zoom expects.

**Webhook request verification** (all subsequent events)

- Uses the `x-zm-signature` header.
- This **does** depend on the raw body being byte-for-byte identical, which is where `express.json()` parsing could be breaking things via your API Gateway if your issue is actually verification.

After reviewing the linked documentation above, can you clarify whether verification or validation is your issue?

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex016/uploads/zoomdeveloper/original/3X/6/1/614bdd549b610bbaa46ff934617683a02bdaa03c.png) [@system](https://devforum.zoom.us/u/system)\
**Post date:** [September 21, 2026, 2:32pm UTC](https://devforum.zoom.us/t/unable-to-validate-zoom-webhook-through-api-gateway/137273/4 "2026-09-21T14:32:42Z")

</div>

Closed on September 21, 2026, 2:32pm UTC

This topic was automatically closed 368 days after the last reply. New replies are no longer allowed.
