PingParrot logo PingParrot

API Documentation

This API sends pages, manages on-call groups, and reads back delivery status over plain JSON — authenticate with an API key for integrations or a bearer token for user sessions, hit the base URL below, and every endpoint returns within the response formats documented on this page.

By Josh Crann · Updated

Base URL

https://pingparrot.app/api

All requests and responses use JSON, per the JSON specification. Include Content-Type: application/json on all POST and PUT requests. Status codes follow the IANA HTTP status code registry — 2xx for success, 4xx for a request you can fix, 5xx for something on our end.

PingParrot offers two authentication methods depending on your use case:

  • →API Key — for monitoring tools, scripts, and third-party integrations. Generate a key in your dashboard. Simple header-based auth.
  • →Bearer Token — for user-authenticated sessions. Login via the API to get a token. Required for reading pages, managing groups, etc.

How do I authenticate with the API?

Use an API key for integrations, or a bearer token for user-authenticated sessions — both go in a request header, no OAuth flow required.

1 API Key — recommended for integrations

Generate an API key in Dashboard → Admin → API Keys. Pass it in the X-API-Key request header. API key auth covers Send a Page, List Schedules, and List Groups (API Key) — everything else needs a Bearer Token from a logged-in session.

curl -X POST https://pingparrot.app/api/external/pages \
  -H "X-API-Key: pp_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"subject": "Server down", "message": "web-01 is unreachable", "priority": "critical", "delivery_mode": "broadcast"}'

2 Bearer Token — for user sessions

Exchange your email and password for a token. Pass it as Authorization: Bearer <token> on every subsequent request.

POST /auth/login
curl -X POST https://pingparrot.app/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "your-password",
    "device_name": "my-script"
  }'

Response

{
  "token": "1|abc123xyz...",
  "user": {
    "id": 1,
    "name": "Jane Smith",
    "email": "[email protected]",
    "is_admin": true
  }
}

Use the returned token on all subsequent requests:

curl https://pingparrot.app/api/auth/me \
  -H "Authorization: Bearer 1|abc123xyz..."
POST /auth/logout

Revokes the current token.

curl -X POST https://pingparrot.app/api/auth/logout \
  -H "Authorization: Bearer 1|abc123xyz..."

What do error responses look like?

Every error returns JSON with an error key. Validation errors return a message and an errors object.

Status Meaning
200Success
201Created (page sent)
401Missing or invalid API key / token
403IP not permitted (API key) or insufficient role
404Resource not found or not accessible
422Validation failed — check the errors object
500Server error

Send a Page

The core endpoint. Use this from your monitoring tools, scripts, or integrations.

POST /external/pages API Key auth
POST /pages Bearer Token auth

Request Body

Field Type Required Description
subject string Yes Alert headline, max 200 chars
message string Yes Full alert body / details
delivery_mode string Yes single · group · broadcast · oncall
priority string No low · normal · high · critical · default: normal
target_user_id integer If single User ID to page directly
target_group_id integer If group Group ID to page — every active member. See List Groups (API Key)
target_schedule_id integer If oncall Schedule ID to resolve — pages only whoever's currently on duty. See List Schedules
repeat_interval_s integer No Seconds between repeats, 30–3600 · default: 60
expires_minutes integer No Auto-cancel after N minutes (1–1440). Omit for no expiry.
escalation array No Escalation rules — see Escalation Rules

Response 201 Created

{
  "message": "Page sent successfully",
  "page_id": 42,
  "recipients": 3
}

Response — Suppressed by Maintenance Window

When an active maintenance window covers the target group or organisation, the page is saved with status suppressed and a 201 is returned with suppressed: true. No push notifications are sent.

{
  "message": "Page suppressed by active maintenance window",
  "page_id": 43,
  "suppressed": true,
  "window": "DB Cluster Maintenance"
}

Delivery Modes

broadcast — Page everyone in your organisation

Sends to all active pager accounts. No target_* field needed.

{
  "subject": "All hands — production is down",
  "message": "Database cluster unreachable. All services affected.",
  "priority": "critical",
  "delivery_mode": "broadcast",
  "repeat_interval_s": 30
}
group — Page a specific on-call group

Sends to all active members of the group. Requires target_group_id. Find group IDs at List Groups (API Key).

{
  "subject": "Disk usage critical on web-01",
  "message": "Disk at 97%. Immediate attention required.",
  "priority": "high",
  "delivery_mode": "group",
  "target_group_id": 2,
  "repeat_interval_s": 60
}
oncall — Page whoever's on duty right now

Resolves the schedule to whoever is currently covering it and pages only them — not the whole group. If nobody's covering it right now, falls back to the schedule's configured group, if it has one; otherwise reaches nobody. Requires target_schedule_id. Find schedule IDs at List Schedules.

{
  "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 — Page one specific person

Sends to a single user. Requires target_user_id.

{
  "subject": "Your deployment failed",
  "message": "Build #1024 failed at test stage. See CI logs.",
  "priority": "normal",
  "delivery_mode": "single",
  "target_user_id": 5
}

Escalation Rules

Automatically escalate to another person or group if the page isn't acknowledged within a set time. Escalation rules are evaluated after initial delivery.

Diagram: a page escalates from the on-call engineer, to backup, to the team lead, with a wait timer between each step until someone acknowledges it Page sent to on-call engineer 5 min, no ack Escalates to backup responder 10 min, no ack Escalates to team lead, repeats until acknowledged
A three-step escalation policy: each step waits for acknowledgment before handing off to the next responder.

Escalation Object Fields

Field Type Description
step integer Escalation order (1, 2, 3…)
delay_seconds integer Seconds after initial send before escalating (min 60)
escalate_to_user_id integer User ID to escalate to
escalate_to_group_id integer Group ID to escalate to
repeat_page boolean Keep repeating after escalation · default: true

Example — page primary on-call, escalate to manager after 5 minutes

{
  "subject": "Payment service is down",
  "message": "Stripe webhook endpoint returning 503.",
  "priority": "critical",
  "delivery_mode": "single",
  "target_user_id": 3,
  "repeat_interval_s": 30,
  "escalation": [
    {
      "step": 1,
      "delay_seconds": 300,
      "escalate_to_user_id": 1,
      "repeat_page": true
    }
  ]
}

List Pages

Returns a paginated list of pages. Admins see all pages; regular users see only pages they are a recipient of.

GET /pages Bearer Token

Query Parameters

status Filter by status: active · acknowledged · expired · cancelled
priority Filter by priority: low · normal · high · critical
curl "https://pingparrot.app/api/pages?status=active" \
  -H "Authorization: Bearer 1|abc123xyz..."

Get a Page

Returns full details for a single page including recipients and acknowledgements.

GET /pages/{id} Bearer Token
curl https://pingparrot.app/api/pages/42 \
  -H "Authorization: Bearer 1|abc123xyz..."

Response

{
  "id": 42,
  "subject": "Server down",
  "message": "web-01 is unreachable",
  "priority": "critical",
  "status": "active",
  "delivery_mode": "broadcast",
  "repeat_interval_s": 30,
  "created_at": "2026-06-23T14:00:00Z",
  "expires_at": null,
  "recipients": [
    {
      "id": 12,
      "user_id": 3,
      "status": "pending",
      "first_sent_at": "2026-06-23T14:00:01Z",
      "acknowledged_at": null,
      "user": { "id": 3, "name": "Sarah M." }
    }
  ]
}

Acknowledge a Page

Marks the page as acknowledged for the authenticated user. When all recipients have acknowledged, the page status changes to acknowledged and repeating stops.

POST /pages/{id}/acknowledge Bearer Token

Request Body (all optional)

response_note string, max 500 chars — optional note on what action was taken
method app · web · sms · voice · default: app
curl -X POST https://pingparrot.app/api/pages/42/acknowledge \
  -H "Authorization: Bearer 1|abc123xyz..." \
  -H "Content-Type: application/json" \
  -d '{"response_note": "Restarted the service, monitoring now."}'

Cancel a Page

Stops repeating and marks the page as cancelled. Admin only.

DELETE /pages/{id} Bearer Token · Admin
curl -X DELETE https://pingparrot.app/api/pages/42 \
  -H "Authorization: Bearer 1|abc123xyz..."

List Schedules

Returns all on-call schedules in your organisation, with whoever's currently covering each one. Use the returned id as target_schedule_id when sending a page with delivery_mode: oncall. Same API key as Send a Page — no dashboard login needed.

GET /external/schedules X-API-Key
curl https://pingparrot.app/api/external/schedules \
  -H "X-Api-Key: pp_live_your_key_here"

Response

[
  {
    "id": 1,
    "name": "Backend On-Call",
    "on_call_user": { "id": 14, "name": "Alex Rivera" },
    "fallback_group": null
  },
  {
    "id": 2,
    "name": "Infra On-Call",
    "on_call_user": null,
    "fallback_group": { "id": 3, "name": "Infra Team" }
  }
]

on_call_user is null when nobody's currently scheduled. In that case a page sent with delivery_mode: oncall goes to fallback_group instead, if the schedule has one set (configurable on the On-Call Schedules page) — otherwise it reaches nobody. Check both fields before relying on delivery.

List Groups (API Key)

Same data as List Groups below, but reachable with an API key — no Bearer Token or dashboard login needed. Use the returned id as target_group_id.

GET /external/groups X-API-Key
curl https://pingparrot.app/api/external/groups \
  -H "X-Api-Key: pp_live_your_key_here"

Response

[
  { "id": 2, "name": "Backend Team", "member_count": 6 },
  { "id": 3, "name": "Infra Team", "member_count": 4 }
]

List Groups

Returns all active groups in your organisation. Use the returned IDs when sending a page with delivery_mode: group.

GET /groups Bearer Token
curl https://pingparrot.app/api/groups \
  -H "Authorization: Bearer 1|abc123xyz..."

Response

[
  { "id": 1, "name": "All", "description": "All pagers in your organization", "is_active": true },
  { "id": 2, "name": "DevOps", "description": "On-call engineers", "is_active": true }
]

Get a Group

Returns a group with its current members.

GET /groups/{id} Bearer Token
curl https://pingparrot.app/api/groups/2 \
  -H "Authorization: Bearer 1|abc123xyz..."

Snooze

Toggle your personal notification snooze on or off. When snoozed, pages dispatched to a group or broadcast will skip you — you will not receive push notifications for those pages. On-call and direct (single-user) pages still reach you even when snoozed.

POST /api/auth/snooze/toggle Bearer Token

No request body required. Each call flips the current snooze state.

Response

{
  "is_snoozed": true
}
Field Description
is_snoozed The snooze state after the toggle. true means you are now snoozed; false means you are now active.
curl -X POST https://pingparrot.app/api/auth/snooze/toggle \
  -H "Authorization: Bearer 1|abc123xyz..."

Grafana Integration

Use Grafana's Webhook contact point to call the PingParrot API when an alert fires.

  1. 1In Grafana, go to Alerting → Contact points → Add contact point
  2. 2Choose type Webhook and set the URL to https://pingparrot.app/api/external/pages
  3. 3Add header X-Api-Key: YOUR_API_KEY and set method to POST
Full Grafana setup guide →

Prometheus / Alertmanager

Add PingParrot as a webhook receiver in alertmanager.yml and your alerts route directly to your on-call team.

receivers:
  - name: 'pingparrot'
    webhook_configs:
      - url: 'https://pingparrot.app/api/external/pages'
        http_config:
          headers:
            X-Api-Key: 'YOUR_API_KEY'
        send_resolved: false

route:
  receiver: 'pingparrot'
Full Prometheus setup guide →

Generic Webhook / Any Tool

Any monitoring tool that can make an HTTP POST request — Nagios, Zabbix, Uptime Robot, custom scripts, CI pipelines — can trigger PingParrot.

curl -X POST https://pingparrot.app/api/external/pages \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Alert: high CPU on web-01",
    "message": "CPU at 95% for 5 minutes.",
    "priority": "critical",
    "target": "oncall",
    "schedule_id": 1
  }'
More examples — Nagios, Zabbix, Python, bash →

cURL Examples

Broadcast a critical alert (API key)

curl -X POST https://pingparrot.app/api/external/pages \
  -H "X-API-Key: pp_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Production is down",
    "message": "All services returning 503. Immediate action required.",
    "priority": "critical",
    "delivery_mode": "broadcast",
    "repeat_interval_s": 30
  }'

Page a specific group (API key)

curl -X POST https://pingparrot.app/api/external/pages \
  -H "X-API-Key: pp_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "High memory usage on app-server-02",
    "message": "Memory at 95%. OOM kill likely within minutes.",
    "priority": "high",
    "delivery_mode": "group",
    "target_group_id": 2,
    "repeat_interval_s": 60,
    "expires_minutes": 30
  }'

Shell script — use in cron or CI/CD

#!/bin/bash
# Usage: ./ping.sh "Subject" "Message body" "critical"

SUBJECT="${1:-Alert}"
MESSAGE="${2:-No details provided}"
PRIORITY="${3:-normal}"

curl -s -X POST https://pingparrot.app/api/external/pages \
  -H "X-API-Key: $PINGPARROT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"subject\": \"$SUBJECT\",
    \"message\": \"$MESSAGE\",
    \"priority\": \"$PRIORITY\",
    \"delivery_mode\": \"broadcast\"
  }"