PYLONMON

Documentation

Everything you need to go from zero to paged-when-it-matters.

Quickstart

Create a free account, add your first monitor, and start getting alerts in about two minutes.

# at the end of your backup / cron job:
curl -fsS https://pylonmon.com/hb/your-mon-id

If we don't hear from it within the window, you get paged. The silence is the signal.

Monitor types

Heartbeat — it pings us

Best for cron jobs, backups, and scripts. Your job hits its unique URL when it finishes; miss the window and we alert. No inbound access to your network required.

HTTP/S — we poll it

Point Watch at a URL and we check it on your schedule from off-site. Any non-2xx response, or an unreachable host, trips an alert with the exact status.

TCP — we connect to a port

Give us host:port and we open a connection on your interval — great for databases, SSH, game servers, or anything that speaks TCP but not HTTP.

Ping — we ping a host

Give us a hostname or IP and we send an ICMP echo (a "ping") on your interval — the simplest reachability check for routers, printers, NAS boxes, and IoT devices that don't expose a port.

DNS — we resolve a name (paid)

Give us a hostname and we resolve it on your interval; optionally assert it resolves to an expected IP. Catches DNS outages and hijacks before your users do.

UDP — we probe a port (paid)

Give us host:port and we send a UDP probe — for DNS servers, game servers, VPNs, and other services that speak UDP.

Prometheus — a metric threshold (paid)

Alert when a number crosses a line. Point us at a /metrics or Prometheus query URL and we pull it, or push values to us from anywhere — full details and examples under Prometheus.

Automatic extras on paid plans

Heartbeats in cron

Append the ping to the job so it only fires on success:

# run at 2am; only pings Watch if the backup command succeeded
0 2 * * *  /usr/local/bin/backup.sh && curl -fsS https://pylonmon.com/hb/your-mon-id

HTTP/S monitors & headers

For endpoints behind auth, add request headers to an HTTP monitor (one per line) — for example an API key or bearer token. They're stored with your monitor and sent on every poll, and masked in the UI.

Authorization: Bearer xxxxxxxx
X-Api-Key: yyyyyyyy

Alert channels

Alerts go to channels. Every account starts with your email channel, so alerts work out of the box. Add more on the Alerts tab:

Each monitor picks its own channels (as many as you like — that's free). A monitor with no channels selected sends no alerts — it stays silent until you choose where it should page, so an auto-created monitor never surprises you by blasting every channel at once.

Webhook-family channels (custom webhook, Slack, Discord, …) can carry a custom JSON payload template on paid plans — override the built-in body entirely with your own shape and placeholders:

{"text": "{{status}}: {{name}} — {{detail}}", "target": "{{target}}", "link": "{{url}}"}

Placeholders: {{title}}, {{status}} (up/down), {{name}}, {{target}}, {{detail}}, {{url}}. The rendered result must be valid JSON (we validate it when you save).

Escalation (paid)

Every plan includes escalation: if a monitor is still down after a delay you set, PylonMon also alerts another set of channels. Stack rungs to build an on-call ladder — nudge a backup channel after 15 minutes, page the on-call after an hour, set a rung to repeat until recovery. Acknowledging the incident silences the ladder while you work.

Incidents (paid)

On paid plans every outage automatically opens an incident — a record you can acknowledge, annotate, and close with a resolution write-up.

On-call rotations (Team+)

Stop hardcoding people into your alerting. On Team and Enterprise, the workspace owner flips on-call on under Settings → On-call rotation; the rotation itself is then managed from its own 📟 On-call section on the Alerts tab:

Public status pages (paid)

Give customers a live status page that shows only the monitors you choose. Turn it on under Settings → Admin → Status page & API (it mints a token you can rotate any time), then flip "show on my public status page" on each monitor you want visible. The page lives at:

https://pylonmon.com/status/your-status-token

Monitors tagged on an open SEV1–SEV3 incident show as degraded (amber); SEV4 incidents never appear. The status token is separate from every other URL, so sharing the page exposes nothing but status.

Maintenance windows (paid)

Planned downtime shouldn't page you. Set a daily maintenance window (UTC) on a monitor from its edit form — we keep checking and recording history, but suppress alerts during the window so expected restarts and backups stay quiet.

Logs & retention

Every check result, alert, incident, and account action is logged — filter and export it as CSV from the Logs tab. We keep history by a mix of age and volume: your tier's number of days or its event count, whichever limit you hit first, so one noisy monitor can't evict the rest of your history.

API & API keys (paid)

Paid workspaces can drive everything from code — monitors, alert channels, and incidents — with a workspace API key. Manage keys under Settings → Admin → Status page & API (up to three named keys; rotate or delete any of them instantly). A key identifies your whole workspace, so treat it like a password. Keys come in three scopes: full workspace access; 👁 read-only — strictly the list/GET endpoints, no writes anywhere (perfect for wallboards, dashboards, and scrapers); and (on Enterprise) the 🤖 agent scope — read plus incident write-back only, built for BYO-AI agents.

Authentication

Send the key on every request in a header — either works, and it always travels over HTTPS, never in the URL:

Authorization: Bearer YOUR_KEY
# or
X-Api-Key: YOUR_KEY

The base URL is https://pylonmon.com. Requests and responses are JSON. Unauthenticated calls get 401; a key on a workspace that has dropped to the free plan is inert.

Monitors

# list your monitors
curl -H "Authorization: Bearer YOUR_KEY" https://pylonmon.com/api/checks

# create one (type: heartbeat | http | tcp | ping | dns | udp | prometheus)
curl -H "Authorization: Bearer YOUR_KEY" \
     -d '{"name":"API","type":"http","url":"https://api.example.com/health","period":60,"labels":["prod","payments"]}' \
     https://pylonmon.com/api/checks

# update (name, period, url, channels, labels, escalations, slow_ms, slow_channels, public...)
curl -H "Authorization: Bearer YOUR_KEY" \
     -d '{"name":"API (prod)","period":30,"labels":["prod","payments"]}' \
     https://pylonmon.com/api/checks/MONITOR_ID/update

# pause / resume (toggles), then delete
curl -X POST   -H "Authorization: Bearer YOUR_KEY" https://pylonmon.com/api/checks/MONITOR_ID/pause
curl -X DELETE -H "Authorization: Bearer YOUR_KEY" https://pylonmon.com/api/checks/MONITOR_ID

The create call returns the new monitor including its id. A heartbeat monitor's id is also the token in its /hb/<id> check-in URL — and those check-ins need no key, the unique URL is the credential.

Labels (labels, array of strings) tag monitors for search and grouping — normalized to lowercase, spaces become dashes, up to 8 per monitor. Slow routing (slow_channels, array of channel ids) sends slow-response alerts and their recoveries to a different channel set than down alerts; empty means "same channels as down". Both come back on every monitor in GET /api/checks, so your scripts can filter on them.

Alert channels

# list channels
curl -H "Authorization: Bearer YOUR_KEY" https://pylonmon.com/api/channels

# create — kind: email | sms | whatsapp | voice | discord | slack | telegram
#          | ntfy | webhook | googlechat | teams | webex | zapier
# email/sms/whatsapp/voice use "addr"; the rest use "url" (telegram: url=token, addr=chat id)
curl -H "Authorization: Bearer YOUR_KEY" \
     -d '{"kind":"slack","name":"#ops","url":"https://hooks.slack.com/services/XXX"}' \
     https://pylonmon.com/api/channels

# update, then delete
curl -H "Authorization: Bearer YOUR_KEY" -d '{"url":"https://hooks.slack.com/services/YYY"}' \
     https://pylonmon.com/api/channels/CHANNEL_ID/update
curl -X DELETE -H "Authorization: Bearer YOUR_KEY" https://pylonmon.com/api/channels/CHANNEL_ID

Attach channels to a monitor by passing their ids in the monitor's channels array (or slow_channels for a separate slow-alert route) on create or update. Tier limits and paid-channel gates (SMS, voice, custom payloads…) apply exactly as they do in the UI.

The API sees your workspace's shared channels only. Members' 🔒 private on-call channels are personal: they're created and managed in the portal (Settings → On-call), never appear in API listings, and can't be attached to monitors — by design, so automation can't page someone's private phone.

Incidents

# list open + recently resolved incidents
curl -H "Authorization: Bearer YOUR_KEY" https://pylonmon.com/api/incidents

# acknowledge (silences escalation paging), annotate, resolve with a write-up
curl -X POST -H "Authorization: Bearer YOUR_KEY" https://pylonmon.com/api/incidents/INCIDENT_ID/ack
curl -X POST -H "Authorization: Bearer YOUR_KEY" -d '{"text":"failing over to replica"}' \
     https://pylonmon.com/api/incidents/INCIDENT_ID/note
curl -X POST -H "Authorization: Bearer YOUR_KEY" -d '{"note":"bad deploy — rolled back"}' \
     https://pylonmon.com/api/incidents/INCIDENT_ID/resolve

# declare an incident from your own tooling (deploy scripts, chatops...)
curl -X POST -H "Authorization: Bearer YOUR_KEY" \
     -d '{"title":"checkout errors","detail":"elevated 500s","checks":["MONITOR_ID"],"status_impact":true}' \
     https://pylonmon.com/api/incidents/declare

Wire these into PagerDuty-style tooling, deploy pipelines, or a chatbot — anything that should open, work, or close incidents without a browser.

pylon-beacon — the node agent (free — 3 nodes; more on paid)

One binary. No open ports. Full node vitals. pylon-beacon is our open-source (MIT) monitoring agent: a single static binary that pushes your machine's vitals to PylonMon — CPU, memory, per-mount disk, temperature, load, uptime, plus anything you add. Because it pushes outbound, it works behind NAT, CGNAT, firewalls, and on boxes you'd never open a port on. No Prometheus, no scrape configs, no sidecar stack — and if the box goes silent, you get paged. The silence is the signal.

1 · Install

Linux (writes /usr/local/bin/pylon-beacon, a config at /etc/pylon-beacon.conf, and a systemd unit):

curl -fsSL https://pylonmon.com/beacon.sh | sh

Windows (PowerShell, as admin — installs to Program Files\pylon-beacon and registers a service):

irm https://pylonmon.com/beacon.ps1 | iex

Both installers prompt for your API key, or read it from PYLON_KEY if it's already set. Prefer building from source? go build in the repo — it's a single main.go, stdlib only.

2 · The key

Create an ingest-scoped API key (Settings → Admin → Status page & API → + New key → scope "ingest"). Ingest keys can push check-ins and metrics and do nothing else — they can't read your monitors, touch incidents, or change anything, so they're safe to sit on every box you own. One key can serve all your nodes. Ingest keys are free (the rest of the API is paid), so anyone can run the agent — the free plan covers 3 nodes, and Pro raises that to your full monitor cap.

3 · The config file

# /etc/pylon-beacon.conf   (Windows: Program Files\pylon-beacon\beacon.conf)
key      = pm_xxxxxxxxxxxx       # your ingest-scoped API key
url      = https://pylonmon.com  # or your own instance
node     = db01                  # optional — defaults to the hostname
interval = 20                    # seconds between pushes (default 20)

[custom]                         # extend what it collects: name = command
# each command runs on your schedule; the FIRST NUMBER in its output is the metric
gpu_temp_c   = nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader
queue_depth  = redis-cli llen jobs
raid_degraded = sh -c "grep -c _ /proc/mdstat"
# is the local site up? 1 = yes, 0 = no — then set a vital rule: site_up < 1
site_up      = sh -c "curl -sf http://localhost/ >/dev/null && echo 1 || echo 0"

Built-in collectors (no config needed): cpu_pct · mem_pct · disk_pct per mount · load1 · temp_c (Linux) · uptime_s. Custom entries ride along in the same push.

Running it on a web server? Two complementary options. For public up/down, add a normal PylonMon HTTP monitor — checking from off-site is actually better, because it sees what your visitors see. For a local check the outside world can't do — "is nginx serving on localhost even though the public route is broken?", or an internal-only service — use the site_up recipe above and set a vital rule site_up < 1. Same beacon, one line.

4 · What happens in PylonMon

Under the hood it's one endpoint — POST /api/ingest/exporter with {"node":"db01","interval":60,"metrics":{…}} — so anything that can speak JSON over HTTPS can be a beacon: the agent is a convenience, not a requirement.

🤖 Bring-your-own-AI agents (Enterprise)

We don't sell you an AI SRE — we page yours. If you run an agent with access to your own infrastructure (Claude, or any agent runtime you trust), PylonMon can page it like a teammate: the alert arrives with full context, the agent investigates on your systems with your credentials, and it writes findings back onto the incident. PylonMon never holds your infrastructure credentials, never runs a model, and never touches your instances — you stay in control of what the agent can reach.

1 · The agent alert channel

Add a channel of type 🤖 AI agent (Alerts → + → AI agent) pointing at your agent's HTTPS endpoint. Every alert and recovery POSTs a structured JSON envelope — no prose parsing:

{
  "source": "pylonmon", "version": 1,
  "event": "alert",                     // or "recovery"
  "title": "🔴 api-prod is DOWN",
  "fields": { "Status": "connection refused", "Type": "http" },
  "monitor": { "id": "…", "name": "api-prod", "type": "http", "url": "…",
               "status": "down", "detail": "…", "labels": ["prod","payments"] },
  "incident": { "id": "…", "severity": 3, "started": 1752969600, "acked": false },
  "actions":  { "ack": "https://pylonmon.com/api/incidents/…/ack",
                "note": "…/note", "resolve": "…/resolve" },
  "api": { "mcp": "https://pylonmon.com/mcp", "auth": "Authorization: Bearer <key>" },
  "instructions": "You are the on-call agent… ack first, note evidence, resolve only when verified."
}

The envelope carries no credentials — your agent authenticates its write-backs with its own key:

# the write-back loop, from your agent
curl -X POST -H "Authorization: Bearer AGENT_KEY" https://pylonmon.com/api/incidents/ID/ack
curl -X POST -H "Authorization: Bearer AGENT_KEY" \
     -d '{"text":"db01 disk 98% full — journal logs; vacuuming now (evidence: df -h output)"}' \
     https://pylonmon.com/api/incidents/ID/note
curl -X POST -H "Authorization: Bearer AGENT_KEY" \
     -d '{"note":"rotated journald, added retention cap; disk at 41%, monitor green"}' \
     https://pylonmon.com/api/incidents/ID/resolve

Notes land on the incident timeline attributed as 🤖 <key name> — whoever gets paged sees the agent's investigation before they've rubbed their eyes.

2 · Agent-scoped API keys — the leash

Create the agent's key with the agent scope (Settings → Admin → Status page & API): it can read monitors, incidents and logs, and ack / note / resolve incidents — and that is all. It cannot create, edit, pause, or delete monitors or channels, declare incidents, publish to your status page, or read teammates' data. A misbehaving agent can annotate your incidents; it can never dismantle your monitoring.

3 · The MCP endpoint

If your agent runtime speaks MCP (Model Context Protocol), skip the glue code entirely — PylonMon is a remote MCP server at https://pylonmon.com/mcp (Streamable HTTP, authenticate with your API key):

// e.g. a Claude-style MCP config
{ "mcpServers": { "pylonmon": {
    "url": "https://pylonmon.com/mcp",
    "headers": { "Authorization": "Bearer AGENT_KEY" } } } }

Tools exposed (10): list_monitors · get_monitor · list_incidents · get_incident · ack_incident · add_incident_note · resolve_incident · search_logs · list_runbooks · get_runbook. The intended flow is baked into the tool descriptions: ack first, read any runbook attached to the monitor, investigate, note evidence, resolve only when verified — so any competent agent behaves like a disciplined on-call engineer out of the box.

4 · Copy-paste agent skill (Claude Code & friends)

Fastest start: save the snippet below as ~/.claude/skills/pylonmon/SKILL.md (Claude Code), or paste it into any agent runtime's system prompt. Then drop your agent-scoped key in ~/.pylonmon/key — outside any git repo, so it never lands in a commit or a transcript — and tell your agent "check my alerts".

---
name: pylonmon
description: Act as this workspace's on-call agent for PylonMon —
  read monitors/incidents/logs over MCP, ack/note/resolve incidents.
  Use when asked to check alerts or investigate an incident.
---

# PylonMon on-call agent

MCP endpoint: POST https://pylonmon.com/mcp (JSON-RPC 2.0).
Auth: read the key from ~/.pylonmon/key — NEVER print it, never
commit it. If the file is missing, ask a human to create an
AGENT-scoped key (portal: Settings → Admin → Status page & API)
and save it there.

    PMKEY=$(cat ~/.pylonmon/key)

Tools (call via method "tools/call", params {name, arguments}):
list_monitors · get_monitor{id} · list_incidents · get_incident{id}
· ack_incident{id} · add_incident_note{id,text}
· resolve_incident{id,note} · search_logs{q,limit}
· list_runbooks · get_runbook{id}

Example — what is on fire:

    curl -s -X POST https://pylonmon.com/mcp \
      -H "Authorization: Bearer $PMKEY" \
      -H "Content-Type: application/json" \
      -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
           "params":{"name":"list_incidents","arguments":{}}}'

Results arrive as result.content[0].text (JSON as text).

## On-call discipline — follow in order
1. list_incidents → pick the open one.
2. ack_incident FIRST (silences escalation paging).
3. get_runbook for any runbook attached to the monitor —
   follow the documented procedure over improvising.
4. Investigate on the systems this agent legitimately has
   access to — its own credentials, not PylonMon's.
5. add_incident_note with EVIDENCE (command output, numbers —
   never guesses). Notes appear as 🤖 <key name>.
6. resolve_incident ONLY when fixed AND verified. A still-down
   auto incident will refuse to resolve — keep noting instead.

## Boundaries
- The agent key cannot create/edit/delete monitors or channels —
  by design. If that seems needed, stop and ask a human.
- If the key 401s it was rotated: ask a human, don't guess.

That file is the whole integration — no SDK, no glue service. The same discipline works pasted into any agent framework that can run curl.

Prometheus / Alertmanager (paid — 25 alert streams on Pro, 200 on Team+)

There are three ways PylonMon works with Prometheus — monitor a metric, send us your alerts (and drop Alertmanager), or let your own Prometheus scrape us:

1. Monitor a metric. Add a monitor of type Prometheus (Monitors → Add → Prometheus) and pick how the value reaches us:

· We pull it (source: pull). Point the monitor at a /metrics exposition endpoint (an exporter or your app) or a Prometheus /api/v1/query?query=… URL, then pick a metric and a threshold. Use the request-headers field for auth. Like all pull monitors, the target must be publicly reachable.

· You push it to us (source: push). For boxes we can't reach — behind NAT or a firewall, outbound only. Create the monitor with source push; its card then shows a URL like https://pylonmon.com/metric/<id>. Send a number to it from a cron job, script, or exporter — any of these work:

# simplest — the value in the query string
curl "https://pylonmon.com/metric/<id>?value=42"

# or a JSON body, or a plain-number body
curl -d '{"value":42}' https://pylonmon.com/metric/<id>
curl --data-binary 42 https://pylonmon.com/metric/<id>

# or pipe an exporter's output — we read the metric you set on the monitor
curl -s http://localhost:9100/metrics | curl --data-binary @- "https://pylonmon.com/metric/<id>"

# on a schedule, straight from crontab (every 5 min):
*/5 * * * * curl -fsS "https://pylonmon.com/metric/<id>?value=$(df --output=pcent / | tail -1 | tr -dc 0-9)" >/dev/null

Either way the monitor goes down and alerts when the value meets your condition. Push monitors also alert if data simply stops arriving (staleness), so a cron that silently dies is itself an alert. All the usual channels, escalation, incidents, and status pages apply.

2. Send us your Prometheus alerts — with or without Alertmanager. PylonMon speaks the Alertmanager v2 API, so your firing and resolved alerts fan out to every channel in your workspace — email, Discord, Slack, ntfy, SMS — with no per-channel receiver config. Two ways in:

· Drop Alertmanager entirely (recommended). Prometheus already knows how to talk to an Alertmanager — just point it at PylonMon instead of running one. Add PylonMon to Prometheus's own alerting block, send your workspace API key as a Bearer token, and you can delete Alertmanager:

# prometheus.yml
alerting:
  alertmanagers:
    - scheme: https
      authorization:
        type: Bearer
        credentials_file: /etc/prometheus/pylonmon.key   # a file holding your API key
      static_configs:
        - targets: ['pylonmon.com']

Prometheus appends /api/v2/alerts on its own and posts alerts exactly as it would to a real Alertmanager — nothing else to run. A copy-paste, runnable example (Prometheus + node-exporter in Docker) lives in the repo under examples/prometheus-to-pylonmon/.

· Keep your Alertmanager. Already invested in Alertmanager routing and grouping? Add a webhook receiver instead and let it keep doing its job — PylonMon just becomes another receiver. The ingest URL is shown on the Alerts tab:

# alertmanager.yml
receivers:
  - name: pylonmon
    webhook_configs:
      - url: https://pylonmon.com/api/ingest/alertmanager?key=YOUR_KEY

Either way: firing alerts page with the alert name, severity, and summary; resolved alerts send the green all-clear. Up to 20 alerts are processed per delivery. Here's what a firing alert looks like once it reaches PylonMon:

🔴 HighNodeCPU firing
Source: Prometheus · Severity: critical · Summary: CPU on node-01 is 92% busy

Each alert becomes a monitor you control. An inbound alert isn't a fire-and-forget message — PylonMon turns each distinct alertname into its own monitor, so it carries the full notification stack: the alert channels it pages, a severity (SEV1–4, mapped from the alert's severity label), an escalation ladder, on-call rotation, and incidents. Firing drives the monitor down; resolved brings it back — and you tune exactly how any alert pages right on its monitor, the same way you'd configure an HTTP or heartbeat check. A brand-new alert with nothing set is silent until you configure it: tracked and visible, but it won't page anyone by surprise.

Set your defaults once with an alert template. Instead of configuring every alert by hand, create a Prometheus incoming-alert template (Monitors → Add → “Prometheus — incoming-alert template”). The channels, severity, and escalation ladder you put on it become the starting config for every newly-discovered alert — so the first time a new alertname fires, it already routes correctly. The incoming alert's own severity label still wins over the template default, and editing the template later never touches alerts already created (each is independent).

Set it up in two steps.

1. Monitors → Add, and choose the template type:

Type ▾
heartbeat · http/s · tcp · ping · dns · udp · Prometheus
Prometheus — incoming-alert template  ◀ choose this

2. Name it and create it, then open the template and set the alert channels, severity, and escalation ladder every new alert should start with (the panel below):

Illustration — the template, and an alert born from it
🧩 Prometheus alert template · last used 3m ago
The starting config every newly-discovered alert inherits.
Alert channels
#oncall-slackPagerDuty
Severity
SEV2 (label overrides)
Incident
auto-create ✓
Escalation ladder
after 5m → #oncall-slack · after 15m → PagerDuty (on-call), repeat every 10m
new alert KafkaLagHigh{severity="critical"} fires the first time
🔴 KafkaLagHigh SEV1
Born configured from the template — pages #oncall-slack + PagerDuty, opens a SEV1 incident (the alert's own critical label beat the template's SEV2), and runs the same ladder. No hand-setup.

Real example: Kubernetes (kube-prometheus-stack)

Say you run kube-prometheus-stack on a homelab or a small cluster. Two things get you from zero to paging in PylonMon:

1. A rule to alert on. A PrometheusRule — here, a node running hot or a disk filling up. Label the ones you want in PylonMon (we route on that label next):

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata: { name: homelab, namespace: monitoring }
spec:
  groups:
    - name: homelab
      rules:
        - alert: NodeTempHigh
          expr: max by (instance) (node_hwmon_temp_celsius) > 70
          for: 3m
          labels: { severity: warning, pylonmon: "true" }
          annotations:
            summary: '{{ $labels.instance }} running hot — {{ printf "%.0f" $value }}°C'
        - alert: NodeDiskLow
          expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 15
          for: 10m
          labels: { severity: critical, pylonmon: "true" }
          annotations:
            summary: '{{ $labels.instance }} disk low — {{ printf "%.0f" $value }}% free'

2. Forward them to PylonMon. Point the bundled Alertmanager at us — route the labelled alerts to a webhook receiver. Keep the key in a mounted secret and send it as a Bearer token:

# kube-prometheus-stack values.yaml
alertmanager:
  alertmanagerSpec:
    secrets: [pylonmon-key]                # mounted at /etc/alertmanager/secrets/…
  config:
    route:
      receiver: "null"
      routes:
        - receiver: pylonmon
          matchers: [ 'pylonmon="true"' ]
    receivers:
      - name: "null"
      - name: pylonmon
        webhook_configs:
          - url: https://pylonmon.com/api/ingest/alertmanager
            send_resolved: true
            http_config:
              authorization: { type: Bearer, credentials_file: /etc/alertmanager/secrets/pylonmon-key/key }

Each alert becomes a monitor seeded from your template — NodeTempHigh and NodeDiskLow show up pre-configured, page your channels, and resolve on their own.

Tip — you probably don't need to write many rules. kube-prometheus-stack already ships ~150 alert rules (KubePodCrashLooping, KubeNodeNotReady, KubePersistentVolumeFillingUp, TargetDown, and more). Instead of a pylonmon="true" label, widen the route to forward the ones you want — e.g. everything severity=~"critical|warning" minus the noisy ones — and you get real coverage with no new rules.

3. Scrape us (any paid plan). PylonMon can also be a Prometheus scrape target, so your own Prometheus can graph and alert on your monitors' up/down state and latency. Turn it on under Settings → Admin → Status page & API → Prometheus metrics (it's off by default), then scrape /api/metrics with one of your API keys — the endpoint is never served unauthenticated, so your metrics stay private to your workspace:

# prometheus.yml
scrape_configs:
  - job_name: pylonmon
    scheme: https
    metrics_path: /api/metrics
    authorization:
      credentials: YOUR_API_KEY
    static_configs:
      - targets: ['pylonmon.com']

You get pylonmon_monitor_up, pylonmon_monitor_latency_ms, pylonmon_monitor_paused, and pylonmon_monitor_last_check_timestamp_seconds, each labelled with the monitor's name, type, and target.

Status badges

Every monitor has a live SVG status badge you can embed in a README, wiki, or status page. Open a monitor's detail to copy the Markdown:

[![PylonMon](https://pylonmon.com/badge/your-badge-token.svg)](https://pylonmon.com)

The badge token is separate from your heartbeat URL, so publishing a badge never exposes a way to ping (or spoof) your monitor.

Security & privacy

Questions? support@pylonmon.com.

Open the console →