200 calls per organization per day
A hard cap, enforced atomically — once you hit it, further calls for that org are logged as rate-limited rather than placed, and the counter resets at midnight UTC. It exists so a runaway alert loop has a ceiling.
The mechanic, not the pitch
No black box. This is the actual pipeline a request travels through — from the moment your monitoring tool POSTs a webhook to the moment your phone rings, with every safety check in between named and explained.
Runbook
01
CallPing is compatible with anything that can POST a webhook
— Datadog, Grafana, Prometheus Alertmanager, Sentry,
Stripe, a curl in a continuous integration (CI)
job, a one-line Lambda forwarder. There’s no software
development kit (SDK) to install and no partnership required;
every tool is just sending HTTP to a URL you generated.
curl -X POST \
https://api.callping.app/api/wh/YOUR_ENDPOINT_UUID \
-H "Content-Type: application/json" \
-d '{"severity": "critical",
"message": "Checkout endpoint returning 5xx"}'
We accept any HTTP method — POST, PUT, PATCH, GET, DELETE. The body is parsed as JSON into fields; anything else — form-encoded, plain text, whatever your tool sends — is captured whole as the message rather than the request being rejected.
The endpoint’s universally unique identifier (UUID) is the credential by default. If you’re running the URL somewhere it might leak — a shared config file, a public CI log — you can turn on a required X-Alert-Key header per endpoint; requests without the matching key are rejected before anything else happens.
Before any of that: a rate limit of 60 requests per 60 seconds applies per endpoint. It exists so a misfiring integration retry-looping your webhook URL can’t do more than flood that one endpoint — everything past the limit is rejected outright, cheaply, before it touches routing logic.
02
Severity is read from whichever of these field names your payload
actually uses — severity, status,
level, priority,
alert_type, alertLevel,
alert_level — first one found wins. Common
values (p1, critical,
high, error, warning,
info, resolved, and others) normalize
to one of critical / major / minor / info,
so you don’t have to rename your tool’s payload to
match ours.
The endpoint is linked to a Scenario, which holds an ordered list
of routing rules evaluated top to bottom. The first rule whose
condition matches wins. Rules aren’t limited to severity
— twelve operators (in, nin,
contains, not_contains,
starts_with, ends_with,
exists, not_exists, gt,
gte, lt, lte) let a rule
match on any field in your payload: the message text, an
environment tag, a service name, whatever your tool sends.
If nothing matches, the scenario’s configurable catch-all default action fires — ring the on-call schedule, ring everyone, or ring the primary phone, set per scenario. An alert is never silently dropped for lack of a matching rule. One honest exception: if that action is “ring the on-call schedule” (or a Project) and nobody happens to be on shift at that moment, CallPing doesn’t fall back to ringing someone off-rotation — it rings nobody and fires an operator alert flagging the coverage gap, loudly, instead of quietly paging the wrong person.
03
The matched action resolves to a list of phone numbers. We write a row recording the incoming request, enqueue one message per phone, and return HTTP 202 to your monitoring tool — the actual dialing happens asynchronously from here, so your webhook sender isn’t held open waiting on a phone call to place.
Before a message is dequeued and dialed, the safety brakes below apply (daily cap, per-phone cooldown, phone-number blocking). None of them require configuration.
04
CallPing runs on 5 registered Asterisk PBX servers across 4 cloud providers (Oracle Cloud, AWS, Google Cloud, Azure) — but only 3 of the 5 currently carry a live SIP trunk and can actually place a call; the other 2 are held in reserve as standby capacity. Those 3 call-capable servers span 2 providers (two on Oracle Cloud, one on Google Cloud) and 5 SIP trunks between them. A health-aware registry selects among the call-capable PBXes in round-robin order, filtered first by which trunks actually serve the destination country — a UK number and a US number don’t necessarily route through the same trunk.
If the selected PBX or trunk fails to place the call, it retries automatically on a different PBX through a different trunk — up to three attempts before the call is logged as failed. That retry can cross a cloud-provider boundary, so a single trunk having a bad day doesn’t end the attempt — though honestly, two of the three call-capable servers currently sit on the same cloud provider and in the same city (Frankfurt), so a provider-wide or metro-wide outage there could still take both of them out at once.
05
A queue consumer picks the message up and asks Asterisk to originate the call through its REST Interface (ARI). Answering-machine detection In progress is being built to run on the call and distinguish a human answering from a voicemail or interactive voice response (IVR) pickup; once it ships, a call that connects to voicemail won’t get treated as delivered. Today, a voicemail pickup is logged the same as a human answer.
There is no voice on the line reading your alert text aloud, no recorded announcement, no “press 1 to acknowledge.” The call itself is the alert.
06
When the call ends, Asterisk posts the outcome to our disposition endpoint, matched back to the original call by its channel ID. Every call resolves to one of five terminal statuses — answered, busy, no-answer, canceled, or failed — derived from the actual SIP cause code, not a generic “call ended” flag. (An active decline isn’t a separate status — it’s recorded as the reason on a busy disposition, not a distinct outcome.)
An answer, an active decline, or a busy/engaged signal that actually reached a phone all stop the entire alert immediately: any other phone still ringing for the same alert is cancelled. Only a genuine no-answer advances the alert (see Step 7).
07
If the matched rule carried an escalation chain and the disposition was a genuine no-answer, the next step in the chain — up to 10 steps total, each with its own delay of up to 15 minutes — gets enqueued, targeting the primary phone, everyone, the on-call schedule, a Project, or one named person. If there’s no chain configured, the alert simply ends at the first disposition.
Full detail on every attempt — the raw ARI status, the SIP cause code, timestamps — is visible in your Call Logs.
Always on
Three brakes apply automatically, before a call ever reaches Asterisk. None of them are configurable, and none of them require setup.
A hard cap, enforced atomically — once you hit it, further calls for that org are logged as rate-limited rather than placed, and the counter resets at midnight UTC. It exists so a runaway alert loop has a ceiling.
The same number can’t be dialed more than once in a 60-second window, no matter how many different rules or escalation steps happen to resolve to it.
Emergency numbers (112, 911, 999, and their regional equivalents), premium-rate numbers, toll-free numbers, and short codes are rejected at every entry point — you cannot configure CallPing to dial one, even by mistake.
Self-select first
We list these because the right people should self-select before they integrate, not after.