Webhooks enable your applications to receive real-time notifications when events occur in your monitoring and observability systems. This eliminates the need for polling and ensures your systems stay synchronized with alerts, metrics, and infrastructure changes across all integrated platforms.
Unizo normalizes webhook events from Datadog, New Relic, Splunk, Prometheus, Grafana, and other observability providers into a consistent format. This means you write your webhook handler once and it works with all supported platforms.
Webhook Configuration
To set up webhooks for your integration, visit the Unizo Console Webhooks section for step-by-step configuration guide.
These are the event types currently supported by Unizo's Observability webhooks. The list keeps growing as we add support for more events across different platforms.
Event Type
Description
Trigger Conditions
alert:triggered
An alert has been triggered
Threshold breach, anomaly detection, or custom conditions
alert:resolved
An alert has been resolved
Metrics return to normal or manual resolution
alert:acknowledged
An alert has been acknowledged
User acknowledges the alert
monitor:created
A new monitor has been created
Monitor creation via UI or API
monitor:updated
Monitor configuration has been modified
Threshold, condition, or notification changes
monitor:deleted
A monitor has been deleted
Monitor removal from the system
dashboard:created
A new dashboard has been created
Dashboard creation via UI or API
dashboard:updated
Dashboard has been modified
Widget additions, layout changes, or filter updates
metric:anomaly_detected
Anomaly detected in metrics
ML-based anomaly detection or statistical deviation
Webhook Security
Every webhook request sent by Unizo includes a cryptographic signature so you can verify that the payload is authentic and has not been tampered with.
Security Headers
Header
Description
x-unizo-event-type
The type of event that triggered the webhook
x-unizo-signature
HMAC-SHA256 signature of the payload, prefixed with v1= (e.g., v1=ee084789...)
x-unizo-timestamp
Unix epoch timestamp (seconds) when the request was signed
x-unizo-delivery-id
Unique identifier for this webhook delivery
Signature Verification
The signed payload is constructed by joining the timestamp and the raw request body with a dot separator: {timestamp}.{payload}. This ensures the timestamp is covered by the signature, preventing replay attacks.
Verification Steps
Parse the timestamp from the x-unizo-timestamp header and reject the request if it falls outside your tolerance window (recommended: 5 minutes).
Reconstruct the signed payload by concatenating the timestamp, a literal dot (.), and the raw request body.
Compute the expected signature using HMAC-SHA256 with your webhook signing secret as the key.
Strip the v1= prefix from the x-unizo-signature header to get the received signature.
Compare the two signatures using a constant-time comparison function to prevent timing attacks.
Reference Implementation
const crypto = require("crypto");
function verifyWebhookSignature(
payload,
signatureHeader,
timestampHeader,
secret,
toleranceSeconds = 300
) {
// 1. Reject stale timestamps to prevent replay attacks
const now = Math.floor(Date.now() / 1000);
const timestamp = parseInt(timestampHeader, 10);
if (Number.isNaN(timestamp)) {
return false;
}
if (Math.abs(now - timestamp) > toleranceSeconds) {
return false;
}
// 2. Reconstruct the signed payload: "{timestamp}.{payload}"
const signedPayload = `${timestamp}.${payload}`;
// 3. Compute the expected signature
const expected = crypto
.createHmac("sha256", secret)
.update(signedPayload)
.digest("hex");
// 4. Strip the "v1=" prefix from the received signature
const received = signatureHeader.startsWith("v1=")
? signatureHeader.slice(3)
: signatureHeader;
// 5. Constant-time comparison to prevent timing attacks
try {
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(received, "hex")
);
} catch {
return false;
}
}
// Usage
const isValid = verifyWebhookSignature(
rawBody, // raw request body string
headers["x-unizo-signature"], // "v1=ee084789..."
headers["x-unizo-timestamp"], // "1774093147"
process.env.UNIZO_WEBHOOK_SECRET // your signing secret
);
if (!isValid) {
return res.status(401).json({ error: "Invalid signature" });
}
// Signature verified — process the event
handleEvent(JSON.parse(rawBody));