Maintenance
Planned maintenance windows, which pause alerts and show on status pages.
Common tasks
Only in the app: Nothing. Maintenance windows can be fully managed with a token.
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.
Maintenance windows
List maintenance windows
A paginated list of your maintenance windows with the monitors, servers and tags each window covers, whether each window is in effect and its current or next occurrence, plus counts in meta. Filter with search, tag and status (active, scheduled, recurring or completed), and sort with sort (schedule, name, monitors or status) and dir.
/organizations/{organization}/maintenance-windowsmonitoring.readRead onlyAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
Request
curl "https://api.infranest.io/api/organizations/42/maintenance-windows" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Get -Uri "https://api.infranest.io/api/organizations/42/maintenance-windows" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.infranest.io/api/organizations/42/maintenance-windows', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.get(
"https://api.infranest.io/api/organizations/42/maintenance-windows",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/maintenance-windows', {
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.infranest.io/api/organizations/42/maintenance-windows", 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
{
"current_page": 1,
"data": [
{
"id": 3,
"organization_id": 1,
"name": "Nightly backup window",
"description": "Alerts are suppressed while backups run.",
"starts_at": null,
"ends_at": null,
"created_at": "2026-01-15T12:00:00.000000Z",
"updated_at": "2026-01-15T12:00:00.000000Z",
"recurrence_type": "daily",
"recurrence_days": null,
"start_time": "03:00",
"duration_minutes": 45,
"suppress_alerts": true,
"status": "scheduled",
"notified_at": null,
"source": "manual",
"deploy_id": null,
"deleted_at": null,
"purge_after": null,
"purge_reminder_sent_at": null,
"deleted_by_id": null,
"deleted_by_label": null,
"deletion_reason": null,
"created_by": null,
"checks_count": 0,
"checks": [],
"servers": [],
"tags": [],
"is_active": false,
"occurrence_starts_at": "2026-01-16T03:00:00Z",
"occurrence_ends_at": "2026-01-16T03:45:00Z",
"schedule_timezone": "UTC"
},
{
"id": 2,
"organization_id": 1,
"name": "Load balancer certificate rotation",
"description": "Replaced the certificate on web-lb and reloaded the listeners.",
"starts_at": "2026-01-06T01:00:00.000000Z",
"ends_at": "2026-01-06T01:30:00.000000Z",
"created_at": "2026-01-15T12:00:00.000000Z",
"updated_at": "2026-01-15T12:00:00.000000Z",
"recurrence_type": "none",
"recurrence_days": null,
"start_time": null,
"duration_minutes": null,
"suppress_alerts": true,
"status": "completed",
"notified_at": null,
"source": "manual",
"deploy_id": null,
"deleted_at": null,
"purge_after": null,
"purge_reminder_sent_at": null,
"deleted_by_id": null,
"deleted_by_label": null,
"deletion_reason": null,
"created_by": null,
"checks_count": 0,
"checks": [],
"servers": [],
"tags": [],
"is_active": false,
"occurrence_starts_at": null,
"occurrence_ends_at": null,
"schedule_timezone": "UTC"
}
],
"first_page_url": "http://localhost/api/organizations/1/maintenance-windows?page=1",
"from": 1,
"last_page": 1,
"last_page_url": "http://localhost/api/organizations/1/maintenance-windows?page=1",
"links": [
{
"url": null,
"label": "« Previous",
"page": null,
"active": false
},
{
"url": "http://localhost/api/organizations/1/maintenance-windows?page=1",
"label": "1",
"page": 1,
"active": true
}
],
"next_page_url": null,
"path": "http://localhost/api/organizations/1/maintenance-windows",
"per_page": 25,
"prev_page_url": null,
"to": 3,
"total": 3,
"meta": {
"counts": {
"total": 3,
"active": 0,
"scheduled": 1,
"recurring": 1,
"completed": 1
},
"tags": []
}
}{
"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"
}{
"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"
}{
"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"
}{
"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 maintenance window
Schedules maintenance for the monitors in check_ids and servers in server_ids; a window with no monitors applies to every monitor. A one-time window needs starts_at and ends_at, a daily or weekly one needs start_time and duration_minutes, and alerts are suppressed during it unless suppress_alerts is false. Subscribers of the affected status pages are told about the new window.
/organizations/{organization}/maintenance-windowsmonitoring.writeChanges dataAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
Bodyapplication/json
namestringrequiredMust not be greater than 255 characters.
descriptionstring, nullableoptionalMust not be greater than 2000 characters.
recurrence_typestring, nullableoptionalOne of: none, daily, weekly
recurrence_daysarrayoptionalMust be at least 0. Must not be greater than 6.
start_timestring, nullableoptionalMust be a valid date in the format H:i.
duration_minutesinteger, nullableoptionalMust be at least 1. Must not be greater than 1440.
starts_atstring, nullableoptionalMust be a valid date.
ends_atstring, nullableoptionalMust be a valid date. Must be a date after starts_at.
suppress_alertsboolean, nullableoptionalcheck_idsarrayoptionalMust match an existing stored value.
server_idsarrayoptionalMust match an existing stored value.
Request
curl -X POST "https://api.infranest.io/api/organizations/42/maintenance-windows" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name":"Load balancer upgrade","starts_at":"2026-01-17T22:00:00Z","ends_at":"2026-01-17T23:00:00Z","suppress_alerts":true,"check_ids":[1]}'$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
$body = @'
{
"name": "Load balancer upgrade",
"starts_at": "2026-01-17T22:00:00Z",
"ends_at": "2026-01-17T23:00:00Z",
"suppress_alerts": true,
"check_ids": [
1
]
}
'@
Invoke-RestMethod -Method Post -Uri "https://api.infranest.io/api/organizations/42/maintenance-windows" -Headers $headers -ContentType "application/json" -Body $body<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.infranest.io/api/organizations/42/maintenance-windows', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
'json' => [
'name' => 'Load balancer upgrade',
'starts_at' => '2026-01-17T22:00:00Z',
'ends_at' => '2026-01-17T23:00:00Z',
'suppress_alerts' => true,
'check_ids' => [
1,
],
],
]);
echo $response->getBody();import os
import requests
response = requests.post(
"https://api.infranest.io/api/organizations/42/maintenance-windows",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
json={
"name": "Load balancer upgrade",
"starts_at": "2026-01-17T22:00:00Z",
"ends_at": "2026-01-17T23:00:00Z",
"suppress_alerts": True,
"check_ids": [
1,
],
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/maintenance-windows', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Load balancer upgrade",
"starts_at": "2026-01-17T22:00:00Z",
"ends_at": "2026-01-17T23:00:00Z",
"suppress_alerts": true,
"check_ids": [
1
]
}),
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
)
func main() {
req, err := http.NewRequest("POST", "https://api.infranest.io/api/organizations/42/maintenance-windows", strings.NewReader(`{"name":"Load balancer upgrade","starts_at":"2026-01-17T22:00:00Z","ends_at":"2026-01-17T23:00:00Z","suppress_alerts":true,"check_ids":[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
{
"name": "Load balancer upgrade",
"description": null,
"recurrence_type": "none",
"recurrence_days": null,
"start_time": null,
"duration_minutes": null,
"starts_at": "2026-01-17T22:00:00.000000Z",
"ends_at": "2026-01-17T23:00:00.000000Z",
"suppress_alerts": true,
"organization_id": 1,
"updated_at": "2026-01-15T12:00:00.000000Z",
"created_at": "2026-01-15T12:00:00.000000Z",
"id": 6,
"checks": [
{
"id": 1,
"name": "Marketing site",
"type": "http",
"interval_minutes": 0,
"pivot": {
"maintenance_window_id": 6,
"monitoring_check_id": 1
}
}
],
"servers": [],
"tags": [],
"is_active": false,
"occurrence_starts_at": "2026-01-17T22:00:00Z",
"occurrence_ends_at": "2026-01-17T23:00:00Z",
"schedule_timezone": "UTC"
}{
"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"
}{
"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"
}{
"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"
}{
"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"
}{
"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"
}{
"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 maintenance window
Changes the fields you send. Sending check_ids or server_ids replaces what the window covers, and an empty list clears it.
/organizations/{organization}/maintenance-windows/{maintenanceWindow}monitoring.writeChanges dataAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
maintenanceWindowintegerrequiredThe maintenance window's ID.
Bodyapplication/json
namestringoptionalMust not be greater than 255 characters.
descriptionstring, nullableoptionalMust not be greater than 2000 characters.
recurrence_typestring, nullableoptionalOne of: none, daily, weekly
recurrence_daysarrayoptionalMust be at least 0. Must not be greater than 6.
start_timestring, nullableoptionalMust be a valid date in the format H:i.
duration_minutesinteger, nullableoptionalMust be at least 1. Must not be greater than 1440.
starts_atstring, nullableoptionalMust be a valid date.
ends_atstring, nullableoptionalMust be a valid date. Must be a date after starts_at.
suppress_alertsboolean, nullableoptionalcheck_idsarrayoptionalMust match an existing stored value.
server_idsarrayoptionalMust match an existing stored value.
Request
curl -X PATCH "https://api.infranest.io/api/organizations/42/maintenance-windows/1" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"description":"Primary database moves to PostgreSQL 17. Expect two minutes of read-only mode."}'$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
$body = @'
{
"description": "Primary database moves to PostgreSQL 17. Expect two minutes of read-only mode."
}
'@
Invoke-RestMethod -Method Patch -Uri "https://api.infranest.io/api/organizations/42/maintenance-windows/1" -Headers $headers -ContentType "application/json" -Body $body<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.infranest.io/api/organizations/42/maintenance-windows/1', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
'json' => [
'description' => 'Primary database moves to PostgreSQL 17. Expect two minutes of read-only mode.',
],
]);
echo $response->getBody();import os
import requests
response = requests.patch(
"https://api.infranest.io/api/organizations/42/maintenance-windows/1",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
json={
"description": "Primary database moves to PostgreSQL 17. Expect two minutes of read-only mode.",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/maintenance-windows/1', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"description": "Primary database moves to PostgreSQL 17. Expect two minutes of read-only mode."
}),
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
)
func main() {
req, err := http.NewRequest("PATCH", "https://api.infranest.io/api/organizations/42/maintenance-windows/1", strings.NewReader(`{"description":"Primary database moves to PostgreSQL 17. Expect two minutes of read-only mode."}`))
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
{
"id": 1,
"organization_id": 1,
"name": "Database cluster upgrade",
"description": "Primary database moves to PostgreSQL 17. Expect two minutes of read-only mode.",
"starts_at": "2026-01-18T02:00:00.000000Z",
"ends_at": "2026-01-18T03:00:00.000000Z",
"created_at": "2026-01-15T12:00:00.000000Z",
"updated_at": "2026-01-15T12:00:00.000000Z",
"recurrence_type": "none",
"recurrence_days": null,
"start_time": null,
"duration_minutes": null,
"suppress_alerts": true,
"status": "scheduled",
"notified_at": null,
"source": "manual",
"deploy_id": null,
"deleted_at": null,
"purge_after": null,
"purge_reminder_sent_at": null,
"deleted_by_id": null,
"deleted_by_label": null,
"deletion_reason": null,
"created_by": null,
"checks": [],
"servers": [],
"tags": [],
"is_active": false,
"occurrence_starts_at": "2026-01-18T02:00:00Z",
"occurrence_ends_at": "2026-01-18T03:00:00Z",
"schedule_timezone": "UTC"
}{
"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"
}{
"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"
}{
"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"
}{
"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"
}{
"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 maintenance window
Permanently deletes the maintenance window.
/organizations/{organization}/maintenance-windows/{maintenanceWindow}monitoring.writeChanges dataAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
maintenanceWindowintegerrequiredThe maintenance window's ID.
Request
curl -X DELETE "https://api.infranest.io/api/organizations/42/maintenance-windows/1" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Delete -Uri "https://api.infranest.io/api/organizations/42/maintenance-windows/1" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('DELETE', 'https://api.infranest.io/api/organizations/42/maintenance-windows/1', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.delete(
"https://api.infranest.io/api/organizations/42/maintenance-windows/1",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.status_code)const response = await fetch('https://api.infranest.io/api/organizations/42/maintenance-windows/1', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("DELETE", "https://api.infranest.io/api/organizations/42/maintenance-windows/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
{
"message": "Deleted."
}{
"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"
}{
"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"
}{
"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"
}{
"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
Complete a maintenance window
Marks a window that is in progress or verifying as completed. Refused for a window in any other state.
/organizations/{organization}/maintenance-windows/{maintenanceWindow}/completemonitoring.writeChanges dataAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
maintenanceWindowintegerrequiredThe maintenance window's ID.
Request
curl -X PATCH "https://api.infranest.io/api/organizations/42/maintenance-windows/1/complete" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Patch -Uri "https://api.infranest.io/api/organizations/42/maintenance-windows/1/complete" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.infranest.io/api/organizations/42/maintenance-windows/1/complete', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.patch(
"https://api.infranest.io/api/organizations/42/maintenance-windows/1/complete",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/maintenance-windows/1/complete', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("PATCH", "https://api.infranest.io/api/organizations/42/maintenance-windows/1/complete", 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
{
"id": 4,
"organization_id": 1,
"name": "Database upgrade",
"description": null,
"starts_at": "2026-01-15T11:50:00.000000Z",
"ends_at": "2026-01-15T13:00:00.000000Z",
"created_at": "2026-01-15T12:00:00.000000Z",
"updated_at": "2026-01-15T12:00:00.000000Z",
"recurrence_type": "none",
"recurrence_days": null,
"start_time": null,
"duration_minutes": null,
"suppress_alerts": true,
"status": "completed",
"notified_at": null,
"source": "manual",
"deploy_id": null,
"deleted_at": null,
"purge_after": null,
"purge_reminder_sent_at": null,
"deleted_by_id": null,
"deleted_by_label": null,
"deletion_reason": null,
"created_by": null,
"checks": [],
"servers": [],
"tags": [],
"is_active": false,
"occurrence_starts_at": null,
"occurrence_ends_at": null,
"schedule_timezone": "UTC"
}{
"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"
}{
"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"
}{
"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"
}{
"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"
}{
"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
Mark a maintenance window as verifying
Moves a window that is in progress to verifying, while you check that everything works again. Refused for a window in any other state.
/organizations/{organization}/maintenance-windows/{maintenanceWindow}/verifyingmonitoring.writeChanges dataAuthorizationheader
AuthorizationstringrequiredBearer and your API token: Bearer $INFRANEST_TOKEN. See Tokens and scopes.
Path parameters
organizationintegerrequiredYour organization's ID: the number after /organizations/ in the app's address, or from GET /organizations.
maintenanceWindowintegerrequiredThe maintenance window's ID.
Request
curl -X PATCH "https://api.infranest.io/api/organizations/42/maintenance-windows/1/verifying" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Accept: application/json"$headers = @{
Authorization = "Bearer $env:INFRANEST_TOKEN"
Accept = "application/json"
}
Invoke-RestMethod -Method Patch -Uri "https://api.infranest.io/api/organizations/42/maintenance-windows/1/verifying" -Headers $headers<?php
// composer require guzzlehttp/guzzle
require "vendor/autoload.php";
$client = new GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.infranest.io/api/organizations/42/maintenance-windows/1/verifying', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('INFRANEST_TOKEN'),
'Accept' => 'application/json',
],
]);
echo $response->getBody();import os
import requests
response = requests.patch(
"https://api.infranest.io/api/organizations/42/maintenance-windows/1/verifying",
headers={
"Authorization": f"Bearer {os.environ['INFRANEST_TOKEN']}",
"Accept": "application/json",
},
)
response.raise_for_status()
print(response.json())const response = await fetch('https://api.infranest.io/api/organizations/42/maintenance-windows/1/verifying', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.INFRANEST_TOKEN}`,
Accept: 'application/json',
},
})
console.log(response.status, await response.text())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("PATCH", "https://api.infranest.io/api/organizations/42/maintenance-windows/1/verifying", 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
{
"id": 4,
"organization_id": 1,
"name": "Database upgrade",
"description": null,
"starts_at": "2026-01-15T11:50:00.000000Z",
"ends_at": "2026-01-15T13:00:00.000000Z",
"created_at": "2026-01-15T12:00:00.000000Z",
"updated_at": "2026-01-15T12:00:00.000000Z",
"recurrence_type": "none",
"recurrence_days": null,
"start_time": null,
"duration_minutes": null,
"suppress_alerts": true,
"status": "verifying",
"notified_at": null,
"source": "manual",
"deploy_id": null,
"deleted_at": null,
"purge_after": null,
"purge_reminder_sent_at": null,
"deleted_by_id": null,
"deleted_by_label": null,
"deletion_reason": null,
"created_by": null,
"checks": [],
"servers": [],
"tags": [],
"is_active": true,
"occurrence_starts_at": "2026-01-15T11:50:00Z",
"occurrence_ends_at": "2026-01-15T13:00:00Z",
"schedule_timezone": "UTC"
}{
"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"
}{
"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"
}{
"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"
}{
"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"
}{
"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