Documentation
Complete guide to setting up website monitoring with PingZen. API documentation, code examples, and best practices.
Alert Configuration
PingZen supports multiple alert channels. Configure one or more channels for redundancy.
Telegram
The fastest way to receive notifications (1-2 seconds). One-click setup.
- In PingZen go to Alerts → Create Alert → select Telegram
- Click 'Connect Telegram' — a link to @pingzen_bot opens automatically
- Press Start in Telegram — your account is linked instantly
- For group alerts: switch to 'Group Chat' tab and click 'Add Bot to Group'
No need to copy Chat IDs manually — the wizard handles everything. You can also enter a Chat ID manually if needed.
Slack
Integration via Incoming Webhooks for team collaboration.
- In Slack go to Settings → Apps → Incoming Webhooks
- Click 'Add New Webhook to Workspace'
- Select a channel for notifications
- Copy the Webhook URL (https://hooks.slack.com/...)
- In PingZen create an alert and paste the URL
Create a dedicated #alerts channel for monitoring notifications.
Discord
One-click OAuth setup or paste a Webhook URL.
- In PingZen go to Alerts → Create Alert → select Discord
- Click 'Connect Discord' — you'll be redirected to Discord
- Select your server and channel, then authorize
- You're redirected back — the webhook is saved automatically
You can also paste a Webhook URL manually if you prefer. Create it in Discord: Server Settings → Integrations → Webhooks.
Microsoft Teams
Send alerts to Microsoft Teams channels via Incoming Webhook.
- 1.In Teams select channel → More options → Connectors
- 2.Find 'Incoming Webhook' and click Configure
- 3.Name the webhook and copy the URL
- 4.In PingZen create an MS Teams alert
- 5.Paste the Webhook URL
Mattermost
Slack-compatible webhooks for self-hosted teams.
- In Mattermost: Main Menu → Integrations → Incoming Webhooks
- Click Add Incoming Webhook
- Select a channel and copy the Webhook URL
- In PingZen use the Mattermost type
Receive alerts via WhatsApp through the Twilio API.
- Create a Twilio account and set up a WhatsApp Business API
- Get your Twilio Account SID, Auth Token, and WhatsApp number
- In PingZen create a WhatsApp alert
- Enter your WhatsApp phone number (with country code, e.g. +1234567890)
WhatsApp alerts require a Twilio account with WhatsApp Business API enabled.
PagerDuty
Route alerts to PagerDuty for on-call escalation.
- In PagerDuty go to Services → Service Directory → select your service
- Go to Integrations tab → Add Integration → Events API v2
- Copy the Integration Key (routing key)
- In PingZen create a PagerDuty alert and paste the routing key
PagerDuty triggers real incidents with escalation policies — ideal for production services.
Browser Push Notifications
Get instant push notifications directly in your browser — no apps or extensions needed.
- Go to Settings → Notifications in PingZen
- Click 'Enable Push Notifications'
- Allow notifications when your browser prompts
- Alerts will be delivered even when PingZen is not open
Browser push works on Chrome, Firefox, and Edge. Requires HTTPS.
Reliable email delivery via Resend. No configuration on your side — just enter an email address.
- In PingZen go to Alerts → Create Alert → select Email
- Enter the recipient email address (personal, team, or a distribution list)
- Save the alert — test delivery fires automatically from alerts@alerts.pingzen.dev
- Check your inbox (and the spam folder on the first delivery) to confirm
Sent from our dedicated alerts.pingzen.dev subdomain with SPF/DKIM/DMARC set up, so messages land in the inbox reliably. Includes a List-Unsubscribe header for Gmail's one-click unsubscribe button.
Webhook
Send JSON data to your HTTP endpoint for custom integrations (Home Assistant, n8n, Node-RED, IFTTT, your own services).
- Create an HTTP endpoint on your server to receive POST requests
- In PingZen create a Webhook alert
- Enter your endpoint URL
- Request method: POST, Content-Type: application/json, User-Agent: PingZen-Alert-Service/1.0
Attached a single webhook to multiple monitors? Jump to "One webhook for multiple monitors", "Home Assistant example", or "ntfy.sh example" below — ready-made recipes with per-monitor routing are there.
JSON Payload Format
POST <your URL>
Content-Type: application/json
User-Agent: PingZen-Alert-Service/1.0
{
"text": "🔴 My Website - Service Down",
"body": "URL: https://example.com\nProtocol: HTTPS\nStatus: DOWN\nResponse Time: 5000ms\n\nOpen monitor: https://pingzen.dev/monitors/123?ws=4",
"priority": "critical",
"timestamp": "2026-04-22T10:30:00+00:00",
"source": "pingzen",
"monitor_url": "https://pingzen.dev/monitors/123?ws=4",
"monitor_id": 123,
"monitor_name": "My Website",
"trigger": "down",
"status": "down",
"probes": [
{"label": "Moscow", "status": "up", "fail_streak": 0},
{"label": "Istanbul", "status": "down", "fail_streak": 3}
]
}What body looks like once parsed:
URL: https://example.com
Protocol: HTTPS
Status: DOWN
Response Time: 5000ms
Open monitor: https://pingzen.dev/monitors/123?ws=4Payload fields
| Field | Description |
|---|---|
| text | Headline: emoji + monitor name + localized status phrase ("Service Down" / "Сервис недоступен", "Service Recovered" / "Сервис восстановлен", "Service Degraded", "Certificate Expiring", etc.). Emoji: 🔴 DOWN/STILL_DOWN, 🟢 RECOVERED, 🟡 DEGRADED, ⚠️ CERTIFICATE_EXPIRING. |
| body | Multi-line body: URL, Protocol, Status (uppercase enum value: DOWN/UP/DEGRADED) or Error, Response Time, HTTP Status, Open monitor. Both labels and status words are localized to the monitor's language. The set of included fields is configurable in the alert form under "Message content". |
| priority | Event priority (NOT localized — safe for routing): critical (DOWN, STILL_DOWN, CERTIFICATE_EXPIRING — "real outage" bucket), high (DEGRADED, RESPONSE_TIME_HIGH), normal (RECOVERED). Filter on `priority == 'critical'` to catch outages and reminders together without picking up degraded/slow-response events. |
| timestamp | Event time in ISO 8601 (UTC). |
| source | Always "pingzen" — handy for filtering when the same endpoint receives events from multiple sources. |
| monitor_url | Link to the monitor page in PingZen. Contains the monitor ID in the path /monitors/{id}. ⚠️ Only sent when the alert form's "Monitor link" toggle is enabled (on by default). |
| monitor_id | Monitor ID (integer). Convenient for direct routing — no regex over monitor_url needed. Not present for synthetic alerts (heartbeat). |
| monitor_name | Monitor name without emoji or status (raw). Same value embedded in text, but as a dedicated field — handy for notification templates. |
| trigger | Event type (raw enum, NOT localized — best primitive for routing): down, still_down (reminder for a still-down monitor), recovered, degraded, certificate_expiring, response_time_high. |
| status | Current monitor status (raw enum, NOT localized): up, down, degraded, warning, transient, timeout, unknown. ⚠️ For test deliveries (see `test`) status carries the synthetic check-result value, not the live monitor status — do not key automation logic off this field. Use `trigger`. |
| test | Present (and equal to `true`) ONLY for deliveries triggered by the UI "Test" button. Production alerts omit this key entirely. Filter test deliveries out of any automation that changes entity state — see the Home Assistant example below. |
| monitors | Array of `{id, name, status, last_check_at}` for EVERY monitor attached to the alert. Present ONLY in test deliveries (alongside `test: true`). Lets HA / n8n automations re-sync ALL entity states from a single Test click instead of needing one click per monitor. Production payloads omit this key — they describe a single check_result via the top-level monitor_id/monitor_name/status fields. |
| probes | Array of `{label, status, fail_streak}` per assigned probe — one entry per probe in `monitor.probe_ids`. Present ONLY for multi-probe monitors (≥2 assigned probes). Single-probe and central-only monitors omit this key. Each entry: `label` is the probe city (e.g. "Istanbul"), `status` is the per-probe check status (up/down/degraded/timeout/error/unknown — NOT localized), `fail_streak` is the consecutive-failure count. Useful for HA / n8n automations that route by region: `{% if probe.status == 'down' and probe.label == 'Istanbul' %}…`. |
One webhook for multiple monitors
You can attach the same webhook URL to many monitors (or to a single alert that fires for a group). For routing, use the machine-readable fields: monitor_id (integer) to identify the monitor and trigger ("down" / "still_down" / "recovered" / "degraded" / "certificate_expiring") for the event type. Both fields are NOT localized. Avoid substring-matching text by "DOWN" — text contains a localized phrase ("Service Down" / "Сервис недоступен"), not the bare token "DOWN".
Example: ntfy.sh
ntfy.sh shows a JSON POST as plain text by default, so a bare /<topic> URL surfaces raw JSON on your phone. Use ntfy's inline templating in the query string — PingZen forwards the URL untouched, so no proxy or bridge is needed. The mapping below converts each PingZen field into the matching ntfy parameter.
Field mapping
| PingZen field | ntfy param | Notes |
|---|---|---|
monitor_name | ?t= (title) | Shown as the bold notification title. |
body | ?m= (message) | Multi-line message body (URL + status + response time). |
trigger ("down" / "recovered" / …) | ?p= (priority 1–5) | down / still_down → 5 (urgent), recovered → 3 (default), others → 4 (high). ntfy requires a number, so use a Go-template if/else. |
trigger (as-is) | ?tags= (emoji/text tags) | ntfy renders matching emojis (warning, white_check_mark) automatically. |
https://ntfy.sh/my-pingzen-topic?template=yes&t={{.monitor_name}}&m={{.body}}&p={{if eq .trigger "down"}}5{{else if eq .trigger "still_down"}}5{{else if eq .trigger "recovered"}}3{{else}}4{{end}}&tags={{.trigger}}🔴 My Website - Service Down URL: https://example.com Status: DOWN · 5000 ms
https://ntfy.example.com/my-pingzen-topic?template=yes&t={{.monitor_name}}&m={{.body}}https://ntfy.sh/my-pingzen-topic?template=yes&t={{.monitor_name}}&m={{.body}}&auth=tk_AgQdq7mVBoFD37zQVxrGuMzfp3KuGExample: Home Assistant
Example automation: routes by monitor_id for per-monitor logic and by trigger for event type (down / still_down / recovered). All fields are locale-independent — works the same for EN and RU monitors.
# configuration.yaml — automations
# 1. Real alerts (DOWN / still_down / recovered / degraded …)
- alias: PingZen alert
trigger:
platform: webhook
webhook_id: pingzen
allowed_methods: [POST]
local_only: false
# IMPORTANT: skip "Test" button deliveries so they don't change entity state.
# Test payloads carry "test": true (production payloads omit the key).
condition:
- "{{ trigger.json.test | default(false) == false }}"
variables:
monitor_id: "{{ trigger.json.monitor_id | int(0) }}"
event: "{{ trigger.json.trigger }}" # down | still_down | recovered | degraded | certificate_expiring
action:
- choose:
# Router: react to the first DOWN only, ignore reminders
- conditions: "{{ monitor_id == 123 and event == 'down' }}"
sequence:
- service: light.turn_on
target: { entity_id: light.kitchen }
data: { flash: short }
# NAS: react to the first DOWN AND to reminder pings
- conditions: "{{ monitor_id == 456 and event in ['down', 'still_down'] }}"
sequence:
- service: notify.mobile_app
data:
title: "{{ trigger.json.text }}"
message: "{{ trigger.json.body }}"
# Any monitor recovered → log it
- conditions: "{{ event == 'recovered' }}"
sequence:
- service: logbook.log
data:
name: "PingZen"
message: "{{ trigger.json.monitor_name }} recovered"
default:
- service: persistent_notification.create
data:
title: "{{ trigger.json.text }}"
message: "{{ trigger.json.body }}"
# 2. Sync state from Test click — iterates the monitors array and sets
# every entity to match PingZen (handy after HA restart or when entity
# state drifts from reality).
- alias: PingZen sync from Test click
trigger:
platform: webhook
webhook_id: pingzen
allowed_methods: [POST]
local_only: false
# ONLY run on Test deliveries that include the monitors array
condition:
- "{{ trigger.json.test | default(false) == true }}"
- "{{ 'monitors' in trigger.json }}"
action:
- repeat:
for_each: "{{ trigger.json.monitors }}"
sequence:
# Adjust this entity_id template to match your naming convention
- service: "{{ 'input_boolean.turn_on' if repeat.item.status == 'up' else 'input_boolean.turn_off' }}"
target:
entity_id: "input_boolean.pingzen_{{ repeat.item.id }}"Tips
- Webhook URL must be HTTPS (HTTP is allowed only for localhost — for local development).
- Timeout is 30 seconds, up to 3 retries with exponential backoff on 5xx errors and network failures. No retries on 401/403 — check credentials.
- For static-token auth, embed the secret in the URL (e.g. ?token=...) — query parameters are preserved and arrive at your endpoint. Home Assistant and n8n support this out of the box.
- The body fields are configurable in the alert form under "Message content" — you can disable any field, including the monitor link. Disabling "Monitor link" also removes the monitor_url field from the payload.
- For routing, use the machine-readable fields (NOT localized): monitor_id to identify the monitor, trigger for event type. The text field is localized — substring-matching it ("DOWN", "UP") is unreliable.
- Reminder notifications (repeated alerts about a still-down monitor) arrive with trigger="still_down" and priority="critical" (same bucket as the first DOWN — the "real outage" signal). Use trigger in ['down', 'still_down'] for finer routing when the reaction differs.
- The "Test" button in the alert form sends a payload with "test": true plus a [TEST] prefix in text and a (Test notification) line at the top of body. ALWAYS filter test deliveries out of automations that change entity state — see the condition block in the example above.
- For test deliveries, status = "up" while trigger = "down" is intentional: the synthetic check_result is UP, but the trigger simulates the most common alert path (DOWN). Don't drive automation logic off body or status for test events — use trigger and the test field.
Alert Triggers
Choose which events should send notifications:
Service Down (DOWN)
Sent when a monitor transitions to DOWN status after confirmation (default: 3 consecutive failures).
Recovery (RECOVERED)
Sent when a monitor recovers after being down.
Degradation (DEGRADED)
Sent when service is degraded (incl. PageSpeed score below threshold).
SSL Expiring
Sent 14 days before SSL certificate expiration.
How alerts fire
Triggers in PingZen are edge-driven — they react to state transitions, not to the current state. This is the most common source of confusion when a dashboard shows 'Critical' but no notifications arrive.
Without 'Send reminders while down'
10:00 monitor goes DOWN → 1× DOWN alert sent 10:01–next day → silence (still DOWN, no transition) next day monitor recovers → 1× RECOVERED alert sent
If a monitor stays DOWN for 5 days you'll get exactly two messages — one at the start, one at the end.
With 'Send reminders while down' enabled
10:00 DOWN → 1× DOWN 10:05 still DOWN → STILL_DOWN (5 min rung) 10:20 still DOWN → STILL_DOWN (15 min) 11:20 still DOWN → STILL_DOWN (1 hour) 15:20, 19:20, 23:20, … → STILL_DOWN every 4 hours recovery → 1× RECOVERED, schedule resets
The escalation ladder restarts every time the monitor recovers and falls again.
Common gotcha
If your dashboard shows 'Critical' but you're not getting alerts, check that 'Send reminders while down' is on for that alert. The 'Down' trigger by itself fires only at the moment of failure, not periodically.
Message Settings
Customize which information is included in alert notifications. By default most fields are enabled. You can toggle each field per alert.
Disable fields you don't need to keep notifications concise. 'Account info' is disabled by default for privacy; 'Checked from' is disabled by default to avoid noise for users who don't use external probes.
Heartbeat Monitor Alerts
Alerts work with both regular monitors and heartbeat monitors. When creating an alert, you can select heartbeat monitors in the 'Heartbeat Monitors' section below the regular monitor list.
One alert can watch both regular and heartbeat monitors at the same time. The monitor count shows the total of both types.
Reminder Alerts
Enable the 'Send reminders while down' toggle to receive periodic notifications while a monitor stays down. Reminder intervals escalate automatically: 5 min → 15 min → 1 hour → then every 4 hours. The schedule resets when the monitor recovers.
Reminders are disabled by default. Enable them for critical services where you need persistent escalation — without this toggle, an outage that lasts days produces only two messages (the initial DOWN and the eventual RECOVERED).
Cooldown Period
Minimum time between repeated alerts for the same issue. Prevents notification spam during unstable connections. Default: 5 minutes. Recovery alerts always bypass cooldown.
Recommended: 5-15 minutes for production environments.
Alert History
The 'History' tab on the Alerts page shows a log of all sent notifications: timestamp, trigger type, channel, target, and delivery status (sent/failed). Failed deliveries include error details.
Use alert history to verify that notifications are being delivered correctly and to diagnose delivery failures.
Alerts API
Manage alerts programmatically via REST API.
List Alerts
Create Alert
Update Alert
Delete Alert
Test Alert
Common Questions
What protocols can I monitor?
PingZen supports 23 protocols: HTTP/HTTPS, WebSocket (WS/WSS), TCP, UDP, ICMP Ping, gRPC, DNS, WHOIS, SSL certificates, Email (SMTP/IMAP/POP3), FTP/FTPS, DNSBL, PageSpeed, SOCKS5, MTProxy, API Check, and Transaction. You can monitor websites, APIs, servers, databases, and any network service.
How fast can I get alerts?
Telegram alerts are delivered within 1-2 seconds of detection. Slack and Discord notifications arrive almost instantly. You can configure multiple alert channels for redundancy.
Can I organize monitors by project?
Yes! PingZen supports workspaces, which let you organize monitors by project, environment, or team. Each workspace can have its own alert configurations and team members.
Is there an API for automation?
Absolutely. PingZen provides a full REST API with OpenAPI documentation. You can create, update, and delete monitors programmatically.
How do status pages work?
Status pages are public, branded pages showing your services' uptime. You can display real-time status and allow customers to subscribe for updates.
What happens if I reach my monitor limit?
We'll notify you when approaching your limit. You can pause some monitors or contact us for increased capacity. We never stop monitoring without warning, ensuring your critical services stay protected.
Ready to stop missing downtime?
Join thousands of teams who trust PingZen. Setup takes 30 seconds.