Send Server Alerts to Telegram with One curl Command
push.tgYour phone is already in your pocket, and Telegram is already on it. So why do server alerts still end up in an email folder nobody reads?
The usual answer is that wiring up Telegram notifications is fiddly. This guide shows the standard DIY route first, then a shortcut that turns it into one curl command with zero setup.
The DIY way: Telegram Bot API
Telegram's official route works well, but it has a few steps:
- Message @BotFather, create a bot, and copy its token.
- Send your new bot a message, then call
getUpdatesto find yourchat_id. - Store the token somewhere safe on every machine that sends alerts.
- Send messages with:
curl -s "https://api.telegram.org/bot<TOKEN>/sendMessage" \
-d chat_id=<CHAT_ID> -d text="Backup finished"It's fine for one project. But the token is a full credential for the bot, chat IDs are annoying for groups, and in practice many of us end up with a graveyard of single-purpose bots.
The shortcut: push.tg
push.tg (bot: @trafficRobot) gives you a personal endpoint that already knows where to deliver.
Step 1. Open @trafficRobot and press Start. You'll get an address like k3x9q@push.tg. Your endpoint is the part before the @:
https://push.tg/k3x9qStep 2. POST any text to it:
curl -d "Backup finished ✅" https://push.tg/k3x9qThat's it. The message appears in your Telegram chat. There's no bot to create, no chat ID to look up, and no token to store.
Copy-paste recipes
Pipe any command's output
df -h / | curl -d @- https://push.tg/k3x9q
echo "Load: $(uptime)" | curl -d @- https://push.tg/k3x9q-d @- tells curl to read the body from standard input, so you can pipe anything into it.
Cron: alert only on failure
0 3 * * * /usr/local/bin/backup.sh || curl -s -d "❌ Backup FAILED on $(hostname)" https://push.tg/k3x9qYou only hear about it when something breaks. That's the whole point of good alerting.
Disk space watchdog
#!/bin/sh
USE=$(df / | awk 'NR==2 {gsub("%",""); print $5}')
[ "$USE" -gt 90 ] && curl -s -d "⚠️ $(hostname): disk at ${USE}%" https://push.tg/k3x9qDrop it in cron every 15 minutes.
Notify when a long job finishes
make build && curl -d "✅ build done" https://push.tg/k3x9q || curl -d "❌ build failed" https://push.tg/k3x9qGreat for model training runs, database migrations, or that rsync you started before lunch.
GitHub Actions
Store your address as a repository secret (PUSHTG_ADDR), then:
- name: Notify Telegram
if: always()
run: curl -s -d "${{ github.repository }}: ${{ job.status }} (${{ github.sha }})" https://push.tg/${{ secrets.PUSHTG_ADDR }}Python
import requests
requests.post("https://push.tg/k3x9q", data="Training finished: val_loss=0.031")Node.js
await fetch("https://push.tg/k3x9q", { method: "POST", body: "New signup 🎉" });Systems that can only send email
Old NAS boxes, UPS software, printers and some monitoring tools can only send email alerts. Point them at k3x9q@push.tg. The same address receives email, and it lands in the same chat.
Alerts for the whole team
Add @trafficRobot to a Telegram group and create an address inside the group. Everyone in the group gets the alerts. That's a lightweight on-call channel without a paging product: deploy notices, failed backups and "the website is down" all in one place your team already reads.
Keep your address secret
Your endpoint works like a password: anyone who knows it can send you messages. Keep it in environment variables or CI secrets rather than in public repos. If it ever leaks, delete it in the bot and create a new one in seconds. A practical pattern is one address per server or project. You can see which machine is talking, and you can rotate one without touching the others.
How does it compare?
- Telegram Bot API (DIY): maximum control and formatting options, but you manage tokens and chat IDs.
- ntfy / Pushover: solid tools, but each needs its own app on your phone.
- Webhook relays like Hook2TG: still have you create your own bot first.
- push.tg: nothing to install, nothing to configure. It delivers to the Telegram you already have, and it also accepts email.
Troubleshooting
- Nothing arrived? Check the response body. A successful call returns JSON with
ok, and an unknown address returns anerror. - Message contains
=or&? The endpoint also accepts form posts, so a body likecpu=95%can be read as a form field. Send it as an explicit field instead:curl --data-urlencode "data=cpu=95% & rising" https://push.tg/k3x9q. - Don't send secrets in alerts. Treat messages like any chat message.
Start now
Open @trafficRobot, press Start, and paste your first curl. Your server will be texting you in under a minute. Docs and examples: push.tg.