API
No key, no rate limit on reads, Access-Control-Allow-Origin: * on every /api/v1 response. Responses carry an ETag and Cache-Control: max-age=30 — send If-None-Match and you will get 304s.
Endpoints
| Method | Path | What it returns |
|---|---|---|
| GET | /api/v1/summary | Overall indicator, every component with its 30/60/90-day uptime, active incidents, current and upcoming maintenance. One call, everything the home page shows. |
| GET | /api/v1/components | The component list on its own. |
| GET | /api/v1/components/{id}/uptime?days=30|60|90 | Daily cells: status, uptime %, downtime and maintenance seconds, linked incident slugs. |
| GET | /api/v1/components/{id}/latency?hours=24|168 | Hourly p50/p95 in ms, aggregated across the probes behind the component. Empty for components with no latency-bearing checks. |
| GET | /api/v1/incidents?status=active|resolved&impact=&page= | Public incidents, newest first, with the full update timeline. |
| GET | /api/v1/incidents/{slug} | One incident by permalink slug. |
| GET | /api/v1/maintenances?status=scheduled|in_progress|completed | Maintenance windows with their affected components. |
| GET | /badge/status.svg · /badge/{component}.svg | SVG badge, ?style=flat|flat-square|plastic and ?label=. |
| GET | /feed.atom · /feed.rss · /maintenance.ics · /status.txt | Pull formats. ?kind=incidents|maintenance narrows the feeds. |
Example
curl -s https://status.planifypro.com/api/v1/summary | jq '.status'
{
"indicator": "none",
"description": "All Systems Operational"
}What this API will never contain
Monitor names, target URLs, hostnames, cloud resource identifiers, check messages and assertion detail stay on the operator side. A component's status is folded from probes whose existence is not public, so the API can tell you that PDF export is degraded but never which probe said so. That boundary is a single allowlist serializer with a test that greps every response.