Or browse the quick start

Webhook signing

Verify that outgoing LoggerMan webhooks were sent by your project.

When you configure an outgoing webhook with a secret, LoggerMan sends:

  • X-LoggerMan-Secret — shared secret (legacy; prefer signature verification)
  • X-LoggerMan-Signature sha256=<hex> HMAC of the raw JSON body

Verification (Node.js)

HMAC verify
import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyLoggerManWebhook(
  rawBody: string,
  secret: string,
  signatureHeader: string | null
): boolean {
  if (!signatureHeader?.startsWith("sha256=")) return false;
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const received = signatureHeader.slice("sha256=".length);
  try {
    return timingSafeEqual(
      Buffer.from(expected, "hex"),
      Buffer.from(received, "hex")
    );
  } catch {
    return false;
  }
}

// Express example
// app.post("/hooks/loggerman", express.raw({ type: "application/json" }), (req, res) => {
//   const raw = req.body.toString("utf8");
//   if (!verifyLoggerManWebhook(raw, process.env.WEBHOOK_SECRET!, req.get("X-LoggerMan-Signature"))) {
//     return res.status(401).send("Invalid signature");
//   }
//   const log = JSON.parse(raw);
//   ...
// });

Important

  • Verify against the raw request body before JSON parsing.
  • Use constant-time comparison (timingSafeEqual) to prevent timing attacks.
  • Rotate secrets in Integration settings if a webhook endpoint is compromised.