Alert rules
An alert rule decides when PathWatch notifies you. Each rule combines:
- a scope — which monitors the rule watches,
- a condition — what has to happen,
- a confirmation block — how sure PathWatch must be before firing,
- a notifications block — recovery notices and recurring reminders,
- one or more channel bindings — where the alert goes, each with an optional escalation delay.
Create and edit rules in the WebUI at Alerts → Rules, or via the
API (POST /api/v1/alert-rules). A rule also carries a name
(required), an optional description, and an enabled flag — disable
a rule to mute it without deleting its configuration.
Scope
A rule watches one monitor, a tagged group, or everything in the organisation:
| Scope type | Fields | Watches |
|---|---|---|
monitor | monitor_id | A single monitor. |
monitor_group | tag | Every monitor carrying the tag. Monitors added to the tag later are covered automatically. See Monitor groups. |
all_monitors | — | Every monitor in the organisation, including ones created after the rule. |
A monitor can match any number of rules; each rule evaluates independently on every check result.
Conditions
Seven condition types are available. Each rule has exactly one condition.
| Condition | Fields | Fires when |
|---|---|---|
status_change | to (list of statuses, at least one) | A check reports any status in to. Statuses: up, down, degraded, timeout. An optional from list is accepted by the API but the current evaluator matches on to only. |
metric_threshold | metric, operator, threshold | The named metric crosses the threshold. operator is one of gt, lt, eq, neq, gte, lte. |
ssl_expiry | days_before (≥ 1) | The monitored certificate has days_before or fewer days until expiry. Use with SSL monitors. |
domain_expiry | days_before (≥ 1) | The monitored domain registration has days_before or fewer days remaining. Use with domain expiration monitors. |
keyword_missing | keyword | The response body does not contain the keyword. |
certificate_changed | — | A check detects that the certificate serving the endpoint changed since the previous check. |
monitoring_unavailable | — | The check could not run at all — no runner or region was available to execute it. This alerts on monitoring coverage, not on your service. |
Metric names for metric_threshold
response_time (alias duration_ms) compares against the check’s
total duration in milliseconds. Any other numeric field from the
check’s result data also works — for example ssl_days_remaining
on SSL checks or packet_loss_pct on ping checks. See the result
data tables on each monitor type’s page for the fields it produces.
Confirmation
The confirmation block controls how much evidence the rule needs before it fires:
| Field | Default | Meaning |
|---|---|---|
consecutive_failures | 1 | The condition must hold for this many checks in a row before the alert fires. |
confirmation_regions | null | Coming soon. Will restrict which regions’ results count toward confirmation. The field is accepted and stored today, but does not yet affect evaluation — consecutive_failures is the active control. |
Failure counts are tracked per region: each (rule, monitor, region) combination keeps its own consecutive-failure counter and its own alerting state, so a wobble in one region doesn’t inherit the count from another. A single passing check from a region resets that region’s counter and recovers its alert.
For tuning advice — thresholds by check interval, multi-region confirmation patterns, and the trade-offs — see Confirmation regions & failure thresholds.
Notifications
| Field | Default | Meaning |
|---|---|---|
on_recovery | true | Send a recovery notice to the rule’s channels when the alert clears. |
recurring | false | Keep re-sending the alert while it stays active and unacknowledged. |
recurring_interval_minutes | null | Minutes between recurring reminders (≥ 1). Required for recurring to take effect. |
Recurring reminders fire to every channel bound to the rule (including escalation-delayed ones), and stop the moment the alert is acknowledged or recovers. Recovery notices likewise go to every bound channel.
Channel bindings and escalation delays
Each rule carries a list of channel bindings:
| Field | Default | Meaning |
|---|---|---|
channel_id | — | An alert channel to notify. |
delay_minutes | 0 | How many minutes after the alert starts before this channel is notified. 0 = immediately. |
Bindings with different delays form an escalation chain: page the team Slack immediately, then PagerDuty 15 minutes later if nobody has acknowledged. A delayed channel never fires if the alert recovers or is acknowledged before its delay elapses. Full behaviour — timing, acknowledgement, recovery interplay — is on the Alert escalation page.
Acknowledging alerts
The Active alerts panel at the top of Alerts lists every currently firing (rule × monitor × region) row. Acknowledging a row stops escalation steps and recurring reminders for that alert; it does not resolve the alert or notify anyone. Acknowledgement is per-region — you can silence one region’s alert while others keep escalating — and re-acknowledging an already-acknowledged alert is harmless.
Via the API: POST /api/v1/alert-rules/:id/acknowledge with
{"monitor_id": "...", "region": "..."} (omit region to target
the monitor-wide alert state).
Every delivery — initial alert, escalation, reminder, recovery, acknowledgement — is recorded in Alerts → History with the channel, timestamp, and delivery status.
Plan limits
| Free | Starter | Pro | Business | |
|---|---|---|---|---|
| Alert rules | 10 | 15 | 25 | 50 |
| Alert channels | 5 | 10 | 20 | 50 |
See Limits & quotas for the full plan comparison.
Examples
The JSON below matches the POST /api/v1/alert-rules request body.
Replace <...-channel-id> with real channel ids from
Alerts → Channels.
Simple down alert
Fire on the first failed check, notify by email, send a recovery notice:
{ "name": "API down", "scope": { "type": "monitor", "monitor_id": "<monitor-id>" }, "condition": { "type": "status_change", "to": ["down", "timeout"] }, "confirmation": { "consecutive_failures": 1, "confirmation_regions": null }, "notifications": { "on_recovery": true, "recurring": false, "recurring_interval_minutes": null }, "channels": [ { "channel_id": "<email-channel-id>", "delay_minutes": 0 } ], "enabled": true}Multi-region confirmed alert
Require two consecutive failures, counted only from the listed regions, before paging — a single-region blip stays quiet:
{ "name": "Checkout down (confirmed)", "scope": { "type": "monitor_group", "tag": "checkout" }, "condition": { "type": "status_change", "to": ["down"] }, "confirmation": { "consecutive_failures": 2, "confirmation_regions": ["us-virginia", "gb-london"] }, "channels": [ { "channel_id": "<slack-channel-id>", "delay_minutes": 0 } ]}Escalation chain (0 min → 15 min)
Slack immediately; PagerDuty only if the alert is still firing and unacknowledged 15 minutes later:
{ "name": "Production outage escalation", "scope": { "type": "all_monitors" }, "condition": { "type": "status_change", "to": ["down", "timeout"] }, "confirmation": { "consecutive_failures": 2, "confirmation_regions": null }, "notifications": { "on_recovery": true, "recurring": false, "recurring_interval_minutes": null }, "channels": [ { "channel_id": "<slack-channel-id>", "delay_minutes": 0 }, { "channel_id": "<pagerduty-channel-id>", "delay_minutes": 15 } ]}Recurring reminder
Re-notify every 30 minutes while the monitor stays down and nobody has acknowledged:
{ "name": "Keep paging until acknowledged", "scope": { "type": "monitor", "monitor_id": "<monitor-id>" }, "condition": { "type": "status_change", "to": ["down"] }, "notifications": { "on_recovery": true, "recurring": true, "recurring_interval_minutes": 30 }, "channels": [ { "channel_id": "<pushover-channel-id>", "delay_minutes": 0 } ]}