Alerts & Notifications

Get notified when your monitors detect issues. Configure alerts via email, Slack, Discord, PagerDuty, or custom webhooks.

When a monitor detects an issue—a website goes down, an API returns errors, a cron job misses its schedule—alerts deliver that information to the right people through the right channels.

How Alerts Work

Alerts connect monitors to notification channels. When a monitor's status changes (for example, from "up" to "down"), Uptime evaluates your alert configuration and sends notifications to the appropriate channels.

The flow is straightforward:

  1. A monitor detects a status change

  2. Uptime checks which alerts are configured for that monitor

  3. Each matching alert sends a notification through its configured channel

  4. The alert event is recorded in your alert history

Every alert has a scope that decides which monitors it hears about: every monitor on the team, every monitor of one kind, or a single monitor. This lets you set up focused alerts for critical services while maintaining a catch-all alert for everything else.

When an Alert Fires During an Outage

For any single outage, an alert follows the same three-part pattern:

  1. Immediately, as soon as the monitor is detected down. The first notification of an outage is never held back—no confirming second check, and no cooldown applies to it. Whatever cooldown you configure, the news that something just broke reaches you on the first failing check.

  2. Again, each time the cooldown expires while the monitor is still down. An ongoing outage keeps reminding you at your configured interval for as long as it lasts. There is no limit on how many notifications one outage can produce: a monitor that stays down for three days on a one-hour cooldown sends roughly one notification an hour for three days.

  3. Once more when it recovers, if Notify on recovery is enabled.

Between those, failing checks that fall inside the cooldown window are recorded in your alert history as skipped rather than sent, and the recovery notification reports how many were held back—so a quiet incident never looks like dropped alerts.

Alert Channels

Uptime supports five notification channels, each suited for different workflows and team setups.

Email

Email alerts are the simplest option—enter an email address, and Uptime sends notifications when issues occur.

Configuration options:

  • Email address — Where to send notifications (can be any valid email, not just team members)

  • Subject prefix (optional) — Add a custom prefix to email subjects for easier filtering (e.g., [PROD] or [CRITICAL])

Email works well for:

  • Personal notifications to on-call engineers

  • Team distribution lists

  • Integration with email-based ticketing systems

  • Backup notifications when other channels might be unavailable

Webhook

Webhooks send HTTP POST requests to your endpoint when alerts trigger. This is the most flexible option, enabling integration with virtually any system.

Configuration options:

  • URL — Your endpoint that will receive the POST request

  • Secret (optional) — A shared secret used to sign requests, allowing you to verify they came from Uptime

  • Signature scheme — How requests are signed: Standard Webhooks (the default for new alerts) or Legacy

When an alert fires, Uptime sends a JSON payload containing:

  • Monitor details (name, type, URL/target)

  • Event type (down, up, degraded)

  • Timestamp

  • Additional context based on monitor type

If you configure a secret, Uptime signs every request so you can verify its authenticity. This prevents malicious actors from spoofing alert notifications.

Verifying Webhook Signatures

With the Standard Webhooks scheme, each request carries the three headers defined by Standard Webhooks:

  • webhook-id — The delivery's id. Retries of one notification reuse it, so you can drop duplicates.

  • webhook-timestamp — When the request was signed, in seconds since the epoch.

  • webhook-signature — v1, followed by the base64 HMAC-SHA256 of webhook-id.webhook-timestamp.body.

Any Standard Webhooks library verifies these. It takes a secret written as whsec_ plus base64, which the alert form shows under the signature scheme once the alert is saved. A secret you entered in that form already is used as it is; any other secret becomes whsec_ followed by the secret in base64.

In Node.js with the standardwebhooks package:

typescript
import { Webhook } from "standardwebhooks";

let webhook = new Webhook(process.env.UPTIME_WEBHOOK_SECRET); // "whsec_…"

export async function handle(request: Request): Promise<Response> {
	let body = await request.text();
	try {
		let alert = webhook.verify(body, Object.fromEntries(request.headers));
		await processAlert(alert);
		return new Response(null, { status: 204 });
	} catch {
		return new Response(null, { status: 401 });
	}
}

Libraries for Python, Go, Ruby, PHP, Java, Rust and more are listed on standardwebhooks.com. They also reject a request whose timestamp is more than five minutes away from your clock, which stops a captured request from being replayed later.

Without a library, verify with Web Crypto, comparing in constant time:

typescript
async function verifyStandardWebhook(request: Request, secret: string) {
	let id = request.headers.get("webhook-id");
	let timestamp = request.headers.get("webhook-timestamp");
	let signatures = request.headers.get("webhook-signature") ?? "";
	if (!id || !timestamp) return null;
	if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return null;

	let body = await request.text();
	let keyBytes = Uint8Array.from(atob(secret.replace(/^whsec_/, "")), (c) => c.charCodeAt(0));
	let key = await crypto.subtle.importKey(
		"raw",
		keyBytes,
		{ name: "HMAC", hash: "SHA-256" },
		false,
		["verify"],
	);

	for (let entry of signatures.split(" ")) {
		let [version, signature] = entry.split(",");
		if (version !== "v1" || !signature) continue;
		let mac = Uint8Array.from(atob(signature), (c) => c.charCodeAt(0));
		let valid = await crypto.subtle.verify(
			"HMAC",
			key,
			mac,
			new TextEncoder().encode(`${id}.${timestamp}.${body}`),
		);
		if (valid) return JSON.parse(body);
	}
	return null;
}

With the Legacy scheme, each request carries Webhook-Signature: sha256=<hex>, the hex HMAC-SHA256 of the raw body keyed by the secret exactly as you entered it:

typescript
async function verifyLegacyWebhook(request: Request, secret: string) {
	let header = request.headers.get("webhook-signature") ?? "";
	if (!header.startsWith("sha256=")) return null;

	let body = await request.text();
	let encoder = new TextEncoder();
	let key = await crypto.subtle.importKey(
		"raw",
		encoder.encode(secret),
		{ name: "HMAC", hash: "SHA-256" },
		false,
		["verify"],
	);
	let mac = Uint8Array.from(header.slice(7).match(/../g) ?? [], (byte) => parseInt(byte, 16));
	let valid = await crypto.subtle.verify("HMAC", key, mac, encoder.encode(body));
	return valid ? JSON.parse(body) : null;
}

Both schemes send their signature in the header named webhook-signature (header names are case-insensitive), so a request carries exactly one of them. The legacy scheme covers only the body; Standard Webhooks also covers the delivery id and the time, which is what lets a receiver reject replays.

Moving an Alert to Standard Webhooks

Alerts created before Standard Webhooks signing existed keep the legacy signature until you switch them, so nothing changes for a receiver that is already in place. To switch one without dropping a notification:

  1. Update your receiver to accept either scheme for the moment: a webhook-signature value starting with sha256= is legacy, and anything else goes to your Standard Webhooks verifier.

  2. Edit the alert and change Signature scheme to Standard Webhooks, or send {"signature": "standard-webhooks"} in a PATCH.

  3. Once notifications arrive with the new headers, remove the legacy branch from your receiver.

The legacy scheme is deprecated: plan to move every webhook alert to Standard Webhooks.

Webhooks are ideal for:

  • Custom dashboards and internal tools

  • Integration with PagerDuty, OpsGenie, or other incident management platforms

  • Triggering automated remediation workflows

  • Feeding data into logging or analytics systems

Slack

Send alerts directly to Slack channels using an incoming webhook URL.

Configuration options:

  • Webhook URL — Your Slack incoming webhook URL. Each webhook posts to the channel it was created for, so create one webhook per channel.

To set up Slack integration:

  1. Create an incoming webhook in your Slack workspace (Apps → Incoming Webhooks)

  2. Copy the webhook URL

  3. Paste it into Webhook URL on your Uptime alert

Slack alerts include formatted messages with:

  • Monitor name and status

  • Direct link to the monitor in Uptime

  • Timestamp and relevant details

Discord

Send alerts to Discord channels using a webhook URL.

Configuration options:

  • Webhook URL — Your Discord channel webhook URL

To set up Discord integration:

  1. Open your Discord server settings

  2. Navigate to Integrations → Webhooks

  3. Create a new webhook and copy the URL

  4. Paste it into your Uptime alert configuration

Discord alerts are formatted as embeds with clear status indicators and monitor details.

PagerDuty

Send alerts to a PagerDuty service, which can page whoever is on call.

Configuration options:

  • Integration key — The integration key of the service's Events API v2 integration, found in PagerDuty under Service → Integrations → Events API V2

Alert Configuration

Every alert has several configuration options beyond the channel settings.

Name

Give your alert a descriptive name that makes it easy to identify in your alert list and in notification messages. Good names describe what the alert covers:

  • "Production API - Engineering Team"

  • "All Monitors - Email Backup"

  • "Critical Services - PagerDuty"

Notify on Recovery

When enabled, Uptime sends a notification when a service comes back up, not just when it goes down. This helps you:

  • Know when issues resolve without manually checking

  • Close incident tickets automatically (via webhooks)

  • Reduce anxiety during outages—you'll know when things are fixed

Recovery notifications are strongly recommended for most alert configurations.

Cooldown Period

The cooldown is how far apart repeat notifications are spaced while a monitor stays broken. It does not delay the first notification of an outage—that one always goes out immediately—it only decides how often the outage keeps reminding you afterwards.

Cooldown is set per alert, in minutes, anywhere from 0 to 1440 (24 hours). When you don't choose one, Uptime uses 60 minutes: an ongoing outage reports itself once an hour, which is frequent enough to stay in front of you and quiet enough that a day-long outage is 24 notifications rather than hundreds.

Common choices:

  • 5 minutes — Critical services where you want frequent updates during an outage

  • 15 minutes — Tighter than the default, for services with short recovery targets

  • 60 minutes — The default; hourly reminders for as long as the outage lasts

  • 120 minutes or more — Minimizes interruptions for low-priority monitors

  • 0 — As often as allowed, for an alert you want to hear from on nearly every failing check

Repeat notifications are never sent more often than once every five minutes, whatever the cooldown says. That floor is why a cooldown of 0 means "as often as allowed" rather than "one notification per check"—the fastest monitor interval is 60 seconds, so a 0 cooldown produces at most 12 notifications an hour instead of 60.

Cooldowns are especially valuable when services are "flapping"—rapidly alternating between up and down states. With a 60-minute cooldown, you get one notification and then silence for an hour, however many times the monitor bounces in between.

Recovery notifications are spaced by the cooldown you configured, and the five-minute floor does not apply to them. Setting a very low cooldown on a flapping monitor can therefore produce a "recovered" message per flap; raising the cooldown is what stops that.

Changing an alert's cooldown only affects that alert. Alerts you configured before the one-hour default existed keep the cooldown you gave them, including 0.

Scope

Every alert is scoped one of three ways, chosen from a single dropdown on the alert form:

  • Team-wide — The alert fires for every monitor on your team, of every kind. This is the default, and it is what every alert created before scoping existed still does.

  • Every monitor of one kind — The alert fires for all your HTTP monitors, or all your DNS, TCP or flow monitors, or all your cron jobs, and for nothing else. The choice covers monitors you add later too, so a new domain is watched the moment you create it.

  • One monitor — The alert fires only for that monitor, whichever kind it is.

Narrowing the scope is useful when:

  • Different services have different on-call rotations

  • You want different notification channels for different environments

  • Critical services need dedicated alerting separate from general monitoring

  • One kind of monitor is noisier than the rest and deserves its own channel

That last case is what DNS monitoring usually runs into. A domain monitor reports every record that stops resolving, every record that changes, and every record it newly discovers across the whole zone, so a busy domain can produce far more notifications than a website going down. Scoping a DNS-only alert to its own channel keeps that traffic away from the one your on-call phone is attached to.

Leaving an alert team-wide provides a safety net—even if you forget to configure a specific alert for a new monitor, the catch-all alert will notify you.

Certificate expiry warnings follow the HTTP monitor they belong to: an alert scoped to that monitor, or to HTTP monitors as a kind, receives them.

If an alert is scoped to a monitor you later delete, its scope reads as an unknown monitor and it stops firing. Editing it makes you pick a new scope before it can be saved, rather than silently widening it back to everything.

Alert Events and History

Every time an alert fires (or would fire but is in cooldown), Uptime records an event. The alert history shows:

  • Alert — Which alert the event belongs to

  • Monitor — Which monitor triggered the alert

  • Event — Down, Degraded, or Recovered

  • Status — Whether the notification was sent, skipped because the cooldown had not expired, or failed

  • Time — When the event occurred

Open it from Alerts with View History. An alert held back by a maintenance window isn't recorded.

Older events may show a "Skipped (Repeat Limit)" status. That came from a previous policy that stopped notifying after a fixed number of notifications per incident; nothing produces it any more, and the label is kept only so historical events still read correctly.

Alert history helps you:

  • Audit past incidents and response times

  • Identify patterns in service failures

  • Verify that notifications are being delivered

  • Debug integration issues with webhooks or chat platforms

Events are kept for 90 days.

Best Practices

Use Cooldowns to Prevent Alert Fatigue

Nothing burns out an on-call engineer faster than constant notifications. You will always hear about a new outage on the first failing check, so the cooldown is purely about how insistently the same outage repeats itself.

Start with the 60-minute default and shorten it for the services where an hour of silence is too long. Lengthening it never costs you the initial notification, and shortening it never gets you more than one notification every five minutes.

Enable Recovery Notifications

Always enable Notify on recovery for alerts. Knowing when a service comes back up is just as important as knowing when it goes down. Recovery notifications:

  • Let you close incidents confidently

  • Reduce the need to constantly check dashboards

  • Provide clear incident timelines for post-mortems

Set Up Multiple Channels for Redundancy

Don't rely on a single notification channel. If Slack is down, you won't get your Slack alerts. Configure at least two channels:

  • Primary: Slack or Discord for team visibility

  • Backup: Email for guaranteed delivery

For critical services, consider adding a PagerDuty alert that can escalate to phone calls.

Use Webhooks for Custom Integrations

Webhooks unlock powerful workflows beyond basic notifications:

  • PagerDuty/OpsGenie — Create incidents automatically with proper severity levels

  • Incident management — Update status pages or create tickets

  • Auto-remediation — Trigger runbooks or restart services

  • Analytics — Feed alert data into your observability stack

When using webhooks, always configure a secret to verify request authenticity.

Stay Within Limits

Each team can configure a maximum of 10 alerts. This limit encourages thoughtful alert design rather than creating an alert for every possible scenario.

If you find yourself needing more alerts, consider:

  • Using unlinked alerts that cover multiple monitors

  • Consolidating similar monitors under single alerts

  • Using webhooks to fan out to multiple destinations from one alert

Next Steps

Documentation