1. Create the heartbeat
Add a monitor with Check type Heartbeat (cron), set the interval to the backup job's schedule and the grace to how long the whole job takes, and copy the ping URL. Heartbeats are on every plan, Free included.
2. Write the hook script
vzdump calls a hook script with the phase as its first argument: job-start, backup-abort (with the guest id as the third argument), job-end and job-abort, among others. Save this as /usr/local/bin/vzdump-heartbeat.sh and make it executable: PING_URL=<your ping URL>; F=/run/vzdump-heartbeat.failed; case "$1" in job-start) rm -f "$F"; curl -fsS -m 10 "$PING_URL/start" ;; backup-abort) echo "$3" >> "$F" ;; job-end) if [ -s "$F" ]; then curl -fsS -m 10 --data-raw "failed guests: $(tr '\n' ' ' < "$F")" "$PING_URL/fail"; else curl -fsS -m 10 "$PING_URL"; fi ;; job-abort) curl -fsS -m 10 --data-raw "vzdump job aborted" "$PING_URL/fail" ;; esac; exit 0.
3. Attach it to vzdump
Add the line script: /usr/local/bin/vzdump-heartbeat.sh to /etc/vzdump.conf on each node, which applies it to every backup job there, as Proxmox's example hook script describes. The script always exits 0, so a failed ping never fails a backup.
4. What it catches
A guest that failed to back up turns the job into a fail ping that names the guest ids. A job that aborts sends a fail ping. A node that is down, a schedule that was removed, or a storage that hung so the job never ended sends nothing, and the heartbeat alerts when interval plus grace passes.
Go deeper
The full reference lives in the docs: Heartbeat monitors documentation. Error codes named above are each explained in the error-code reference.