Documentation
Start monitoring your cron jobs in under 2 minutes.
Quick Start
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.
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-slugGet 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.
last ping + interval + grace period. If no ping arrives before the deadline, the monitor is marked down.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
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
slugstringMonitor slug (path param)status"success" | "fail"Optional. Report a failure explicitlydurationnumberOptional. Job duration in msResponse
{ "ok": true }Same as GET, but accepts a JSON body for additional metadata.
Body Parameters
status"success" | "fail"Optional. Defaults to "success"durationnumberOptional. Job duration in msbodystringOptional. 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"
fiRate 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-backupAlert Channels
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
/api/v1/monitorsList all monitors/api/v1/monitorsCreate a monitor/api/v1/monitors/{id}Get monitor details/api/v1/monitors/{id}Update a monitor/api/v1/monitors/{id}Delete a monitor/api/v1/monitors/{id}/pausePause a monitor/api/v1/monitors/{id}/resumeResume a monitor/api/v1/monitors/{id}/pingsPing history (paginated)/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 pulsemonSet your API key as an environment variable:
PULSEMON_API_KEY=pm_your-key-hereThen ask your agent things like "check my monitors", "create a monitor called nightly-backup that runs daily", or "pause the data-sync monitor".