ProcessDuty.aiSign in

Heartbeats

Your process sends us one HTTP request on a rhythm you choose. When one does not arrive on time, we message you. That is the whole thing.

A channel

Where alerts are delivered: a Telegram chat or a WhatsApp number. You set one up once and reuse it across as many monitors as you like.

A monitor

One thing you are watching: a worker, a job, a daemon. It knows how often to expect a heartbeat, and which channel to write to when one is missing.

Step 1

Pick where alerts land

Create a channel and choose how you want to hear about things.

Telegram

Create a bot with @BotFather, paste its token and the chat ID. Free, and it can post to a group or a topic.

WhatsApp

Enter your number and type the code we send you. Nothing else to set up, and alerts arrive where you already look.

Step 2

Create a monitor

Create a monitor and say how often you expect a report and how much lateness is normal. A worker that beats every minute might allow 30 seconds of grace; an hourly backup might allow 5 minutes.

You get a token, once. It is what authenticates every heartbeat, and it is how we know which monitor is reporting, so the request carries nothing else.

Save it somewhere your job can read it, the same way you would any other secret. If you lose it, open the monitor and regenerate it: the old one stops working immediately.

export PROCESSDUTY_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Step 3

Periodically send the heartbeat

One POST with the token. No body, nothing to serialize.

curl
curl -fsS -X POST https://processduty.ai/api/heartbeat \
  -H "Authorization: Bearer $PROCESSDUTY_TOKEN"
Node.js
await fetch("https://processduty.ai/api/heartbeat", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.PROCESSDUTY_TOKEN}` },
});
Python
requests.post(
    "https://processduty.ai/api/heartbeat",
    headers={"Authorization": f"Bearer {os.environ['PROCESSDUTY_TOKEN']}"},
    timeout=10,
)
Go
req, _ := http.NewRequest("POST", "https://processduty.ai/api/heartbeat", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("PROCESSDUTY_TOKEN"))
http.DefaultClient.Do(req)
Ruby
uri = URI("https://processduty.ai/api/heartbeat")
Net::HTTP.post(uri, "", "Authorization" => "Bearer #{ENV['PROCESSDUTY_TOKEN']}")
PHP
$ch = curl_init("https://processduty.ai/api/heartbeat");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("PROCESSDUTY_TOKEN")],
]);
curl_exec($ch);
Crontab
0 * * * * /opt/backup.sh && curl -fsS -X POST https://processduty.ai/api/heartbeat -H "Authorization: Bearer $PROCESSDUTY_TOKEN"

Step 4

Know what came back

204

Reported. The clock starts again from now.

401

The token is wrong, was regenerated, or the monitor was deleted. Retrying will not help.

The first heartbeat is what arms a monitor. Until one arrives it sits as Waiting and can never be late, so something you have not deployed yet will not wake you up.

Step 5

What happens when it goes quiet

A monitor is late once interval + grace passes with no report. We check every minute, so shortly after that the alert reaches the channel you picked for that monitor, carrying the message you wrote on it.

You get one alert per outage, not one per check. If the job starts reporting again, we tell you it recovered, unless you turned that off.

Create account

Takes about two minutes to have the first monitor running.