Webhook Notifications
Using generic webhooks, you can send incident notifications in JSON format to any HTTPS endpoint. This is convenient for integrating with your own systems or automation tools.
Requirements
Section titled “Requirements”- HTTPS required: HTTP (unencrypted) URLs cannot be used
- Public endpoint: Private network URLs are blocked
- Signature verification secret: Any string of 1 or more characters
Manako Configuration
Section titled “Manako Configuration”- Open the “Notification Channels” menu in the dashboard
- Click “Add Channel” and select Webhook as the Type
- Enter the destination HTTPS URL
- Enter the signature verification secret
- Enter a channel name and click “Add Channel”
Payload
Section titled “Payload”Notifications are sent as POST requests. The Content-Type is application/json.
Common Fields
Section titled “Common Fields”Fields included in all events:
| Field | Type | Description |
|---|---|---|
event | string | Event type (incident.created, incident.resolved, webchange.detected) |
monitorName | string | Monitor name |
monitorId | string | null | Monitor ID (null if the monitor has been deleted) |
teamId | string | Team ID |
incidentId | string | Incident ID |
timestamp | string | ISO 8601 formatted timestamp |
Additional Fields by Event
Section titled “Additional Fields by Event”| Event | Field | Type | Description |
|---|---|---|---|
incident.created | monitorUrl | string | Monitored URL |
incident.created | severity | string | Severity ("critical" or "warning") |
incident.created / incident.resolved | title | string | undefined | Title for manual incidents (omitted for automatic incidents) |
webchange.detected | diffSummary | string | Summary of changes |
Payload Examples
Section titled “Payload Examples”{ "event": "incident.created", "monitorName": "API Server", "monitorId": "01JWAB1234567890ABCDEF", "teamId": "01JWAB0987654321FEDCBA", "incidentId": "01JWABINCIDENT12345678", "monitorUrl": "https://api.example.com/health", "severity": "critical", "timestamp": "2025-01-15T10:30:00.000Z"}{ "event": "incident.resolved", "monitorName": "API Server", "monitorId": "01JWAB1234567890ABCDEF", "teamId": "01JWAB0987654321FEDCBA", "incidentId": "01JWABINCIDENT12345678", "timestamp": "2025-01-15T10:45:00.000Z"}{ "event": "webchange.detected", "monitorName": "Pricing Page", "monitorId": "01JWAB1234567890ABCDEF", "teamId": "01JWAB0987654321FEDCBA", "incidentId": "01JWABINCIDENT12345678", "diffSummary": "Price changed from $10 to $15", "timestamp": "2025-01-15T11:00:00.000Z"}Signature Verification
Section titled “Signature Verification”Notification requests include an X-Manako-Signature header. You can verify that the request was sent from Manako by validating the HMAC-SHA256 signature of the request body using your secret.
The signature format is sha256=\{hex_digest\}.
Verification Code Examples
Section titled “Verification Code Examples”import crypto from "node:crypto";
function verifySignature(body, secret, signature) { const expected = "sha256=" + crypto.createHmac("sha256", secret).update(body).digest("hex"); return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signature), );}
// Express exampleapp.post("/webhook", express.text({ type: "application/json" }), (req, res) => { const signature = req.headers["x-manako-signature"]; if (!verifySignature(req.body, process.env.WEBHOOK_SECRET, signature)) { return res.status(401).send("Invalid signature"); } const payload = JSON.parse(req.body); console.log(`Event: ${payload.event}, Monitor: ${payload.monitorName}`); res.status(200).send("OK");});import hashlibimport hmacimport os
def verify_signature(body: bytes, secret: str, signature: str) -> bool: expected = "sha256=" + hmac.new( secret.encode(), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature)
# Flask example@app.route("/webhook", methods=["POST"])def webhook(): signature = request.headers.get("X-Manako-Signature", "") if not verify_signature( request.get_data(), os.environ["WEBHOOK_SECRET"], signature ): return "Invalid signature", 401 payload = request.get_json() print(f"Event: {payload['event']}, Monitor: {payload['monitorName']}") return "OK", 200