Uptime API
Monitor service health with heartbeats, monitors, and incidents.
All uptime endpoints live under /v1/projects/:projectId. Monitoring is heartbeat-based: your service signals “I am alive” on an interval, and Vanta marks the monitor down when a heartbeat does not arrive in time.
Monitors
A monitor is a named target with an expected interval and a grace period. The default expected interval is 60 seconds and the default grace period is 30 seconds. A service that has never sent a heartbeat reports an unknown status; after the deadline passes without a heartbeat it reports down. Monitors can also be paused. Statuses are up, down, unknown, and paused.
Monitor types
| Type | Description |
|---|---|
heartbeat | General purpose heartbeat monitor. Default. |
worker | Background worker process. |
bot | Discord or other bot. |
cron | Scheduled job. |
http | HTTP endpoint. Still heartbeat-based; no real HTTP probing. |
custom | Anything else. |
The type is descriptive only; every type is monitored through heartbeats.
Create a monitor
POST /v1/projects/:projectId/monitors{
"name": "Discord bot",
"type": "bot",
"expectedIntervalMs": 30000,
"gracePeriodMs": 10000,
"tags": { "region": "us-east" }
}Request fields:
| Field | Type | Description |
|---|---|---|
name | string | Monitor name. Required. |
type | string | One of heartbeat, http, worker, bot, cron, or custom. Defaults to heartbeat. |
expectedIntervalMs | number | Expected interval between heartbeats. Defaults to 60000. |
gracePeriodMs | number | Late allowance after the interval. Defaults to 30000. |
metadata | object | Optional call metadata. |
tags | object | Optional key/value tags. |
Response:
{
"data": {
"id": "m_9f2c...",
"name": "Discord bot",
"type": "bot",
"status": "unknown",
"expectedIntervalMs": 30000,
"gracePeriodMs": 10000
}
}List monitors
GET /v1/projects/:projectId/monitorsReturns every monitor for the project with its current status.
Response:
{
"data": [
{
"id": "m_9f2c...",
"name": "Discord bot",
"type": "bot",
"status": "up",
"expectedIntervalMs": 30000,
"gracePeriodMs": 10000,
"timeUp": 18522000
}
]
}Monitor overview
GET /v1/projects/:projectId/monitors/overviewReturns a compact overview for every monitor, including current status and latest heartbeat, sized for status panels and dashboards.
Get a monitor
GET /v1/projects/:projectId/monitors/:monitorIdReturns a single monitor by id. Returns 404 if it does not exist.
Monitor status
GET /v1/projects/:projectId/monitors/:monitorId/statusReturns just the current status of one monitor, one of up, down, unknown, or paused.
History
GET /v1/projects/:projectId/monitors/:monitorId/history?window=7dReturns the status history of a monitor across a window. Valid windows are 24h, 7d, 30d, and 90d (default 90d).
Update a monitor
PATCH /v1/projects/:projectId/monitors/:monitorIdUpdates fields such as name, expectedIntervalMs, and gracePeriodMs. Only the fields present in the body change.
{
"expectedIntervalMs": 60000
}Delete a monitor
DELETE /v1/projects/:projectId/monitors/:monitorIdDeletes the monitor and its data. Returns 404 if it does not exist.
Send a heartbeat
POST /v1/projects/:projectId/heartbeats/:monitorSlugSends a heartbeat for the monitor identified by its slug. If the monitor does not exist yet, it is created on demand as a heartbeat monitor. A heartbeat marks the monitor up, and a recovering heartbeat after downtime resolves the active incident.
{
"metadata": { "shard": "2", "guilds": 150 }
}expectedIntervalMs and gracePeriodMs can be passed in the body to create, or update, the monitor with those settings.
Response:
{
"data": {
"accepted": true,
"monitor": {
"id": "m_9f2c...",
"name": "Discord bot",
"type": "heartbeat",
"status": "up",
"lastHeartbeatAt": "2026-08-24T10:32:01.000Z"
},
"statusChanged": false
}
}Heartbeat history
GET /v1/projects/:projectId/monitors/:monitorId/heartbeatsReturns the heartbeat history for a monitor, optionally bounded with from and to ISO timestamps.
Response:
{
"data": [
{
"id": "h_1a2b...",
"at": "2026-08-24T10:32:01.000Z",
"metadata": { "shard": "2" }
}
]
}Incidents
GET /v1/projects/:projectId/monitors/:monitorId/incidentsAn incident is created automatically when a monitor goes down and resolved when a heartbeat arrives and brings the monitor back up. This endpoint lists incidents for a single monitor.
Response:
{
"data": [
{
"id": "i_3c4d...",
"monitorId": "m_9f2c...",
"status": "resolved",
"startedAt": "2026-08-24T09:50:00.000Z",
"endedAt": "2026-08-24T10:32:01.000Z",
"durationMs": 2521000,
"title": "Database connection pool exhausted",
"description": "Read replicas fell behind and the API returned 503s for about 40 minutes."
}
]
}Update an incident
PATCH /v1/projects/:projectId/incidents/:incidentIdSet a title and description on an incident to record what actually happened. Both fields are optional but at least one is required; a field set to an empty string is cleared. Returns the updated incident.
{
"title": "Database connection pool exhausted",
"description": "Connection pool drained under load; recovered after a failover."
}Statistics
GET /v1/projects/:projectId/monitors/:monitorId/stats?period=7dReturns uptime statistics for one monitor over a period such as 7d or 24h. The period format is a number followed by d or h. You can also pass from and to ISO timestamps instead of a period.
Response:
{
"data": {
"uptimePercentage": 99.94,
"downtimeMs": 52000,
"incidentCount": 2,
"currentStatus": "up",
"lastHeartbeat": "2026-08-24T10:32:01.000Z",
"totalHeartbeats": 51240,
"successfulHeartbeats": 51240,
"failedHeartbeats": 0,
"avgLatencyMs": 82.5,
"minLatencyMs": 14,
"maxLatencyMs": 410
}
}uptimePercentage, downtimeMs, and incidentCount are derived from incidents. The heartbeat fields (totalHeartbeats, successfulHeartbeats, failedHeartbeats, and the latency stats) are summed from raw heartbeats for recent windows and from pre-aggregated hourly rollups for older windows. Latency stats are null when no heartbeat carried a latency value.