Browse documentation

Pharos / Docs / v1.0.1

n8n and the outgoing webhook

Updated 2026-10-22 · Pharos 1.0.1

Inbound is just the API: an HTTP Request node posting to /api/v1/incidents or /api/v1/components/{id}.

Outbound is configured under Integrations → Send out. Paste an n8n webhook URL and save; the first save generates a 32 character signing secret. It fires on the moments you tick for that destination (incident opened, update posted, resolved, maintenance), whether the incident came from you, the API, or a check.

The Send out screen: add a destination in numbered steps (Slack, Microsoft Teams, Discord, Telegram, Signal or Generic JSON), then the moments it receives, beside the destinations of this page with their health
Integrations & API → Send out. Pick where updates go, connect it, and choose the moments: incident opened, update posted, resolved and maintenance. Each destination shows whether it is working, failing or paused, with Send test.
{
  "event": "incident.created",
  "incident": {
    "id": 12,
    "name": "Mail queue backed up",
    "status": "Identified",
    "impact": "major",
    "occurred_at": "2026-08-25T16:50:03+00:00",
    "resolved_at": null,
    "components": ["Mail relay", "Webmail"]
  }
}

Every request carries X-Pharos-Signature: a lowercase hex HMAC-SHA256 of the exact request body, keyed with your secret. Verify it: anyone who learns your webhook URL can otherwise forge events.

const expected = crypto.createHmac('sha256', SECRET)
  .update(req.body)              // the RAW body; a JSON parser changes the bytes
  .digest('hex');

if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
  return res.status(401).json({ error: 'bad signature' });
}

Delivery is one attempt with a five-second timeout and no retries. A slow receiver must never hold up publishing an incident, so a failure is logged and never shown to you mid-outage.