Eight events, one routing matrix, templates you control
Every alert in LastPing is one of eight events — down,
recovery, fail, every-run,
success, started, blocked,
note — routed per monitor to any mix of email, Slack,
Discord, Telegram, signed webhooks, ntfy, Pushover, Microsoft Teams
and Google Chat, with a per-event message template you can rewrite.
This page is the reference.
The eight events
Three open incidents, one closes them, four are running commentary.
| Event | When it fires | Typical use |
|---|---|---|
| down | The expected signal didn't arrive. Grace window exhausted (cause: silence), a started run that never finished (overrun), a started run that stopped reporting progress (stalled), or a CI run that never started (never_started). Opens an incident. | The default page-me event for every monitor. |
| fail | An explicit failure signal. A /fail ping, a non-zero /<exit-code>, or a failed CI run. Opens an incident immediately — no waiting for grace. | Jobs that can report their own errors; CI pipelines. |
| recovery | The next success after an incident. Closes the open incident automatically — no manual reset. | The all-clear, to the same channels that got the alert. |
| every-run | Every completed run, success or fail. Only emitted for monitors with a destination subscribed to it. | Positive confirmation and audit trails (see below). |
| success | A completed run that succeeded. A /success ping or a successful CI run, independent of any incident. | Positive confirmation without every-run's duplicate on failures. |
| started | The run began. A /start ping, paired with the matching success or fail to compute duration. | Confirms a job actually kicked off. |
| blocked | The agent has stopped and is waiting on a human — approval, credentials, or a decision. Alert-class, not rate-limited alongside the informational events, because a blocked agent needs a person now. | Long-running or autonomous agent jobs that can stall on a human step. |
| note | A labelled informational signal carrying free text the agent chooses to send, with no state change attached. | An agent narrating its own progress or decisions. |
When to use every-run. For jobs that
run rarely and matter enormously — the weekly billing run, the monthly
report, the quarterly cert rotation — silence-based alerting is
asymmetric: you'd hear about failure, but success is just… quiet.
every-run flips that: a positive "it ran, here's the
outcome" message on every completion. On a monitor that runs every
minute it's noise; on the jobs you'd otherwise double-check by hand,
it's the double-check.
The routing matrix
Per monitor: a destination × event grid. Tick where each event should go.
- Destinations — nine of them: email, Slack, Discord, Telegram, signed webhook, ntfy, Pushover, Microsoft Teams and Google Chat. Your verified email is attached automatically at signup, so the first alert needs zero setup.
- Mix freely — e.g. down and fail to Slack and email, recovery to Slack only, every-run to a webhook feeding your own audit log.
- Test-send — every destination has a test button, so you verify the pipe before you need it.
- Silent-monitor warning — a monitor with no destination is loudly flagged in the console. A monitor nobody hears is a checkbox, not a monitor.
- Flap damping — a monitor that fails and immediately recovers within the damping window doesn't page you.
Message templates
Each monitor can override the message for any of the eight events. The
console's editor, with its live preview, covers six of them —
down, recovery, fail,
every-run, blocked and note; set
success and started through the API, MCP or
Terraform. The default is:
| Variable | Renders as |
|---|---|
| {check_name} | The monitor's name. |
| {status} | Current state: up, late, or down. |
| {event} | The event type: down, recovery, fail, every-run, success, started, blocked, or note. |
| {cause} | Why: silence, fail, overrun, stalled, never_started, or runaway. |
| {last_ping} | Time since the last signal, e.g. "2m ago". |
| {schedule} | The human-readable schedule, e.g. "every 1h". |
| {incident_url} | Deep link into the console. |
| {run_url} | Link to the CI run (CI monitors). |
| {branch} | Git branch of the run (CI). |
| {commit} | Short commit SHA (CI). |
| {actor} | Who triggered the run (CI). |
| {failing_stage} | The failing step or stage (CI). GitLab: always. GitHub: only if the repo webhook also subscribes to Workflow jobs. Jenkins: never — the Notification plugin payload has no step detail. |
| {duration} | Run duration — from a paired start/success or the CI run. |
| {last_step} | The last progress step the run reported, e.g. "db migrate" (runs that report steps). |
| {step_count} | How many steps the run reported before it stopped (runs that report steps). |
| {run_duration} | How long the run had been going when the incident opened (started runs). |
| {latency} | Probe latency in ms (HTTP monitors). |
| {status_code} | Probe HTTP status (HTTP monitors). |
| {url} | The probed URL (HTTP monitors). |
| {body} | The triggering ping's own free text, capped at 500 characters (blocked and note). |
Example — a CI failure template that tells the on-call everything before they click:
Templates pair with the guides: wire the signals with cron, GitHub Actions, or an HTTP monitor, then shape what lands in the channel here. Browse all guides.
Coming from another tool? The mapping for migrating Opsgenie heartbeats covers how intervals, grace windows and alert routing translate.
An alert should read like a briefing, not a riddle.
Events, routing, and templates are all free — and LastPing monitors itself the same way.