Pingtower is live. The app is in review.
As of today, Pingtower is a real service you can sign up for. The hosted tower runs at api.pingtower.com, signups are open, and the whole …
Live — hosted & self-host
Your app writes down every failure — then buries it under forty thousand lines of routine noise nobody reads at 3 a.m. Pingtower reads the stream for you: repeats collapse into single alerts, your rules decide what matters, and it keeps paging until a human acks.
The fix
Point anything that can make an HTTP request at Pingtower. It extracts the shape of every message so repeats collapse into one alert with a counter, declarative rules decide what opens an alert, and escalation ladders decide who hears about it — Slack, Telegram, signed webhooks, or push to the native iOS app.
Use cases
A level 500 opens an alert and starts the ladder. If Slack doesn't get acked, your phone rings next — silent switch or not — until someone answers.
The same stack trace 40,000 times is one alert with a count of 40,000. Your channel gets one message and a running tally, not a flood.
A threshold like 5 hits in 10 minutes catches the webhook that fails a little more every hour — the slow bleed no single error would justify paging for.
Group alerts by identifier keys like username, and fifty different errors about the same account become one alert telling one story.
No agent, no SDK. A curl in the error path is enough for the smallest service you run to reach your phone.
Write the post-mortem as a report and share one link — public by UUID, password-protected if you want.
The API
One endpoint, one bearer token per source. Send a message, a severity from 100 to 500, and whatever keys and tags your rules should match on. Every language, cron job, and shell script already speaks it.
curl -s $PINGTOWER_URL/v1/ingest \
-H "Authorization: Bearer $SOURCE_TOKEN" \
-d '{
"message": "payment worker crashed",
"level": 500,
"keys": { "service": "payments", "signal": "SIGSEGV" },
"tags": ["prod"]
}'Addons
The addons agent is one Go binary on any box beyond your infrastructure. It runs HTTP, TCP, DNS, certificate-expiry, and ping checks on a schedule and reports every measurement through the same ingest plane your logs use — metrics are just events, and your rules threshold them.
$ addons check httpcheck \
--param url=https://example.com --report
UP in 101ms — sent, template f5b97ca2, alerted
$ addons check tlscert \
--param address=example.com:443
{ "days_until_expiry": 14, "handshake_ms": 34.7 }Why Pingtower
Pingtower strips the variable parts of each message to recover its shape, then hashes it — so the same failure bumps a counter on one alert instead of flooding a channel. Or group by keys like a username, and get one alert per affected account.
Match on level, source, tags, or message shape; add conditions on structured keys; set thresholds like “fire after 5 hits in 10 minutes” or “only when 3 different sources see it.” One engine, no separate monitor concept.
Ladders move an unacked alert up level by level — Slack first, on-call push later — repeating on the schedule you set until someone acks. Acked alerts hold their place; quiet ones auto-resolve.
Every notification is a durable outbox row, delivered at-least-once and logged per integration — a restart never drops a page. Webhooks are HMAC-SHA256 signed, and failing channels surface their errors instead of hiding them.
Tenant-supplied URLs pass an SSRF guard — no private ranges, no redirects, DNS-rebinding pinned. Delivery secrets are AES-256-GCM encrypted at rest, tokens compare in constant time, and everything lands in an audit log.
One Go binary, zero CGO, stdlib HTTP, pure-Go SQLite in WAL mode. Each tenant is its own database file, so a backup is a file copy. Self-host the daemon with a handful of flags on any box you own — ingest, rules, escalation, and webhook delivery all run there. The iOS app and its push notifications are hosted by us.
Attach an HTTP action to a rule and it fires the moment the alert opens or escalates — restart the worker, flush the queue, open a ticket. Credentials are sealed at rest, every run is logged with status and response, and you can test-fire before you trust it.
Organizations with owner, admin, and member roles; email invites; API keys you can mint and revoke per tenant. Belong to several orgs with one account, switch between them in the app — and every sensitive change lands in the audit log.
On-call
Build rotations from your project's members: layers take timed shifts, restrictions carve out business hours and nights in your timezone, and a later layer overrides the ones below — nights on top of a daytime base. When an alert fires, the push goes to the phone of whoever is on shift. Everyone else sleeps.
The app
Alerts that matter shouldn't queue behind muted Slack channels and filtered email. Pingtower has its own native iOS app — critical alerts sound through Silent mode and Focus, a permission you grant once, and one swipe in the app acks the alert and stops the escalation ladder. The whole product is in the app: rules, integrations, runbooks, reports, your team.
How it works
Create a project, add a source, get a token. One POST with a message, level, keys, and tags — from an error hook, a shell script, anywhere.
Each event's shape is matched against your rules. New problem: an alert opens. Repeat: the count bumps. Threshold not met yet: it waits.
The on-call rotation picks whose phone rings; integrations fan out — Slack, Telegram, signed webhooks, critical push to the iOS app — and runbook actions fire automatically. Unacked alerts climb the ladder.
Changelog
As of today, Pingtower is a real service you can sign up for. The hosted tower runs at api.pingtower.com, signups are open, and the whole …
Getting a new phone onto Pingtower used to mean finding an API key, copying it off a laptop, and pasting it into a text field before you …