Skip to main content
The webhook alert channel POSTs a JSON payload to any HTTPS URL when a monitor changes state. This page covers the payload format, available template variables, and how to verify webhook signatures. For setup instructions, see Alert channels — Webhook.

Events

EventDescription
monitor_downA monitor has been confirmed down
monitor_recoveredA monitor is back up
cert_expiringAn SSL certificate is nearing expiry
testA manual test alert sent from the dashboard

Default payload

Without a custom template, Larm sends:
{
  "text": "{{monitor_name}} is {{status}}.{{last_error}}{{downtime_duration}}\nURL: {{monitor_url}}\nTime: {{timestamp}}"
}
Which produces something like:
{
  "text": "My API is down. Connection timeout\nURL: https://api.example.com\nTime: 2024-01-15 14:30:45 UTC"
}
This is a single text field. If you need structured data (e.g. for automation platforms), use a custom payload template.

Template variables

Variables use {{variable}} syntax. Unknown variables are replaced with an empty string.
VariableDescriptionAvailability
eventEvent type (monitor_down, monitor_recovered, cert_expiring, test)All events
statusStatus string (down, up, warning, test)All events
monitor_idMonitor UUIDAll events
monitor_nameMonitor nameAll events
monitor_urlURL or host from monitor configAll events
channel_nameAlert channel nameAll events
timestampTimestamp in 2024-01-15 14:30:45 UTC formatAll events
last_errorError message (prefixed with a space)monitor_down only
downtime_duratione.g. " Was down for 5m 30s." (prefixed with a space)monitor_recovered only
cert_expiry_dateCertificate expiry date in 2024-12-31 formatcert_expiring only
days_remainingDays until certificate expiry (as string)cert_expiring only
last_error and downtime_duration include a leading space so they read naturally in the default template. When using a custom template, you may want to trim them.

Custom payload templates

Set a custom payload template in the alert channel config to control the JSON structure. The template must be valid JSON with {{variable}} placeholders. Recommended template for automation platforms:
{
  "event": "{{event}}",
  "status": "{{status}}",
  "monitor_id": "{{monitor_id}}",
  "monitor_name": "{{monitor_name}}",
  "monitor_url": "{{monitor_url}}",
  "channel_name": "{{channel_name}}",
  "timestamp": "{{timestamp}}",
  "last_error": "{{last_error}}",
  "downtime_duration": "{{downtime_duration}}",
  "cert_expiry_date": "{{cert_expiry_date}}",
  "days_remaining": "{{days_remaining}}"
}
Event-specific variables are empty strings when not applicable.

Signature verification

If you set a signing secret on the alert channel, Larm includes an x-larm-signature-256 header with each request. The value is sha256= followed by the hex-encoded HMAC-SHA256 of the raw JSON body using your signing secret as the key.

Node.js

const crypto = require("crypto");

function verifySignature(body, secret, signatureHeader) {
  const expected =
    "sha256=" + crypto.createHmac("sha256", secret).update(body).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader)
  );
}

// In your request handler:
const signature = req.headers["x-larm-signature-256"];
const isValid = verifySignature(req.rawBody, process.env.LARM_SECRET, signature);

Python

import hashlib
import hmac

def verify_signature(body: bytes, secret: str, signature_header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)

# In your request handler:
signature = request.headers.get("x-larm-signature-256")
is_valid = verify_signature(request.body, os.environ["LARM_SECRET"], signature)

curl

To compute the expected signature for testing:
echo -n '{"event":"test"}' | openssl dgst -sha256 -hmac "your-secret" | awk '{print "sha256="$2}'

Headers

Every webhook request includes:
HeaderValue
content-typeapplication/json
user-agentLarm/1.0
x-larm-signature-256sha256={hex} (only if signing secret is set)
Custom headers set in the alert channel config are included as-is.

Retries

Failed deliveries are retried up to 3 times with exponential backoff. A 401 or 403 response is treated as a permanent failure — the delivery is not retried and the alert channel is automatically disabled. You’ll receive an email notification and can re-enable the channel from the dashboard after fixing the issue.