Examples
Real-world recipes. Replace the host, tokens, and topic names with your own.
Disk-space alert from a cron
Set up a topic share token with wo access and publish from a host's crontab:
#!/bin/sh
USAGE=$(df / | awk 'NR==2 {gsub("%",""); print $5}')
if [ "$USAGE" -gt 90 ]; then
curl -s https://pingd.example.com/topics/alerts.disk/messages \
-H 'Content-Type: application/json' \
-H "X-Topic-Token: $PINGD_TOPIC_TOKEN" \
-d "{
\"priority\": 3,
\"tags\": [\"disk\", \"$(hostname)\"],
\"payload\": {
\"title\": \"Disk ${USAGE}% full\",
\"body\": \"$(hostname): / is ${USAGE}% full\"
}
}"
fi
*/5 * * * * /usr/local/bin/disk-alert.sh
CI deploy notifications
Create a CI user with write-only permission on deploy.>, then mint a bearer token for it:
pingd-cli users create \
--username ci-bot --password '<strong-password>' --role user
pingd-cli permissions create \
--username ci-bot --access wo --pattern 'deploy.>'
pingd-cli tokens create --username ci-bot --label github-actions
Then in your GitHub Actions workflow:
- name: Notify deploy
run: |
curl -s "$PINGD_URL/topics/deploy.prod.api/messages" \
-H "Authorization: Bearer ${{ secrets.PINGD_TOKEN }}" \
-H 'Content-Type: application/json' \
-d '{
"tags": ["github", "${{ github.repository }}"],
"payload": {
"title": "Deployed ${{ github.sha }}",
"body": "${{ github.actor }} deployed to prod"
}
}'
Watch a topic from a terminal
pingd-cli messages watch --topic alerts.disk
Or with raw curl:
curl -N https://pingd.example.com/topics/alerts.disk/stream \
-H "Authorization: Bearer $PINGD_TOKEN"
Grafana alerting
Webhook template for alerts.grafana:
{
"template": {
"title": "{{title}}",
"body": "{{message}}",
"tags": "grafana,{{state}}",
"priority": 3
}
}
Point Grafana's webhook contact point at the /hooks/... URL.
Home Assistant automation
From a Home Assistant rest_command. Store the full bearer header value in secrets.yaml.
rest_command:
pingd_doorbell:
url: "https://pingd.example.com/topics/home.frontdoor/messages"
method: POST
headers:
Authorization: !secret pingd_authorization_header
Content-Type: application/json
payload: |
{
"priority": 3,
"tags": ["frontdoor"],
"payload": {
"title": "Doorbell",
"body": "Front door rung at {{ now().strftime('%H:%M') }}"
}
}
Python publisher
import os, requests
requests.post(
f"{os.environ['PINGD_URL']}/topics/alerts.app/messages",
headers={
"Authorization": f"Bearer {os.environ['PINGD_TOKEN']}",
"Content-Type": "application/json",
},
json={
"priority": 2,
"tags": ["python"],
"payload": {
"title": "Job finished",
"body": "Nightly batch completed successfully",
},
},
timeout=5,
)
Node.js SSE listener
import EventSource from "eventsource";
const es = new EventSource(
"https://pingd.example.com/topics/alerts.app/stream",
{ headers: { Authorization: `Bearer ${process.env.PINGD_TOKEN}` } },
);
es.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log(message.payload.title, "-", message.payload.body);
};
Topic per host (NATS-style)
Use a topic per host for fanout to many machines:
alerts.host.web-01
alerts.host.web-02
alerts.host.db-01
A permission grant like alerts.host.> can cover read access for the whole fleet. Subscriptions are still concrete topic names.
Per-environment topics
deploy.prod.api
deploy.prod.web
deploy.staging.api
deploy.staging.web
Give CI wo on deploy.>, and on-call users ro on deploy.prod.>. Subscribe devices to the concrete prod topics that should notify them.