Send Uptime Kuma alerts to WhatsApp
A Webhook notification, a custom body and two headers. No phone number of your own, no WhatsApp Business account, and nothing extra to keep running.
Uptime Kuma has had a WhatsApp (WAHA) notification type since March 2025, and it wants a WAHA server of your own behind it — a self-hosted gateway you run and keep alive, holding a WhatsApp number of yours open as a linked device, which is the thing that gets numbers banned. That is also where the issue that asked for this ended up; the official-API answers in it want a Meta developer account, a registered number and an approved template before the first message.
This is the plain Webhook notification type instead, posting to an endpoint that already has a number and a template. It takes about three minutes.
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 messaged 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 notification
In Uptime Kuma: Settings → Notifications → Setup Notification, and choose Webhook as the notification type.
Post URL https://api.jabee.ai/api/v1/alerts
Request Body Custom Body
Choosing Custom Body reveals a text area. This is the whole of it:
{
"title": "{{ monitorJSON.name }} is {% if heartbeatJSON.status == 1 %}up{% else %}down{% endif %}",
"body": "{{ msg }}"
}
Then open Additional Headers and put in both of these:
{
"Authorization": "Bearer jak_your_key_here",
"Content-Type": "application/json"
}
The content type matters. In custom-body mode Uptime Kuma sends the string you wrote without declaring what it is, and an endpoint that is told nothing will not parse it as JSON. Setting it here is one line and removes the whole class of problem.
Press Test. A WhatsApp message should arrive in about a second.
3. Attach it to your monitors
Tick Default enabled before you save and every new monitor gets it. Existing monitors each need the notification ticked in their own edit screen — Uptime Kuma does not retrofit it.
Worth setting deliberately: Resend Notification if Down X times. It is how often a continuing outage messages you again, and on WhatsApp that is the difference between being informed and being nagged.
What arrives
Two messages per incident, one when it goes down and one when it comes back:
api.example.com is down
[api.example.com] [🔴 Down] Request failed with status code 502
api.example.com is up
[api.example.com] [✅ Up] 200 - OK
That is Uptime Kuma's design and there is no switch for it: one notification channel fires on both events. It is worth knowing because it is two of your monthly allowance per outage rather than one. The Grafana route drops recoveries unless you ask for them, because there Grafana says which kind of event it is sending; here the notification itself does not get that choice.
Adding the link
You can put the monitor's address in the message, so it is one tap from the phone:
{
"title": "{{ monitorJSON.name }} is {% if heartbeatJSON.status == 1 %}up{% else %}down{% endif %}",
"body": "{{ msg }}",
"url": "{{ monitorJSON.url }}"
}
Only for HTTP monitors. A ping, port or DNS monitor has no address, and Uptime Kuma
fills the field with https:// or nothing at all — neither is a real
URL, and the request is rejected with a 400 rather than silently losing
the message. If your monitors are a mixture, leave url out.
One honest caveat: the body is a string, not an object
Uptime Kuma renders your custom body as text and sends the result, so the JSON is
only valid if the values are. A monitor named api "prod" closes the
string early and the request fails — the template language it uses has no filter
that would escape it for you.
In practice: avoid double quotes and backslashes in monitor names, which almost nobody has anyway. If you cannot, send the name in the body rather than the title and keep the title fixed.
Where it goes
One phone per business, and it is your own: the account owner's verified number by default, or another handset — an ops phone, a shared on-call one — which you point alerts at in the dashboard, under Where alerts go. Either way that phone verifies itself by sending one message to the Jabee number, carrying a code from the dashboard.
So there is nothing to address and no recipient field. To reach several people, connect your own WhatsApp number and send from there: alerts on Jabee's number go out on a sender every business here shares, and the volume you send spends a reputation everybody else depends on.
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 this up and watch a message arrive before paying for anything. No per-seat charge.
Two messages per outage, remember, unless you are only watching things that never recover.
Questions
Can Uptime Kuma send WhatsApp alerts without a WhatsApp Business account?
Yes, using the plain Webhook notification type rather than the
built-in WhatsApp one. Point it at https://api.jabee.ai/api/v1/alerts
with Request Body set to Custom Body, put your key on the
Authorization header as Bearer jak_..., and add
Content-Type: application/json alongside it. The number and the
template are Jabee's, so there is no Meta developer account, no number to register
and no template to submit.
Why does my Uptime Kuma webhook return 400 title is required?
Almost always the content type. In custom-body mode Uptime Kuma sends your
string without declaring that it is JSON, so the far end does not parse it and sees
an empty request. Add "Content-Type": "application/json" to Additional
Headers. The other cause is invalid JSON after rendering, usually a double quote
inside a monitor name.
Can I get only the down alerts and not the up ones?
Not from Uptime Kuma's side: one notification channel fires on both events and there is no per-event switch. Both arrive, and both count against your allowance. If one message per incident matters more than knowing it recovered, the Grafana and Alertmanager route drops recoveries by default.
Which template variables can I use in the custom body?
Three: msg, the line Uptime Kuma would have sent anywhere else;
monitorJSON, the monitor including name and
url; and heartbeatJSON, the event including
status, where 1 is up and 0 is down. They are rendered with a Liquid
template, so {% if %} works as shown above.
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.
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 if nobody ever answers the messages?
Five notifications in a row that a handset never replies to and we stop sending to it, with an email to the account owner saying so. Sending any message to the Jabee number starts it again. One number's standing with Meta is shared by every business on it, which is why the rule exists.