Uptime Monitors

A monitor watches a website or API for you. Zenhook can check a public URL from outside your infrastructure, or receive signed results from a check running inside your private network.

Monitors vs. webhooks

These are the two opposite directions Zenhook works in, and it is easy to mix them up:

  • Channels (webhooks): your app calls Zenhook. You POST a webhook to a channel URL and Zenhook turns it into an alert.
  • Monitors (uptime): Zenhook checks a public URL, or your scheduler checks a private one and reports the signed result. Zenhook alerts when it goes down or recovers.

A monitor tracks one service's state over time. Public checks need only a URL. Private checks need the generated command running inside the network.

Add a monitor

1. Open Monitors. On the web, click Monitors under Inbox, then Add monitor. On your phone, open the Monitors tab and tap +.

2. Paste the URL. Enter the address you want watched, for example https://example.com or a health endpoint like https://api.example.com/health.

3. Save. Zenhook starts checking right away and shows the current status, last response time, and recent check history.

Monitor a private network

Choose Private network for a service on a VPN, tailnet, VPC, LAN, or localhost. Zenhook gives you a command to run inside that network. It checks the target locally and sends only the signed result to Zenhook over HTTPS.

The heartbeat secret is shown once. Zenhook stores a hash of the full secret and a short prefix to help you identify it. If results stop arriving within the grace period, Zenhook marks the monitor down. This also detects a stopped scheduler, disconnected network, or failed host.

No inbound port, public health endpoint, VPN peer, or Zenhook agent is required. Put the generated command in cron, a systemd timer, Kubernetes CronJob, CI runner, or any scheduler that can run curl.

How checks work

Every monitor is requested every minute on Free and every 30 seconds on Pro, with a 10 second timeout. A check passes when the URL answers with an HTTP status from 200 to 399 (redirects are followed).

A single failure never pages you. When a check fails, Zenhook rechecks 10 seconds later, and asks an independent vantage point, on another network with its own DNS resolver, whether it can still reach the site. A monitor only flips to down once the failure is confirmed and that second opinion cannot reach it either. While a site is down it is checked every 10 seconds, and the first successful check flips it straight back to up.

In practice you hear about a real outage at most about 70 seconds after your site went down on Free, 40 seconds on Pro, and about its recovery within 10 seconds of it.

When the status changes, from up to down, or back to up, Zenhook sends an alert through your notification channels (sound, desktop, push, and email), the same way channel alerts are delivered.

A site that keeps going down

A site that fails for a minute every ten minutes would alert you twice each time. So at the second outage within an hour, Zenhook tells you once that the monitor is unstable, then stops announcing its short outages.

While it is unstable, you still hear about an outage that lasts 5 minutes, and about its recovery. After an hour without an outage, one alert closes the episode with the number of outages and how long it lasted. The monitor's page lists every outage of the last 24 hours, announced or not.

Pause a monitor

On the web, open the monitor and click Pause, or use the menu on its tile. There are three choices:

  • Alerts for 1 hour or Alerts for 24 hours: the monitor is still checked and its page keeps the history, nothing is sent. Alerts come back by themselves at the end of the time.
  • The monitor: the checks stop too, until you resume.

Resume undoes either one. On your phone, Pause in the monitor's menu pauses the monitor.

From a script or an AI agent, with a token from Settings, API Tokens:

bash
# Your monitors and their ids
curl -H "Authorization: Bearer $ZENHOOK_TOKEN" https://zenhook.dev/api/monitors

# Alerts paused until a time (7 days ahead at most); null resumes them
curl -X PATCH -H "Authorization: Bearer $ZENHOOK_TOKEN" -H "Content-Type: application/json" \
  -d '{"mutedUntil": "2026-10-12T08:00:00Z"}' https://zenhook.dev/api/monitors/MONITOR_ID

# The monitor paused; true resumes it
curl -X PATCH -H "Authorization: Bearer $ZENHOOK_TOKEN" -H "Content-Type: application/json" \
  -d '{"enabled": false}' https://zenhook.dev/api/monitors/MONITOR_ID

A 200 is not always up

Plenty of outages answer with a perfectly healthy status code. Zenhook reads the response, not just its number, and treats these as down:

  • CDN error pages served as 200: bad gateway, service unavailable, origin unreachable, SSL handshake failed, and the rest of the familiar wall of text.
  • Stale cache: your CDN is serving a cached copy because it cannot reach your origin. Visitors see a site, but the site is down.
  • Bot challenge pages: a CAPTCHA or challenge is not your content.

FAQ

Do you check from several places at once?

Not on every check, and it is not a vote. The scheduled check runs from one place. A second, independent vantage point is only consulted when that check fails, and it holds a veto: if it can still reach your site, the outage is treated as our problem and you are not alerted. We only alert when nobody can reach you. That asymmetry is deliberate, the expensive mistake is waking you at 3am for a site that was up.

Can I change the check interval?

Public URLs are checked every minute on Free and every 30 seconds on Pro, and every 10 seconds on any plan while they fail. The generated private-network command is designed to run every minute; Zenhook marks it down if results stop arriving within its grace period.

Why does my access log show a _zenhook query parameter?

That is us. Each check appends a unique _zenhook value so no cache, ours or yours, can answer on your server's behalf. A monitor that hits a cache is not monitoring anything.

How do I allowlist Zenhook in my firewall or WAF?

Checks identify themselves with the user agent Zenhook Uptime Monitor/1.0. If your WAF challenges or blocks it, the monitor will read as down while your site is fine.

Can I monitor localhost or a private address?

Yes. Choose Private network when you add the monitor. Run the generated command inside the network. It checks localhost or the private address locally, then posts a signed result outward to Zenhook.

Why does Recent Checks show fewer entries than I expect?

The list shows the most recent checks first, the statistics cover the last 24 hours, and individual check history is kept for 7 days.

Will I get paged forty times if Zenhook itself breaks?

No. When an unusual share of monitors fail in the same cycle, the cause is almost never that every unrelated site went down at once, so Zenhook suppresses those alerts, keeps the statuses untouched, and raises the problem with us instead of with you.

Plan limits

The Free plan includes 3 monitors. Pro raises this to 20 monitors.

Not receiving monitor alerts? See notification troubleshooting