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.
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
204Reported. The clock starts again from now.
401The 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.
Takes about two minutes to have the first monitor running.