API Overview
Authentication, abilities, pagination, errors and rate limits.
The Pingi REST API lets you manage monitors and read their results from your own tools, scripts and CI pipelines. Everything the API does goes through the same rules as the dashboard: your role, your plan's limits and the same URL safety checks.
The full endpoint reference, with request and response schemas, is the interactive API reference.
Base URL and versioning
All endpoints live under /api/v1, for example https://pingi.io/api/v1/monitors.
Breaking changes only ever ship under a new version prefix.
Authentication
Create a personal API token under Workspace → API in the dashboard and send it as a bearer token:
curl https://pingi.io/api/v1/monitors \
-H "Authorization: Bearer pingi_…" \
-H "Accept: application/json"
A token belongs to one workspace and acts as the member who created it. It can
never do more than that member's current role allows. GET /api/v1/token
tells you which workspace a token acts in and which abilities it has.
See API Tokens for the full token lifecycle.
Abilities
Each endpoint needs one ability on the token:
| Ability | Allows |
|---|---|
monitors:read |
List and read monitors, their checks and statistics, and the list of regions |
monitors:write |
Create, update, pause, resume and delete monitors |
incidents:read |
List incidents and read their timeline |
incidents:write |
Acknowledge incidents, change their status and add notes |
status-pages:read |
List and read status pages |
status-pages:write |
Create, update and delete status pages, and choose their monitors |
notification-channels:read |
List and read notification channels (never their credentials) |
notification-channels:write |
Create, update and delete notification channels |
webhooks:read |
List and read webhooks (owners and admins only) |
webhooks:write |
Create, update and delete webhooks and rotate their signing secret (owners and admins only) |
A request with a valid token but without the ability gets 403 Forbidden.
Requests and responses
- Send JSON bodies with
Content-Type: application/json. - Single records are wrapped in
data; lists addlinksandmetafor pagination. - Timestamps are ISO 8601 in UTC.
- Use the
idvalues returned by the API: ULID strings for monitors, numbers for incidents, status pages and notification channels. A status page'sidstays the same when itsslug(public address) changes. PATCHupdates are partial: fields you leave out keep their current value.- Notification channel credentials (
config) are write-only. Responses show a safedestinationsummary instead, and on update any config key you leave out keeps its stored value — so secrets never need to be sent again. - Status page logos, favicons and custom domains are managed in the dashboard.
Pagination
Monitor lists use pages: ?page=2&per_page=50 (at most 100 per page). The
meta object has current_page, last_page and total.
Check results use a cursor, because new checks arrive all the time: pass the
meta.next_cursor value back as ?cursor=… until it is null.
Errors
Errors always come back as JSON with a message:
| Status | Meaning |
|---|---|
401 |
Missing, invalid, expired or revoked token |
403 |
The token lacks the ability, or your plan's limit is reached (the message says which) |
404 |
No such record in the token's workspace — records of other workspaces are never visible |
422 |
Validation failed; errors lists the messages per field |
429 |
Rate limit exceeded; wait Retry-After seconds |
{
"message": "The url field is required.",
"errors": { "url": ["The url field is required."] }
}
Rate limits
Limits apply per token, per minute, and depend on your plan (see
Workspace → Billing). Every response includes X-RateLimit-Limit and
X-RateLimit-Remaining.
Example: add a monitor
curl -X POST https://pingi.io/api/v1/monitors \
-H "Authorization: Bearer pingi_…" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/health", "check_interval_seconds": 300}'
Only url is required. The response is the new monitor with status pending;
its first check runs shortly afterwards. Addresses on private or internal
networks are rejected.