A webhook destination sends alerts and reports to your own HTTPS endpoint as JSON. Every request carries a signature, so your endpoint can be sure it came from LogZuno and wasn't changed on the way.
The request
{
"type": "event",
"title": "Payment received",
"body": "Growth plan, yearly",
"url": "https://platform.logzuno.app/…",
"project": "Web App",
"fields": [],
"data": {},
"sent_at": "2026-10-23T10:00:00+00:00"
}LogZuno waits up to 10 seconds for a 2xx answer. Any other answer, or no answer, is recorded as a failed delivery in the alert's history.
The signature
The LogZuno-Signature header looks like t=1792771200,v1=42d2…:
tis the Unix time the request was signed.v1is the hex HMAC-SHA256 oft, a dot and the raw request body, keyed with the destination's signing secret. Find it under Project settings → Destinations, on the webhook.
To verify, compute the same HMAC over the raw body (before any JSON parsing), compare it in constant time, and reject timestamps older than a few minutes so a captured request can't be replayed:
// Node.js: verify a LogZuno webhook before trusting it.
// LogZuno-Signature: t=<unix time>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyLogZunoSignature(rawBody, header, secret, toleranceSeconds = 300, now = Date.now() / 1000) {
const parts = Object.fromEntries((header ?? "").split(",").map((p) => p.split("=", 2)));
const t = Number(parts.t);
if (!parts.v1 || !Number.isInteger(t)) return false;
// Reject old deliveries, so a captured request can't be replayed later.
if (Math.abs(now - t) > toleranceSeconds) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const a = Buffer.from(expected, "hex");
const b = Buffer.from(parts.v1, "hex");
return a.length === b.length && timingSafeEqual(a, b);
}
// Express: read the raw body, verify, then parse.
// app.post("/hooks/logzuno", express.raw({ type: "application/json" }), (req, res) => {
// const ok = verifyLogZunoSignature(req.body.toString("utf8"), req.get("LogZuno-Signature"), process.env.LOGZUNO_WEBHOOK_SECRET);
// if (!ok) return res.sendStatus(401);
// const notice = JSON.parse(req.body);
// res.sendStatus(200);
// });The same check works in any language with an HMAC-SHA256 function.