AlphornAlphorn Docs

Uptime Monitoring

Route uptime and downtime alerts from Uptime Kuma, Healthchecks.io, or a custom curl check to Slack, email, SMS, or any supported channel.

Uptime monitors check whether your services are online and fire alerts when something goes down. Instead of configuring each monitor to notify each channel individually, point them all at Alphorn and let routing rules handle the rest.

With Uptime Kuma

Uptime Kuma is a popular self-hosted monitoring tool. It supports webhook notifications out of the box.

Simple setup

The quickest way - just point Uptime Kuma at your Alphorn webhook. Alphorn uses Uptime Kuma's msg field as the message and forwards it to your channels.

  1. Create a webhook in Alphorn and copy the URL
  2. In Uptime Kuma, go to Settings → Notifications
  3. Add a new notification with type Webhook
  4. Paste your Alphorn webhook URL as the Post URL
  5. Enable Additional Headers and add {"Authorization": "Bearer alp_..."} with your Alphorn API key
  6. Done - Uptime Kuma sends its default payload and Alphorn routes it

This works out of the box. Notifications carry Uptime Kuma's default message text with no separate title and no priority at all, so priority filters (other than "does not equal") never match them.

Advanced setup

For richer notifications with priority-based routing and custom tags, configure a custom request body:

  1. In the Uptime Kuma notification settings, set Request Body to Custom Body
  2. Use this template (Uptime Kuma renders it with LiquidJS):
{% if heartbeatJSON['status'] == 1 %}{% assign state = "UP" %}{% else %}{% assign state = "DOWN" %}{% endif %}
{
  "title": {{ monitorJSON['name'] | append: " is " | append: state | json }},
  "message": {{ msg | json }},
  "priority": {% if heartbeatJSON['status'] == 1 %}2{% else %}5{% endif %},
  "tags": ["uptime", "{% if heartbeatJSON['status'] == 1 %}recovery{% else %}down{% endif %}"]
}

This gives you:

  • Dynamic priority - DOWN events get priority 5 (critical), UP recoveries get priority 2 (low)
  • Tags - down or recovery tags for filtering
  • Readable titles - "My API is DOWN" instead of just Uptime Kuma's message text

The | json filter quotes and escapes the values, so monitor names with quotes or backslashes still produce valid JSON.

Uptime Kuma's Test button sends no heartbeat or monitor (heartbeatJSON and monitorJSON are null), so the test notification renders as " is DOWN" with priority 5. Real events fill in both.

Routing examples

With the advanced setup you can route based on priority and tags:

ChannelFilterPurpose
PagerDutyPriority greater than 3Page on-call for outages
Slack (#incidents)Tags has any of downTeam visibility when services go down
Slack (#incidents)Tags has any of recoveryNotify when services recover
EmailNo filterFull audit trail

With Healthchecks.io

Healthchecks.io monitors cron jobs and heartbeats. Configure a webhook integration pointing to your Alphorn endpoint, with a request header Authorization: Bearer alp_... set to your Alphorn API key, method POST, and a JSON request body. An empty body produces an empty notification, so use the body from Integrations.

Custom uptime check

A simple bash script that checks a URL and sends the result to Alphorn:

#!/bin/bash
URL="https://your-app.com/health"
WEBHOOK="https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT"
ALPHORN_API_KEY="${ALPHORN_API_KEY:-alp_...}"  # or export it in the environment

STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$URL")

if [ "$STATUS" -ne 200 ]; then
  curl -fsS -X POST "$WEBHOOK" \
    -H "Authorization: Bearer $ALPHORN_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{
      \"title\": \"Health check failed\",
      \"message\": \"$URL returned HTTP $STATUS\",
      \"priority\": 5,
      \"tags\": [\"uptime\", \"down\"]
    }"
fi

Run this with cron every minute:

* * * * * /path/to/healthcheck.sh

On this page