Skip to main content
Each webhook request includes headers that allow you to verify the signature and prevent replay attacks. Signature headers:
HeaderDescription
svix-idUnique message ID
svix-timestampUnix timestamp of when the message was sent
svix-signatureBase64-encoded HMAC-SHA256 signature

Verifying with the Svix SDK

The easiest way to verify signatures is with an official Svix library.
import { Webhook } from "svix";

const secret = process.env.SVIX_SIGNING_SECRET; // from Svix dashboard

export async function handleWebhook(request: Request): Promise<Response> {
  const wh = new Webhook(secret);

  const payload = await request.text();
  const headers = {
    "svix-id": request.headers.get("svix-id") ?? "",
    "svix-timestamp": request.headers.get("svix-timestamp") ?? "",
    "svix-signature": request.headers.get("svix-signature") ?? "",
  };

  try {
    const event = wh.verify(payload, headers);
    // Process event...
    return new Response("OK", { status: 200 });
  } catch (err) {
    return new Response("Invalid signature", { status: 400 });
  }
}

Getting your signing secret

  1. Open the Juo Admin Portal and navigate to Settings → Webhooks
  2. Navigate to your endpoint
  3. Copy the Signing Secret shown under the endpoint settings
Each endpoint has its own unique signing secret.

Manual verification

If you prefer not to use the Svix SDK, you can verify the signature manually:
  1. Construct the signed content: {svix-id}.{svix-timestamp}.{raw-body}
  2. Compute HMAC-SHA256 using the signing secret (base64-decoded)
  3. Compare the result against the svix-signature header (strip the v1, prefix)
  4. Reject messages older than 5 minutes using svix-timestamp
See the Svix documentation for details.