PingParrot works with any tool that can make an HTTP request — Nagios, Zabbix, Uptime Robot, New Relic, Datadog, custom shell scripts, CI pipelines, or code you write yourself. One POST request and your team is being paged.
Works with any tool that supports webhooks or HTTP
One header. No OAuth dance.
Every request needs an X-Api-Key header. Generate one from Settings → API Keys — it's shown once, so store it in your monitoring tool's secrets manager, not in a config file that gets committed.
Optionally restrict a key to specific source IPs when you create it — useful if your monitoring stack has a fixed egress IP. Requests from any other IP get a 403.
A key with no IP restriction works from anywhere. There's no rate limit on this endpoint today — if you're planning to send hundreds of pages per minute, talk to us first so we can make sure your monitoring tool isn't misconfigured and about to page your whole team on a loop.
X-Api-KeyPOST a page to a person, a group, everyone, or whoever's on call.
single · group · broadcast · oncalldelivery_mode is singledelivery_mode is groupdelivery_mode is oncall — resolved to whoever's covering right now, no need to know who that is. IDs are on your on-call schedules pagelow · normal (default) · high · criticalA group or broadcast page suppressed by an active maintenance window still returns 201, with "suppressed": true instead of recipients — check for that field rather than assuming every 201 paged someone.
Same endpoint, four payload shapes.
oncall{
"subject": "Disk usage above 90% on db-prod-01",
"message": "Disk /dev/sda1 at 92%. Immediate attention required.",
"priority": "critical",
"delivery_mode": "oncall",
"target_schedule_id": 1
}
single{
"subject": "Deploy pipeline failed",
"message": "Build #4821 failed at the test stage.",
"priority": "high",
"delivery_mode": "single",
"target_user_id": 14
}
group{
"subject": "Database replication lag > 60s",
"message": "Replica db-replica-02 is falling behind.",
"priority": "critical",
"delivery_mode": "group",
"target_group_id": 3
}
broadcast{
"subject": "Site-wide outage",
"message": "All services down. Investigating.",
"priority": "critical",
"delivery_mode": "broadcast"
}
{
"message": "Page sent successfully",
"page_id": 4821,
"recipients": 1
}
201 on success. recipients is how many people were actually paged — it can be 0 if a schedule has nobody on call or everyone in a group is snoozed.
Define who gets paged next, per page, in the same request.
Pass an escalation array and PingParrot will move on to the next step automatically if nobody acknowledges in time — no separate API call needed. Each step needs a step number and a delay_seconds, plus either an escalate_to_user_id or escalate_to_group_id.
{
"subject": "Payment processor returning 500s",
"message": "Checkout is down. Error rate at 40%.",
"priority": "critical",
"delivery_mode": "single",
"target_user_id": 14,
"escalation": [
{ "step": 1, "delay_seconds": 300, "escalate_to_user_id": 22 },
{ "step": 2, "delay_seconds": 600, "escalate_to_group_id": 3, "repeat_page": true }
]
}
In this example: page user 14 first. If unacknowledged after 5 minutes, escalate to user 22. If still unacknowledged 10 minutes after that, page the whole of group 3 and keep repeating.
Swap in a real API key and a real target_user_id (your own user ID works) and run this — you should get paged within a couple of seconds.
curl -s -X POST https://pingparrot.app/api/external/pages \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"subject":"Test page","message":"Just testing the API","priority":"low","delivery_mode":"single","target_user_id":YOUR_USER_ID}'
define command {
command_name notify-pingparrot
command_line /usr/bin/curl -s -X POST https://pingparrot.app/api/external/pages \
-H "X-Api-Key: $USER1$" \
-H "Content-Type: application/json" \
-d '{"subject":"$NOTIFICATIONTYPE$: $HOSTNAME$ $SERVICEDESC$","message":"$SERVICEOUTPUT$","priority":"critical","delivery_mode":"oncall","target_schedule_id":1}'
}
#!/bin/bash
# Zabbix passes: $1 = target group ID, $2 = subject, $3 = message
curl -s -X POST https://pingparrot.app/api/external/pages \
-H "X-Api-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d "{
\"subject\": \"$2\",
\"message\": \"$3\",
\"priority\": \"high\",
\"delivery_mode\": \"group\",
\"target_group_id\": $1
}"
# In Zabbix: Alerts → Media types → Script, name the params
# {ALERT.SENDTO}, {ALERT.SUBJECT}, {ALERT.MESSAGE}
#!/bin/bash
API_KEY="your_api_key_here"
DISK=$(df -h / | awk 'NR==2{print $5}' | tr -d '%')
if [ "$DISK" -gt 85 ]; then
curl -s -X POST https://pingparrot.app/api/external/pages \
-H "X-Api-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"subject\": \"Disk usage at ${DISK}% on $(hostname)\",
\"message\": \"Root filesystem is ${DISK}% full. Investigate immediately.\",
\"priority\": \"high\",
\"delivery_mode\": \"oncall\",
\"target_schedule_id\": 1
}"
fi
import requests
def page_oncall(subject, message, priority="high", schedule_id=1):
resp = requests.post(
"https://pingparrot.app/api/external/pages",
headers={"X-Api-Key": "YOUR_API_KEY"},
json={
"subject": subject,
"message": message,
"priority": priority,
"delivery_mode": "oncall",
"target_schedule_id": schedule_id,
},
timeout=10,
)
resp.raise_for_status()
return resp.json()
async function pageOnCall(subject, message, priority = "high", scheduleId = 1) {
const res = await fetch("https://pingparrot.app/api/external/pages", {
method: "POST",
headers: {
"X-Api-Key": process.env.PINGPARROT_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
subject,
message,
priority,
delivery_mode: "oncall",
target_schedule_id: scheduleId,
}),
});
if (!res.ok) throw new Error(`PingParrot page failed: ${res.status}`);
return res.json();
}
$body = @{
subject = "Alert: $($Alert.Name) on $($Alert.MonitoringObjectDisplayName)"
message = $Alert.Description
priority = "high"
delivery_mode = "oncall"
target_schedule_id = 1
} | ConvertTo-Json
Invoke-RestMethod -Uri "https://pingparrot.app/api/external/pages" `
-Method Post `
-Headers @{ "X-Api-Key" = "your_api_key_here" } `
-ContentType "application/json" `
-Body $body
Free for up to 3 pagers. First call can be under a minute away.