Active monitors
Unlike heartbeat, where your service “calls” Notifly, an active monitor works the other way: a Notifly serverless function itself checks the specified resource every N seconds. If a configured number of attempts in a row fail, an alert is sent; when the connection is restored, a recovery is sent.
There are 27 supported check types — from a simple HTTP GET to lightweight
protocol handshakes for mail, databases, queues and network services,
DNS resolution and TLS certificate checks.
Basic checks:
kind | What it checks | Target format |
|---|---|---|
http | GET <url>, expects 2xx (or expectedStatus) | https://example.com/health |
tcp | TCP handshake — port is open | host:port |
ssl | TLS certificate: chain of trust and host name are valid, more than certMinDays days left before expiry (default 14) | example.com or example.com:8443 |
tls | TCP+TLS handshake (TLS 1.2+, certificate verified); expectedStatus = minimum certificate validity buffer in days, 0 — check the handshake only | host:port |
dns | Resolve a name using the system or specified resolver | example.com or example.com@8.8.8.8:53 |
Protocol handshakes (target is host:port; for sip, ntp, snmp the port can be omitted):
kind | What it checks |
|---|---|
smtp | TCP, read 220 banner (or send EHLO right away), expect 250, QUIT |
imap | TCP, wait for * OK ..., send a LOGOUT |
pop3 | TCP, wait for +OK ..., send QUIT |
ssh | TCP, read SSH-... banner |
ftp | TCP, wait for 220 banner, send QUIT |
redis | TCP, send PING, expect +PONG (a -NOAUTH reply also counts as alive) |
postgres | TCP, send StartupMessage, expect R/E/N |
mysql | TCP, read handshake packet (protocol_version=10) |
mongodb | TCP, send hello (OP_MSG), expect a response |
memcached | TCP, send version, expect VERSION ... |
clickhouse | TCP, native protocol: Client Hello |
cassandra | TCP, CQL OPTIONS, expect SUPPORTED |
zookeeper | TCP, ruok command |
mqtt | TCP, CONNECT (MQTT 3.1.1), expect CONNACK |
kafka | TCP, ApiVersions request |
amqp | TCP, AMQP 0-9-1 header, expect Connection.Start (RabbitMQ etc.) |
nats | TCP, wait for INFO ... banner |
ldap | TCP, anonymous root DSE SearchRequest, expect a response |
rdp | TCP, send X.224 Connection Request, expect a response |
sip | UDP, OPTIONS (default port :5060) |
ntp | UDP, NTP request (default port :123) |
snmp | UDP, SNMPv1 GetRequest (default port :161) |
Protocol checks do not authenticate against the service — they confirm that the server is alive and speaks its protocol.
How it works
Section titled “How it works”every minute: timer-trigger → notifly-monitor └─▶ take monitors whose next_check_at is due (except paused) └─▶ check with timeoutSec ├─ success → status=up, failCount=0 │ if it was "down" and an alert was sent → recovery (if text is set) └─ failure → failCount++ < consecutiveFails → status=degraded ≥ consecutiveFails → status=down; alert, unless already sent- Check — a separate
notifly-monitorfunction, started once a minute by a timer trigger. If there are more due monitors than fit into one invocation, the work is spread across additional invocations. - Notification — a normal Notifly message in the channel chosen when creating the monitor. It reaches all your devices (web, Android, iOS, desktop) like any other push notification and is then escalated according to the channel’s delivery settings.
- History — every check is written to history (per-minute, per-hour and per-day aggregates plus a log of recent checks) — see REST endpoints.
Monitor statuses: pending (created or resumed, no checks yet), up,
degraded (there are failures, but the consecutiveFails threshold is not reached), down, paused.
Events
Section titled “Events”Since Notifly initiates the communication, there are two explicit events:
| Event | When sent | Text |
|---|---|---|
| Connection lost (alert) | After consecutiveFails failures in a row, once per outage. The technical error is appended to the text in parentheses (for example, (connection refused)) | alertTitle + alertMessage |
| Connection restored (recovery) | On the first successful check after down — only if recoveryMessage is set and an alert about the outage was actually sent | recoveryTitle + recoveryMessage |
Both messages are sent with priority alertPriority.
There’s no repeated alert spam: once an alert is sent, the monitor records the
time in the alertedAt field and, while it stays down, sends no new messages —
checks continue at the normal interval and simply record the status. The
exception is re-arm: if you change check parameters via PUT /monitor/:id
(kind, target, interval, timeout, expectedStatus, certMinDays,
consecutiveFails), alertedAt is cleared and the monitor is checked right
away; if the target is still unreachable, a fresh alert is sent. Editing the
name, texts or priority doesn’t reset the timer and doesn’t re-arm.
What else affects notifications:
- Read = escalation stops. While an alert is unread, the channel’s escalation may keep delivering it (email, SMS, voice call, messengers, webhooks). Marking it as read — in the app or via the link in the email/Telegram message — stops delivery through the remaining methods.
- Quiet hours of the channel owner suppress escalation
to external channels for messages with a priority below the
breakthroughPrioritythreshold (8 by default). To have an alert wake you up at night, setalertPriorityat or above the threshold. - Maintenance windows: during a window, checks keep running and are written to history, but the alert is deferred — if the target is still down after the window, the very first check sends it. If a monitor goes down and comes back within the window, you get neither an alert nor a recovery.
- Status page of the channel: going
downopens an auto-incident on the public page, recovery closes it.
Creating a monitor
Section titled “Creating a monitor”Through the admin UI
Section titled “Through the admin UI”- Open app.notifly.ru → Monitoring → Monitors.
- Click “Create” — the “What do you want to check?” wizard opens. For a protocol monitor pick the “Service on a host/port is alive” card (then a protocol from the list) or “SSL certificate isn’t expiring”. The other cards lead to the specialized monitors and heartbeat.
- Fill in:
- Name — for display, e.g. “Prod site” or “Postgres replica”.
- Channel — which channel to send the notification through (your own or one shared with you with send permission).
- Check type — one of the 27
kinds (see the tables above). - Target — the format depends on the type: URL,
host:port, host or DNS name. - Period (sec) — between checks (minimum 30, maximum 86400).
- Timeout (sec) — how long to wait for a response per attempt (default 10, maximum 30).
- Consecutive failures — how many failed checks in a row before an alert (default 1, maximum 20; typically 2–3 to avoid reacting to one-off network jitter).
- Expected HTTP code (
httponly) —0means “any 2xx”, otherwise an explicit code (e.g.200). - Alert N days before certificate expiry (
tlsonly) —0= check the handshake only;30= alert if the certificate has less than 30 days left. - Warn N days before expiry (
sslonly) — 1–365, default 14. - Alert / recovery text — what arrives in the push. Recovery is enabled by the “Notify on recovery” checkbox.
- The “Test” button runs a single check right from the dialog — without saving the monitor.
Via REST API
Section titled “Via REST API”# HTTP checkcurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <api-token>" \ -d '{ "appid": 12345, "name": "Prod site", "kind": "http", "target": "https://example.com/health", "intervalSec": 60, "timeoutSec": 10, "expectedStatus": 0, "consecutiveFails": 2, "alertTitle": "Prod site is down", "alertMessage": "Site is unreachable!", "alertPriority": 9, "recoveryMessage": "Site is responding again." }'
# TCP checkcurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <api-token>" \ -d '{ "appid": 12345, "name": "Postgres replica", "kind": "tcp", "target": "db-replica.example.com:5432", "intervalSec": 60, "timeoutSec": 5, "consecutiveFails": 3, "alertMessage": "Replica is not accepting connections.", "recoveryMessage": "Replica is reachable again." }'
# SSL — certificate validity and an alert 21 days before expirycurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <api-token>" \ -d '{ "appid": 12345, "name": "SSL prod", "kind": "ssl", "target": "example.com", "intervalSec": 3600, "certMinDays": 21, "alertMessage": "The example.com certificate is invalid or expiring soon!" }'
# DNS — resolve check via the specified servercurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <api-token>" \ -d '{ "appid": 12345, "name": "Prod zone DNS", "kind": "dns", "target": "example.com@8.8.8.8:53", "intervalSec": 300, "timeoutSec": 5, "alertMessage": "The example.com zone does not resolve via 8.8.8.8" }'Request body fields:
| Field | Required | Description |
|---|---|---|
appid | yes | Channel ID for notifications; cannot be changed with PUT |
name | yes | 1–200 characters |
kind | yes | check type (see the tables above) |
target | yes | target in the format of its kind |
intervalSec | yes | 30–86400 |
timeoutSec | 1–30, default 10 | |
consecutiveFails | 1–20, default 1 | |
expectedStatus | http: 0 or a code 100–599; tls: minimum certificate buffer in days | |
certMinDays | ssl only: 1–365, default 14 | |
alertMessage | yes | 1–2000 characters |
alertTitle | title of the alert message | |
alertPriority | 0–10, priority of the alert and recovery | |
recoveryTitle, recoveryMessage | recovery title and text; empty recoveryMessage — no recovery is sent |
The response is the monitor object with the computed fields status, failCount,
lastCheckAt, lastError, nextCheckAt, alertedAt.
Examples by type
Section titled “Examples by type”Typical kind + target combinations for common tasks:
{ "kind": "smtp", "target": "mx.example.com:587" } // SMTP answers EHLO{ "kind": "imap", "target": "imap.example.com:143" } // IMAP is alive (plain){ "kind": "pop3", "target": "pop3.example.com:110" } // POP3 is alive{ "kind": "ssh", "target": "jump.example.com:22" } // SSH banner{ "kind": "redis", "target": "redis.example.com:6379" } // Redis answers PING{ "kind": "postgres", "target": "pg.example.com:5432" } // PostgreSQL accepts connections{ "kind": "mysql", "target": "db.example.com:3306" } // MySQL sends handshake{ "kind": "ntp", "target": "ntp.example.com" } // NTP over UDP, port 123 by default{ "kind": "tls", "target": "smtps.example.com:465", "expectedStatus": 14 } // TLS on port 465 is alive, certificate has ≥ 14 days{ "kind": "ssl", "target": "example.com", "certMinDays": 30 } // certificate is valid and won't expire within 30 daysVia MCP (for an AI assistant)
Section titled “Via MCP (for an AI assistant)”If you have the Notifly MCP server configured (see MCP), just ask:
Create a monitor for https://api.example.com/health, check every 30 seconds, alert after 3 consecutive failures with the text “API is down”, recovery “API is back up”.
Available MCP tools: list_monitors, create_monitor, update_monitor,
delete_monitor, pause_monitor, resume_monitor, test_monitor.
REST endpoints
Section titled “REST endpoints”| Method | Path | Description |
|---|---|---|
GET | /monitor | List the user’s monitors |
POST | /monitor | Create |
PUT | /monitor/:id | Update settings (appid cannot be changed) |
DELETE | /monitor/:id | Delete |
POST | /monitor/:id/pause | Pause (checks are not performed) |
POST | /monitor/:id/resume | Resume: status pending, check runs right away |
POST | /monitor/test | One-off check (dry-run) without creating a monitor — returns ok, durationMs, details, error |
GET | /monitor-history/:kind/:id | Check aggregates by bucket; parameters bucket (1m/1h/1d, default 1h), from, to (unix seconds) |
GET | /monitor-history/:kind/:id/log | Recent checks (the log is kept for 7 days); parameter limit (default 50, maximum 200) |
All endpoints require an API token or a device token —
login/password is not accepted.
For modifying operations (POST/PUT/DELETE, as well as pause/resume) the API
token needs write access; for reads (GET lists, history) and for POST /monitor/test,
read is enough. If the token is limited to certain channels, it only sees and
changes monitors of those channels.
The POST /monitor/test endpoint accepts { "kind", "target", "timeoutSec", "expectedStatus", "certMinDays" }
(timeout up to 60 seconds, default 10) and runs one check right now without saving
anything — handy to verify the target is reachable before creating a monitor:
curl -X POST "$NOTIFLY_URL/monitor/test" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <api-token>" \ -d '{ "kind": "tcp", "target": "db.example.com:5432", "timeoutSec": 5 }'# → {"ok":true,"durationMs":42,"details":"Connected to db.example.com:5432"}An unreachable target returns 200 with "ok": false and the error text in error.
History is available for every kind of monitoring: :kind is the entity kind —
monitor (this page), http_monitor, content_monitor, port_monitor,
workflow_monitor, browser_workflow_monitor or heartbeat, and :id is the
monitor ID. By default history returns the last 24 hours for 1m, 7 days for
1h and 30 days for 1d. Each bucket contains bucketTs, checksCount,
successCount, failCount, sumDurationMs/minDurationMs/maxDurationMs and
lastStatus; a log entry contains ts, success, durationMs, error.
Other monitor types
Section titled “Other monitor types”The /monitor described above covers “lightweight” protocol checks (HTTP GET, TCP
and protocol handshakes, DNS, TLS/SSL). For more complex scenarios Notifly has
specialized monitors with their own settings, timeout limits and separate REST APIs:
- HTTP monitors — full requests with method, headers, body, status/content checks and response time (timeout up to 30 s).
- Content monitors — watch for changes in page content or a value in a JSON API, timeout up to 60 s.
- Port monitors — check a set of ports on a host (timeout up to 10 s).
- Port scanning — discover the open ports of a host.
- Workflow monitors — chains of HTTP steps with value extraction and assertions (timeout up to 60 s).
- Browser workflow — scenarios in a real browser (clicks, input, on-page assertions), timeout up to 120 s.
Related monitoring features:
- Metrics — ingest numeric metrics and alert on thresholds.
- Domain verification — proving ownership of a host.
- Heartbeat — the reverse scenario: your service periodically “calls” Notifly, and an alert comes when a ping is missed.
- Maintenance windows — planned work without false alerts.
- Status pages — public status and uptime of a channel’s monitors.
Limitations
Section titled “Limitations”- Minimum period: 30 seconds.
- Maximum period: 24 hours (for rare checks, heartbeat is more economical).
- Every check is an event in the plan’s daily quota (Free — 1,000 events per day, see Quotas and plans). A monitor with a 60-second period uses 1,440 events per day. When the quota is exhausted, checks are postponed until 00:05 Moscow time the next day, and you get a single quota notification.
- Checks run from Yandex Cloud, so the target must be reachable from the public internet; private, loopback and link-local addresses are not allowed.
- Protocol checks (
smtp/imap/pop3/redis/…) run without TLS — for encrypted ports usekind: "tls"orkind: "ssl". - There’s no domain registration expiry check (WHOIS/RDAP) —
sslonly watches the certificate.