Wocha Docs

webhook_verification_failed

Webhook signature verification failures

HTTP status: N/A (SDK validation)
Category: Webhook signature verification

What this error means

The Wocha SDK rejected an incoming webhook because the HMAC-SHA256 signature could not be verified. This is thrown by constructWebhookEvent() in @wocha/sdk/webhooks with error code webhook_verification_failed.

Common causes

  • Wrong webhook signing secret (typo, stale secret after rotation)
  • Request body was parsed as JSON before verification (must use the raw string)
  • Missing or malformed X-Wocha-Signature header
  • Timestamp outside the tolerance window (replay or clock skew)
  • Proxy middleware modified the request body

How to fix it

  1. Copy the signing secret from Console → Webhooks → [subscription] → Signing secret.
  2. Pass the raw request body string to constructWebhookEvent() — do not use req.json() first.
  3. Forward the exact X-Wocha-Signature header value (t=<iso8601>,v1=<hex>).
  4. Increase toleranceSeconds only if you have verified clock skew; default is 300 seconds.
  5. Use @wocha/testing to generate valid signed payloads in unit tests.

Example

import { constructWebhookEvent } from "@wocha/sdk/webhooks";
import { isGreetError } from "@wocha/sdk";
 
export async function POST(req: Request) {
  const body = await req.text(); // raw body — not req.json()
  const signature = req.headers.get("x-wocha-signature") ?? "";
 
  try {
    const event = await constructWebhookEvent(body, signature, process.env.WOCHA_WEBHOOK_SECRET!);
    switch (event.event_type) {
      case "user.created":
        await provisionUser(event.data);
        break;
    }
    return new Response("ok", { status: 200 });
  } catch (err) {
    if (isGreetError(err) && err.errorCode === "webhook_verification_failed") {
      console.error("Webhook signature invalid:", err.docsUrl);
      return new Response("invalid signature", { status: 401 });
    }
    throw err;
  }
}

See also

On this page