Any monitoring tool

One API endpoint.
Any monitoring tool.

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.

Get Your API Key Free View API Docs

Works with any tool that supports webhooks or HTTP

Nagios Zabbix Uptime Robot New Relic Datadog Grafana Prometheus CheckMK LibreNMS Netdata cron jobs CI pipelines custom scripts

Authentication

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.

Auth errors

401
Missing or invalid X-Api-Key
403
Key valid, but request IP isn't on its allowlist

The API — one endpoint, four ways to target it

POST a page to a person, a group, everyone, or whoever's on call.

Required fields

subject
Short title, max 200 characters
message
Details — shown in push, email, and SMS (truncated to 160 chars for SMS)
delivery_mode
single · group · broadcast · oncall
target_user_id
Required when delivery_mode is single
target_group_id
Required when delivery_mode is group
target_schedule_id
Required when delivery_mode is oncall — resolved to whoever's covering right now, no need to know who that is. IDs are on your on-call schedules page

Optional fields

priority
low · normal (default) · high · critical
repeat_interval_s
30–3600 seconds between repeat pushes. Default 60
expires_minutes
1–1440. Page stops repeating and auto-expires if never acknowledged
escalation
Array of escalation steps — see below

A 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.

Pick a target

Same endpoint, four payload shapes.

Whoever's on call — 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
}
One specific person — single
{
  "subject": "Deploy pipeline failed",
  "message": "Build #4821 failed at the test stage.",
  "priority": "high",
  "delivery_mode": "single",
  "target_user_id": 14
}
A specific team — group
{
  "subject": "Database replication lag > 60s",
  "message": "Replica db-replica-02 is falling behind.",
  "priority": "critical",
  "delivery_mode": "group",
  "target_group_id": 3
}
Everyone in the org — broadcast
{
  "subject": "Site-wide outage",
  "message": "All services down. Investigating.",
  "priority": "critical",
  "delivery_mode": "broadcast"
}

Success response

{
  "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.

Error responses

422
Validation failed — response body lists which field and why
401
Missing or invalid API key
403
Key not allowed from this IP
500
Something broke on our end — safe to retry

Escalation policies

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.

Test it right now

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}'

Code examples

Nagios notification command
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}'
}
Zabbix media type script
#!/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}
Shell script / cron alert
#!/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
Python (requests)
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()
Node.js (fetch)
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();
}
PowerShell (SCOM / Windows monitoring)
$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

Connect your monitoring stack today

Free for up to 3 pagers. First call can be under a minute away.

Grafana Integration → vs PagerDuty → vs OpsGenie → Prometheus Integration → Outgoing Webhook Docs →