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.

1

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.

2

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
3

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.

POST /api/monitors/{id}/ping
POST /api/monitors/{id}/ping/start
POST /api/monitors/{id}/ping/fail

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.

FieldTypeDescription
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

CodeMeaning
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.

Bash — simple heartbeat

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
Bash — start + success/fail recommended

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
Python
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
Node.js
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);
}
Go
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
<?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;
}
Ruby
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.

StatusMeaning
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.

EndpointLimitScope
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.

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please reload the page.