Notifications & webhooks
Push EntraGuard events (scan completed, scan failed, new finding, severity escalated, compliance report ready) to Slack, Microsoft Teams, an email address, or any custom HTTPS endpoint.
Where to configure
Open the dashboard at http://localhost:3000, then go to Settings → EntraGuard → Webhooks. Pick a channel, name it, paste the URL or email, choose which events should trigger it, and save. Test the endpoint right away with the Send test button.
Multiple endpoints can coexist (e.g. Slack for the team channel, email for the on-call rotation, a webhook to your SOAR). Each endpoint subscribes independently to events.
Available events
| Event | Fires when |
|---|---|
| scan.completed | A scan finishes successfully — full or incremental. |
| scan.failed | A scan terminates with errors (Graph throttle, expired token, network). |
| finding.new | A finding appears that did not exist in the previous scan. |
| finding.severity_changed | An existing finding's severity is recomputed up or down. |
| compliance.report_ready | A new compliance report (CIS, NIST, ISO, SOC 2) is generated. |
Slack
- Open api.slack.com/messaging/webhooks and create an Incoming Webhook in your workspace.
- Pick the channel where alerts should land (e.g.
#sec-alerts) and copy the URL — it looks likehttps://hooks.slack.com/services/T0…/B0…/…. - In EntraGuard Settings → Webhooks, choose Slack, paste the URL, pick events, and Send test.
EntraGuard formats Slack messages with severity colour, tenant, and a deep link to the finding. Sample payload:
{
"text": ":rotating_light: EntraGuard finding — *PIM-002 Excessive permanent privileged roles*",
"attachments": [
{
"color": "#dc2626",
"fields": [
{ "title": "Severity", "value": "high", "short": true },
{ "title": "Tenant", "value": "contoso.onmicrosoft.com", "short": true },
{ "title": "Affected", "value": "5 users with permanent Global Administrator", "short": false }
]
}
]
} Microsoft Teams
- In Teams, open the channel → Connectors → Incoming Webhook.
- Name it EntraGuard, optionally upload our logo, then copy the URL.
- In EntraGuard Settings → Webhooks, choose Webhook (the generic JSON channel), paste the Teams URL, and save.
EntraGuard sends a Teams-compatible MessageCard for scan summaries:
{
"@type": "MessageCard",
"@context": "http://schema.org/extensions",
"summary": "EntraGuard scan completed",
"themeColor": "0078d4",
"sections": [{
"activityTitle": "Scan completed — Contoso production",
"facts": [
{ "name": "Score", "value": "82 / 100 (B)" },
{ "name": "New findings", "value": "3 (1 high, 2 medium)" },
{ "name": "Run id", "value": "scan_2026-04-28T07:00Z" }
]
}]
} - In Settings → Webhooks, choose Email and enter a single address (rotations supported on the recipient side via mail aliases / distribution lists).
- SMTP credentials are picked up from the platform's
.env(SMTP_HOST,SMTP_USER,SMTP_PASSWORD). Brevo, SendGrid, AWS SES and any RFC 5321 SMTP relay are supported.
Custom webhook (SOAR, ITSM, in-house)
EntraGuard does an HTTP POST with Content-Type: application/json to your URL on every selected event. The body shape is stable across versions (additive only).
{
"event": "finding.new",
"timestamp": "2026-04-28T07:12:43Z",
"tenant_id": "8d6310d1-...",
"scan_id": "scan_2026-04-28T07:00Z",
"finding": {
"id": "PIM-002",
"title": "Excessive permanent privileged roles",
"severity": "high",
"category": "privileged-access",
"affected": ["[email protected]", "[email protected]"],
"remediation_url": "https://your-host/api/entraguard/findings/PIM-002"
}
} - HMAC signing (Enterprise): each request includes
X-Coderaft-Signature: sha256=<hex>computed over the body with the shared secret saved in Settings — verify before processing. - Retries: 3 attempts with exponential back-off (10 s / 1 min / 5 min) on non-2xx responses.
- Timeout: 10 s per attempt.
- Authoritative source: re-fetch
/api/entraguard/findings/<id>with an API key — webhook payloads are notifications, not the system of record.
Troubleshooting
- No alert received after a scan: check that the endpoint is enabled (toggle in Settings) and that the event you expect is in the trigger list.
- Slack returns 400: usually the webhook was rotated/disabled. Generate a new one.
- Teams shows raw JSON: Teams expects the
MessageCardshape — make sure you're using the Webhook channel (not Slack) for the Teams URL. - Custom webhook gets duplicate events: that's the retry layer firing again because your endpoint returned non-2xx the first time. Return 200 even if you queue the event for later processing.