Sonny Labs Docs
SDK ReferenceTypeScript

verifyWebhook

Constant-time HMAC-SHA256 verification for inbound Sonny Labs webhook deliveries, plus VerifyWebhookOptions for replay-window tolerance and clock injection.

verifyWebhook validates the Sonny-Signature header on an inbound webhook delivery. The backend signs each delivery with Sonny-Signature: t=<unix>,v1=<hex> where <hex> is HMAC-SHA256(secret, "${t}.${body}"). Receivers must verify the MAC and reject deliveries whose timestamp falls outside a 5-minute replay window — the helper enforces both in one call.

Signature

import { verifyWebhook } from "@sonnylabs/sdk";

function verifyWebhook(
  body: string | Uint8Array,
  header: string,
  secret: string,
  options?: VerifyWebhookOptions,
): boolean;

Returns true if both the HMAC and the timestamp window check pass; false otherwise. Never throws on a malformed header — that's just an invalid signature.

ParameterDescription
bodyThe raw request body bytes (NOT a re-serialised object). HMAC is computed over the exact bytes the server signed.
headerThe value of the Sonny-Signature header.
secretThe webhook signing secret returned at webhook registration / rotation. Store in your secrets manager; never log it.
optionsOptional VerifyWebhookOptions — replay-window tolerance and a clock-injection hook for unit tests.
import express from "express";
import { verifyWebhook } from "@sonnylabs/sdk";

const app = express();

app.post(
  "/webhooks/sonny",
  // Express must give us the raw bytes — re-serialising via express.json()
  // breaks HMAC verification.
  express.raw({ type: "*/*" }),
  (req, res) => {
    const ok = verifyWebhook(
      req.body,
      req.header("sonny-signature") ?? "",
      process.env.SONNY_WEBHOOK_SECRET!,
    );
    if (!ok) return res.status(400).send("invalid signature");
    // ... process the event
    res.status(204).end();
  },
);

VerifyWebhookOptions

Prop

Type

On this page