Stats API
Stats provide aggregated uptime and performance data for your monitors. Sentro rolls up individual check results into daily statistics, giving you a clear picture of reliability over time without needing to process thousands of raw checks.
The current day is always included. Because the nightly rollup only covers completed days, today's figures are computed from raw checks on request — so an outage happening right now is reflected immediately rather than appearing tomorrow.
Daily Stat Object
{
"date": "2025-01-15",
"totalChecks": 1440,
"successfulChecks": 1436,
"uptimePercentage": 99.72,
"avgLatencyMs": 187,
"minLatencyMs": 94,
"maxLatencyMs": 1203
}
| Field | Type | Description |
|---|---|---|
date | string | Date in YYYY-MM-DD format (UTC) |
totalChecks | number | Total number of checks performed on this day |
successfulChecks | number | Number of checks that succeeded |
uptimePercentage | number | Percentage of successful checks for the day (0-100) |
avgLatencyMs | number | Average response time in milliseconds for the day |
minLatencyMs | number | Fastest response of the day, in milliseconds |
maxLatencyMs | number | Slowest response of the day, in milliseconds |
List Monitor Stats
GET /v1/monitors/:monitorId/stats
Returns daily statistics for a specific monitor, ordered by most recent date first, together with a summary across the whole period. Each record represents one day of check data.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
monitorId | string | The monitor ID |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
from | string | 30 days ago | Start date filter (ISO 8601, e.g. 2025-01-01) |
to | string | now | End date filter (ISO 8601, e.g. 2025-01-31) |
limit | number | 90 | Number of days to return (max 365) |
Example Request
curl "https://api.sentro.dev/v1/monitors/cly1abc2d0001abcdef012345/stats?from=2025-01-01&to=2025-01-31&limit=31" \
-H "Authorization: Bearer sentro_sk_live_your_key_here"
Response 200 OK
{
"data": {
"monitorId": "cly1abc2d0001abcdef012345",
"summary": {
"uptimePercentage": 99.07,
"avgLatencyMs": 220,
"totalChecks": 4320,
"successfulChecks": 4280,
"daysWithData": 3
},
"daily": [
{
"date": "2025-01-15",
"totalChecks": 1440,
"successfulChecks": 1436,
"uptimePercentage": 99.72,
"avgLatencyMs": 187,
"minLatencyMs": 94,
"maxLatencyMs": 1203
},
{
"date": "2025-01-14",
"totalChecks": 1440,
"successfulChecks": 1440,
"uptimePercentage": 100.0,
"avgLatencyMs": 162,
"minLatencyMs": 88,
"maxLatencyMs": 402
},
{
"date": "2025-01-13",
"totalChecks": 1440,
"successfulChecks": 1404,
"uptimePercentage": 97.5,
"avgLatencyMs": 312,
"minLatencyMs": 91,
"maxLatencyMs": 4008
}
]
}
}
Summary Object
The summary field provides aggregate metrics across the whole requested period.
| Field | Type | Description |
|---|---|---|
uptimePercentage | number | null | Share of all checks in the period that succeeded |
avgLatencyMs | number | null | Average response time in milliseconds across the days with data |
totalChecks | number | Total check count across the period |
successfulChecks | number | Successful check count across the period |
daysWithData | number | Number of days that recorded at least one check |
When a monitor recorded no checks in the requested period, uptimePercentage and avgLatencyMs
are null and daily is empty. A monitor that was never checked is never reported as 100% up —
treat null as "not measured" rather than substituting a value.
Errors
Monitor not found:
{
"error": {
"code": "NOT_FOUND",
"message": "Monitor with id 'mon_invalid' not found"
}
}
Invalid date range:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Parameter 'from' must be a valid ISO 8601 date"
}
}
Fetch daily uptime and performance stats for a specific monitor.
/v1/monitors/:monitorId/stats?limit=90Get Organization Overview
GET /v1/stats/overview
Returns a high-level summary of your organization's current resource counts. Useful for building dashboards, health widgets, and at-a-glance status indicators.
Example Request
curl "https://api.sentro.dev/v1/stats/overview" \
-H "Authorization: Bearer sentro_sk_live_your_key_here"
Response 200 OK
{
"data": {
"monitors": {
"total": 24,
"active": 21,
"paused": 3
},
"incidents": {
"total": 147,
"open": 2,
"resolved": 145
},
"alertChannels": 5,
"heartbeats": 8,
"statusPages": 2
}
}
Overview Fields
| Field | Type | Description |
|---|---|---|
monitors.total | number | Total number of monitors in the organization |
monitors.active | number | Number of monitors currently active and checking |
monitors.paused | number | Number of monitors that are paused |
incidents.total | number | Total number of incidents ever recorded |
incidents.open | number | Number of currently unresolved incidents |
incidents.resolved | number | Number of resolved incidents |
alertChannels | number | Total configured alert channels |
heartbeats | number | Total heartbeat monitors |
statusPages | number | Total public status pages |
Get organization-level overview counts for monitors, incidents, and more.
/v1/stats/overviewLimiting the Period
Use from, to, and limit to control the window. There is no offset — a single request covers
the whole period you ask for, up to 365 days.
# Last 7 days
GET /v1/monitors/:id/stats?limit=7
# A specific calendar month
GET /v1/monitors/:id/stats?from=2025-01-01&to=2025-01-31
Days on which the monitor recorded no checks are omitted from daily, so daily.length may be
smaller than limit. Use summary.daysWithData to see how many days actually held data.
Common Patterns
Calculate Monthly Uptime
Retrieve stats for a full calendar month and use the summary:
curl "https://api.sentro.dev/v1/monitors/mon_123/stats?from=2025-01-01&to=2025-01-31&limit=31" \
-H "Authorization: Bearer sentro_sk_live_your_key_here"
const response = await fetch(
'https://api.sentro.dev/v1/monitors/mon_123/stats?from=2025-01-01&to=2025-01-31&limit=31',
{ headers: { Authorization: `Bearer ${API_KEY}` } },
);
const { data } = await response.json();
if (data.summary.uptimePercentage === null) {
console.log('January: no checks recorded');
} else {
console.log(`January uptime: ${data.summary.uptimePercentage.toFixed(2)}%`);
console.log(`Average latency: ${data.summary.avgLatencyMs}ms`);
console.log(`Total checks: ${data.summary.totalChecks}`);
}
Compare Performance Over Time
Fetch stats for two different periods and compare:
async function fetchStats(monitorId, from, to) {
const res = await fetch(
`https://api.sentro.dev/v1/monitors/${monitorId}/stats?from=${from}&to=${to}&limit=365`,
{ headers: { Authorization: `Bearer ${API_KEY}` } },
);
const { data } = await res.json();
return data;
}
const thisMonth = await fetchStats('mon_123', '2025-01-01', '2025-01-31');
const lastMonth = await fetchStats('mon_123', '2024-12-01', '2024-12-31');
// Only compare periods that both have data
if (thisMonth.summary.uptimePercentage !== null && lastMonth.summary.uptimePercentage !== null) {
const latencyDelta = thisMonth.summary.avgLatencyMs - lastMonth.summary.avgLatencyMs;
const uptimeDelta = thisMonth.summary.uptimePercentage - lastMonth.summary.uptimePercentage;
console.log(`Latency change: ${latencyDelta > 0 ? '+' : ''}${latencyDelta}ms`);
console.log(`Uptime change: ${uptimeDelta > 0 ? '+' : ''}${uptimeDelta.toFixed(2)}%`);
}
Build a Dashboard Summary
Combine the overview endpoint with per-monitor stats:
// Fetch organization overview
const overviewRes = await fetch('https://api.sentro.dev/v1/stats/overview', {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const { data: overview } = await overviewRes.json();
console.log(`Monitors: ${overview.monitors.active} active / ${overview.monitors.total} total`);
console.log(`Open incidents: ${overview.incidents.open}`);
console.log(`Alert channels: ${overview.alertChannels}`);
console.log(`Status pages: ${overview.statusPages}`);
// Fetch last 7 days of stats for a specific monitor
const statsRes = await fetch('https://api.sentro.dev/v1/monitors/mon_123/stats?limit=7', {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const { data } = await statsRes.json();
console.log(`\n7-day uptime: ${data.summary.uptimePercentage ?? 'not measured'}`);
console.log(`7-day avg latency: ${data.summary.avgLatencyMs ?? 'not measured'}`);
Detect Performance Degradation
Find days where response time or uptime crossed a threshold:
const { data } = await fetch(
'https://api.sentro.dev/v1/monitors/mon_123/stats?from=2025-01-01&to=2025-01-31&limit=31',
{ headers: { Authorization: `Bearer ${API_KEY}` } },
).then((r) => r.json());
const LATENCY_THRESHOLD_MS = 500;
const UPTIME_THRESHOLD = 99.5;
const slowDays = data.daily.filter((day) => day.avgLatencyMs > LATENCY_THRESHOLD_MS);
const degradedDays = data.daily.filter((day) => day.uptimePercentage < UPTIME_THRESHOLD);
if (slowDays.length > 0) {
console.log(`${slowDays.length} day(s) with avg latency above ${LATENCY_THRESHOLD_MS}ms:`);
slowDays.forEach((day) => console.log(` ${day.date}: ${day.avgLatencyMs}ms`));
}
if (degradedDays.length > 0) {
console.log(`${degradedDays.length} day(s) below ${UPTIME_THRESHOLD}% uptime:`);
degradedDays.forEach((day) => console.log(` ${day.date}: ${day.uptimePercentage}%`));
}
Generate an SLA Report
Calculate SLA compliance for a given period. A period with no checks is not compliance — it is an absence of evidence, so handle it separately rather than treating it as a pass:
const SLA_TARGET = 99.9;
const { data } = await fetch(
'https://api.sentro.dev/v1/monitors/mon_123/stats?from=2025-01-01&to=2025-01-31&limit=31',
{ headers: { Authorization: `Bearer ${API_KEY}` } },
).then((r) => r.json());
if (data.summary.uptimePercentage === null) {
console.log('No checks recorded for this period — SLA cannot be assessed.');
} else {
const slaBreaches = data.daily.filter((day) => day.uptimePercentage < SLA_TARGET);
const compliant = data.summary.uptimePercentage >= SLA_TARGET;
console.log(`SLA target: ${SLA_TARGET}%`);
console.log(`Actual uptime: ${data.summary.uptimePercentage.toFixed(3)}%`);
console.log(`Status: ${compliant ? 'COMPLIANT' : 'BREACHED'}`);
console.log(`Days in violation: ${slaBreaches.length} / ${data.summary.daysWithData}`);
}