Documentation

Start monitoring your cron jobs in under 2 minutes.

Quick Start

1

Create a monitor

Go to your dashboard and click "New Monitor". Give it a name, pick how often it should be pinged, and set a grace period.

2

Add a ping to your job

At the end of your cron job or script, add an HTTP request to your monitor's unique ping URL.

# Add this at the end of your cron job
curl -fsS --retry 3 https://pulsemon.dev/api/ping/your-slug
3

Get alerted

If your job misses a ping, PulseMon detects it within 60 seconds and sends you an alert via email, Slack, Discord, or webhook.

How Monitoring Works

PulseMon uses a dead-man's-switch model. Your job pings us on success; if we don't hear from it in time, we alert you.

ConceptDescription
IntervalHow often your job runs (e.g. every 300 s for a 5-minute cron). PulseMon expects a ping at least once per interval.
Grace periodExtra time added on top of the interval for network latency and clock skew. Defaults scale with your interval: 30 s for fast jobs, up to 30 min for weekly ones.
Deadlinelast ping + interval + grace period. If no ping arrives before the deadline, the monitor is marked down.
Check cyclePulseMon checks every monitor once every 60 seconds. Worst case, a missed deadline is detected ~60s after it passes.

Alert escalation: When a monitor goes down you receive an immediate alert, then follow-up reminders at 1 h, 6 h, and 24 h. After that, reminders repeat daily until the monitor recovers.

Ping API

GET/api/ping/{slug}

Send a heartbeat ping for the given monitor. Always returns 200 OK, even on internal errors, so your cron job won't fail because of monitoring.

Parameters

ParameterTypeDescription
slugstringMonitor slug (path param)
status"success" | "fail"Optional. Report a failure explicitly
durationnumberOptional. Job duration in ms

Response

{ "ok": true }
POST/api/ping/{slug}

Same as GET, but accepts a JSON body for additional metadata.

Body Parameters

ParameterTypeDescription
status"success" | "fail"Optional. Defaults to "success"
durationnumberOptional. Job duration in ms
bodystringOptional. Job output or error message (max 10 KB)
curl -X POST https://pulsemon.dev/api/ping/your-slug \
  -H "Content-Type: application/json" \
  -d '{"status": "success", "duration": 1234, "body": "Processed 500 records"}'

Reporting Failures

By default, every ping is treated as a success and resets the monitor's deadline. If your job detects an error, you can report it explicitly with ?status=fail.

A fail ping is recorded in your ping history but does not mark the monitor as "up". It won't reset the deadline or resolve an open incident. Use this to tell apart "the job ran but errored" from "the job ran successfully."

#!/bin/bash
set -e

if /usr/local/bin/backup.sh; then
  curl -fsS --retry 3 "https://pulsemon.dev/api/ping/nightly-backup"
else
  curl -fsS --retry 3 "https://pulsemon.dev/api/ping/nightly-backup?status=fail"
fi

Rate Limiting

The ping endpoint enforces a rate limit of 1 request per second per slug. If you exceed this limit, the endpoint returns a 429 status code.

// 429 response
{ "ok": false, "error": "Rate limited" }

This prevents accidental flood loops. Any real cron job or heartbeat stays well under 1 req/sec. If you use curl --retry 3, retries will back off naturally and won't hit this limit.

Integration Examples

# Run backup every day at 2am, ping PulseMon on success
0 2 * * * /usr/local/bin/backup.sh && curl -fsS --retry 3 https://pulsemon.dev/api/ping/nightly-backup

Alert Channels

EmailSends alerts to your account email by default. Add more addresses on the Alerts page.
SlackAdd a Slack incoming webhook URL to receive alerts in any Slack channel.
DiscordAdd a Discord webhook URL to receive alerts in any Discord channel.
Custom WebhookSends JSON POST requests to any URL, signed with HMAC-SHA256.

Webhook Payload

When an alert fires, PulseMon sends a JSON POST request with this payload:

{
  "event": "monitor.down",
  "monitor": {
    "id": "uuid",
    "name": "Nightly Backup",
    "slug": "nightly-backup",
    "status": "down",
    "lastPingAt": "2025-01-15T02:00:00Z",
    "expectedInterval": 86400
  },
  "incident": {
    "id": "uuid",
    "startedAt": "2025-01-16T02:05:00Z"
  },
  "timestamp": "2025-01-16T02:05:00Z"
}

Recovery events have the same shape with "event": "monitor.up" and the incident includes resolvedAt and duration (seconds the monitor was down).

Webhook Signature Verification

If you configure a secret on your webhook alert channel, PulseMon signs every request with an HMAC-SHA256 signature in the X-PulseMon-Signature header. The format is sha256=<hex>. Verify this before processing the payload.

import crypto from "crypto";

function verifySignature(body, secret, signatureHeader) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret).update(body).digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader),
  );
}

// In your webhook handler:
app.post("/webhooks/pulsemon", (req, res) => {
  const signature = req.headers["x-pulsemon-signature"];
  const body = JSON.stringify(req.body);

  if (!signature || !verifySignature(body, process.env.WEBHOOK_SECRET, signature)) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  const event = req.body;
  console.log(`Monitor ${event.monitor.name} is ${event.event}`);
  res.json({ ok: true });
});

API Keys

Create API keys in Settings → API Keys to manage monitors programmatically. Keys use Bearer token auth with the prefix pm_. You only see the raw key once at creation, so store it somewhere safe.

Authentication

curl https://pulsemon.dev/api/v1/monitors \
  -H "Authorization: Bearer pm_your-api-key"

Endpoints

MethodPathDescription
GET/api/v1/monitorsList all monitors
POST/api/v1/monitorsCreate a monitor
GET/api/v1/monitors/{id}Get monitor details
PATCH/api/v1/monitors/{id}Update a monitor
DELETE/api/v1/monitors/{id}Delete a monitor
POST/api/v1/monitors/{id}/pausePause a monitor
POST/api/v1/monitors/{id}/resumeResume a monitor
GET/api/v1/monitors/{id}/pingsPing history (paginated)
GET/api/v1/monitors/{id}/incidentsIncident history (paginated)

Example: Create a Monitor

curl -X POST https://pulsemon.dev/api/v1/monitors \
  -H "Authorization: Bearer pm_your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Nightly Backup",
    "slug": "nightly-backup",
    "expectedInterval": 86400,
    "gracePeriod": 900
  }'

All endpoints return { "data": T, "error": null } on success and { "data": null, "error": { "code": "...", "message": "..." } } on failure. Missing or invalid keys return 401.

OpenClaw Skill

Use PulseMon from WhatsApp, Telegram, or Slack via OpenClaw. Install the skill and manage your monitors with natural language.

clawhub install pulsemon

Set your API key as an environment variable:

PULSEMON_API_KEY=pm_your-key-here

Then ask your agent things like "check my monitors", "create a monitor called nightly-backup that runs daily", or "pause the data-sync monitor".