Symptom: your webhook endpoint returns invalid signatures for events you know are genuine, or the SDK verify call throws on every request.
1. Confirm the cause: check how you read the request body. If any code parses the JSON and stringifies it again before verification, that is the bug: the cryptographic signature is sensitive to even the slightest change, and re-stringified JSON is never byte-identical.
2. Fix: read the raw request body as text. In Next.js, use const payload = await req.text() and pass that string to verification. Never pass a parsed-then-stringified object.
3. Pass the three Svix headers exactly as received: svix-id, svix-timestamp, svix-signature, plus the signing secret from the webhook details page in the dashboard (the create, retrieve, and list webhook API calls also return it).
4. Fix with the SDK: call resend.webhooks.verify with the raw payload, the headers object, and the webhook secret; it throws on invalid and returns the parsed payload on success.
5. Fix manually: use the Svix library for your language (npm install svix for Node) and call wh.verify(payload, headers) with the raw body string.
6. Verify: send a test event from the dashboard and confirm your endpoint accepts it. If verification still fails, confirm you are using the secret for that exact webhook endpoint, not a different one.