Documentation
Regularis monitors your cron jobs by waiting for them to check in. Each monitor has a unique ping URL — your job calls it on success, and Regularis alerts you when it stops arriving.
Quick Start
Get your first cron job monitored in under two minutes.
Create a monitor
Go to your Dashboard, click Add Monitor, give it a name, and set the cron schedule that matches your job. Set a grace period to allow a few minutes of slack before an alert fires.
Copy the ping URL
After saving, open the monitor detail page and copy the ping URL shown at the top. It looks like:
https://regularis.io/api/monitors/YOUR_MONITOR_ID/ping
Call the URL from your job
Add a curl call at the end of your cron script.
When Regularis stops receiving pings past the grace period, it alerts you.
curl -fsS -X POST https://regularis.io/api/monitors/YOUR_MONITOR_ID/ping
Ping Endpoints
Three endpoints let you report exactly what your job is doing. No authentication required — the monitor ID is the access key. All three are anonymous and rate-limited.
Auto duration tracking: call /ping/start before your job
and /ping or /ping/fail after —
the elapsed duration is computed and stored automatically.
Optional request body — /ping and /ping/fail
All fields are optional. Omit the body entirely for a simple heartbeat. When sending a body use
Content-Type: application/json.
| Field | Type | Description |
|---|---|---|
| durationMs | number | Manual duration in milliseconds. Overrides auto-computed duration from /ping/start. /ping only. |
| status | string | "success" (default) or "failed". Setting "failed" is equivalent to calling /ping/fail. /ping only. |
| output | string | Job output or error message to store with this ping. Shown in the Ping History table on the monitor detail page. Truncated to 10 000 characters. |
Response codes
| Code | Meaning |
|---|---|
| 200 | Request recorded successfully. |
| 404 | No monitor found with that ID. |
| 429 | Rate limit exceeded — max 10 requests per minute per monitor. |
Integration Examples
Replace YOUR_MONITOR_ID with the UUID from your monitor detail page.
The simplest integration: ping on success only.
#!/bin/bash
set -e
# Your job logic here
/usr/local/bin/my-backup-script.sh
# Ping Regularis on success
curl -fsS -X POST https://regularis.io/api/monitors/YOUR_MONITOR_ID/ping
Call /ping/start before your job to track runtime and report failures explicitly.
#!/bin/bash
BASE="https://regularis.io/api/monitors/YOUR_MONITOR_ID"
# Signal that the job has started (enables duration tracking)
curl -fsS -X POST "$BASE/ping/start"
# Run your job, capture output
output=$(/usr/local/bin/my-backup-script.sh 2>&1)
exit_code=$?
if [ $exit_code -eq 0 ]; then
curl -fsS -X POST "$BASE/ping" # success
else
# Send failure with captured output
curl -fsS -X POST "$BASE/ping/fail" \
-H 'Content-Type: application/json' \
--data-raw "{\"output\": $(echo "$output" | head -c 1000 | jq -Rs .)}"
exit $exit_code
fi
import requests
BASE = "https://regularis.io/api/monitors/YOUR_MONITOR_ID"
def run_job():
pass # Your job logic here
requests.post(f"{BASE}/ping/start", timeout=10)
try:
run_job()
requests.post(f"{BASE}/ping", timeout=10)
except Exception as e:
requests.post(
f"{BASE}/ping/fail",
json={"output": str(e)[:1000]},
timeout=10,
)
raise
const BASE = "https://regularis.io/api/monitors/YOUR_MONITOR_ID";
async function runJob() {
// Your job logic here
}
await fetch(`${BASE}/ping/start`, { method: "POST" });
try {
await runJob();
await fetch(`${BASE}/ping`, { method: "POST" });
} catch (err) {
await fetch(`${BASE}/ping/fail`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ output: String(err).slice(0, 1000) }),
});
process.exit(1);
}
package main
import (
"log"
"net/http"
)
const base = "https://regularis.io/api/monitors/YOUR_MONITOR_ID"
func ping(suffix string) {
if _, err := http.Post(base+suffix, "", nil); err != nil {
log.Printf("ping warning: %v", err)
}
}
func runJob() error {
// Your job logic here
return nil
}
func main() {
ping("/ping/start")
if err := runJob(); err != nil {
ping("/ping/fail")
log.Fatalf("job failed: %v", err)
}
ping("/ping")
}
<?php
$base = 'https://regularis.io/api/monitors/YOUR_MONITOR_ID';
function ping(string $url): void {
$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true]);
curl_exec($ch);
curl_close($ch);
}
ping("$base/ping/start");
try {
// Your job logic here
ping("$base/ping");
} catch (Throwable $e) {
ping("$base/ping/fail");
throw $e;
}
require 'net/http'
BASE = 'https://regularis.io/api/monitors/YOUR_MONITOR_ID'
def ping(suffix)
Net::HTTP.post(URI("#{BASE}#{suffix}"), '')
end
ping('/ping/start')
begin
# Your job logic here
ping('/ping')
rescue => e
ping('/ping/fail')
warn "Job failed: #{e}"
exit 1
end
Monitor Statuses
Regularis computes status in real time from your cron schedule, grace period, and last ping.
| Status | Meaning |
|---|---|
| Waiting | Never received a ping. All new monitors start here. |
| Healthy | A ping was received within the expected window. |
| Late | The expected time has passed but still within the grace period. No alert yet. |
| Failed | Grace period expired with no ping, or the last ping reported status=failed. An alert email is sent. |
| Paused | Monitoring paused. No alerts fire. Useful during planned maintenance. |
Rate Limits
Limits are applied per endpoint to keep the service reliable for everyone.
| Endpoint | Limit | Scope |
|---|---|---|
| POST /api/monitors/{'{id}'}/ping | 10 / minute | Per monitor ID |
| POST /api/monitors/{'{id}'}/ping/start | 10 / minute | Per monitor ID |
| POST /api/monitors/{'{id}'}/ping/fail | 10 / minute | Per monitor ID |
| POST /api/auth/login | 10 / 15 minutes | Per IP address |
| POST /api/auth/register | 10 / 15 minutes | Per IP address |
If you receive a 429, wait a minute before retrying. The ping limit is per monitor — use one monitor per cron job, don't share IDs across multiple jobs.