Webhooks to
Telegram, Slack
& Discord.
POST any payload to your unique URL.
It lands in your chat within seconds.
No account. No dashboard. No config.
Type /start โ get your URL in under 10 seconds.
Works with anything that can send a POST request
How It Works
Three steps. Under a minute.
No email. No OAuth. No SDK.
Start the bot
Open Telegram, message @PingHookBot, and type /start. You get a unique webhook URL immediately.
Paste the URL anywhere
Add it to GitHub Actions, Grafana, n8n, a cron job, or just curl it from your terminal. If it sends HTTP, it works.
Get notified instantly
Every POST becomes a message in your Telegram chat. Optionally connect Slack or Discord via /connect slack and fan out to all three at once.
Features
Everything you need. Nothing you don't.
Multi-Channel Delivery
Fan out to Telegram, Slack, and Discord simultaneously. Connect Slack with /connect slack <url> โ PingHook validates and sends a test ping before saving.
Smart Labels
Tag events by source: /send/key/ci-failed, /send/key/payment-received. The label shows in every message and powers alerting rules.
Smart Formatting
JSON is auto-indented in a code block. Plain text supports Markdown โ **bold**, _italic_, and ~~strikethrough~~ render natively.
The Label Is the Logic
Fire /send/KEY/ci-failed only when CI fails. Fire /send/KEY/payment-received only on success. When you own the code, the label carries the signal โ no backend rules needed.
Zero Config
No SDK. No OAuth. No account. Your webhook URL is your only credential โ paste it, POST to it, done. The Telegram bot is the entire control plane.
History & Replay
Use /history to see your last 10 delivered pings with payload previews. Use /replay 3 to re-dispatch any ping to all channels โ perfect for recovering a missed alert or testing a rule change.
Filtering & rules โ three layers: inline pinghook_rules in your JSON body, query params (?if=, ?textif=, ?dedup=, ?channel=, ?silent=), or global bot rules via /rules for sources you can't touch at all. See the docs section below.
Quick Start
Paste. Send. Done.
Replace YOUR_KEY with the URL from the bot.
# Send a JSON payload with a label curl -X POST https://pinghook.dev/send/YOUR_KEY/ci-failed \ -H "Content-Type: application/json" \ -d '{"event":"test_failed","repo":"myapp","branch":"main","run":142}' # Response { "status": "success", "channels_notified": 2 }
# Plain text โ no Content-Type header needed curl -X POST https://pinghook.dev/send/YOUR_KEY/cron-done \ -d "Backup completed at $(date)" # Fan out to one specific platform only curl -X POST "https://pinghook.dev/send/YOUR_KEY/deploy?channel=slack" \ -d "Deploy succeeded on main"
# Plain text with Markdown โ renders natively in Telegram curl -X POST https://pinghook.dev/send/YOUR_KEY/deploy \ -d "**Deploy succeeded** on main _Started by:_ asaf _Duration:_ 42s _Status:_ ~~failing~~ passing" # Supported: **bold** _italic_ ~~strikethrough~~ # JSON payloads are auto-formatted in a code block โ no Markdown needed
# .github/workflows/notify.yml - name: Notify via PingHook if: always() run: | curl -s -X POST \ https://pinghook.dev/send/${{ secrets.PINGHOOK_KEY }}/github \ -H "Content-Type: application/json" \ -d '{ "event": "workflow_${{ job.status }}", "repo": "${{ github.repository }}", "branch": "${{ github.ref_name }}", "run": "${{ github.run_number }}" }'
# pip install requests import requests PINGHOOK_URL = "https://pinghook.dev/send/YOUR_KEY" requests.post( f"{PINGHOOK_URL}/payment-received", json={"amount": 49.00, "customer": "jane@acme.com"} ) # Or plain text requests.post(PINGHOOK_URL + "/cron-done", data="ETL pipeline finished")
Everything documented, nothing hidden
API reference ยท bot commands ยท integration guides for Grafana, GitHub Actions, Uptime Kuma, n8n, Python, cron jobs ยท self-hosting.
FAQ
Common questions
How do I add Slack or Discord?
Open the Telegram bot and send /connect slack https://hooks.slack.com/... or /connect discord https://discord.com/api/webhooks/.... PingHook validates the URL with a test ping before saving. Once connected, all future webhooks fan out to every channel at once.
What's the rate limit?
Free tier: 100 requests per hour, 1,000 per day, per webhook URL. Payloads over 100 KB are rejected with a 413. The error response includes a resets_in field so you know exactly when you can retry.
What payload formats are supported?
JSON is auto-indented in a monospace code block. Plain text supports Markdown โ **bold**, _italic_, and ~~strikethrough~~ all render natively in Telegram. Both formats support labels.
How do filtering and alerting rules work?
PingHook has three layers. Layer 1: add a pinghook_rules key to your JSON body with conditions, logic, dedup, and channel โ evaluated against your payload fields, stripped before delivery. Layer 2: append ?if=, ?textif=, ?dedup=, ?channel=, or ?silent= to the URL โ works for any source without touching the body. Layer 3: global bot rules via /rules add keyword, /rules add dedup, /rules add labels โ fallback for sources you can't touch at all. More specific layers take full priority.
What if someone gets my webhook URL?
The URL is write-only โ it can only trigger notifications to your chat, never read data. If compromised, send /regen confirm in the bot. Your old key is invalidated immediately and all connected channels receive the new URL automatically.
Can I self-host this?
Yes. PingHook is fully open source. Clone the repo, add your own .env, run the schema in Supabase, and start with Uvicorn. The schema.sql creates everything in any PostgreSQL database.