Skip to content

Working with checks

Every Uptime check runs on a schedule and confirms a failure before it alerts, so a single slow response doesn’t page anyone.

When a check fails, it waits for its confirmation period and checks once more. A failure during the confirmation period opens no incident and sends no alert. If the re-check fails too, the check goes Down, opens one incident, and alerts once. When it recovers, it sends a recovery alert, but only after it was Down.

Heartbeats work differently: their grace period is the confirmation.

These are under Advanced settings in the Add check dialog and in each check’s settings. When you save a check’s settings, only the fields you changed are saved.

Setting Default Options
Check frequency 3 minutes 20 s, 30 s, 1, 2, 3, 5, 10, 15, or 30 minutes.
Confirmation period 2 minutes Immediately, 30 s, 1, 2, 3, or 5 minutes.
Request timeout 30 seconds 5, 10, 15, 30, 45, or 60 seconds. For ping checks the field is Ping timeout: 5 or 10 seconds, default 10. DNS checks also allow 5 or 10 seconds.
Follow redirects On Follows up to 10 redirects. Off: a redirect response counts as the response.
Internet Protocol (IP) version Both IPv4 and IPv6 IPv4 only or IPv6 only. Website, keyword, ping, and TCP port checks. See IP version.
SSL/TLS verification On Treats an invalid, expired, or self-signed certificate as down.
SSL expiration Alert 14 days before (https URLs) Don’t check for SSL expiration, or alert 1, 2, 3, 7, or 14 days, or 1 or 2 months before. See below.
Domain expiration Don’t check for domain expiration Alert 1, 2, 3, 7, or 14 days, or 1 or 2 months before. See below.

Advanced settings of a website check, with the IP version set to Both IPv4 and IPv6 and SSL expiration to Alert 14 days before.

Website and keyword checks also have request settings and SSL and domain expiration, and TCP port checks have a TLS option.

Internet Protocol (IP) version sets how website, keyword, ping, and TCP port checks connect. It’s Both IPv4 and IPv6 by default. With IPv4 only or IPv6 only, the check connects only over that family, from every location it runs from.

If the host has no address of the chosen family, or you entered an IP address of the other kind, the check is down with, for example, “ipv4.google.com has no IPv6 address”. DNS checks don’t have this setting: the DNS server’s address decides.

Website and keyword checks can watch their site’s SSL certificate and its domain registration. Choose how early to be told with SSL expiration and Domain expiration. Both lists have the same choices.

The SSL expiration list open: Don’t check for SSL expiration, then Alert 1 day before through Alert 2 months before, with Alert 14 days before selected.

  • Once the certificate or the domain is within that many days of expiring, the check opens an expiry incident and alerts its alert channels.
  • The incident closes by itself once the certificate or domain is renewed, with an alert saying “…was renewed: it now expires on” and the new date. It can’t be resolved by hand.
  • Expiry dates are checked every hour, and a few seconds after you save a check. A domain’s date comes from its registry (RDAP), which TunnelHQ asks at most once a day. When the registry gave no date, because of an error or because it doesn’t publish one, TunnelHQ asks again after 6 hours.
  • SSL expiration needs an https:// address, and is greyed out for an http:// one. If a check’s address changes to http://, it stops watching the certificate, and any open certificate incident closes. It watches the site’s own certificate, the one your visitors’ browsers are shown, and doesn’t depend on SSL/TLS verification.
  • New checks start with SSL expiration at 14 days and domain expiration off.
  • The choice is shared: changing either one in a check’s settings applies it to the project’s other website and keyword checks on the same host. Adding a check doesn’t change the others.

A few seconds after you save a check, its card and its settings under Domain expiration show the date when it’s known, such as “example.com expires on 13 August 2027, in 321 days”. Some registries don’t publish expiry dates, for example for .de, .io, and .pk domains. The settings then say so, such as “The registry for .de doesn’t publish expiry dates”, and domain expiration never alerts for that domain.

SSL expiration set to Alert 14 days before and Domain expiration to Alert 2 months before, with the line example.com expires on 13 August 2027, in 321 days.

TCP port checks with TLS keep their own reminders, at 21, 14, and 7 days, without an incident.

Check cards show the days left, such as Cert 60d and Domain 45d. Each turns amber within the check’s chosen window, or within 14 days if that’s longer: with Alert 7 days before, from 14 days; with Alert 2 months before, from 60 days. An expired certificate reads Cert expired, and one that isn’t trusted for another reason, such as a self-signed certificate, reads Cert invalid.

A website check’s card with the chips Cert 32d and Domain 321d.

With SSL/TLS verification off, a check stays up while its certificate is expired, and its card still says Cert expired:

A website check on expired.badssl.com that reads Healthy, with the chip Cert expired.

The alerts say what expires, when, and what happens if it lapses, for example:

  • “The domain example.com expires in 13 days, on 9 October 2026. Renew it with its registrar before then: Website stops working if it lapses.”
  • “The SSL certificate of www.example.com expires in 5 days, on 1 October 2026. Renew it before then: once it expires, browsers and apps refuse to connect to Website.”

An expiry incident shows as Expiring, in amber, never as Down. It reads, for example, “Domain example.com expires on 9 October 2026” or “SSL certificate of www.example.com expires on 1 October 2026”, and its detail panel says “Closes by itself once the certificate or the domain is renewed”.

An Expiring incident on the Incidents page: Expired certificate, SSL certificate of expired.badssl.com expired on 12 April 2015, and the check’s address.

The incident's detail panel: one Expiring badge, the message and address, Acknowledge Incident, the activity log, and Closes by itself once the certificate or the domain is renewed. There's no Resolve button.

Expiry incidents sort after outages, and don’t count in outage figures such as active outages and response times.

  • In Add check, every alert channel in the project is selected to start with.
  • At least one must stay selected when you add a check. Otherwise you’ll see “Pick at least one. To alert nobody, change it on the check once it is added.”
  • On a check’s Settings tab, you can clear every channel. The check then alerts nobody.

Checks connect from TunnelHQ’s servers, so private and reserved addresses, such as 10.x.x.x, 192.168.x.x, 127.0.0.1, and 169.254.169.254, are refused when you save:

  • “URL is not allowed (must be a public hostname)”
  • “Host is not allowed (it must be a public address)”
  • Host "x" could not be found. Check the address. for a host that doesn’t resolve

When there’s more than one place to check from, Check from is the last field in Advanced settings. The main location is always included.

Advanced settings of a DNS check, with Check from showing Germany selected and Canada and UAE available.

  • With two or more locations, a check is Down only when most of the locations still checking see it down: both of 2, 2 of 3, or 3 of 4. Fewer is Partial. This differs from tunnels, where a monitor is Down only when no location is up.
  • A location with no working checker is left out.
  • Alert on a partial outage also alerts when only some locations see the check down. It’s off by default, and can only be turned on with two or more locations.

A website check’s page: its status, how long it has been up, the last check, incidents, the health timeline and the response-time chart.

  • Run Now, at the top right, runs the check immediately (so does the ▷ button on its card in the Uptime list). It doesn’t use the on-demand test quota that tunnel tests use. Heartbeats have no run button: they’re checked when your job calls their address.
  • Send test alert sends a test through every channel the check alerts. It needs a role that can edit monitors.
  • A response-time chart, and an availability table for the last 24 hours, 7 days, 30 days, and 90 days: availability, downtime, number of incidents, and the longest and average incident. See Availability.
  • Currently up for and Last checked.
  • For checks that use TLS, the number of days until the certificate expires is also shown on the check’s card.

The availability table on a check’s page counts outages. A period’s availability is the share of it with no incident, counted from when the check was created if that’s later, so it always agrees with the downtime beside it. For example, 1 hour down in the last 24 hours reads 95.83%.

  • A failure that ends within the confirmation period never becomes an incident, so it isn’t downtime.
  • Until a check has its first result, the table shows no figure.

The bars in the health timeline and the uptime figure on a check’s card are worked out differently: checks count their results, and heartbeats measure time. For a check that was down a lot, the card’s figure and the table can differ slightly, because they cover slightly different windows.

In the REST API, GET /api/v1/servers?family=uptime lists Uptime checks (family=all lists tunnels and checks together; the default is tunnels only), and POST /api/v1/servers creates website, keyword, ping, TCP port, and DNS checks, and heartbeats. Groups are managed in the dashboard only: "type": "group" is refused with 400 “Groups are created in the dashboard for now.”

When you create a check, you can also send:

Field Values Checks
ssl_expiration Days before the certificate expires to alert: 1, 2, 3, 7, 14, 30, or 60. 0 or null turns it off. Needs an https:// URL. Website, keyword
domain_expiration Days before the domain expires to alert, with the same values. 0 or null turns it off. Website, keyword
ip_version "ipv4", "ipv6", or null for both. Website, keyword, ping, TCP port

30 and 60 match Alert 1 month before and Alert 2 months before. A field you leave out takes the value of the project’s other checks on the same host, or, for the host’s first check, the default: 14 days for an https:// URL, and domain expiration off. Check rows return the same three fields, where null means off, or both IP versions.

A DNS check is created with "type": "dns" and these fields:

Field Details
host The DNS server to monitor: a public IP address, such as 1.1.1.1, or an IPv6 address with or without brackets. A private or reserved address, or a name, is refused with 400 “host must be the DNS server’s public IP address, like 1.1.1.1.”
domain The domain to ask it about, such as example.com. Labels may start with _, as in _dmarc.example.com. Anything else is refused with 400 “domain must be a domain name to query, like example.com.”
keyword Optional. Text the answer must contain, usually the address the domain should point to. Up to 255 characters.

DNS checks refuse ip_version, because the DNS server’s address decides it, and ssl_expiration and domain_expiration. Queries always go to port 53. Every check row has a domain field: the domain a DNS check asks about, or null for other checks. A DNS check’s host is its DNS server.

PUT /api/v1/servers/:id updates a website, keyword, ping, TCP port, or DNS check (heartbeats have their own fields). Send only the fields you want to change; the rest stay as they are.

Fields Checks
name, interval, timeout, maxretries, tags All
ip_version Website, keyword, ping, TCP port
url, accepted_statuscodes, ssl_expiration, domain_expiration Website, keyword
keyword Keyword, DNS
invert_keyword Keyword
host Ping, TCP port, DNS
port TCP port
domain DNS
  • interval has the same minimum as when you create the check, and the expiration and IP version fields take the same values.
  • Changing either expiration setting applies it to the project’s other website and keyword checks on the same host, as in the dashboard.
  • When you create or change a check, a field its type doesn’t have is refused with 400 and a message naming it, such as “port is for port checks.” or “keyword is for keyword and DNS checks.”
  • For a DNS check, keyword set to "" or null clears it.
  • A check’s type can’t be changed: the API answers “Create a new check instead”.
  • active pauses (false) or resumes (true) the check, as the dashboard’s Pause and Resume buttons do: its history shows “Monitoring paused” or “Monitoring resumed”, and the monitor.paused and monitor.resumed webhooks fire. It needs permission to pause monitors as well as to edit them, and a resume can be refused with 403 by the plan. Any value other than true or false is refused with 400 “active must be true or false.” It can go in the same request as other changes, such as {"active": true, "interval": 300}.
  • A running check picks up a change at once. A paused check stays paused unless the request also sends "active": true.

POST /api/v1/incidents/:id/retest retests any check behind an incident, including a DNS check. The MCP server and the CLI manage Uptime checks from version 0.4.0.