Skip to content

Status pages ​

Public status pages and what they show.

Common tasks

Only in the app: Creating a status page, its custom domain and its look.

How it works in the app: help article.

Scopes: Read with monitoring.read, change with monitoring.write. See Tokens and scopes.

Every endpoint below takes a token in the Authorization: Bearer header and answers JSON. Errors use the shared format in Errors. Base address: https://api.infranest.io/api.

Status pages ​

List status pages ​

Every status page in your organization with its component and subscriber counts, how many components are operational or degraded, which are down, and the page’s 90-day uptime.

GET/organizations/{organization}/status-pages
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
[
  {
    "id": 1,
    "organization_id": 1,
    "name": "Northwind Cloud Status",
    "slug": "northwind",
    "custom_domain": "status.northwind.example",
    "is_public": true,
    "password_hash": null,
    "description": "Live status of Northwind Cloud services.",
    "logo_url": null,
    "show_incident_history": true,
    "show_uptime_percentage": true,
    "subscriber_notifications_enabled": true,
    "theme": "light",
    "created_at": "2026-01-15T12:00:00.000000Z",
    "updated_at": "2026-01-15T12:00:00.000000Z",
    "overall_status": "major_outage",
    "custom_domain_status": "pending",
    "allow_indexing": true,
    "show_group_labels": true,
    "footer_text": null,
    "footer_url": null,
    "show_tags": false,
    "show_badge_branding": true,
    "edge_published": false,
    "deleted_at": null,
    "purge_after": null,
    "purge_reminder_sent_at": null,
    "deleted_by_id": null,
    "deleted_by_label": null,
    "deletion_reason": null,
    "header_image_url": null,
    "density": "comfortable",
    "history_days": 90,
    "show_aggregate_bar": true,
    "show_maintenance": true,
    "show_third_party": true,
    "template": "default",
    "on_call_note": "Primary: Sam Okoye · +31 6 12 34 56 78 · #northwind-oncall on Slack. Escalation after 15m: Alex Rivera.",
    "header_style": "band",
    "accent_color": null,
    "header_gradient": true,
    "links": null,
    "subscriber_reply_to": null,
    "meta_title": null,
    "show_name_with_logo": true,
    "custom_domain_pending_since": null,
    "components_count": 8,
    "subscribers_count": 3,
    "components_up": 6,
    "down_components": [
      "Checkout & payments"
    ],
    "degraded_count": 1,
    "uptime_90d": 100,
    "edge_publish_eligible": false
  }
]
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get a status page ​

One status page with its settings, its components with the monitor and group behind each, and counts of components, announcements and subscribers.

GET/organizations/{organization}/status-pages/{statusPage}
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "organization_id": 1,
  "name": "Northwind Cloud Status",
  "slug": "northwind",
  "custom_domain": "status.northwind.example",
  "is_public": true,
  "password_hash": null,
  "description": "Live status of Northwind Cloud services.",
  "logo_url": null,
  "show_incident_history": true,
  "show_uptime_percentage": true,
  "subscriber_notifications_enabled": true,
  "theme": "light",
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "overall_status": "major_outage",
  "custom_domain_status": "pending",
  "allow_indexing": true,
  "show_group_labels": true,
  "footer_text": null,
  "footer_url": null,
  "show_tags": false,
  "show_badge_branding": true,
  "edge_published": false,
  "deleted_at": null,
  "purge_after": null,
  "purge_reminder_sent_at": null,
  "deleted_by_id": null,
  "deleted_by_label": null,
  "deletion_reason": null,
  "header_image_url": null,
  "density": "comfortable",
  "history_days": 90,
  "show_aggregate_bar": true,
  "show_maintenance": true,
  "show_third_party": true,
  "template": "default",
  "on_call_note": "Primary: Sam Okoye · +31 6 12 34 56 78 · #northwind-oncall on Slack. Escalation after 15m: Alex Rivera.",
  "header_style": "band",
  "accent_color": null,
  "header_gradient": true,
  "links": null,
  "subscriber_reply_to": null,
  "meta_title": null,
  "show_name_with_logo": true,
  "custom_domain_pending_since": null,
  "components_count": 8,
  "announcements_count": 2,
  "subscribers_count": 3,
  "edge_publish_eligible": false,
  "components": [
    {
      "id": 1,
      "status_page_id": 1,
      "monitoring_check_id": 1,
      "display_name": "Website",
      "sort_order": 0,
      "status": "operational",
      "status_override": false,
      "show_uptime_bar": true,
      "created_at": "2026-01-15T12:00:00.000000Z",
      "updated_at": "2026-01-15T12:00:00.000000Z",
      "runbook_url": null,
      "status_page_component_group_id": 1,
      "description": null,
      "affects_overall_status": true,
      "group_name": "Public",
      "monitoring_check": {
        "id": 1,
        "name": "Marketing site",
        "type": "http",
        "interval_minutes": 0
      },
      "group": {
        "id": 1,
        "name": "Public"
      }
    },
    {
      "id": 2,
      "status_page_id": 1,
      "monitoring_check_id": 2,
      "display_name": "Web app",
      "sort_order": 1,
      "status": "operational",
      "status_override": false,
      "show_uptime_bar": true,
      "created_at": "2026-01-15T12:00:00.000000Z",
      "updated_at": "2026-01-15T12:00:00.000000Z",
      "runbook_url": null,
      "status_page_component_group_id": 1,
      "description": null,
      "affects_overall_status": true,
      "group_name": "Public",
      "monitoring_check": {
        "id": 2,
        "name": "App — northwind-app.dev",
        "type": "http",
        "interval_minutes": 0
      },
      "group": {
        "id": 1,
        "name": "Public"
      }
    }
  ],
  "link_card_url": "http://localhost/api/status/northwind/card.png?v=66f618c615aff8ba"
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get status page traffic ​

Views, unique visitors and subscribe clicks over the last days (7, 30 or 90; default 30), compared with the period before, with the busiest day and a daily series. Counts only; no individual visits are recorded.

GET/organizations/{organization}/status-pages/{statusPage}/analytics
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/analytics" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/analytics" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/analytics', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/analytics",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/analytics', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/analytics", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "days": 30,
  "totals": {
    "views": 0,
    "unique_visitors": 0,
    "subscribe_clicks": 0
  },
  "previous": {
    "views": 0,
    "unique_visitors": 0,
    "subscribe_clicks": 0
  },
  "change_pct": null,
  "busiest": null,
  "series": [
    {
      "d": "2025-12-17",
      "views": 0,
      "unique_visitors": 0,
      "subscribe_clicks": 0
    },
    {
      "d": "2025-12-18",
      "views": 0,
      "unique_visitors": 0,
      "subscribe_clicks": 0
    }
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


List status page announcements ​

The announcements you posted on this page, newest first, including ones scheduled for later or no longer shown.

GET/organizations/{organization}/status-pages/{statusPage}/announcements
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/announcements" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/announcements" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/announcements', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/announcements",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/announcements', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/announcements", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
[
  {
    "id": 2,
    "status_page_id": 1,
    "title": "Released: v2.14.0",
    "body": "Faster search and a clearer billing page.",
    "show_from": "2026-01-15T09:00:00.000000Z",
    "show_until": "2026-01-22T12:00:00.000000Z",
    "created_at": "2026-01-15T09:00:00.000000Z",
    "updated_at": "2026-01-15T12:00:00.000000Z",
    "kind": "information"
  },
  {
    "id": 1,
    "status_page_id": 1,
    "title": "Scheduled maintenance this weekend",
    "body": "We'll be upgrading our database cluster on Saturday 02:00–03:00 UTC. Brief API slowdowns are possible; no downtime is expected.",
    "show_from": "2026-01-14T12:00:00.000000Z",
    "show_until": "2026-01-21T12:00:00.000000Z",
    "created_at": "2026-01-14T12:00:00.000000Z",
    "updated_at": "2026-01-15T12:00:00.000000Z",
    "kind": "information"
  }
]
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Post a status page announcement ​

Publishes a notice with a title and body on the public page. kind is information or warning, and show_from and show_until limit when it is shown.

POST/organizations/{organization}/status-pages/{statusPage}/announcements
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Bodyapplication/json
titlestringrequired

Must not be greater than 255 characters.

bodystringrequired

Must not be greater than 10000 characters.

kindstring, nullableoptional

Two, on purpose: anything louder than a warning is an incident.

One of: information, warning

show_fromstring, nullableoptional

Must be a valid date.

show_untilstring, nullableoptional

Must be a valid date. Must be a date after or equal to show_from.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/status-pages/1/announcements" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"title":"New status page address","body":"This page now also answers at status.northwind.example."}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "title": "New status page address",
  "body": "This page now also answers at status.northwind.example."
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/announcements" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/status-pages/1/announcements', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'title' => 'New status page address',
        'body' => 'This page now also answers at status.northwind.example.',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/status-pages/1/announcements",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "title": "New status page address",
        "body": "This page now also answers at status.northwind.example.",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/announcements', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "title": "New status page address",
    "body": "This page now also answers at status.northwind.example."
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/status-pages/1/announcements", strings.NewReader(`{"title":"New status page address","body":"This page now also answers at status.northwind.example."}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "title": "New status page address",
  "body": "This page now also answers at status.northwind.example.",
  "status_page_id": 1,
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "created_at": "2026-01-15T12:00:00.000000Z",
  "id": 3
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The title field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "title": [
      "The title field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Update a status page announcement ​

Changes the announcement’s title, body, kind or display window.

PATCH/organizations/{organization}/status-pages/{statusPage}/announcements/{announcement}
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

announcementintegerrequired

The announcement's ID.

Bodyapplication/json
titlestringoptional

Must not be greater than 255 characters.

bodystringoptional

Must not be greater than 10000 characters.

kindstring, nullableoptional

One of: information, warning

show_fromstring, nullableoptional

Must be a valid date.

show_untilstring, nullableoptional

Must be a valid date. Must be a date after or equal to show_from.

Request

sh
curl -X PATCH "https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"title":"Status page has moved","kind":"information"}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "title": "Status page has moved",
  "kind": "information"
}
'@
Invoke-RestMethod -Method Patch -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'title' => 'Status page has moved',
        'kind' => 'information',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.patch(
    "https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "title": "Status page has moved",
        "kind": "information",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "title": "Status page has moved",
    "kind": "information"
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("PATCH", "https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1", strings.NewReader(`{"title":"Status page has moved","kind":"information"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "status_page_id": 1,
  "title": "Status page has moved",
  "body": "We'll be upgrading our database cluster on Saturday 02:00–03:00 UTC. Brief API slowdowns are possible; no downtime is expected.",
  "show_from": "2026-01-14T12:00:00.000000Z",
  "show_until": "2026-01-21T12:00:00.000000Z",
  "created_at": "2026-01-14T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "kind": "information"
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The title field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "title": [
      "The title field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
422 validation_failed
429 rate_limited


Delete a status page announcement ​

Removes the announcement from the page permanently.

DELETE/organizations/{organization}/status-pages/{statusPage}/announcements/{announcement}
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

announcementintegerrequired

The announcement's ID.

Request

sh
curl -X DELETE "https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Delete -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('DELETE', 'https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.delete(
    "https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.status_code)
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("DELETE", "https://api.infranest.io/api/organizations/42/status-pages/1/announcements/1", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "message": "Deleted."
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
429 rate_limited


Get custom domain CNAME setup ​

Whether the page’s custom domain, or the one in domain, sits in a DNS zone you manage in InfraNest, whether InfraNest can create the CNAME record there for you, and whether it is already published. Includes the CNAME target to point the domain at.

GET/organizations/{organization}/status-pages/{statusPage}/cname-setup
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/cname-setup" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/cname-setup" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/cname-setup', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/cname-setup",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/cname-setup', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/cname-setup", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "manageable": false,
  "matched": false,
  "published": false,
  "cname_target": "pages.infranest.io"
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


List status page groups ​

The page’s component groups in display order, each with how many components it holds.

GET/organizations/{organization}/status-pages/{statusPage}/component-groups
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/component-groups', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/component-groups', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
[
  {
    "id": 1,
    "status_page_id": 1,
    "name": "Public",
    "sort_order": 0,
    "created_at": "2026-01-15T12:00:00.000000Z",
    "updated_at": "2026-01-15T12:00:00.000000Z",
    "shows_platform_status": false,
    "components_count": 5
  },
  {
    "id": 2,
    "status_page_id": 1,
    "name": "Developer",
    "sort_order": 1,
    "created_at": "2026-01-15T12:00:00.000000Z",
    "updated_at": "2026-01-15T12:00:00.000000Z",
    "shows_platform_status": false,
    "components_count": 3
  }
]
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Create a status page group ​

Adds a group with a name at the end of the page. Names must be unique within the page.

POST/organizations/{organization}/status-pages/{statusPage}/component-groups
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Bodyapplication/json
namestringrequired

Must not be greater than 255 characters.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name":"Customer apps"}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "name": "Customer apps"
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/status-pages/1/component-groups', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'name' => 'Customer apps',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "name": "Customer apps",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/component-groups', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "name": "Customer apps"
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups", strings.NewReader(`{"name":"Customer apps"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "name": "Customer apps",
  "sort_order": 2,
  "status_page_id": 1,
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "created_at": "2026-01-15T12:00:00.000000Z",
  "id": 3
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The name field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "name": [
      "The name field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Update a status page group ​

Renames the group for every component in it. Setting shows_platform_status to true on one group clears it from every other group on the page.

PATCH/organizations/{organization}/status-pages/{statusPage}/component-groups/{componentGroup}
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

componentGroupintegerrequired

The component group's ID.

Bodyapplication/json
namestringoptional

Must not be greater than 255 characters.

shows_platform_statusbooleanoptional

Request

sh
curl -X PATCH "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name":"Customer-facing apps"}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "name": "Customer-facing apps"
}
'@
Invoke-RestMethod -Method Patch -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'name' => 'Customer-facing apps',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.patch(
    "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "name": "Customer-facing apps",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "name": "Customer-facing apps"
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("PATCH", "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1", strings.NewReader(`{"name":"Customer-facing apps"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "status_page_id": 1,
  "name": "Customer-facing apps",
  "sort_order": 0,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "shows_platform_status": false
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The name field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "name": [
      "The name field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
422 validation_failed
429 rate_limited


Delete a status page group ​

Removes the group but keeps its components, which become ungrouped. The response says how many were ungrouped.

DELETE/organizations/{organization}/status-pages/{statusPage}/component-groups/{componentGroup}
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

componentGroupintegerrequired

The component group's ID.

Request

sh
curl -X DELETE "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Delete -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('DELETE', 'https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.delete(
    "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.status_code)
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("DELETE", "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/1", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "message": "Deleted.",
  "components_ungrouped": 5
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
429 rate_limited


Reorder status page groups ​

Sets the display order from order, a list of group IDs. Every ID must belong to this page.

POST/organizations/{organization}/status-pages/{statusPage}/component-groups/sort
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Bodyapplication/json
orderarrayoptional

Must match an existing stored value.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/sort" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"order":[2,1]}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "order": [
    2,
    1
  ]
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/sort" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/sort', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'order' => [
            2,
            1,
        ],
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/sort",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "order": [
            2,
            1,
        ],
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/sort', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "order": [
      2,
      1
    ]
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/status-pages/1/component-groups/sort", strings.NewReader(`{"order":[2,1]}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "message": "Order updated."
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The order field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "order": [
      "The order field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


List status page components ​

The page’s components in display order, each with its group, linked monitor and uptime bars over the page’s history window. A component with no monitor has no bars.

GET/organizations/{organization}/status-pages/{statusPage}/components
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/components" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/components" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/components', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/components",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/components', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/components", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
[
  {
    "id": 1,
    "status_page_id": 1,
    "monitoring_check_id": 1,
    "display_name": "Website",
    "sort_order": 0,
    "status": "operational",
    "status_override": false,
    "show_uptime_bar": true,
    "created_at": "2026-01-15T12:00:00.000000Z",
    "updated_at": "2026-01-15T12:00:00.000000Z",
    "runbook_url": null,
    "status_page_component_group_id": 1,
    "description": null,
    "affects_overall_status": true,
    "group_name": "Public",
    "monitoring_check": {
      "id": 1,
      "name": "Marketing site",
      "type": "http",
      "last_status": "up",
      "external_service_id": null,
      "interval_minutes": 0
    },
    "group": {
      "id": 1,
      "name": "Public",
      "sort_order": 0
    },
    "uptime_bars": [
      {
        "date": "2025-10-17",
        "uptime_pct": 100,
        "colour": "green",
        "incidents": [],
        "imported": false
      },
      {
        "date": "2025-10-18",
        "uptime_pct": 100,
        "colour": "green",
        "incidents": [],
        "imported": false
      }
    ]
  },
  {
    "id": 2,
    "status_page_id": 1,
    "monitoring_check_id": 2,
    "display_name": "Web app",
    "sort_order": 1,
    "status": "operational",
    "status_override": false,
    "show_uptime_bar": true,
    "created_at": "2026-01-15T12:00:00.000000Z",
    "updated_at": "2026-01-15T12:00:00.000000Z",
    "runbook_url": null,
    "status_page_component_group_id": 1,
    "description": null,
    "affects_overall_status": true,
    "group_name": "Public",
    "monitoring_check": {
      "id": 2,
      "name": "App — northwind-app.dev",
      "type": "http",
      "last_status": "up",
      "external_service_id": null,
      "interval_minutes": 0
    },
    "group": {
      "id": 1,
      "name": "Public",
      "sort_order": 0
    },
    "uptime_bars": [
      {
        "date": "2025-10-17",
        "uptime_pct": 100,
        "colour": "green",
        "incidents": [],
        "imported": false
      },
      {
        "date": "2025-10-18",
        "uptime_pct": 100,
        "colour": "green",
        "incidents": [],
        "imported": false
      }
    ]
  }
]
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Add a component to a status page ​

Adds a component with a display_name, optionally linked to one of your monitors with monitoring_check_id. A group_name that does not exist yet creates that group, and a runbook_url must start with https:// and is only shown internally.

POST/organizations/{organization}/status-pages/{statusPage}/components
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Bodyapplication/json
display_namestringrequired

Must not be greater than 255 characters.

descriptionstring, nullableoptional

What this service IS, for the reader who does not already know. Must not be greater than 255 characters.

group_namestring, nullableoptional

Must not be greater than 255 characters.

sort_orderintegeroptional

Must be at least 0.

monitoring_check_idinteger, nullableoptional

Must match an existing stored value.

statusstring, nullableoptional
status_overridebooleanoptional
show_uptime_barbooleanoptional
affects_overall_statusbooleanoptional
runbook_urlstring, nullableoptional

Followed by somebody in a hurry who will not read the scheme first. Must be a valid URL. Must start with one of https:// Must not be greater than 500 characters.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/status-pages/1/components" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"display_name":"Payments API"}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "display_name": "Payments API"
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/components" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/status-pages/1/components', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'display_name' => 'Payments API',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/status-pages/1/components",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "display_name": "Payments API",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/components', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "display_name": "Payments API"
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/status-pages/1/components", strings.NewReader(`{"display_name":"Payments API"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "display_name": "Payments API",
  "description": null,
  "status_page_component_group_id": null,
  "sort_order": 8,
  "monitoring_check_id": null,
  "status": "operational",
  "status_override": false,
  "show_uptime_bar": true,
  "affects_overall_status": true,
  "runbook_url": null,
  "status_page_id": 1,
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "created_at": "2026-01-15T12:00:00.000000Z",
  "id": 9,
  "group_name": null,
  "monitoring_check": null,
  "group": null
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The display name field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "display_name": [
      "The display name field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Update a status page component ​

Changes the fields you send, such as the name, description, linked monitor, status override, group or runbook link. A new group_name creates that group.

PATCH/organizations/{organization}/status-pages/{statusPage}/components/{component}
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

componentintegerrequired

The component's ID.

Bodyapplication/json
display_namestringoptional

Must not be greater than 255 characters.

descriptionstring, nullableoptional

Must not be greater than 255 characters.

group_namestring, nullableoptional

Must not be greater than 255 characters.

sort_orderintegeroptional

Must be at least 0.

monitoring_check_idinteger, nullableoptional

Must match an existing stored value.

statusstring, nullableoptional
status_overridebooleanoptional
show_uptime_barbooleanoptional
affects_overall_statusbooleanoptional
runbook_urlstring, nullableoptional

Followed by somebody in a hurry who will not read the scheme first. Must be a valid URL. Must start with one of https:// Must not be greater than 500 characters.

Request

sh
curl -X PATCH "https://api.infranest.io/api/organizations/42/status-pages/1/components/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"display_name":"Checkout","description":"Payments and order confirmation"}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "display_name": "Checkout",
  "description": "Payments and order confirmation"
}
'@
Invoke-RestMethod -Method Patch -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/components/1" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.infranest.io/api/organizations/42/status-pages/1/components/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'display_name' => 'Checkout',
        'description' => 'Payments and order confirmation',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.patch(
    "https://api.infranest.io/api/organizations/42/status-pages/1/components/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "display_name": "Checkout",
        "description": "Payments and order confirmation",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/components/1', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "display_name": "Checkout",
    "description": "Payments and order confirmation"
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("PATCH", "https://api.infranest.io/api/organizations/42/status-pages/1/components/1", strings.NewReader(`{"display_name":"Checkout","description":"Payments and order confirmation"}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "id": 1,
  "status_page_id": 1,
  "monitoring_check_id": 1,
  "display_name": "Checkout",
  "sort_order": 0,
  "status": "operational",
  "status_override": false,
  "show_uptime_bar": true,
  "created_at": "2026-01-15T12:00:00.000000Z",
  "updated_at": "2026-01-15T12:00:00.000000Z",
  "runbook_url": null,
  "status_page_component_group_id": 1,
  "description": "Payments and order confirmation",
  "affects_overall_status": true,
  "group_name": "Public",
  "monitoring_check": {
    "id": 1,
    "name": "Marketing site",
    "type": "http",
    "last_status": "up",
    "external_service_id": null,
    "interval_minutes": 0
  },
  "group": {
    "id": 1,
    "name": "Public",
    "sort_order": 0
  }
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The display name field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "display_name": [
      "The display name field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
422 validation_failed
429 rate_limited


Remove a component from a status page ​

Deletes the component from the page. The monitor behind it is not affected.

DELETE/organizations/{organization}/status-pages/{statusPage}/components/{component}
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

componentintegerrequired

The component's ID.

Request

sh
curl -X DELETE "https://api.infranest.io/api/organizations/42/status-pages/1/components/1" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Delete -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/components/1" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('DELETE', 'https://api.infranest.io/api/organizations/42/status-pages/1/components/1', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.delete(
    "https://api.infranest.io/api/organizations/42/status-pages/1/components/1",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.status_code)
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/components/1', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("DELETE", "https://api.infranest.io/api/organizations/42/status-pages/1/components/1", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "message": "Deleted."
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
429 rate_limited


Add several monitors to a status page ​

Adds a component for each of up to 50 monitors in monitoring_check_ids, named after the monitor and optionally placed in group_name. Monitors already on the page are skipped and listed in skipped; third-party monitors are added ungrouped and do not affect the page’s overall status.

POST/organizations/{organization}/status-pages/{statusPage}/components/bulk
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Bodyapplication/json
monitoring_check_idsarrayoptional

Must match an existing stored value.

group_namestring, nullableoptional

Must not be greater than 255 characters.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/status-pages/1/components/bulk" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"monitoring_check_ids":[1,2,3]}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "monitoring_check_ids": [
    1,
    2,
    3
  ]
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/components/bulk" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/status-pages/1/components/bulk', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'monitoring_check_ids' => [
            1,
            2,
            3,
        ],
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/status-pages/1/components/bulk",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "monitoring_check_ids": [
            1,
            2,
            3,
        ],
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/components/bulk', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "monitoring_check_ids": [
      1,
      2,
      3
    ]
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/status-pages/1/components/bulk", strings.NewReader(`{"monitoring_check_ids":[1,2,3]}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "created": [],
  "skipped": [
    1,
    2
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The monitoring check ids field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "monitoring_check_ids": [
      "The monitoring check ids field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Reorder status page components ​

Sets the display order from order, a list of component IDs. Every ID must belong to this page.

POST/organizations/{organization}/status-pages/{statusPage}/components/sort
Scope monitoring.writeChanges data
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Bodyapplication/json
orderarrayoptional

Must match an existing stored value.

Request

sh
curl -X POST "https://api.infranest.io/api/organizations/42/status-pages/1/components/sort" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"order":[8,7,6,5,4,3,2,1]}'
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
$body = @'
{
  "order": [
    8,
    7,
    6,
    5,
    4,
    3,
    2,
    1
  ]
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/components/sort" -Headers $headers -ContentType "application/json" -Body $body
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/status-pages/1/components/sort', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'order' => [
            8,
            7,
            6,
            5,
            4,
            3,
            2,
            1,
        ],
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.post(
    "https://api.infranest.io/api/organizations/42/status-pages/1/components/sort",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
    json={
        "order": [
            8,
            7,
            6,
            5,
            4,
            3,
            2,
            1,
        ],
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/components/sort', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "order": [
      8,
      7,
      6,
      5,
      4,
      3,
      2,
      1
    ]
  }),
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/status-pages/1/components/sort", strings.NewReader(`{"order":[8,7,6,5,4,3,2,1]}`))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "message": "Order updated."
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.write scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.write",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "idempotency_in_progress",
  "message": "A request with this Idempotency-Key is still being handled.",
  "hint": "Wait a few seconds, then send the same request with the same key again to get its result.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#idempotency_in_progress",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "validation_failed",
  "message": "The order field is required.",
  "hint": "Fix the fields listed in \"errors\" and send the request again.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#validation_failed",
  "errors": {
    "order": [
      "The order field is required."
    ]
  },
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied write_disabled organization_suspended
404 not_found
409 idempotency_in_progress
422 validation_failed idempotency_key_reused
429 rate_limited


Get the internal view of a status page ​

The team-only view of the page: each component with its monitor, runbook link, regions reporting and 30 days of uptime, plus active incidents, the next maintenance and the on-call note. These internal fields are never shown on the public page, and this view needs a plan that includes private status pages.

GET/organizations/{organization}/status-pages/{statusPage}/internal
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/internal" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/internal" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/internal', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/internal",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/internal', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/internal", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "page": {
    "id": 1,
    "name": "Northwind Cloud Status",
    "slug": "northwind",
    "logo_url": null,
    "is_public": true,
    "on_call_note": "Primary: Sam Okoye · +31 6 12 34 56 78 · #northwind-oncall on Slack. Escalation after 15m: Alex Rivera."
  },
  "metrics": {
    "overall_status": "major_outage",
    "monitors_up": 6,
    "monitors_total": 8,
    "uptime_30d": 100,
    "next_maintenance": null
  },
  "groups": [
    {
      "name": "Public",
      "components": [
        {
          "id": 1,
          "display_name": "Website",
          "status": "operational",
          "monitoring_check_id": 1,
          "monitor_name": "Marketing site",
          "runbook_url": null,
          "last_checked_at": "2026-01-15T11:58:00+00:00",
          "regions_reporting": null,
          "regions_total": null,
          "uptime_bars": [
            {
              "date": "2025-12-16",
              "uptime_pct": 100,
              "colour": "green",
              "incidents": [],
              "imported": false
            },
            {
              "date": "2025-12-17",
              "uptime_pct": 100,
              "colour": "green",
              "incidents": [],
              "imported": false
            }
          ]
        },
        {
          "id": 2,
          "display_name": "Web app",
          "status": "operational",
          "monitoring_check_id": 2,
          "monitor_name": "App — northwind-app.dev",
          "runbook_url": null,
          "last_checked_at": "2026-01-15T11:58:00+00:00",
          "regions_reporting": null,
          "regions_total": null,
          "uptime_bars": [
            {
              "date": "2025-12-16",
              "uptime_pct": 100,
              "colour": "green",
              "incidents": [],
              "imported": false
            },
            {
              "date": "2025-12-17",
              "uptime_pct": 100,
              "colour": "green",
              "incidents": [],
              "imported": false
            }
          ]
        }
      ]
    },
    {
      "name": "Developer",
      "components": [
        {
          "id": 6,
          "display_name": "API",
          "status": "operational",
          "monitoring_check_id": 3,
          "monitor_name": "API health",
          "runbook_url": "https://wiki.northwind.example/runbooks/api",
          "last_checked_at": "2026-01-15T11:58:00+00:00",
          "regions_reporting": null,
          "regions_total": null,
          "uptime_bars": [
            {
              "date": "2025-12-16",
              "uptime_pct": 100,
              "colour": "green",
              "incidents": [],
              "imported": false
            },
            {
              "date": "2025-12-17",
              "uptime_pct": 100,
              "colour": "green",
              "incidents": [],
              "imported": false
            }
          ]
        },
        {
          "id": 7,
          "display_name": "Search API",
          "status": "degraded",
          "monitoring_check_id": 6,
          "monitor_name": "Search API",
          "runbook_url": null,
          "last_checked_at": "2026-01-15T11:58:00+00:00",
          "regions_reporting": null,
          "regions_total": null,
          "uptime_bars": [
            {
              "date": "2025-12-16",
              "uptime_pct": 100,
              "colour": "green",
              "incidents": [],
              "imported": false
            },
            {
              "date": "2025-12-17",
              "uptime_pct": 100,
              "colour": "green",
              "incidents": [],
              "imported": false
            }
          ]
        }
      ]
    }
  ],
  "active_incidents": [
    {
      "id": 1,
      "monitoring_check_id": 4,
      "title": "Checkout returning 503",
      "status": "investigating",
      "impact": "major",
      "started_at": "2026-01-15T11:20:00+00:00",
      "is_planned": false,
      "public_url": "/status/northwind/incidents/1"
    }
  ],
  "matrix_days": 30
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


List incidents and maintenance on a status page ​

The incidents and maintenance windows that appear on this page automatically from its monitors, from the last 90 days or still open. Read-only; edit each one on the incident or maintenance window itself.

GET/organizations/{organization}/status-pages/{statusPage}/other-notices
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/other-notices" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/other-notices" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/other-notices', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/other-notices",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/other-notices', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/other-notices", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "notices": [
    {
      "kind": "incident",
      "id": 1,
      "title": "Checkout returning 503",
      "starts_at": "2026-01-15T11:20:00+00:00",
      "ends_at": null,
      "open": true,
      "href": "/monitoring/incidents"
    },
    {
      "kind": "incident",
      "id": 2,
      "title": "Brief marketing-site blip",
      "starts_at": "2026-01-09T11:45:00+00:00",
      "ends_at": "2026-01-09T12:00:00+00:00",
      "open": false,
      "href": "/monitoring/incidents"
    }
  ]
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get a status page overview ​

The page at a glance: setup (components, custom domain, subscribers, whether it is public), uptime over the page’s history window, current status with active incidents, and the next maintenance and announcement due to end.

GET/organizations/{organization}/status-pages/{statusPage}/overview
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/overview" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/overview" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/overview', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/overview",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/overview', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/overview", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "setup": {
    "components": {
      "count": 8,
      "linked": 8,
      "groups": 2
    },
    "domain": {
      "hostname": "status.northwind.example",
      "status": "pending"
    },
    "subscribers": {
      "enabled": true,
      "count": 3
    },
    "is_public": true
  },
  "uptime": {
    "days": 90,
    "pct": 100,
    "bars": [
      {
        "d": "2025-10-17",
        "p": 100,
        "c": "green"
      },
      {
        "d": "2025-10-18",
        "p": 100,
        "c": "green"
      }
    ]
  },
  "now": {
    "overall_status": "major_outage",
    "components_total": 8,
    "by_status": {
      "operational": 6,
      "major_outage": 1,
      "degraded": 1
    },
    "incidents": [
      {
        "id": 1,
        "monitoring_check_id": 4,
        "title": "Checkout returning 503",
        "status": "investigating",
        "impact": "major",
        "started_at": "2026-01-15T11:20:00+00:00",
        "is_planned": false,
        "public_url": "/status/northwind/incidents/1"
      }
    ]
  },
  "upcoming": {
    "maintenance": null,
    "announcement_ends": {
      "id": 1,
      "title": "Scheduled maintenance this weekend",
      "ends_at": "2026-01-21T12:00:00+00:00"
    }
  }
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


Get status page subscriber counts ​

How many people subscribe to the page, how many have confirmed or are pending, a count per channel, and a 90-day growth curve. Counts only; use the subscriber list for individual entries.

GET/organizations/{organization}/status-pages/{statusPage}/subscribers
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/subscribers" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/subscribers" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/subscribers', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/subscribers",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/subscribers', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/subscribers", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "total": 3,
  "confirmed": 3,
  "pending": 0,
  "channels": {
    "email": 3,
    "slack": 0,
    "teams": 0,
    "discord": 0
  },
  "growth": {
    "days": 90,
    "points": [
      {
        "d": "2025-10-18",
        "total": 0,
        "confirmed": 0
      },
      {
        "d": "2025-10-19",
        "total": 0,
        "confirmed": 0
      }
    ]
  }
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited


List status page subscribers ​

The page’s subscribers, newest first, with their channel, label, confirmation date and whether delivery is failing. Filter with q (searches email addresses) and status (confirmed or pending), and page with per_page (10 to 100); reading the list is recorded in your audit log, and webhook addresses are never shown in full.

GET/organizations/{organization}/status-pages/{statusPage}/subscribers/list
Scope monitoring.readRead only
Authorizationheader
Authorizationstringrequired

Bearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.

Path parameters
organizationintegerrequired

Your organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.

statusPageintegerrequired

The status page's ID.

Request

sh
curl "https://api.infranest.io/api/organizations/42/status-pages/1/subscribers/list" \
  -H "Authorization: Bearer $INFRANEST_TOKEN" \
  -H "Accept: application/json"
powershell
$headers = @{
  Authorization = "Bearer $env:INFRANEST_TOKEN"
  Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/status-pages/1/subscribers/list" -Headers $headers
php
<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";

$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/status-pages/1/subscribers/list', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

echo $response->getBody();
python
import os

import requests

response = requests.get(
    "https://api.infranest.io/api/organizations/42/status-pages/1/subscribers/list",
    headers={
        "Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
        "Accept": "application/json",
    },
)
response.raise_for_status()
print(response.json())
js
const response = await fetch('https://api.infranest.io/api/organizations/42/status-pages/1/subscribers/list', {
  headers: {
    Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
    Accept: 'application/json',
  },
})
console.log(response.status, await response.text())
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/status-pages/1/subscribers/list", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRANEST_TOKEN"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}

Response

json
{
  "data": [
    {
      "id": 3,
      "channel": "email",
      "label": "oncall@northwind.example",
      "confirmed_at": "2026-01-10T12:00:00+00:00",
      "subscribed_at": "2026-01-15T12:00:00+00:00",
      "undeliverable": null
    },
    {
      "id": 2,
      "channel": "email",
      "label": "sre@northwind.example",
      "confirmed_at": "2025-12-29T12:00:00+00:00",
      "subscribed_at": "2026-01-15T12:00:00+00:00",
      "undeliverable": null
    }
  ],
  "total": 3,
  "per_page": 25,
  "current_page": 1,
  "last_page": 1
}
json
{
  "code": "unauthenticated",
  "message": "You are not signed in, or the API token is missing, wrong, expired or revoked.",
  "hint": "Send a valid token in the Authorization header, as the word Bearer followed by the token. Create a new one under My account → Developer if it expired or was revoked.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#unauthenticated",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "scope_missing",
  "message": "This API token does not have the monitoring.read scope.",
  "hint": "Create a token that includes the scope named in \"required\". Give each token only the scopes it needs.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#scope_missing",
  "required": "monitoring.read",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "not_found",
  "message": "Nothing exists at this address, or you cannot see it.",
  "hint": "Check the IDs in the address. A resource in another organization answers as not found.",
  "retryable": false,
  "docs_url": "https://developers.infranest.io/errors#not_found",
  "reference": "k3j9x0b2qa"
}
json
{
  "code": "rate_limited",
  "message": "This token made more than 300 requests in a minute.",
  "hint": "Wait the number of seconds in \"retry_after\" (also the Retry-After header), then retry.",
  "retryable": true,
  "docs_url": "https://developers.infranest.io/errors#rate_limited",
  "limit_key": "api_requests_per_minute",
  "limit": 300,
  "retry_after": 12,
  "reference": "k3j9x0b2qa"
}

401 unauthenticated
403 scope_missing wrong_organization test_token_required test_token_sandbox_only permission_denied
404 not_found
429 rate_limited