Send Grafana alerts to WhatsApp

A contact point, a URL and a key. No phone number of your own, no Meta business account, no message template, and nothing running in between.

Every other answer to this needs something in the middle — a messaging account you pay separately for, or a small service you write and then have to keep alive, which is a strange thing to put in charge of telling you that things have stopped working. This route reads Grafana's own webhook body, so there is nothing between Grafana and the phone.

It takes about two minutes, and the first three alerts are free.

1. Make a key

In the Jabee dashboard, go to Management then Approvals and create an API key. It starts jak_. Copy it now; it is not shown again.

Whoever is going to be woken up needs a verified phone, which they get by tapping a link in the dashboard and sending one message. Until somebody has done that there is nobody to deliver to.

2. Add the contact point

In Grafana: Alerting → Contact points → Add contact point, and choose Webhook as the integration.

URL      https://api.jabee.ai/api/v1/alerts/grafana
Method   POST

Then open Optional Webhook settings and set the authorisation header:

Authorization Header Scheme        Bearer
Authorization Header Credentials   jak_your_key_here

That is the whole configuration. Leave everything else alone — in particular, you do not need a notification template, and you do not need Grafana 12. The route reads the body Grafana sends by default, which is the point of it.

Press Test. A WhatsApp message should arrive in about a second.

3. Point a notification policy at it

A contact point does nothing until something routes to it: Alerting → Notification policies, then either make it the default or add a child policy matching the labels you care about.

Worth setting deliberately rather than leaving at the default: Group wait, Group interval and Repeat interval. They decide how often a continuing problem messages you again, and on WhatsApp that is the difference between being informed and being nagged. A repeat interval of four hours is a reasonable starting point for something that wakes a person.

What arrives

Grafana groups alerts, so a bad minute is one notification carrying several problems. That arrives as one WhatsApp message, not one per alert — which is both quieter and the difference between spending three of your monthly allowance and spending twenty:

3 alerts firing: DiskPressure, HighLatency, QueueBacklog

Disk is nearly full
• DiskPressure — instance=db-1 — A=94.24
• HighLatency — instance=api-2
• QueueBacklog — instance=worker-1

https://grafana.example/d/abc

Eight alerts get a line each; beyond that they are counted (and 12 more), including any Grafana itself truncated. The link is the dashboard the first alert came from, falling back to the panel, then the alert rule, then your Grafana front page.

If you already use a notification template, its title and message are sent as you wrote them. Somebody who went to that trouble has said what they want the message to read like, and overriding it would be a strange thanks.

Sending it to the right person

A monitoring tool will not let you write the request body, so addressing lives on the query string. Add it to the contact point's URL:

Add to the URLWhat it does
?resolved=trueAlso be told when things recover. Off by default.

?resolved=true is the only parameter this route reads. There is nothing to address: alerts go to the one phone this business has verified, or the account owner's.

Recovery messages are off unless you ask

Grafana posts again with status: "resolved" when a problem clears. Passing those on doubles the messages per incident, so they are dropped unless the URL says ?resolved=true.

A dropped one answers 200 OK with {"ignored": "resolved"} rather than an error. That is deliberate: Grafana treats any 4xx or 5xx as a failed delivery and retries it, and there is no number of retries that will make us want a message you have switched off.

Prometheus Alertmanager works on the same URL

Grafana's webhook body is Alertmanager's, extended — so Alertmanager, and anything that speaks its shape, posts to exactly the same place:

receivers:
  - name: jabee
    webhook_configs:
      - url: https://api.jabee.ai/api/v1/alerts/grafana
        send_resolved: false
        http_config:
          authorization:
            type: Bearer
            credentials: jak_your_key_here

send_resolved is worth setting explicitly, because Alertmanager defaults it to true. Left alone, it posts every recovery and this end drops every one of them — harmless, and a lot of pointless requests. Set it to false, or leave it true and add ?resolved=true to the URL if you want the all-clear.

One honest caveat: no deduplication

If Grafana retries a delivery it never saw succeed, you may get the same message twice.

That is a deliberate choice rather than an oversight. The obvious thing to deduplicate on is Grafana's groupKey, and it is the wrong key: Grafana reuses it for every repeat of an ongoing incident, so suppressing on it would silence exactly the reminders your repeat interval exists to send — and a later, genuinely new incident on the same group would be swallowed by the first one. A duplicate message is a smaller harm than an alert that never arrives, so that is the trade we made.

What it costs

$29 a month for 500 alerts and approvals together, then 3 cents each. The first three are free, so you can wire up the contact point, press Test, and watch one arrive before paying for anything.

No per-seat charge. Remember that one notification is one alert here however many problems it carries, so the 500 goes further than it looks if your grouping is sensible.

Questions

Do I need a WhatsApp number or a Meta account?

No, neither, at any point. The message goes over Meta's official Cloud API on Jabee's registered number using Jabee's approved template, so you need an API key and nothing else. There is no number of yours involved, so there is nothing of yours to get banned.

Does this need Grafana 12?

No. Grafana 12 added custom webhook payloads, which would let you reshape the body yourself — but this route reads the default body, so any Grafana that can send a webhook with an authorisation header works, Grafana Cloud included.

Can it message my customers?

No, deliberately. It reaches your own people, once they have verified their phone. A shared number messaging strangers is what gets numbers banned. To reach customers you connect your own number, which is the inbox.

What happens when twenty things break at once?

Grafana groups them into one notification and you get one WhatsApp message naming the first few and counting the rest, with the dashboard link for the detail. It costs one alert against your allowance, not twenty.

Can I send to different teams for different alerts?

Not on Jabee's number. Alerts go to one phone per business — the account owner's, or an ops handset you verify in the dashboard, under Where alerts go — so there is nothing to address. To route different alerts to different people, connect your own WhatsApp number and send from there.

Why did my test send nothing?

Most often no phone is verified yet — open the dashboard, tap the link and send the one message it writes for you. After that, check the key is on the Authorization header as Bearer jak_..., and that you are not sending only recoveries with ?resolved=true absent.