Notification channels
Where pages are delivered — Slack, Telegram, email, PagerDuty, Opsgenie, Teams, SMS, voice and webhooks.
Incidents & On-Call → Channels is where you define the places a page can land.
Supported channels
| Channel | Needs | Notes |
|---|---|---|
| Slack | Incoming webhook URL, or OAuth | Rich formatting; messages trimmed to Slack's limits automatically |
| Telegram | Bot token + chat ID | HTML formatting; capped at 4096 characters |
| App-level SMTP (see environment) | Per-user, not broadcast, when paging a person | |
| PagerDuty | Events API v2 routing key | Creates and resolves PD incidents |
| Opsgenie | API key | |
| Microsoft Teams | Incoming webhook | |
| SMS / voice | Twilio | Opt-in, default off — see below |
| Webhook | URL, optional signing secret | Anything you want to build against |
Channel kind
Every channel has a kind that decides what is routed to it:
| Kind | Receives |
|---|---|
alerts | Alert fired / recovered |
incidents | Incident opened / updated / resolved |
| both | Everything |
A channel with the wrong kind is the most common reason a message "never arrived" — nothing failed, nothing matched.
Test before you trust
Every channel has a Test button. It sends a synthetic message through the real path: the same client, the same credentials, the same formatting.
Do it when you create the channel and again after any credential rotation. A webhook that was revoked three months ago looks identical to one that works, right up until the first real page.
Voice and SMS are opt-in
Twilio voice and SMS are off by default and must be enabled per organisation. Voice never fires on an untargeted broadcast — only on a notification aimed at a specific person through an escalation policy.
This is deliberate. A broadcast that rings phones is how a minor alert wakes an entire team, and it only has to happen once for people to start ignoring the phone.
Routing rules
Channels are the destination; routing rules decide which alerts reach them. Rules match on severity, service, team and environment.
An alert that matches no rule falls back to the broadcast channels for its category. An alert that matches several is delivered to each, once.
Webhooks
A webhook channel receives a JSON body for every event. Use it for anything not in the list above — a ticketing system, a home-grown dashboard, an internal bot.
See Webhooks for the payload shape and signature verification.
What happens when a channel fails
Nothing is dropped silently. Every attempt is logged, failures are retried three times, and what is left lands in the DLQ with a retry button. See Notification delivery.
Where this behaviour lives: backend/internal/notification/dispatcher.go, backend/internal/domain/notification.go. If the code and this page disagree, the code is right — please fix the page.
Part of Incidents and on-call — Turning a reading into a page, and a page into a resolved incident.