Group monthly summary
Read one client group's month as JSON: uptime, outages with their cause, certificate and domain expiry, and DNS, hosting and content changes, with every field explained.
Last reviewed
On this page
The monthly summary returns one group's month in a single request: totals for the group and one entry for each site in it. It is the same data as the monthly summary email, limited to the sites in the group, so the figures match what you send a client. Use it to build a client report from your own code. Any key can call it, a read key included.
Request
GEThttps://octoping.com/api/groups/{group_id}/monthly-summary
Get a group's monthly summary
Access needed: Read only
Returns the group's totals and one entry per site: uptime and average response time, every outage with its start, end, length and cause, the latest known certificate and domain expiry, and the DNS, hosting and content changes found in the month. It is the same data as the monthly summary email, limited to the sites in the group. A read key gets a site's address without any user name and password written into it, so https://user:pass@example.com/ is returned as https://example.com/. The rest of the address, including its query string, is returned as stored, and a read and write key or an admin key gets the whole address. month is a calendar month in UTC written YYYY-MM and defaults to the last complete month. A month that has not started, or a value that is not a month, is refused with 422. The month in progress is allowed and reports what has been recorded so far. Each list holds the newest 50 entries and the true number is given beside it (outage_count, dns_change_count, hosting_change_count and content_change_count). A site with nothing recorded in the month reports null instead of zero. days_left on the certificate and the domain is counted from generated_at. data_truncated is true when the start of the month has been deleted under the plan's data retention, so the figures are a minimum. It is false for a site added during the month, and for a site that still has checks from before the month. The answer is reused for a few minutes, and for an hour once the month is over, and generated_at says when it was computed. Only one summary is prepared at a time for a workspace. A request that needs a fresh one while another is being prepared is refused with 429, the code summary_in_progress and a Retry-After header. Wait that many seconds and ask again. Renaming the group does not make the figures stale.
group_id(path, string, required)month(query, string, optional)
Find the group's id with the list groups operation in the API reference. A group that isn't in your workspace answers 404.
export GROUP_ID="the group's id"
curl -fsS -H "X-API-Key: $OCTOPING_API_KEY" "https://octoping.com/api/groups/$GROUP_ID/monthly-summary?month=2026-10"To print one line for each site, pipe the answer to jq.
curl -fsS -H "X-API-Key: $OCTOPING_API_KEY" "https://octoping.com/api/groups/$GROUP_ID/monthly-summary?month=2026-10" \
| jq -r '.sites[] | [.url, .uptime_percentage, .outage_count] | @tsv'Response
The answer is JSON with these keys. A trimmed example follows the tables.
| Key | Type | Meaning |
|---|---|---|
group | object | The group: its id and name. |
month | string | The month the summary covers, as YYYY-MM. |
period | object | start is the first instant of the month and end the first instant of the next, both in UTC. The start is included and the end isn't. |
generated_at | string | When OctoPing computed the answer. See How current the answer is below. |
totals | object | Figures for the whole group. |
sites | list | One entry for each site in the group, ordered by URL. |
totals
| Key | Type | Meaning |
|---|---|---|
sites | whole number | The number of sites in the group. |
uptime_percentage | number or null | The mean of the sites' uptime, so each site weighs the same. A site with no counted checks is left out. It is the figure the monthly summary email shows. |
outages | whole number or null | The outages across all sites. Null when no site has anything recorded in the month. |
downtime_seconds | number or null | The time the sites were down, in seconds. Null when no site has anything recorded. |
average_response_time_ms | number or null | The mean of the sites' average response times, in milliseconds. |
content_changes | whole number | The page content changes found across all sites. |
dns_changes | whole number | The DNS changes found across all sites. |
hosting_changes | whole number | The hosting changes found across all sites. |
data_truncated | true or false | True when any site's is. See the field of the same name in each site. |
Each entry in sites
| Key | Type | Meaning |
|---|---|---|
id, url | string | The site's id and URL. A read key gets a site's address without any user name and password written into it. |
name | string | The site's URL again. A site has no separate name. |
uptime_percentage, average_response_time_ms | number or null | The site's uptime and average response time for the month. |
outage_count, downtime_seconds | number or null | How many outages the site had and how long it was down, in seconds. |
outages | list | The site's outages. See the next table. |
ssl | object or null | The latest known certificate: expires_at, days_left and issuer. Null until a certificate check has run. |
domain | object or null | The latest known domain registration: expires_at, days_left and registrar. Null until a domain check has run. |
dns_change_count, hosting_change_count, content_change_count | whole number | The true number of changes of each kind found in the month. |
dns_changes, hosting_changes | list | The changes, each with detected_at and a short summary. |
content_changes | list | The content changes, each with detected_at. |
data_truncated | true or false | True when the plan's data retention has already deleted the start of the month for this site, so the outages, downtime and counts are a minimum. It is false for a site added during the month, and for a site that still has checks from before the month. |
Each outage
| Key | Type | Meaning |
|---|---|---|
started_at | string | When the outage began. It is the start of the month if the outage began earlier. |
ended_at | string or null | When the site recovered. Null when it hadn't recovered by the end of the month, or by now for a month in progress. |
duration_seconds | number | The length of the outage inside the month. When outages holds as many entries as outage_count, the durations add up to downtime_seconds. |
reason | object or null | Why the outage began, as a stable code and a readable label. The codes are timeout, dns, connection, tls, blocked, http_client, http_server, unknown, as the failure reasons page describes. |
{
"group": {
"id": "00000000-0000-0000-0000-000000000000",
"name": "Acme Corp"
},
"month": "2026-10",
"period": {
"start": "2026-10-01T00:00:00Z",
"end": "2026-11-01T00:00:00Z"
},
"generated_at": "2026-11-02T08:15:00Z",
"totals": {
"sites": 2,
"uptime_percentage": 99.84,
"outages": 1,
"downtime_seconds": 2760,
"average_response_time_ms": 412.5,
"content_changes": 3,
"dns_changes": 0,
"hosting_changes": 0,
"data_truncated": false
},
"sites": [
{
"id": "00000000-0000-0000-0000-000000000001",
"name": "https://acme.example",
"url": "https://acme.example",
"uptime_percentage": 99.68,
"average_response_time_ms": 388.2,
"outage_count": 1,
"downtime_seconds": 2760,
"outages": [
{
"started_at": "2026-10-14T02:10:00Z",
"ended_at": "2026-10-14T02:56:00Z",
"duration_seconds": 2760,
"reason": {
"code": "http_server",
"label": "Service Unavailable (HTTP 503)"
}
}
],
"ssl": {
"expires_at": "2027-01-09T23:59:59Z",
"days_left": 68,
"issuer": "Let's Encrypt"
},
"domain": {
"expires_at": "2027-06-30T00:00:00Z",
"days_left": 240,
"registrar": "Example Registrar"
},
"dns_change_count": 0,
"dns_changes": [],
"hosting_change_count": 0,
"hosting_changes": [],
"content_change_count": 3,
"content_changes": [
{
"detected_at": "2026-10-22T09:30:00Z"
},
{
"detected_at": "2026-10-12T14:05:00Z"
},
{
"detected_at": "2026-10-03T08:00:00Z"
}
],
"data_truncated": false
}
]
}Null means no data
A site with nothing recorded in the month reports null for uptime_percentage, average_response_time_ms, outage_count and downtime_seconds. Zero outages means the site was checked and stayed up. Null means the month holds nothing to report. In the same way, totals.outages and totals.downtime_seconds are null when no site has anything recorded, so an empty month never reads as a clean one.
Lists are capped
Each list in a site's entry holds the newest 50 entries, newest first, and the true number sits beside it in outage_count, dns_change_count, hosting_change_count and content_change_count. A list that is shorter than its count is a cut list, and the count is the number to report.
Certificate and domain expiry
The certificate and domain expiry are the latest known values and are not limited to the month the summary covers. days_left is counted from generated_at to expires_at in whole days, and it is negative once the certificate or registration has expired.
How current the answer is
OctoPing reuses an answer for 5 minutes, or 60 minutes once the month is over. A change to the group's sites, such as a site moved in or out or a site's URL, gets a fresh answer. A new group name shows at once, because the name isn't part of the reused figures. generated_at says when the figures were computed, so polling faster than that returns the same numbers and spends requests from the workspace's limits.
When another summary is being prepared
Computing a month of checks takes a moment, so OctoPing prepares one summary at a time for each workspace. A request that needs a fresh one while another is being prepared is refused with HTTP 429, the code summary_in_progress and a Retry-After header. Wait that many seconds and ask again. A request that finds an answer it can reuse is never refused for this reason. The refused request counts against the workspace's limits, so don't retry in a tight loop. The API keys page lists the codes that requests made with a key are refused with.
Related
- DocsAPI overviewHow the OctoPing API works: the endpoints that need no key, the operations that take an API key, how to authenticate, a first request, the limits and the errors.
- DocsAPI keysCreate an API key, choose what it can do, send it in the X-API-Key header, and read about its limits, error codes, rotation, revocation and what happens when people change roles or a workspace pauses.
- DocsAPI referenceEvery operation an API key can call: sites and their checks, heartbeats, groups, maintenance windows, status pages and incidents, with the access each one needs and the fields to send.
- DocsUptime, downtime and outagesHow uptime percentage, downtime and outage counts are computed, why they don't add up to each other and how maintenance and probe results change them.
- DocsFailure reasonsThe stable failure codes OctoPing assigns to a failed check, their labels and the order in which a failure is classified.
- DocsContactsAdd your clients to a status page so they get every alert for its sites and a monthly summary: consent, what is sent, when and how a contact leaves.