Start here
60-second getting started
Create a monitor in your dashboard and copy its private ping URL. The URL’s token is the monitor credential, so keep it out of public source code and logs.
Monitor my script generates a Python or Bash wrapper for your existing job, entirely in your browser.
Follow the Python and Bash setup guide to add the wrapper and check your first run.
Example only: https://pulsewatch.example/ping/example-monitor-token
Replace that whole URL with the one shown for your monitor. This is a deliberately fake URL and token.
- StartSend
/startwhen the job begins. PulseWatch records the run as in progress. - Finish normallySend
/successonce the work completes. - Report an errorSend
/failif the job terminates with an error. An optionalmessagequery value is saved with the failed run.
Ping endpoints accept GET or POST. A fresh /start supersedes an older unfinished run for the same monitor, so one monitor should represent one active job at a time.
Integration
Validate useful output before reporting success
PulseWatch does not inspect or judge workflow output automatically. Your integration decides when the work is genuinely successful by applying an explicit local rule before it sends /success. If execution raises an exception or the result fails that rule, send /fail and let the job exit as failed.
The rule must fit the workflow. Zero processed records may reveal a broken daily export, while zero may be a legitimate result for a job that only processes new records.
This standard-library example treats an empty daily export as a failure. The check enforces only that specific rule; it does not prove that arbitrary business output is correct.
import os
from urllib.request import urlopen
PING_URL = os.environ["PULSEWATCH_PING_URL"].rstrip("/")
TIMEOUT_SECONDS = 5
def ping(outcome):
try:
with urlopen(f"{PING_URL}/{outcome}", timeout=TIMEOUT_SECONDS):
pass
except Exception:
# A monitoring request must not change the job's result or exception.
pass
ping("start")
try:
record_count = export_daily_records()
if record_count < 1:
raise RuntimeError("daily export produced no records")
except Exception:
ping("fail")
raise
else:
ping("success")
Keep the private ping URL in deployment configuration, as shown here, rather than in source code. Do not put customer data, secrets, or sensitive output in monitor names or failure messages.
Need help choosing a first explicit check? Email support@pulsewatch.ai.
Integration
curl / Bash
Do not use set -e around this pattern. It captures the job’s status, reports it, and exits with that same status so a ping cannot turn a failed job into a successful one.
#!/usr/bin/env bash
PING_URL="https://pulsewatch.example/ping/example-monitor-token"
ping() {
curl --fail --silent --show-error --max-time 5 "$1" >/dev/null || true
}
ping "$PING_URL/start"
./your-existing-job
job_status=$?
if [ "$job_status" -eq 0 ]; then
ping "$PING_URL/success"
else
ping "$PING_URL/fail"
fi
exit "$job_status"
Configuration
Expected interval, grace, and max runtime
- Expected interval
- How often the job should run. PulseWatch expects another successful run within this interval.
- Grace
- Extra time allowed after the expected interval before a run is
MISSING. The missing deadline is expected interval + grace, measured from the start of the latest successful run. - Max runtime
- How long a run may remain in progress before it is
STUCK. It is independent of the missing deadline: it checks a current/startthat has not yet finished.
PulseWatch’s separate watchdog service applies these rules on its scheduled checks, so an alert is sent on the next applicable check after a deadline—not at an exact second.
Example: for a daily job that normally starts around 09:00, use an expected interval of 24 hours, grace of 2 hours, and max runtime of 1 hour. If no later success is recorded, it becomes MISSING after 11:00 the next day. A run still open for more than an hour becomes STUCK.
Timing
Allow for scheduler jitter
A scheduler set to run every 15 minutes does not guarantee that a 15-minute grace is safe. External schedulers, including GitHub Actions, can start late and can occasionally skip or delay runs.
Choose grace from the late starts you actually observe, rather than copying the scheduler’s nominal interval. Leave enough room for normal queueing and platform delays, while keeping it short enough to surface a genuinely missed run.
Reference
Health and alert states
- MISSING
- No successful run is on record, or the latest success is older than the expected interval plus grace. Before the first success, even a fresh
/startor a first/failisMISSINGimmediately and can trigger an email on the next applicable check. After a success establishes the baseline, this is the dead-man’s-switch check. - STUCK
- At least one run is still running beyond max runtime. This takes precedence over missing and failed states. A run left open beyond the monitor’s orphan age is reported as
ORPHANEDinstead. - FAILED
- The most recent completed run ended with
/fail, provided the monitor is not missing or stuck. Missing and stuck states take precedence over failure. A newer/successreturns the monitor toOK, provided it is not missing or stuck. - Flapping
- Flapping is not a separate health status. It means terminal runs changed between success and failure at least four times in a rolling two-hour window. PulseWatch suppresses ordinary transition alerts while unstable, sends one flapping alert, then one stabilised alert when the monitor settles.
A monitor with no pings at all is NEVER_RUN and sends no alerts. Finish one real run successfully to establish the baseline before relying on missing-run alerts. The first healthy check is silent; later transitions into an unhealthy state or back to OK send emails, except while flapping.
PAUSED means no checks or alerts. Its /start, /success and /fail ping requests return HTTP 409 with status: paused and monitored: false; no run is recorded. Contact support to arrange resuming. Resuming retains history but waits for new pings, using only runs started after resume for health and flapping. Send a fresh start and outcome to establish the new baseline. Upgrading a plan alone does not resume paused monitors.