Webhooks
Webhooks turn any HTTPS endpoint into an alert destination — pipe alerts into PagerDuty, Opsgenie, your own incident tooling, a data pipeline, or anything else that can accept a POST. Add the endpoint once and it becomes a selectable channel in every alert rule.
Add an endpoint
Section titled “Add an endpoint”-
In Integrations, find the Webhook card.
-
Enter a label, the HTTPS URL, and (recommended) a signing secret — any string you generate. With a secret set, every delivery carries an HMAC signature your endpoint can verify.
-
Click Add Webhook, then select it as a channel in the alert rules that should deliver to it.
The delivery
Section titled “The delivery”Each alert is one POST with Content-Type: application/json and user agent Monita-Alerts/1.0:
{ "ruleId": "alr_9f2c41d0", "orgId": "org_2caccd11", "domainId": "dom_71b3a9e2", "severity": "high", "type": "tag_volume_change", "title": "Meta Pixel purchase volume drop", "body": "Alert \"Meta Pixel purchase volume drop\" matched event \"purchase\" on www.example.com/checkout (vendor Facebook (Meta Pixel))", "impactValue": 12500, "context": { "event_name": "purchase", "vendor": "Facebook (Meta Pixel)", "url": "https://www.example.com/checkout", "host": "www.example.com", "path": "/checkout", "system": "google_tag_manager" }, "firedAt": "2026-08-13T09:30:00.000Z"}| Field | Meaning |
|---|---|
ruleId / orgId / domainId |
The alert rule, organisation and property the alert belongs to. domainId is absent for org-wide rules. |
severity |
low, medium, high or critical — or recovered on the matching recovery delivery. |
type |
The alert type, e.g. tag_volume_change, data_validation, journey. |
title / body |
Human-readable summary — the same text Slack and email receive. |
impactValue |
The rule’s configured value protected, in dollars. Absent when not set. |
context |
The matched event’s locus: event name, vendor, URL, host, path and source system. Fields vary by alert type — treat all of them as optional. |
firedAt |
ISO 8601 timestamp of when the alert fired. |
Recoveries are delivered to the same endpoint with the same shape and severity: "recovered", so your receiver can close whatever it opened.
Verify the signature
Section titled “Verify the signature”When the integration has a signing secret, Monita sends an x-monita-signature header: the lowercase-hex HMAC-SHA256 of the raw request body, keyed with your secret. Verify it before trusting a delivery:
import { createHmac, timingSafeEqual } from 'node:crypto';
function isFromMonita(rawBody, signatureHeader, secret) { // rawBody must be the exact bytes received — verify before any JSON parsing. const expected = createHmac('sha256', secret).update(rawBody).digest('hex'); return ( signatureHeader?.length === expected.length && timingSafeEqual(Buffer.from(signatureHeader, 'hex'), Buffer.from(expected, 'hex')) );}The same recipe works anywhere: HMAC_SHA256(secret, raw_body), hex-encoded, compared with a constant-time comparison. Compute it over the raw body exactly as received — re-serialising the parsed JSON can reorder keys and break the match.
Responding
Section titled “Responding”Return any 2xx status quickly — do your processing after acknowledging, not before. Non-2xx responses and timeouts count as failed deliveries; Monita retries failed deliveries a limited number of times, so make your handler idempotent (the ruleId + firedAt pair identifies a delivery).