Account & Billing

Webhooks

How Everguardly fires HMAC-signed HTTPS callbacks on incident state changes — payload, verification, and delivery semantics.

Updated 2026-05-26 · 1 min read

Webhooks are the push complement to the REST API. When an incident opens, gets acknowledged, or resolves, we POST a signed JSON payload to every webhook URL subscribed to that event type.

Setup

Configure webhooks in Settings → Webhooks (owner only). You pick a URL, name it, and check which events to subscribe to. We generate a 64-character hex secret on create — copy it; the UI never shows it again though it stays in our DB so you can rotate by deleting and re-creating.

Payload shape

{
  "id": "f47b…",
  "type": "incident.opened",
  "createdAt": "2026-05-26T14:32:08Z",
  "data": {
    "incidentId": "uuid",
    "monitorId": "uuid",
    "scope": "global",
    "affectedRegions": ["eu-central", "us-east"],
    "summary": "Monitor is down"
  }
}

Event types (V1)

  • incident.opened — fresh failure crossed the retry-confirmation gate. data: { incidentId, monitorId, scope, affectedRegions, summary }
  • incident.acknowledged — a teammate marked "we know about this". data: { incidentId, monitorId, monitorName, actor }
  • incident.resolved — monitor recovered (auto) or someone manually closed the incident. data: { incidentId, monitorId, manual?, downtimeSeconds, affectedRegions }

monitor.up and monitor.down are reserved for V1.2 — they'll fire on individual check transitions, independent of incident lifecycle.

Signature verification

Every request carries X-Everguardly-Signature: sha256=<hex>. The hex is HMAC-SHA256 of the raw request body using your webhook's secret. Verify on your side:

import crypto from 'node:crypto';

function verify(rawBody, secret, headerValue) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(headerValue),
    Buffer.from(expected),
  );
}

Reject any request whose signature doesn't match. We never sign anything except real events.

Headers

  • X-Everguardly-Event — same value as type in the body, useful for fast filtering before parsing
  • X-Everguardly-Signature — HMAC-SHA256 hex as above
  • X-Everguardly-Delivery-Id — per-delivery UUID, useful for dedup if you receive the same event twice on a retry

Delivery semantics

We attempt twice (immediate + one retry after 500ms) per event. 2xx responses mark the delivery successful; 4xx are not retried (your endpoint refused us — that's terminal); 5xx triggers the single retry. After both attempts fail, we record the error in the webhook row and surface it in the dashboard.

We do not have an exponential backoff queue in V1 — that's V1.2. Your endpoint MUST return within 8 seconds or we time out.

Recommended pattern

Respond 200 immediately with an empty body, then process the payload asynchronously. Long-running work in the request handler will time out and trigger phantom failures in the dashboard.

Need something this doesn't cover? Email hello@everguardly.com — we'll write the doc.