Uptime-Kuma & WLED

Uptime-Kuma & WLED

Visual Uptime Alerts with Uptime Kuma and WLED

If you’re running a self-hosted homelab, Uptime Kuma is a great tool for monitoring your services. But why settle for a notification on your phone when you can have a LED strip on your desk turn red the moment something goes down? Here’s how to wire up Uptime Kuma’s webhook directly to a WLED device — no middleware, no code, no extra services required.

What You’ll Need

  • Uptime Kuma (recent version with Custom Body webhook support)
  • A WLED device on your local network
  • Both on the same network (or routable to each other)

How It Works

Uptime Kuma can POST a webhook to a URL whenever a monitor changes state. WLED exposes a simple JSON HTTP API at /json/state that lets you set colors and effects. By pointing Uptime Kuma’s webhook directly at WLED and using Liquid templating to switch the payload based on status, you can drive the LED color from Uptime Kuma with no relay in between.

Setting It Up

1. Create a New Notification in Uptime Kuma

Go to Settings → Notifications → Add Notification and fill in the following:

FieldValue
Notification TypeWebhook
Friendly NameWLED Status Light (or whatever you like)
Post URLhttp://<your-wled-ip>/json/state
HTTP MethodPOST
Request BodyCustom Body

2. Add the Content-Type Header

Toggle on Additional Headers and enter:

{"Content-Type": "application/json"}

This is required — without it, WLED will reject the request with a 400 error even though the body is valid JSON.

3. Add the Custom Body

Uptime Kuma’s Custom Body supports Liquid templating. The key variable here is heartbeatJSON['status'], which is an integer: 1 for up, 0 for down.

Paste this into the Custom Body field:

{% if heartbeatJSON['status'] == 1 %}{"on":true,"seg":[{"col":[[0,255,0]],"fx":0}]}{% else %}{"on":true,"seg":[{"col":[[255,0,0]],"fx":2}]}{% endif %}

This sends:

  • Green, solid (fx:0) when the monitor comes back up
  • Red, breathing (fx:2) when the monitor goes down

4. Assign to Your Monitors

Save the notification, then edit your monitors and attach it. You can also toggle Apply on all existing monitors when saving if you want it everywhere.

Testing It

Hit the Test button in the notification form. Since it’s not a real down event, Uptime Kuma will send a status of 1 (up), so your LEDs should turn solid green. To test the down state, you can temporarily monitor a URL that doesn’t exist and wait for it to fail, or briefly pause the monitor.

Customizing

The WLED JSON API gives you a lot of room to tune the behavior. A few ideas:

Change the effect — swap "fx":2 for another effect ID. Some useful ones:

fxEffect
0Solid
2Breathe
6Pulse
9Blink

Adjust brightness — add "bri":150 to the segment (0–255):

{% if heartbeatJSON['status'] == 1 %}{"on":true,"seg":[{"col":[[0,255,0]],"fx":0,"bri":100}]}{% else %}{"on":true,"seg":[{"col":[[255,0,0]],"fx":2,"bri":255}]}{% endif %}

Target a specific segment — if your WLED device has multiple segments, add an "id" field to target just one:

{% if heartbeatJSON['status'] == 1 %}{"on":true,"seg":[{"id":0,"col":[[0,255,0]],"fx":0}]}{% else %}{"on":true,"seg":[{"id":0,"col":[[255,0,0]],"fx":2}]}{% endif %}

Use monitor name in the notification — you can reference {{ name }} in other notification types if you want to log which service triggered it.

Why This Works (and the Gotchas)

A couple of things tripped me up along the way:

  • {{ status }} is not an integer. The top-level status variable in Uptime Kuma’s Liquid context is a human-readable string like "✅ Up" or "🔴 Down". The integer you want is heartbeatJSON['status'].
  • The Content-Type header is not set automatically when using Custom Body. You must add it manually via Additional Headers, otherwise WLED returns a 400.
  • Test fires the “up” branch. The Test button sends a simulated up event, so you’ll always see green when testing. This is expected behavior.

That’s all there is to it — a surprisingly clean integration with no extra moving parts.