Help center / Developers

Pingerer API

Manage sites, monitors, incidents, heartbeats, alerts, status pages and maintenance, and read check results.

Every request needs an API token, sent as `Authorization: Bearer `.
Create one on the API tokens page; a token can be read only, and can be
limited to one account.

Requests are for one account: the `Pingerer-Account` header (an account id
like `acct_...`, or its number) or the `account_id` parameter picks it.
Without either, it's the token's account, else your first team account,
else your personal one. An account paused by Pingerer answers
`403 account_suspended`.

Responses are `{"data": ..., "meta": {...}}`. Lists are paginated with
`page` and `per_page` (up to 100, 20 by default), and `meta` has `page`,
`per_page`, `total`, `total_pages`, `next_page` and `prev_page`. Errors are
`{"error": "code", "message": "...", "details": {...}}`: `bad_request`
(400), `unauthorized` (401), `forbidden`, `read_only_token`,
`account_suspended` and `password_change_required` (403), `not_found`
(404), `validation_failed` and `plan_limit` (422), `rate_limited` (429).
Each token may make 300 requests a minute.

Ids are stable prefixed ids (`site_...`, `mon_...`). PUT and PATCH
change only the fields sent (except a monitor's settings, which PUT
replaces), so sending the same request twice changes nothing more. The
Terraform provider and the GitHub Action are built on these endpoints.

Durations (`every`, `grace`, `since`, `duration`) take seconds or `30s`, `5m`, `1h`,
`1d`, `1w`. Times are ISO 8601.

OpenAPI 3.1 spec (YAML) API tokens

Quick start

curl https://staging.pingerer.com/api/v1/status \
  -H "Authorization: Bearer $PINGERER_TOKEN"

# or with the command line tool
gem install pingerer
pingerer login
pingerer status

Terraform and GitHub Actions

The Terraform provider (pingerer/pingerer) manages sites, monitors, alert channels and rules, status pages, their components and maintenance windows as code. The GitHub Action pauses alerts or opens a maintenance window while you deploy, then waits until your site is up again.

terraform {
  required_providers {
    pingerer = { source = "pingerer/pingerer" }
  }
}

resource "pingerer_site" "shop" {
  url = "https://shop.yourbakery.com"
}

# .github/workflows/deploy.yml
- uses: pingerer/pingerer-action@v1
  with:
    api_token: ${{ secrets.PINGERER_TOKEN }}
    action: maintenance-start
    site: shop.yourbakery.com
    duration: 15m

Endpoints

Account

GET /api/v1/me

The person the token belongs to

Works for any account, even a paused one. The CLI's `login` checks a token with it.

curl https://staging.pingerer.com/api/v1/me \
  -H "Authorization: Bearer $PINGERER_TOKEN"

GET /api/v1/accounts

Your accounts

Every account you belong to (a plain array). Use an id in the Pingerer-Account header.

curl https://staging.pingerer.com/api/v1/accounts \
  -H "Authorization: Bearer $PINGERER_TOKEN"

GET /api/v1/push_devices

Your devices for push alerts

The phones and tablets the Pingerer app registered for you (docs/mobile-apps.md).

curl https://staging.pingerer.com/api/v1/push_devices \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/push_devices

Register a device for push alerts

What the apps call on each launch. Registering a token again
updates its device. A token registered by someone else moves to
you only with that install's `install_id` (a random id the app
makes once per install), else 409. `environment` is `sandbox` for
iOS debug builds only.

curl -X POST https://staging.pingerer.com/api/v1/push_devices \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"token":"a1b2c3…","platform":"ios","install_id":"4f1c9a7e-2b3d-4e5f-8a9b-0c1d2e3f4a5b","name":"Sam's iPhone","app_version":"1.4"}'

DELETE /api/v1/push_devices/{id}

Remove a device (on sign-out)

curl -X DELETE https://staging.pingerer.com/api/v1/push_devices/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

GET /api/v1/status

The account at a glance

Overall status (down, degraded, up or pending), sites and monitors counted by status, down sites and unresolved incidents.

curl https://staging.pingerer.com/api/v1/status \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Sites

GET /api/v1/sites

List sites

curl https://staging.pingerer.com/api/v1/sites \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/sites

Add a site

Adds the site and a monitor for each of `kinds` (default http, ssl,
domain, dns, email_auth). `every` sets how often the uptime kinds
(http, tcp, ping, smtp) check; the plan's shortest by default. `detect: true`
looks the site up first to fill in each check's settings.
`create_monitors: false` adds the site alone (Terraform adds each
monitor itself), and `paused: true` adds it paused.

curl -X POST https://staging.pingerer.com/api/v1/sites \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"yourbakery.com","kinds":["http","ssl","domain"],"every":"1m"}'

POST /api/v1/sites/detect

Look a site up before adding it

What Pingerer finds for an address (certificate, domain, DNS, email) and the checks it suggests.

curl -X POST https://staging.pingerer.com/api/v1/sites/detect \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"yourbakery.com"}'

GET /api/v1/sites/{id}

A site and its monitors

curl https://staging.pingerer.com/api/v1/sites/yourbakery.com \
  -H "Authorization: Bearer $PINGERER_TOKEN"

PATCH /api/v1/sites/{id}

Rename, pause or resume a site

`paused` pauses or resumes it, like the pause and resume endpoints. PUT works the same, and sending the same body twice changes nothing.

curl -X PATCH https://staging.pingerer.com/api/v1/sites/yourbakery.com \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Your Bakery","paused":false}'

DELETE /api/v1/sites/{id}

Delete a site, its monitors, results and incidents

curl -X DELETE https://staging.pingerer.com/api/v1/sites/yourbakery.com \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/sites/{id}/pause

Pause a site and its monitors

curl -X POST https://staging.pingerer.com/api/v1/sites/yourbakery.com/pause \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/sites/{id}/resume

Resume a site and the monitors pausing it stopped

curl -X POST https://staging.pingerer.com/api/v1/sites/yourbakery.com/resume \
  -H "Authorization: Bearer $PINGERER_TOKEN"

GET /api/v1/sites/{id}/uptime

Uptime of a site's uptime monitors over 24h, 7d, 30d and 90d

curl https://staging.pingerer.com/api/v1/sites/yourbakery.com/uptime \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Monitors

GET /api/v1/monitors

List monitors

curl https://staging.pingerer.com/api/v1/monitors \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/monitors

Add a monitor to a site

`settings` are the kind's (for http: url, http_method, expected_statuses, keyword, keyword_absent, max_response_ms, follow_redirects, headers). A multi-step check (kind steps, paid plans) takes `settings.steps` (up to 10 of name, method, url, headers, body_type none/form/json, body, follow_redirects, assertions [{type, field, value}] and extract [{name, from, field}]) and `secrets`, its secret variables (write-only, always shown masked).

curl -X POST https://staging.pingerer.com/api/v1/monitors \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"site_id":"yourbakery.com","kind":"tcp","name":"Port 22","settings":{"host":"yourbakery.com","port":22}}'

GET /api/v1/monitors/{id}

A monitor

curl https://staging.pingerer.com/api/v1/monitors/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

PATCH /api/v1/monitors/{id}

Change a monitor

Settings given are merged into the current ones. With PUT instead,
they replace them: settings left out go back to their defaults.
`paused` pauses or resumes it. Fields left out stay as they are.

curl -X PATCH https://staging.pingerer.com/api/v1/monitors/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"every":"5m","settings":{"keyword":"Open today"}}'

DELETE /api/v1/monitors/{id}

Delete a monitor and its results

curl -X DELETE https://staging.pingerer.com/api/v1/monitors/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/monitors/{id}/pause

Pause a monitor

curl -X POST https://staging.pingerer.com/api/v1/monitors/mon_8xKq2/pause \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/monitors/{id}/resume

Resume a monitor

A plan with no room for another active monitor answers 422 plan_limit.

curl -X POST https://staging.pingerer.com/api/v1/monitors/mon_8xKq2/resume \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/monitors/{id}/test

Run one check now

Checks once from `region` (default the monitor's first) and returns the result without recording it.

curl -X POST https://staging.pingerer.com/api/v1/monitors/mon_8xKq2/test \
  -H "Authorization: Bearer $PINGERER_TOKEN"

GET /api/v1/monitors/{id}/uptime

Uptime of a monitor over 24h, 7d, 30d and 90d

curl https://staging.pingerer.com/api/v1/monitors/mon_8xKq2/uptime \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Results

GET /api/v1/monitors/{monitor_id}/results

A monitor's check results, newest first

curl https://staging.pingerer.com/api/v1/monitors/mon_8xKq2/results \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Incidents

GET /api/v1/incidents

List incidents, newest first

curl https://staging.pingerer.com/api/v1/incidents \
  -H "Authorization: Bearer $PINGERER_TOKEN"

GET /api/v1/incidents/{id}

An incident and its timeline

curl https://staging.pingerer.com/api/v1/incidents/INC-0042 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/incidents/{id}/acknowledge

Acknowledge an incident

Stops escalation. Any member may acknowledge.

curl -X POST https://staging.pingerer.com/api/v1/incidents/INC-0042/acknowledge \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/incidents/{id}/notes

Add a note to an incident's timeline

curl -X POST https://staging.pingerer.com/api/v1/incidents/INC-0042/notes \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"Restarted the web server"}'

POST /api/v1/incidents/{id}/resolve

Resolve an incident

curl -X POST https://staging.pingerer.com/api/v1/incidents/INC-0042/resolve \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"Fixed by the host"}'

Heartbeats

GET /api/v1/heartbeats

List heartbeats

curl https://staging.pingerer.com/api/v1/heartbeats \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/heartbeats

Add a heartbeat

Your job requests the returned `ping_url` each time it runs. No ping within `every` plus `grace` opens an incident. With `email_pings` (where Pingerer has turned on email heartbeats for the account), an email to `ping_email` counts as a ping too; a subject with "failed" in it reports a failure.

curl -X POST https://staging.pingerer.com/api/v1/heartbeats \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Nightly backup","every":"1d","grace":"30m"}'

GET /api/v1/heartbeats/{id}

A heartbeat

curl https://staging.pingerer.com/api/v1/heartbeats/mon_5hB1 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

PATCH /api/v1/heartbeats/{id}

Change a heartbeat

curl -X PATCH https://staging.pingerer.com/api/v1/heartbeats/mon_5hB1 \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"every":"12h"}'

DELETE /api/v1/heartbeats/{id}

Delete a heartbeat

curl -X DELETE https://staging.pingerer.com/api/v1/heartbeats/mon_5hB1 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Alerts

GET /api/v1/alert_channels

List alert channels and their rules

curl https://staging.pingerer.com/api/v1/alert_channels \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/alert_channels

Add an alert channel

Settings by kind: email `addresses`; slack `webhook_url` and `channel`;
discord and teams `webhook_url`; telegram `chat_id`; webhook `url`
(its signing secret is in this response only); sms `numbers`; push
`user_ids` (members' ids or emails; none means everyone with the
app) and `critical`, once Pingerer's push is set up.
`site_ids` limits it to some sites (default every site), and `events`
to some events (default all); `default_rule: false` adds no rule, for
adding each one with POST /api/v1/alert_rules. Email to an address
that isn't a member's is sent a confirmation link first.

curl -X POST https://staging.pingerer.com/api/v1/alert_channels \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind":"webhook","name":"Ops webhook","url":"https://ops.example.com/pingerer"}'

GET /api/v1/alert_channels/{id}

An alert channel

curl https://staging.pingerer.com/api/v1/alert_channels/ach_3Lm9 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

PATCH /api/v1/alert_channels/{id}

Change an alert channel

Changes `name`, `enabled` and the kind's settings that are sent (the
same as when adding one); the rest stay as they are, so secrets
needn't be sent again. A new destination needs verifying again. The
kind can't change. PUT works the same.

curl -X PATCH https://staging.pingerer.com/api/v1/alert_channels/ach_3Lm9 \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Ops team","enabled":true}'

DELETE /api/v1/alert_channels/{id}

Delete an alert channel

curl -X DELETE https://staging.pingerer.com/api/v1/alert_channels/ach_3Lm9 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

GET /api/v1/alert_rules

List alert rules

Which sites' events go to which channel. A rule with no site covers every site, new ones too.

curl https://staging.pingerer.com/api/v1/alert_rules \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/alert_rules

Send a site's events to a channel

`site_id` (an id or host; leave it out for every site), `events`
(default all) and `escalate_after_minutes` (alert this channel only
if an incident is still unacknowledged that long). A channel has one
rule per site.

curl -X POST https://staging.pingerer.com/api/v1/alert_rules \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"alert_channel_id":"ach_3Lm9","site_id":"yourbakery.com","events":["down","recovered"]}'

GET /api/v1/alert_rules/{id}

An alert rule

curl https://staging.pingerer.com/api/v1/alert_rules/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

PATCH /api/v1/alert_rules/{id}

Change an alert rule

Changes the fields sent (`site_id` null for every site); the channel can't change. PUT works the same.

curl -X PATCH https://staging.pingerer.com/api/v1/alert_rules/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"events":["down"],"escalate_after_minutes":15}'

DELETE /api/v1/alert_rules/{id}

Delete an alert rule

curl -X DELETE https://staging.pingerer.com/api/v1/alert_rules/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Regions

GET /api/v1/regions

Where checks run from

Every region, home first. `meta.max_per_monitor` is how many a
monitor may use on the account's plan (null for all), `meta.default`
the regions a new monitor gets, and `meta.min_interval_seconds` the
plan's shortest interval.

curl https://staging.pingerer.com/api/v1/regions \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Status pages

GET /api/v1/status_pages

List status pages

curl https://staging.pingerer.com/api/v1/status_pages \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/status_pages

Make a status page

Up to the plan's limit. The slug is made from the name unless given.
It isn't public until `published` is true. A `custom_domain` is
verified with the TXT record in `custom_domain_records`, then served
once its CNAME points at us.

curl -X POST https://staging.pingerer.com/api/v1/status_pages \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Your Bakery","slug":"your-bakery","published":true}'

GET /api/v1/status_pages/{id}

A status page, its components and their status now

curl https://staging.pingerer.com/api/v1/status_pages/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

PATCH /api/v1/status_pages/{id}

Change, publish or unpublish a status page

Changes the fields sent; the rest stay as they are. PUT works the same.

curl -X PATCH https://staging.pingerer.com/api/v1/status_pages/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"published":true,"brand_color":"#2F45E8"}'

DELETE /api/v1/status_pages/{id}

Delete a status page, its components, updates and subscribers

curl -X DELETE https://staging.pingerer.com/api/v1/status_pages/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

GET /api/v1/status_pages/{status_page_id}/components

A status page's components, in order

curl https://staging.pingerer.com/api/v1/status_pages/{status_page_id}/components \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/status_pages/{status_page_id}/components

Add a component

A component follows sites (their uptime monitors) and monitors
(a heartbeat, say): `site_ids` takes ids or hosts. It goes last
unless `position` (0 is first) says otherwise.

curl -X POST https://staging.pingerer.com/api/v1/status_pages/{status_page_id}/components \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Online shop","site_ids":["shop.yourbakery.com"]}'

GET /api/v1/status_pages/{status_page_id}/components/{id}

A component

curl https://staging.pingerer.com/api/v1/status_pages/{status_page_id}/components/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

PATCH /api/v1/status_pages/{status_page_id}/components/{id}

Change or move a component

Changes the fields sent; `site_ids` and `monitor_ids` replace what it followed. `position` moves it, and the others move along. PUT works the same.

curl -X PATCH https://staging.pingerer.com/api/v1/status_pages/{status_page_id}/components/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"position":0}'

DELETE /api/v1/status_pages/{status_page_id}/components/{id}

Remove a component

curl -X DELETE https://staging.pingerer.com/api/v1/status_pages/{status_page_id}/components/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

GET /api/v1/status_pages/{status_page_id}/updates

A status page's updates, newest first

curl https://staging.pingerer.com/api/v1/status_pages/{status_page_id}/updates \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/status_pages/{status_page_id}/updates

Post a status update

Posts to the page and emails its confirmed subscribers (when the page
is published). `components` maps a component's name or id to its
impact (an empty string leaves it out). Pass `thread_id` to follow
up on an earlier update: the title and components carry over, and
`resolved` marks them operational. Admins only.

curl -X POST https://staging.pingerer.com/api/v1/status_pages/{status_page_id}/updates \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state":"investigating","title":"Checkout errors","message":"We're looking into it.","components":{"Online shop":"partial_outage"}}'

GET /api/v1/status_pages/{status_page_id}/updates/{id}

A status update

curl https://staging.pingerer.com/api/v1/status_pages/{status_page_id}/updates/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

PATCH /api/v1/status_pages/{status_page_id}/updates/{id}

Change an update's wording, state or components

Doesn't email subscribers again.

curl -X PATCH https://staging.pingerer.com/api/v1/status_pages/{status_page_id}/updates/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Maintenance

GET /api/v1/maintenance_windows

List maintenance windows

Newest first. `state` filters to `upcoming` (scheduled, in progress or repeating), `done` or `cancelled`.

curl https://staging.pingerer.com/api/v1/maintenance_windows \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/maintenance_windows

Schedule maintenance

During the window checks keep running and are stored, but the affected
sites' monitors don't open incidents or send alerts, and the time
doesn't count against uptime. Times without an offset are local to
`time_zone` (the account's by default). `sites` takes ids or hosts;
or set `all_sites`. `recurrence: weekly` repeats on `days` (sun..sat;
the start's day by default) at the same local time.
`notify_subscribers_before` is hours before (default 24; `false` for
no email to status page subscribers).

For a deploy, `duration` (like `15m`) without `starts_at` starts it
now, and without `ends_at` ends it that long after it starts; the
title is then "Maintenance" unless given.

curl -X POST https://staging.pingerer.com/api/v1/maintenance_windows \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Database upgrade","starts_at":"2026-10-14T02:00:00-04:00","ends_at":"2026-10-14T02:30:00-04:00","sites":["shop.yourbakery.com"]}'

GET /api/v1/maintenance_windows/{id}

A maintenance window

curl https://staging.pingerer.com/api/v1/maintenance_windows/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

PATCH /api/v1/maintenance_windows/{id}

Change a maintenance window

Takes the same fields as scheduling one; those left out stay as they are.

curl -X PATCH https://staging.pingerer.com/api/v1/maintenance_windows/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

DELETE /api/v1/maintenance_windows/{id}

Delete a maintenance window

curl -X DELETE https://staging.pingerer.com/api/v1/maintenance_windows/mon_8xKq2 \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/maintenance_windows/{id}/cancel

Cancel a maintenance window

It stays in the list as cancelled and no longer holds anything back.

curl -X POST https://staging.pingerer.com/api/v1/maintenance_windows/mon_8xKq2/cancel \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/maintenance_windows/{id}/end

End a maintenance window now

One in progress ends now (a weekly one also stops repeating), so its
history stays; one that hasn't started is cancelled; one that's over
is left as it is. Safe to call twice.

curl -X POST https://staging.pingerer.com/api/v1/maintenance_windows/mon_8xKq2/end \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Reports

GET /api/v1/reports/{month}

A month's report

Overall uptime (every uptime monitor's checks together, so busier
monitors weigh more), incidents, downtime, average response, a row
per site and heartbeat against the account's SLA target, and what's
worth fixing. Maintenance windows don't count. The month in progress
is reported so far; a month that hasn't started is a bad request.

curl https://staging.pingerer.com/api/v1/reports/{month} \
  -H "Authorization: Bearer $PINGERER_TOKEN"

Clients

GET /api/v1/clients

List an agency's client workspaces

The account must be an agency (the Agency plan). Each client has its
own sites, alerts, status pages and reports, and shares the agency's
monitor pool. To work inside a client, pass its id in the
Pingerer-Account header.

curl https://staging.pingerer.com/api/v1/clients \
  -H "Authorization: Bearer $PINGERER_TOKEN"

POST /api/v1/clients

Add a client workspace

Agency admins only. The agency's members can open it; invite the client's own people from the Clients page.

curl -X POST https://staging.pingerer.com/api/v1/clients \
  -H "Authorization: Bearer $PINGERER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Your Bakery"}'

Questions about the API? Contact us and a person will reply.