# Maintenance Planned maintenance windows, which pause alerts and show on status pages. **Common tasks** - [Plan a maintenance window](#post-organizations-organization-maintenance-windows) - [Mark it complete](#patch-organizations-organization-maintenance-windows-maintenancewindow-complete) **Only in the app:** Nothing. Maintenance windows can be fully managed with a token. **How it works in the app:** [help article](https://infranest.io/docs/maintenance). **Scopes:** Read with `monitoring.read`, change with `monitoring.write`. See [Tokens and scopes](../tokens-and-scopes.md#scopes).
[Maintenance windows](#maintenance-windows) 6
Every endpoint below takes a token in the `Authorization: Bearer` header and answers JSON. Errors use the shared format in [Errors](../errors.md). Base address: `https://api.infranest.io/api`. ## Maintenance windows ### List maintenance windows {#get-organizations-organization-maintenance-windows}
`GET` `/organizations/{organization}/maintenance-windows` **Scope:** `monitoring.read` · **Changes data:** no 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`. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`not_found`](../errors.md#not_found), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl "https://api.infranest.io/api/organizations/42/maintenance-windows" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" ``` **Response** · 200 ```json { "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": [] } } ```
--- ### Create a maintenance window {#post-organizations-organization-maintenance-windows}
`POST` `/organizations/{organization}/maintenance-windows` **Scope:** `monitoring.write` · **Changes data:** yes — only where API writes are switched on for the organization 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. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `name`
body · required | string | Must not be greater than 255 characters. | | `description`
body | string, nullable | Must not be greater than 2000 characters. | | `recurrence_type`
body | string, nullable | One of: `none`, `daily`, `weekly`. | | `recurrence_days`
body | array | Must be at least 0. Must not be greater than 6. | | `start_time`
body | string, nullable | Must be a valid date in the format H:i. | | `duration_minutes`
body | integer, nullable | Must be at least 1. Must not be greater than 1440. | | `starts_at`
body | string, nullable | Must be a valid date. | | `ends_at`
body | string, nullable | Must be a valid date. Must be a date after starts_at. | | `suppress_alerts`
body | boolean, nullable | | | `check_ids`
body | array | Must match an existing stored value. | | `server_ids`
body | array | Must match an existing stored value. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`write_disabled`](../errors.md#write_disabled), [`organization_suspended`](../errors.md#organization_suspended), [`not_found`](../errors.md#not_found), [`idempotency_in_progress`](../errors.md#idempotency_in_progress), [`validation_failed`](../errors.md#validation_failed), [`idempotency_key_reused`](../errors.md#idempotency_key_reused), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh 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]}' ``` **Response** · 201 — Created ```json { "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" } ```
--- ### Update a maintenance window {#patch-organizations-organization-maintenance-windows-maintenancewindow}
`PATCH` `/organizations/{organization}/maintenance-windows/{maintenanceWindow}` **Scope:** `monitoring.write` · **Changes data:** yes — only where API writes are switched on for the organization Changes the fields you send. Sending `check_ids` or `server_ids` replaces what the window covers, and an empty list clears it. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `maintenanceWindow_id`
path · required | integer | The maintenanceWindow's ID. | | `name`
body | string | Must not be greater than 255 characters. | | `description`
body | string, nullable | Must not be greater than 2000 characters. | | `recurrence_type`
body | string, nullable | One of: `none`, `daily`, `weekly`. | | `recurrence_days`
body | array | Must be at least 0. Must not be greater than 6. | | `start_time`
body | string, nullable | Must be a valid date in the format H:i. | | `duration_minutes`
body | integer, nullable | Must be at least 1. Must not be greater than 1440. | | `starts_at`
body | string, nullable | Must be a valid date. | | `ends_at`
body | string, nullable | Must be a valid date. Must be a date after starts_at. | | `suppress_alerts`
body | boolean, nullable | | | `check_ids`
body | array | Must match an existing stored value. | | `server_ids`
body | array | Must match an existing stored value. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`write_disabled`](../errors.md#write_disabled), [`organization_suspended`](../errors.md#organization_suspended), [`not_found`](../errors.md#not_found), [`validation_failed`](../errors.md#validation_failed), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh 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."}' ``` **Response** · 200 ```json { "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" } ```
--- ### Delete a maintenance window {#delete-organizations-organization-maintenance-windows-maintenancewindow}
`DELETE` `/organizations/{organization}/maintenance-windows/{maintenanceWindow}` **Scope:** `monitoring.write` · **Changes data:** yes — only where API writes are switched on for the organization Permanently deletes the maintenance window. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `maintenanceWindow_id`
path · required | integer | The maintenanceWindow's ID. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`write_disabled`](../errors.md#write_disabled), [`organization_suspended`](../errors.md#organization_suspended), [`not_found`](../errors.md#not_found), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl -X DELETE "https://api.infranest.io/api/organizations/42/maintenance-windows/1" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" ``` **Response** · 200 ```json { "message": "Deleted." } ```
--- ### Complete a maintenance window {#patch-organizations-organization-maintenance-windows-maintenancewindow-complete}
`PATCH` `/organizations/{organization}/maintenance-windows/{maintenanceWindow}/complete` **Scope:** `monitoring.write` · **Changes data:** yes — only where API writes are switched on for the organization Marks a window that is in progress or verifying as completed. Refused for a window in any other state. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `maintenanceWindow_id`
path · required | integer | The maintenanceWindow's ID. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`write_disabled`](../errors.md#write_disabled), [`organization_suspended`](../errors.md#organization_suspended), [`not_found`](../errors.md#not_found), [`validation_failed`](../errors.md#validation_failed), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl -X PATCH "https://api.infranest.io/api/organizations/42/maintenance-windows/1/complete" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" ``` **Response** · 200 ```json { "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" } ```
--- ### Mark a maintenance window as verifying {#patch-organizations-organization-maintenance-windows-maintenancewindow-verifying}
`PATCH` `/organizations/{organization}/maintenance-windows/{maintenanceWindow}/verifying` **Scope:** `monitoring.write` · **Changes data:** yes — only where API writes are switched on for the organization Moves a window that is in progress to `verifying`, while you check that everything works again. Refused for a window in any other state. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `maintenanceWindow_id`
path · required | integer | The maintenanceWindow's ID. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`write_disabled`](../errors.md#write_disabled), [`organization_suspended`](../errors.md#organization_suspended), [`not_found`](../errors.md#not_found), [`validation_failed`](../errors.md#validation_failed), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl -X PATCH "https://api.infranest.io/api/organizations/42/maintenance-windows/1/verifying" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" ``` **Response** · 200 ```json { "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" } ```