Skip to content

Uptime Kuma

Uptime Kuma watches your websites, servers and services. A monitor that goes down arrives as “API is down”, with Uptime Kuma’s reason, a Critical notification that repeats until you acknowledge it; when it comes back up, “API is back up” arrives with the response time. There are two ways to set it up:

  • Quick: a webhook Source. Paste its URL into Uptime Kuma’s Webhook notification and leave the body as it is: Pocketbell knows Uptime Kuma’s events, so there’s nothing to write.
  • Your own body: an API Source with a custom body, for choosing every field yourself.

Both work with Uptime Kuma 1.23 and 2.x.

  1. In the Pocketbell app, create a Source named Uptime Kuma, choose Webhook, and copy its URL.
  2. In Uptime Kuma, open Settings → Notifications → Setup Notification, set Notification Type to Webhook, and paste the URL as the Post URL. Leave Request Body on Preset - application/json, and add no headers.
  3. Tick Default enabled, and Apply on all existing monitors if every monitor should alert you.
  4. Click Test, then Save. The test arrives as Uptime Kuma.

“API is back up” stops the alert repeating and starts “Down for 12 min”, and both stay in the inbox, in order. To change any of it, set your own title, message or priority in the Source’s setup: what you set wins, part by part. HTTP monitors also get a button that opens the site.

  1. In the Pocketbell app, create a Source named Uptime Kuma, choose API, and copy its key.

  2. In Uptime Kuma, open Settings → Notifications → Setup Notification, and set Notification Type to Webhook.

  3. Set Post URL to:

    https://api.pocketbell.dev/v1/messages
  4. In 2.x, leave HTTP Method on POST. Set Request Body to Custom Body and paste:

    {
    {% if heartbeatJSON == nil %}
    "title": "Uptime Kuma",
    "message": {{ msg | json }},
    "priority": "normal",
    {% elsif heartbeatJSON.status == 0 %}
    "title": {{ monitorJSON.name | append: " is down" | json }},
    "message": {{ heartbeatJSON.msg | default: "No details from Uptime Kuma." | json }},
    "priority": "critical",
    {% else %}
    "title": {{ monitorJSON.name | append: " is back up" | json }},
    {% if heartbeatJSON.ping %}
    "message": {{ heartbeatJSON.msg | append: " · " | append: heartbeatJSON.ping | append: " ms" | json }},
    {% else %}
    "message": {{ heartbeatJSON.msg | default: "It's responding again." | json }},
    {% endif %}
    "priority": "normal",
    {% endif %}
    "replace": "uptime-kuma-{{ monitorJSON.id | default: 'test' }}",
    "tags": ["uptime-kuma"]
    }
  5. Turn on Additional Headers and paste, with your key in place of pb_live_…:

    {
    "Authorization": "Bearer pb_live_…",
    "Content-Type": "application/json"
    }
  6. Tick Default enabled so new monitors use it, and Apply on all existing monitors if every monitor you have should alert you. Otherwise, turn it on in each monitor’s settings under Notifications.

  7. Click Test, then Save.

  • Down arrives as “Notifications API is down”, with Uptime Kuma’s reason (“timeout of 48000ms exceeded”) as the message. It’s Critical: it repeats every five minutes, for up to an hour, until you acknowledge it on any device. Add "expire": 10800 for up to three hours, or "retry" (30 to 3600 seconds) to change the pace.
  • Up arrives as “Notifications API is back up”, with the check’s result and response time (“200 - OK, keyword is found · 84 ms”). It has the same replace key, uptime-kuma- and the monitor’s ID, so it takes the alert’s place, the repeats stop, and it shows how long the monitor was down.
  • The body uses the monitor’s own fields, not Uptime Kuma’s msg, which is written for chat apps, with brackets and emoji.
  • Test sends a normal notification titled Uptime Kuma, since a test has no monitor behind it.
  • | json turns a value into a JSON string, quotes included, so a monitor name or error message with quotes in it still makes a valid request. Don’t put quotes around it.

For HTTP monitors, add a button that opens the site that went down, after the "tags" line:

{% if monitorJSON.url and monitorJSON.url != "" and monitorJSON.url != "https://" %}
, "url": {{ monitorJSON.url | json }}, "url_title": "Open site"
{% endif %}

Other monitor types have no web address (Uptime Kuma may keep https:// there), so the condition leaves it out.

  • Additional Headers is not a valid JSON: the headers box needs straight double quotes and a comma between the two lines.
  • 401 invalid_api_key: the key is wrong, or Bearer is missing in front of it.
  • 400 invalid_request: the answer’s message says what to change. “The request body isn’t valid JSON”: check the commas around the {% if %} lines. “Send the body as JSON”: add the Content-Type header. Any other: details names the field that’s wrong or empty.