- Trigger
- Webhook, POST on the path /grafana-alert with header authentication
- Nodes
- 8
- Requires
- Telegram, Header Auth (on the webhook)
- Category
- Monitoring
- From the course
- Grafana, Prometheus and Loki
- Published
- 2026-09-10
Node types used
- Webhook
- Switch
- Edit Fields (Set)
- If
- Telegram
What it does
Grafana can notify Telegram directly, and for one alert that is enough. What it cannot do is decide that a disk filling at 03:00 is worth waking you for while a container restart is not, or that a resolved notification never needs to make a sound. Putting n8n between Grafana and your phone is where that decision goes.
A Webhook node accepts POST on the path grafana-alert with header authentication turned on, so a leaked URL alone is not enough to page you. A Switch reads body.status and sends firing and resolved down separate named outputs. Each branch has its own Set node that composes a one-line message: the firing one uses commonLabels.alertname, falls back from commonLabels.host to the words "the box", and prefers commonAnnotations.summary over the alert title; the resolved one is the same line without the host. Firing messages then pass an If node that tests whether the current hour is at least 8 and less than 22. Inside those hours the message goes to one Telegram chat, outside them it goes to a second, quieter chat. Resolved messages always go to the quiet chat and never touch the hours check.
The quiet hours rule is the whole of the logic. There is no deduplication, no grouping of alerts that fire together, no escalation if nobody acknowledges, and no severity handling: an alert Grafana labels critical is treated exactly like one labelled info.
Node by node
- 1
Webhook Accepts POST on the path grafana-alert with authentication set to header auth and responseMode onReceived, so Grafana gets its acknowledgement immediately.
- 2
Firing or resolved A Switch on $json.body.status with two named outputs: firing and resolved. There is no fallback, so any other status ends the run.
- 3
Firing message A Set node building message as "{alertname} is firing on {commonLabels.host or the words the box}" followed by commonAnnotations.summary, or the alert title if there is no summary.
- 4
Resolved message The same idea for the resolved branch: alertname, the word resolved, then the summary or the title.
- 5
Waking hours? An If node combining $now.hour greater than or equal to 8 with $now.hour less than 22. The hour is read in the timezone the n8n instance is set to.
- 6
Telegram (loud) Sends the message to the primary chat when the alert fires inside waking hours.
- 7
Telegram (quiet) Sends the same message to a second chat when the alert fires outside those hours.
- 8
Telegram (resolved) Sends every resolved notification to the quiet chat, whatever the hour.
Setup after import
- 1
Create a Telegram credential from your bot token and select it on all three Telegram nodes. The export ships without one attached.
- 2
Replace YOUR_TELEGRAM_LOUD_CHAT_ID and YOUR_TELEGRAM_QUIET_CHAT_ID with your own chat ids. The quiet id appears on two nodes.
- 3
Create a Header Auth credential and select it on the Webhook node, then add the same header and value to the Grafana contact point.
- 4
In Grafana, add a webhook contact point pointing at the production URL n8n shows for the path grafana-alert, and route the alert rules you care about to it.
- 5
Check the n8n instance timezone before trusting the quiet hours. $now.hour uses it, not the timezone of whoever is on call.
- 6
Adjust the 8 and 22 values in Waking hours? if your hours are different.
Limits
No deduplication and no grouping. Ten alerts firing together send ten messages.
No severity handling. Every firing alert follows the same path.
Resolved notifications always go to the quiet chat, even in the middle of the day.
The Switch has no fallback output, so a payload with any status other than firing or resolved is dropped.
Download the workflow
The 8 node export as n8n reads it. Credential ids, personal values and real endpoints are replaced with placeholders, so nothing here can reach an account that is not yours. No email, no account.
Download grafana-alerts-to-telegram.jsonGet help with this in the community
If the import fails, if a node errors on the first run, or if you want to point this at a service it does not cover yet, post it in the free House of Loops community. Say which template it is and paste the error. Shannon Atkinson answers, and the answer stays there for the next person who hits the same thing.
Ask in the communityMore templates
Weekly Plausible and Umami summary to Slack in n8n
Every Monday at 08:00, pulls last week's visitors and pageviews from Plausible and Umami, plus Umami's top three paths, and posts one message to Slack.
- Trigger
- Schedule Trigger, cron 0 8 * * 1 (Mondays at 08:00)
- Nodes
- 8
Stripe webhook signature verification in n8n
A Webhook node with Raw Body on, a Code node that checks the Stripe-Signature HMAC, and a Postgres insert that ignores duplicate event ids.
- Trigger
- Stripe webhook, POST on the path /stripe
- Nodes
- 3
Stripe subscription lifecycle router in n8n
Verifies the Stripe signature, then routes customer.subscription events, invoice.paid and invoice.payment_failed to one branch per subscription status.
- Trigger
- Stripe webhook, POST on the path /stripe-subscription-lifecycle
- Nodes
- 15