From 738dd3f6ee7085ddd0dd0b79b5f038f205aebb53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Aug 2026 15:28:03 +0000 Subject: [PATCH] chore: update generated API types from latest spec --- docs/openapi/monitoring-api.json | 11250 +++++++++++++++++++++-------- src/devhelm/_generated.py | 3477 +++++++-- 2 files changed, 10864 insertions(+), 3863 deletions(-) diff --git a/docs/openapi/monitoring-api.json b/docs/openapi/monitoring-api.json index a9b7d44..2eb9634 100644 --- a/docs/openapi/monitoring-api.json +++ b/docs/openapi/monitoring-api.json @@ -196,7 +196,9 @@ "zapier", "datadog", "jira", - "gitlab" + "gitlab", + "sms", + "phone_call" ] } }, @@ -891,13 +893,13 @@ } } }, - "/api/v1/alert-channels/{id}/test": { - "post": { + "/api/v1/alert-channels/{id}/enabled": { + "patch": { "tags": [ "Alert Channels" ], - "summary": "Test a saved alert channel's connectivity", - "operationId": "test_2", + "summary": "Enable or disable an alert channel without re-uploading config", + "operationId": "setEnabled", "parameters": [ { "name": "id", @@ -909,112 +911,11 @@ } } ], - "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseTestChannelResult" - } - } - } - }, - "400": { - "description": "Bad request — the payload failed validation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden — the actor lacks permission for this resource", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Not found — the requested resource does not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "409": { - "description": "Conflict — the request collides with current resource state", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error — see the message field for details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "502": { - "description": "Bad gateway — an upstream provider returned an error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "503": { - "description": "Service unavailable — try again shortly", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - } - }, - "/api/v1/alert-channels/test": { - "post": { - "tags": [ - "Alert Channels" - ], - "summary": "Test alert channel connectivity using raw config (no saved channel required)", - "operationId": "testConfig", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TestAlertChannelRequest" + "$ref": "#/components/schemas/SetEnabledRequest" } } }, @@ -1026,7 +927,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseTestChannelResult" + "$ref": "#/components/schemas/SingleValueResponseAlertChannelDto" } } } @@ -1114,14 +1015,13 @@ } } }, - "/api/v1/alert-deliveries/{id}/attempts": { - "get": { + "/api/v1/alert-channels/{id}/test": { + "post": { "tags": [ - "Alert Deliveries" + "Alert Channels" ], - "summary": "List delivery attempts for a specific alert delivery", - "description": "Returns the ordered list of delivery attempts (request/response audit data) for the given delivery ID.", - "operationId": "listAttempts", + "summary": "Test a saved alert channel's connectivity", + "operationId": "test_2", "parameters": [ { "name": "id", @@ -1139,7 +1039,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultDeliveryAttemptDto" + "$ref": "#/components/schemas/SingleValueResponseTestChannelResult" } } } @@ -1227,32 +1127,30 @@ } } }, - "/api/v1/alert-deliveries/{id}/retry": { + "/api/v1/alert-channels/test": { "post": { "tags": [ - "Alert Deliveries" + "Alert Channels" ], - "summary": "Retry a failed delivery", - "description": "Resets a FAILED delivery to RETRY_PENDING so the delivery worker re-attempts it.", - "operationId": "retry", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" + "summary": "Test alert channel connectivity using raw config (no saved channel required)", + "operationId": "testConfig", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestAlertChannelRequest" + } } - } - ], + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseAlertDeliveryDto" + "$ref": "#/components/schemas/SingleValueResponseTestChannelResult" } } } @@ -1340,20 +1238,32 @@ } } }, - "/api/v1/api-keys": { + "/api/v1/alert-deliveries/{id}/attempts": { "get": { "tags": [ - "API Keys" + "Alert Deliveries" + ], + "summary": "List delivery attempts for a specific alert delivery", + "description": "Returns the ordered list of delivery attempts (request/response audit data) for the given delivery ID.", + "operationId": "listAttempts", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "List API keys", - "operationId": "list_13", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultApiKeyDto" + "$ref": "#/components/schemas/TableValueResultDeliveryAttemptDto" } } } @@ -1439,30 +1349,34 @@ } } } - }, + } + }, + "/api/v1/alert-deliveries/{id}/retry": { "post": { "tags": [ - "API Keys" + "Alert Deliveries" ], - "summary": "Create API key", - "operationId": "create_14", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateApiKeyRequest" - } + "summary": "Retry a failed delivery", + "description": "Resets a FAILED delivery to RETRY_PENDING so the delivery worker re-attempts it.", + "operationId": "retry", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" } - }, - "required": true - }, + } + ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseApiKeyCreateResponse" + "$ref": "#/components/schemas/SingleValueResponseAlertDeliveryDto" } } } @@ -1550,27 +1464,23 @@ } } }, - "/api/v1/api-keys/{id}": { - "delete": { + "/api/v1/api-keys": { + "get": { "tags": [ "API Keys" ], - "summary": "Delete API key", - "operationId": "delete_11", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], + "summary": "List API keys", + "operationId": "list_13", "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultApiKeyDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -1654,40 +1564,254 @@ } } }, - "patch": { + "post": { "tags": [ "API Keys" ], - "summary": "Update API key", - "operationId": "update_15", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], + "summary": "Create API key", + "operationId": "create_14", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateApiKeyRequest" + "$ref": "#/components/schemas/CreateApiKeyRequest" } } }, "required": true }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseApiKeyDto" + "$ref": "#/components/schemas/SingleValueResponseApiKeyCreateResponse" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/api-keys/{id}": { + "delete": { + "tags": [ + "API Keys" + ], + "summary": "Delete API key", + "operationId": "delete_11", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "patch": { + "tags": [ + "API Keys" + ], + "summary": "Update API key", + "operationId": "update_16", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateApiKeyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseApiKeyDto" } } } @@ -2005,7 +2129,7 @@ "Audit Log" ], "summary": "List audit events for the current organization", - "operationId": "list_19", + "operationId": "list_20", "parameters": [ { "name": "action", @@ -4545,7 +4669,7 @@ "Incidents" ], "summary": "Get incident details including update timeline", - "operationId": "get_11", + "operationId": "get_9", "parameters": [ { "name": "id", @@ -4649,15 +4773,13 @@ } } } - } - }, - "/api/v1/incidents/{id}/resolve": { - "post": { + }, + "patch": { "tags": [ "Incidents" ], - "summary": "Resolve an incident", - "operationId": "resolve", + "summary": "Update incident title and/or severity", + "operationId": "update_15", "parameters": [ { "name": "id", @@ -4673,10 +4795,11 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResolveIncidentRequest" + "$ref": "#/components/schemas/UpdateIncidentRequest" } } - } + }, + "required": true }, "responses": { "200": { @@ -4772,13 +4895,14 @@ } } }, - "/api/v1/incidents/{id}/updates": { + "/api/v1/incidents/{id}/acknowledge": { "post": { "tags": [ "Incidents" ], - "summary": "Add an update to an incident (optionally change status)", - "operationId": "addUpdate", + "summary": "Acknowledge all open notification dispatches for an incident", + "description": "Atomically acknowledges every DELIVERED or ESCALATING dispatch for the incident. Already-acknowledged and non-acknowledgeable dispatches are returned in skipped (not errors). MEMBER+.", + "operationId": "acknowledgeAll", "parameters": [ { "name": "id", @@ -4790,23 +4914,13 @@ } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddIncidentUpdateRequest" - } - } - }, - "required": true - }, "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseIncidentDetailDto" + "$ref": "#/components/schemas/SingleValueResponseAcknowledgeAllIncidentsResponse" } } } @@ -4894,21 +5008,50 @@ } } }, - "/api/v1/integrations": { + "/api/v1/incidents/{id}/events": { "get": { "tags": [ - "Integrations" + "Incidents" + ], + "summary": "List merged activity events for an incident", + "description": "Cursor-paginated unified activity stream merging incident updates, notification dispatches, alert deliveries, forensic state transitions, and linked status-page updates. Ordered by time descending.", + "operationId": "listEvents_1", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 50 + } + } ], - "summary": "List all supported integration types", - "description": "Returns the full static catalog of supported alert channel integration types with their metadata and config field schemas. Used by the frontend to dynamically render the 'Add Alert Channel' form.", - "operationId": "list_18", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultIntegrationDto" + "$ref": "#/components/schemas/CursorPageIncidentActivityEventDto" } } } @@ -4996,20 +5139,52 @@ } } }, - "/api/v1/invites": { + "/api/v1/incidents/{id}/related": { "get": { "tags": [ - "Invites" + "Incidents" + ], + "summary": "List related incidents sharing the same origin", + "description": "Returns same-origin recurrence (monitor, service, or resource group) within the window, excluding the current incident. total is the full count for “Nth outage this month” copy.", + "operationId": "listRelated", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "windowDays", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 30 + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 3 + } + } ], - "summary": "List invites", - "operationId": "list_10", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultInviteDto" + "$ref": "#/components/schemas/RelatedIncidentsResponse" } } } @@ -5095,30 +5270,42 @@ } } } - }, + } + }, + "/api/v1/incidents/{id}/resolve": { "post": { "tags": [ - "Invites" + "Incidents" + ], + "summary": "Resolve an incident", + "operationId": "resolve", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "Create invite", - "operationId": "create_11", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateInviteRequest" + "$ref": "#/components/schemas/ResolveIncidentRequest" } } - }, - "required": true + } }, "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseInviteDto" + "$ref": "#/components/schemas/SingleValueResponseIncidentDetailDto" } } } @@ -5206,31 +5393,41 @@ } } }, - "/api/v1/invites/{inviteId}/resend": { + "/api/v1/incidents/{id}/updates": { "post": { "tags": [ - "Invites" + "Incidents" ], - "summary": "Resend invite", - "operationId": "resend_1", + "summary": "Add an update to an incident (optionally change status)", + "operationId": "addUpdate", "parameters": [ { - "name": "inviteId", + "name": "id", "in": "path", "required": true, "schema": { - "type": "integer", - "format": "int32" + "type": "string", + "format": "uuid" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddIncidentUpdateRequest" + } + } + }, + "required": true + }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseInviteDto" + "$ref": "#/components/schemas/SingleValueResponseIncidentDetailDto" } } } @@ -5318,27 +5515,24 @@ } } }, - "/api/v1/invites/{inviteId}/revoke": { - "post": { + "/api/v1/integrations": { + "get": { "tags": [ - "Invites" - ], - "summary": "Revoke invite", - "operationId": "revoke", - "parameters": [ - { - "name": "inviteId", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } + "Integrations" ], + "summary": "List all supported integration types", + "description": "Returns the full static catalog of supported alert channel integration types with their metadata and config field schemas. Used by the frontend to dynamically render the 'Add Alert Channel' form.", + "operationId": "list_19", "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultIntegrationDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -5423,42 +5617,21 @@ } } }, - "/api/v1/maintenance-windows": { + "/api/v1/integrations/voice-languages": { "get": { "tags": [ - "Maintenance Windows" - ], - "summary": "List maintenance windows for the authenticated org", - "description": "Returns maintenance windows for the caller's organisation. Optionally filter by monitor_id, and/or by status: 'active' (currently in window) or 'upcoming' (starts in the future).", - "operationId": "list_9", - "parameters": [ - { - "name": "monitorId", - "in": "query", - "description": "Filter by monitor UUID", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "filter", - "in": "query", - "description": "Filter by status: 'active' or 'upcoming'", - "required": false, - "schema": { - "type": "string" - } - } + "Integrations" ], + "summary": "List supported voice languages for phone call alerts", + "description": "Returns BCP-47 locale codes and human-readable labels for all TTS languages supported by the phone call alert channel.", + "operationId": "listVoiceLanguages", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultMaintenanceWindowDto" + "$ref": "#/components/schemas/TableValueResultVoiceLanguageDto" } } } @@ -5544,31 +5717,22 @@ } } } - }, - "post": { + } + }, + "/api/v1/invites": { + "get": { "tags": [ - "Maintenance Windows" + "Invites" ], - "summary": "Create a maintenance window", - "description": "Creates a new maintenance window. Set monitorId to null to create an org-wide window that suppresses alerts for all monitors.", - "operationId": "create_10", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateMaintenanceWindowRequest" - } - } - }, - "required": true - }, + "summary": "List invites", + "operationId": "list_10", "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseMaintenanceWindowDto" + "$ref": "#/components/schemas/TableValueResultInviteDto" } } } @@ -5654,33 +5818,30 @@ } } } - } - }, - "/api/v1/maintenance-windows/{id}": { - "get": { + }, + "post": { "tags": [ - "Maintenance Windows" + "Invites" ], - "summary": "Get a single maintenance window by ID", - "operationId": "getById_2", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" + "summary": "Create invite", + "operationId": "create_11", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateInviteRequest" + } } - } - ], + }, + "required": true + }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseMaintenanceWindowDto" + "$ref": "#/components/schemas/SingleValueResponseInviteDto" } } } @@ -5766,41 +5927,33 @@ } } } - }, - "put": { + } + }, + "/api/v1/invites/{inviteId}/resend": { + "post": { "tags": [ - "Maintenance Windows" + "Invites" ], - "summary": "Update a maintenance window", - "operationId": "update_12", + "summary": "Resend invite", + "operationId": "resend_1", "parameters": [ { - "name": "id", + "name": "inviteId", "in": "path", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "integer", + "format": "int32" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateMaintenanceWindowRequest" - } - } - }, - "required": true - }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseMaintenanceWindowDto" + "$ref": "#/components/schemas/SingleValueResponseInviteDto" } } } @@ -5886,21 +6039,23 @@ } } } - }, - "delete": { + } + }, + "/api/v1/invites/{inviteId}/revoke": { + "post": { "tags": [ - "Maintenance Windows" + "Invites" ], - "summary": "Delete a maintenance window", - "operationId": "delete_8", + "summary": "Revoke invite", + "operationId": "revoke", "parameters": [ { - "name": "id", + "name": "inviteId", "in": "path", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "integer", + "format": "int32" } } ], @@ -5991,20 +6146,32 @@ } } }, - "/api/v1/members": { + "/api/v1/maintenance-windows": { "get": { "tags": [ - "Members" + "Maintenance Windows" ], - "summary": "List organization members", - "operationId": "list_17", + "summary": "List maintenance windows for the authenticated org", + "description": "Returns maintenance windows for the caller's organisation. Optionally filter by monitor_id, and/or by status: 'active' (currently in window) or 'upcoming' (starts in the future).", + "operationId": "list_9", "parameters": [ { - "name": "pageable", + "name": "monitorId", "in": "query", - "required": true, + "description": "Filter by monitor UUID", + "required": false, "schema": { - "$ref": "#/components/schemas/Pageable" + "type": "string", + "format": "uuid" + } + }, + { + "name": "filter", + "in": "query", + "description": "Filter by status: 'active' or 'upcoming'", + "required": false, + "schema": { + "type": "string" } } ], @@ -6014,7 +6181,117 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultMemberDto" + "$ref": "#/components/schemas/TableValueResultMaintenanceWindowDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "post": { + "tags": [ + "Maintenance Windows" + ], + "summary": "Create a maintenance window", + "description": "Creates a new maintenance window. Set monitorId to null to create an org-wide window that suppresses alerts for all monitors.", + "operationId": "create_10", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateMaintenanceWindowRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Created", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseMaintenanceWindowDto" } } } @@ -6102,27 +6379,34 @@ } } }, - "/api/v1/members/{userId}": { - "delete": { + "/api/v1/maintenance-windows/{id}": { + "get": { "tags": [ - "Members" + "Maintenance Windows" ], - "summary": "Remove member from organization", - "operationId": "remove_2", + "summary": "Get a single maintenance window by ID", + "operationId": "getById_2", "parameters": [ { - "name": "userId", + "name": "id", "in": "path", "required": true, "schema": { - "type": "integer", - "format": "int32" + "type": "string", + "format": "uuid" } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseMaintenanceWindowDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -6205,23 +6489,21 @@ } } } - } - }, - "/api/v1/members/{userId}/role": { + }, "put": { "tags": [ - "Members" + "Maintenance Windows" ], - "summary": "Change member role", - "operationId": "changeRole", + "summary": "Update a maintenance window", + "operationId": "update_12", "parameters": [ { - "name": "userId", + "name": "id", "in": "path", "required": true, "schema": { - "type": "integer", - "format": "int32" + "type": "string", + "format": "uuid" } } ], @@ -6229,15 +6511,22 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChangeRoleRequest" + "$ref": "#/components/schemas/UpdateMaintenanceWindowRequest" } } }, "required": true }, "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseMaintenanceWindowDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -6320,36 +6609,24 @@ } } } - } - }, - "/api/v1/members/{userId}/status": { - "put": { + }, + "delete": { "tags": [ - "Members" + "Maintenance Windows" ], - "summary": "Change member status", - "operationId": "changeStatus", + "summary": "Delete a maintenance window", + "operationId": "delete_8", "parameters": [ { - "name": "userId", + "name": "id", "in": "path", "required": true, "schema": { - "type": "integer", - "format": "int32" + "type": "string", + "format": "uuid" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChangeStatusRequest" - } - } - }, - "required": true - }, "responses": { "204": { "description": "No Content" @@ -6437,103 +6714,14 @@ } } }, - "/api/v1/monitors": { + "/api/v1/members": { "get": { "tags": [ - "Monitors" + "Members" ], - "summary": "List monitors for the authenticated org", - "description": "Supports filtering by `enabled`, `status` (alias active|paused for enabled), `type`, `managedBy`, `tag` / `tags`, `search`, and `environmentId`. Unrecognised query parameters are silently ignored (Spring's default binding behaviour) — pin to the documented set above.", - "operationId": "list_8", + "summary": "List organization members", + "operationId": "list_18", "parameters": [ - { - "name": "enabled", - "in": "query", - "description": "Filter by enabled state (true/false)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "status", - "in": "query", - "description": "Lifecycle status alias: 'active' (enabled=true) or 'paused' (enabled=false). Ignored when ?enabled is also supplied.", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "type", - "in": "query", - "description": "Filter by monitor type", - "required": false, - "schema": { - "type": "string", - "enum": [ - "HTTP", - "DNS", - "MCP_SERVER", - "TCP", - "ICMP", - "HEARTBEAT" - ] - } - }, - { - "name": "managedBy", - "in": "query", - "description": "Filter by managed-by source", - "required": false, - "schema": { - "type": "string", - "enum": [ - "DASHBOARD", - "CLI", - "TERRAFORM", - "MCP", - "API" - ] - } - }, - { - "name": "tags", - "in": "query", - "description": "Filter by tag names, comma-separated (e.g. prod,critical); OR semantics", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "tag", - "in": "query", - "description": "Filter by a single tag name (alias for ?tags=); merged with ?tags using OR semantics", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "search", - "in": "query", - "description": "Case-insensitive name search", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "environmentId", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - }, { "name": "pageable", "in": "query", @@ -6549,7 +6737,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultMonitorDto" + "$ref": "#/components/schemas/TableValueResultMemberDto" } } } @@ -6635,33 +6823,29 @@ } } } - }, - "post": { + } + }, + "/api/v1/members/{userId}": { + "delete": { "tags": [ - "Monitors" + "Members" ], - "summary": "Create a new monitor", - "operationId": "create_9", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateMonitorRequest" - } + "summary": "Remove member from organization", + "operationId": "remove_2", + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" } - }, - "required": true - }, + } + ], "responses": { - "201": { - "description": "Created", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -6746,35 +6930,38 @@ } } }, - "/api/v1/monitors/{id}": { - "get": { + "/api/v1/members/{userId}/role": { + "put": { "tags": [ - "Monitors" + "Members" ], - "summary": "Get a single monitor by id", - "operationId": "get_6", + "summary": "Change member role", + "operationId": "changeRole", "parameters": [ { - "name": "id", + "name": "userId", "in": "path", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "integer", + "format": "int32" } } ], - "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorDto" - } + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChangeRoleRequest" } } }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, "400": { "description": "Bad request — the payload failed validation", "content": { @@ -6856,21 +7043,23 @@ } } } - }, + } + }, + "/api/v1/members/{userId}/status": { "put": { "tags": [ - "Monitors" + "Members" ], - "summary": "Update a monitor", - "operationId": "update_11", + "summary": "Change member status", + "operationId": "changeStatus", "parameters": [ { - "name": "id", + "name": "userId", "in": "path", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "integer", + "format": "int32" } } ], @@ -6878,22 +7067,15 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateMonitorRequest" + "$ref": "#/components/schemas/ChangeStatusRequest" } } }, "required": true }, "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -6976,27 +7158,126 @@ } } } - }, - "delete": { + } + }, + "/api/v1/monitors": { + "get": { "tags": [ "Monitors" ], - "summary": "Soft-delete a monitor", - "operationId": "delete_7", + "summary": "List monitors for the authenticated org", + "description": "Supports filtering by `enabled`, `status` (alias active|paused for enabled), `type`, `managedBy`, `tag` / `tags`, `search`, and `environmentId`. Unrecognised query parameters are silently ignored (Spring's default binding behaviour) — pin to the documented set above.", + "operationId": "list_8", "parameters": [ { - "name": "id", - "in": "path", - "required": true, + "name": "enabled", + "in": "query", + "description": "Filter by enabled state (true/false)", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "status", + "in": "query", + "description": "Lifecycle status alias: 'active' (enabled=true) or 'paused' (enabled=false). Ignored when ?enabled is also supplied.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "Filter by monitor type", + "required": false, + "schema": { + "type": "string", + "enum": [ + "HTTP", + "DNS", + "MCP_SERVER", + "TCP", + "ICMP", + "HEARTBEAT", + "BROWSER", + "MULTI_STEP_API" + ] + } + }, + { + "name": "managedBy", + "in": "query", + "description": "Filter by managed-by source", + "required": false, + "schema": { + "type": "string", + "enum": [ + "DASHBOARD", + "CLI", + "TERRAFORM", + "MCP", + "API" + ] + } + }, + { + "name": "tags", + "in": "query", + "description": "Filter by tag names, comma-separated (e.g. prod,critical); OR semantics", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "tag", + "in": "query", + "description": "Filter by a single tag name (alias for ?tags=); merged with ?tags using OR semantics", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "search", + "in": "query", + "description": "Case-insensitive name search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "environmentId", + "in": "query", + "description": "Filter by environment ID", + "required": false, "schema": { "type": "string", "format": "uuid" } + }, + { + "name": "pageable", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/Pageable" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultMonitorDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -7079,29 +7360,26 @@ } } } - } - }, - "/api/v1/monitors/{id}/pause": { + }, "post": { "tags": [ "Monitors" ], - "summary": "Pause a monitor (set enabled=false)", - "operationId": "pause", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" + "summary": "Create a new monitor", + "operationId": "create_9", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateMonitorRequest" + } } - } - ], + }, + "required": true + }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { @@ -7193,14 +7471,13 @@ } } }, - "/api/v1/monitors/{id}/results": { + "/api/v1/monitors/{id}": { "get": { "tags": [ - "Check Results" + "Monitors" ], - "summary": "List raw check results", - "description": "Returns check results for the given monitor with optional time-range, region, and pass/fail filtering. Uses cursor-based pagination — pass the returned `cursor` value on subsequent requests to retrieve the next page. The cursor encodes the original time bounds, so `from`/`to` are ignored when a cursor is present.", - "operationId": "getResults", + "summary": "Get a single monitor by id", + "operationId": "get_6", "parameters": [ { "name": "id", @@ -7210,84 +7487,25 @@ "type": "string", "format": "uuid" } - }, - { - "name": "from", - "in": "query", - "description": "Start of time range (ISO 8601, inclusive); defaults to 24 hours ago", - "required": false, - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "to", - "in": "query", - "description": "End of time range (ISO 8601, inclusive); defaults to now", - "required": false, - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor from a previous response for pagination", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Maximum results per page (1–200)", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "default": 50 - }, - "example": 50 - }, - { - "name": "region", - "in": "query", - "description": "Filter by region (e.g. us-east)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "passed", - "in": "query", - "description": "Filter by pass/fail status", - "required": false, - "schema": { - "type": "boolean" - } } ], "responses": { "200": { - "description": "Paginated check results", + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/CursorPageCheckResultDto" + "$ref": "#/components/schemas/SingleValueResponseMonitorDto" } } } }, "400": { - "description": "Invalid query parameters", + "description": "Bad request — the payload failed validation", "content": { - "*/*": { + "application/json": { "schema": { - "$ref": "#/components/schemas/CursorPageCheckResultDto" + "$ref": "#/components/schemas/ErrorResponse" } } } @@ -7303,21 +7521,21 @@ } }, "403": { - "description": "Monitor does not belong to the caller's org", + "description": "Forbidden — the actor lacks permission for this resource", "content": { - "*/*": { + "application/json": { "schema": { - "$ref": "#/components/schemas/CursorPageCheckResultDto" + "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { - "description": "Monitor not found", + "description": "Not found — the requested resource does not exist", "content": { - "*/*": { + "application/json": { "schema": { - "$ref": "#/components/schemas/CursorPageCheckResultDto" + "$ref": "#/components/schemas/ErrorResponse" } } } @@ -7363,16 +7581,13 @@ } } } - } - }, - "/api/v1/monitors/{id}/results/summary": { - "get": { + }, + "put": { "tags": [ - "Check Results" + "Monitors" ], - "summary": "Get results summary", - "description": "Returns a dashboard summary for the monitor: current status derived from the latest result per region, time-bucketed chart data, the 24-hour uptime percentage, and the selected window's uptime percentage.", - "operationId": "getSummary", + "summary": "Update a monitor", + "operationId": "update_11", "parameters": [ { "name": "id", @@ -7382,40 +7597,35 @@ "type": "string", "format": "uuid" } - }, - { - "name": "chartWindow", - "in": "query", - "description": "Chart window: 24h returns hourly buckets, 7d/30d/90d return daily buckets", - "required": false, - "schema": { - "type": "string", - "enum": [ - "24h", - "7d", - "30d", - "90d" - ] - } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateMonitorRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "Results summary", + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/ResultSummaryDto" + "$ref": "#/components/schemas/SingleValueResponseMonitorDto" } } } }, "400": { - "description": "Invalid chartWindow parameter", + "description": "Bad request — the payload failed validation", "content": { - "*/*": { + "application/json": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseResultSummaryDto" + "$ref": "#/components/schemas/ErrorResponse" } } } @@ -7431,21 +7641,21 @@ } }, "403": { - "description": "Monitor does not belong to the caller's org", + "description": "Forbidden — the actor lacks permission for this resource", "content": { - "*/*": { + "application/json": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseResultSummaryDto" + "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { - "description": "Monitor not found", + "description": "Not found — the requested resource does not exist", "content": { - "*/*": { + "application/json": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseResultSummaryDto" + "$ref": "#/components/schemas/ErrorResponse" } } } @@ -7491,15 +7701,13 @@ } } } - } - }, - "/api/v1/monitors/{id}/resume": { - "post": { + }, + "delete": { "tags": [ "Monitors" ], - "summary": "Resume a monitor (set enabled=true)", - "operationId": "resume", + "summary": "Soft-delete a monitor", + "operationId": "delete_7", "parameters": [ { "name": "id", @@ -7512,15 +7720,8 @@ } ], "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -7605,14 +7806,13 @@ } } }, - "/api/v1/monitors/{id}/rotate-token": { + "/api/v1/monitors/{id}/pause": { "post": { "tags": [ "Monitors" ], - "summary": "Rotate the ping token for a heartbeat monitor", - "description": "Generates a new ping token. The old token remains valid for 24 hours to allow cron jobs to be updated without downtime. Only supported for HEARTBEAT monitors.", - "operationId": "rotateToken", + "summary": "Pause a monitor (set enabled=false)", + "operationId": "pause", "parameters": [ { "name": "id", @@ -7718,13 +7918,14 @@ } } }, - "/api/v1/monitors/{id}/tags": { + "/api/v1/monitors/{id}/results": { "get": { "tags": [ - "Monitors" + "Check Results" ], - "summary": "Get all tags applied to a monitor", - "operationId": "getMonitorTags", + "summary": "List raw check results", + "description": "Returns check results for the given monitor with optional time-range, region, and pass/fail filtering. Uses cursor-based pagination — pass the returned `cursor` value on subsequent requests to retrieve the next page. The cursor encodes the original time bounds, so `from`/`to` are ignored when a cursor is present.", + "operationId": "getResults", "parameters": [ { "name": "id", @@ -7734,25 +7935,84 @@ "type": "string", "format": "uuid" } + }, + { + "name": "from", + "in": "query", + "description": "Start of time range (ISO 8601, inclusive); defaults to 24 hours ago", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "to", + "in": "query", + "description": "End of time range (ISO 8601, inclusive); defaults to now", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "cursor", + "in": "query", + "description": "Opaque cursor from a previous response for pagination", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum results per page (1–200)", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 50 + }, + "example": 50 + }, + { + "name": "region", + "in": "query", + "description": "Filter by region (e.g. us-east)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "passed", + "in": "query", + "description": "Filter by pass/fail status", + "required": false, + "schema": { + "type": "boolean" + } } ], "responses": { "200": { - "description": "OK", + "description": "Paginated check results", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultTagDto" + "$ref": "#/components/schemas/CursorPageCheckResultDto" } } } }, "400": { - "description": "Bad request — the payload failed validation", + "description": "Invalid query parameters", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/CursorPageCheckResultDto" } } } @@ -7768,21 +8028,21 @@ } }, "403": { - "description": "Forbidden — the actor lacks permission for this resource", + "description": "Monitor does not belong to the caller's org", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/CursorPageCheckResultDto" } } } }, "404": { - "description": "Not found — the requested resource does not exist", + "description": "Monitor not found", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/CursorPageCheckResultDto" } } } @@ -7828,13 +8088,16 @@ } } } - }, - "post": { + } + }, + "/api/v1/monitors/{id}/results/summary": { + "get": { "tags": [ - "Monitors" + "Check Results" ], - "summary": "Add tags to a monitor; supports existing tag IDs and inline creation of new tags", - "operationId": "addMonitorTags", + "summary": "Get results summary", + "description": "Returns a dashboard summary for the monitor: current status derived from the latest result per region, time-bucketed chart data, the 24-hour uptime percentage, and the selected window's uptime percentage.", + "operationId": "getSummary", "parameters": [ { "name": "id", @@ -7844,35 +8107,40 @@ "type": "string", "format": "uuid" } + }, + { + "name": "chartWindow", + "in": "query", + "description": "Chart window: 24h returns hourly buckets, 7d/30d/90d return daily buckets", + "required": false, + "schema": { + "type": "string", + "enum": [ + "24h", + "7d", + "30d", + "90d" + ] + } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddMonitorTagsRequest" - } - } - }, - "required": true - }, "responses": { "200": { - "description": "OK", + "description": "Results summary", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultTagDto" + "$ref": "#/components/schemas/ResultSummaryDto" } } } }, "400": { - "description": "Bad request — the payload failed validation", + "description": "Invalid chartWindow parameter", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseResultSummaryDto" } } } @@ -7888,21 +8156,21 @@ } }, "403": { - "description": "Forbidden — the actor lacks permission for this resource", + "description": "Monitor does not belong to the caller's org", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseResultSummaryDto" } } } }, "404": { - "description": "Not found — the requested resource does not exist", + "description": "Monitor not found", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseResultSummaryDto" } } } @@ -7948,13 +8216,15 @@ } } } - }, - "delete": { + } + }, + "/api/v1/monitors/{id}/resume": { + "post": { "tags": [ "Monitors" ], - "summary": "Remove tags from a monitor by their IDs", - "operationId": "removeMonitorTags", + "summary": "Resume a monitor (set enabled=true)", + "operationId": "resume", "parameters": [ { "name": "id", @@ -7966,20 +8236,17 @@ } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RemoveMonitorTagsRequest" + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseMonitorDto" + } } } }, - "required": true - }, - "responses": { - "204": { - "description": "No Content" - }, "400": { "description": "Bad request — the payload failed validation", "content": { @@ -8063,14 +8330,14 @@ } } }, - "/api/v1/monitors/{id}/test": { + "/api/v1/monitors/{id}/rotate-token": { "post": { "tags": [ "Monitors" ], - "summary": "Test an existing monitor", - "description": "Runs the saved config and assertions of an existing monitor once, without persisting any result. Runs synchronously and returns the same shape as the ad-hoc test.", - "operationId": "testExisting", + "summary": "Rotate the ping token for a heartbeat monitor", + "description": "Generates a new ping token. The old token remains valid for 24 hours to allow cron jobs to be updated without downtime. Only supported for HEARTBEAT monitors.", + "operationId": "rotateToken", "parameters": [ { "name": "id", @@ -8088,7 +8355,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorTestResultDto" + "$ref": "#/components/schemas/SingleValueResponseMonitorDto" } } } @@ -8176,142 +8443,14 @@ } } }, - "/api/v1/monitors/{id}/uptime": { - "get": { - "tags": [ - "Check Results" - ], - "summary": "Get uptime statistics", - "description": "Returns uptime percentage and latency statistics for the requested time window, computed from continuous aggregates. Uses hourly aggregates for 24h/7d windows and daily aggregates for 30d/90d windows.", - "operationId": "getUptime", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "window", - "in": "query", - "description": "Time window for uptime calculation", - "required": false, - "schema": { - "type": "string", - "enum": [ - "24h", - "7d", - "30d", - "90d" - ] - } - } - ], - "responses": { - "200": { - "description": "Uptime statistics", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/UptimeDto" - } - } - } - }, - "400": { - "description": "Invalid window parameter", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseUptimeDto" - } - } - } - }, - "401": { - "description": "Unauthorized — missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Monitor does not belong to the caller's org", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseUptimeDto" - } - } - } - }, - "404": { - "description": "Monitor not found", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseUptimeDto" - } - } - } - }, - "409": { - "description": "Conflict — the request collides with current resource state", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error — see the message field for details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "502": { - "description": "Bad gateway — an upstream provider returned an error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "503": { - "description": "Service unavailable — try again shortly", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - } - }, - "/api/v1/monitors/{id}/versions": { + "/api/v1/monitors/{id}/status-pages": { "get": { "tags": [ "Monitors" ], - "summary": "List version history for a monitor", - "description": "Returns a paginated list of mutation snapshots for the monitor, newest first. Each version captures the full monitor config at the time of a PUT /monitors/{id} call.", - "operationId": "listVersions", + "summary": "List status pages that contain this monitor as a component", + "description": "Returns all status pages where this monitor appears as a component, enabling the detail page to show 'Appears On' cross-links.", + "operationId": "listStatusPagesForMonitor", "parameters": [ { "name": "id", @@ -8321,14 +8460,6 @@ "type": "string", "format": "uuid" } - }, - { - "name": "pageable", - "in": "query", - "required": true, - "schema": { - "$ref": "#/components/schemas/Pageable" - } } ], "responses": { @@ -8337,7 +8468,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultMonitorVersionDto" + "$ref": "#/components/schemas/TableValueResultStatusPageDto" } } } @@ -8425,14 +8556,13 @@ } } }, - "/api/v1/monitors/{id}/versions/{version}": { + "/api/v1/monitors/{id}/tags": { "get": { "tags": [ "Monitors" ], - "summary": "Get a specific version snapshot for a monitor", - "description": "Returns the full monitor config snapshot captured at the given version number.", - "operationId": "getVersion", + "summary": "Get all tags applied to a monitor", + "operationId": "getMonitorTags", "parameters": [ { "name": "id", @@ -8442,15 +8572,6 @@ "type": "string", "format": "uuid" } - }, - { - "name": "version", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } } ], "responses": { @@ -8459,7 +8580,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorVersionDto" + "$ref": "#/components/schemas/TableValueResultTagDto" } } } @@ -8545,18 +8666,16 @@ } } } - } - }, - "/api/v1/monitors/{monitorId}/alert-channels": { - "put": { + }, + "post": { "tags": [ - "Monitor Alert Channels" + "Monitors" ], - "summary": "Replace the linked alert channel set for a monitor", - "operationId": "setChannels", + "summary": "Add tags to a monitor; supports existing tag IDs and inline creation of new tags", + "operationId": "addMonitorTags", "parameters": [ { - "name": "monitorId", + "name": "id", "in": "path", "required": true, "schema": { @@ -8569,7 +8688,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SetAlertChannelsRequest" + "$ref": "#/components/schemas/AddMonitorTagsRequest" } } }, @@ -8581,7 +8700,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseListUUID" + "$ref": "#/components/schemas/TableValueResultTagDto" } } } @@ -8667,18 +8786,16 @@ } } } - } - }, - "/api/v1/monitors/{monitorId}/assertions": { - "post": { + }, + "delete": { "tags": [ - "Monitor Assertions" + "Monitors" ], - "summary": "Add an assertion to a monitor", - "operationId": "add", + "summary": "Remove tags from a monitor by their IDs", + "operationId": "removeMonitorTags", "parameters": [ { - "name": "monitorId", + "name": "id", "in": "path", "required": true, "schema": { @@ -8691,22 +8808,15 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateAssertionRequest" + "$ref": "#/components/schemas/RemoveMonitorTagsRequest" } } }, "required": true }, "responses": { - "201": { - "description": "Created", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorAssertionDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -8791,25 +8901,17 @@ } } }, - "/api/v1/monitors/{monitorId}/assertions/{assertionId}": { - "put": { + "/api/v1/monitors/{id}/test": { + "post": { "tags": [ - "Monitor Assertions" + "Monitors" ], - "summary": "Update an assertion on a monitor", - "operationId": "update_10", + "summary": "Test an existing monitor", + "description": "Runs the saved config and assertions of an existing monitor once, without persisting any result. Runs synchronously and returns the same shape as the ad-hoc test. MULTI_STEP_API and BROWSER are rejected with MONITOR_CODE_CHECK_TEST_UNAVAILABLE until fleet dry-run is available.", + "operationId": "testExisting", "parameters": [ { - "name": "monitorId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "assertionId", + "name": "id", "in": "path", "required": true, "schema": { @@ -8818,138 +8920,16 @@ } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAssertionRequest" - } - } - }, - "required": true - }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorAssertionDto" - } - } - } - }, - "400": { - "description": "Bad request — the payload failed validation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden — the actor lacks permission for this resource", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Not found — the requested resource does not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "409": { - "description": "Conflict — the request collides with current resource state", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error — see the message field for details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "502": { - "description": "Bad gateway — an upstream provider returned an error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "503": { - "description": "Service unavailable — try again shortly", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseMonitorTestResultDto" } } } - } - } - }, - "delete": { - "tags": [ - "Monitor Assertions" - ], - "summary": "Remove an assertion from a monitor", - "operationId": "remove_1", - "parameters": [ - { - "name": "monitorId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "assertionId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "204": { - "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -9034,16 +9014,17 @@ } } }, - "/api/v1/monitors/{monitorId}/auth": { - "put": { + "/api/v1/monitors/{id}/test-notifications": { + "post": { "tags": [ - "Monitor Auth" + "Monitors" ], - "summary": "Update authentication config for a monitor", - "operationId": "update_9", + "summary": "Send test notifications through the monitor's alert channels", + "description": "Sends a test alert to all specified channel IDs (must be channels attached to this monitor). If no channelIds are provided, tests all attached channels. Returns per-channel results.", + "operationId": "testNotifications", "parameters": [ { - "name": "monitorId", + "name": "id", "in": "path", "required": true, "schema": { @@ -9056,7 +9037,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateMonitorAuthRequest" + "$ref": "#/components/schemas/TestMonitorNotificationsRequest" } } }, @@ -9068,7 +9049,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorAuthDto" + "$ref": "#/components/schemas/TableValueResultTestChannelResult" } } } @@ -9154,51 +9135,59 @@ } } } - }, - "post": { + } + }, + "/api/v1/monitors/{id}/uptime": { + "get": { "tags": [ - "Monitor Auth" + "Check Results" ], - "summary": "Set authentication config for a monitor", - "operationId": "set", + "summary": "Get uptime statistics", + "description": "Returns uptime percentage and latency statistics for the requested time window, computed from continuous aggregates. Uses hourly aggregates for 24h/7d windows and daily aggregates for 30d/90d windows.", + "operationId": "getUptime", "parameters": [ { - "name": "monitorId", + "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } + }, + { + "name": "window", + "in": "query", + "description": "Time window for uptime calculation", + "required": false, + "schema": { + "type": "string", + "enum": [ + "24h", + "7d", + "30d", + "90d" + ] + } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetMonitorAuthRequest" - } - } - }, - "required": true - }, "responses": { - "201": { - "description": "Created", + "200": { + "description": "Uptime statistics", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorAuthDto" + "$ref": "#/components/schemas/UptimeDto" } } } }, "400": { - "description": "Bad request — the payload failed validation", + "description": "Invalid window parameter", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseUptimeDto" } } } @@ -9214,21 +9203,21 @@ } }, "403": { - "description": "Forbidden — the actor lacks permission for this resource", + "description": "Monitor does not belong to the caller's org", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseUptimeDto" } } } }, "404": { - "description": "Not found — the requested resource does not exist", + "description": "Monitor not found", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseUptimeDto" } } } @@ -9274,27 +9263,45 @@ } } } - }, - "delete": { + } + }, + "/api/v1/monitors/{id}/versions": { + "get": { "tags": [ - "Monitor Auth" + "Monitors" ], - "summary": "Remove authentication config from a monitor", - "operationId": "remove", + "summary": "List version history for a monitor", + "description": "Returns a paginated list of mutation snapshots for the monitor, newest first. Each version captures the full monitor config at the time of a PUT /monitors/{id} call.", + "operationId": "listVersions", "parameters": [ { - "name": "monitorId", + "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } + }, + { + "name": "pageable", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/Pageable" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultMonitorVersionDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -9379,33 +9386,41 @@ } } }, - "/api/v1/monitors/{monitorId}/policy": { + "/api/v1/monitors/{id}/versions/{version}": { "get": { "tags": [ - "Incident Policies" + "Monitors" ], - "summary": "Get incident policy for a monitor", - "description": "Returns the trigger rules, confirmation settings, and recovery settings for the given monitor.", - "operationId": "get_5", + "summary": "Get a specific version snapshot for a monitor", + "description": "Returns the full monitor config snapshot captured at the given version number.", + "operationId": "getVersion", "parameters": [ { - "name": "monitorId", + "name": "id", "in": "path", - "description": "Monitor UUID", "required": true, "schema": { "type": "string", "format": "uuid" } + }, + { + "name": "version", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } } ], "responses": { "200": { - "description": "Policy found", + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/IncidentPolicyDto" + "$ref": "#/components/schemas/SingleValueResponseMonitorVersionDto" } } } @@ -9441,11 +9456,11 @@ } }, "404": { - "description": "Monitor or policy not found", + "description": "Not found — the requested resource does not exist", "content": { - "*/*": { + "application/json": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseIncidentPolicyDto" + "$ref": "#/components/schemas/ErrorResponse" } } } @@ -9491,19 +9506,19 @@ } } } - }, + } + }, + "/api/v1/monitors/{monitorId}/alert-channels": { "put": { "tags": [ - "Incident Policies" + "Monitor Alert Channels" ], - "summary": "Update incident policy for a monitor", - "description": "Replaces the trigger rules, confirmation settings, and recovery settings. All fields are validated before saving.", - "operationId": "update_8", + "summary": "Replace the linked alert channel set for a monitor", + "operationId": "setChannels", "parameters": [ { "name": "monitorId", "in": "path", - "description": "Monitor UUID", "required": true, "schema": { "type": "string", @@ -9515,119 +9530,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateIncidentPolicyRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Policy updated", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/IncidentPolicyDto" - } - } - } - }, - "400": { - "description": "Validation error in JSONB shape", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseIncidentPolicyDto" - } - } - } - }, - "401": { - "description": "Unauthorized — missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden — the actor lacks permission for this resource", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Monitor or policy not found", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseIncidentPolicyDto" - } - } - } - }, - "409": { - "description": "Conflict — the request collides with current resource state", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error — see the message field for details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "502": { - "description": "Bad gateway — an upstream provider returned an error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "503": { - "description": "Service unavailable — try again shortly", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - } - }, - "/api/v1/monitors/bulk": { - "post": { - "tags": [ - "Monitors" - ], - "summary": "Bulk action on monitors", - "description": "Applies PAUSE, RESUME, DELETE, ADD_TAG, or REMOVE_TAG to a list of monitors. Returns a partial-success response indicating which monitors succeeded and which failed.", - "operationId": "bulkAction", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BulkMonitorActionRequest" + "$ref": "#/components/schemas/SetAlertChannelsRequest" } } }, @@ -9639,7 +9542,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseBulkMonitorActionResult" + "$ref": "#/components/schemas/SingleValueResponseListUUID" } } } @@ -9727,31 +9630,41 @@ } } }, - "/api/v1/monitors/test": { + "/api/v1/monitors/{monitorId}/assertions": { "post": { "tags": [ - "Monitors" + "Monitor Assertions" + ], + "summary": "Add an assertion to a monitor", + "operationId": "add", + "parameters": [ + { + "name": "monitorId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "Ad-hoc monitor test", - "description": "Executes a one-off check from an inline config without saving the monitor. Runs synchronously and returns status code, response time, assertion results, body preview, and headers.", - "operationId": "testAdHoc", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MonitorTestRequest" + "$ref": "#/components/schemas/CreateAssertionRequest" } } }, "required": true }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseMonitorTestResultDto" + "$ref": "#/components/schemas/SingleValueResponseMonitorAssertionDto" } } } @@ -9839,19 +9752,26 @@ } } }, - "/api/v1/notification-dispatches": { - "get": { + "/api/v1/monitors/{monitorId}/assertions/{assertionId}": { + "put": { "tags": [ - "Notification Dispatches" + "Monitor Assertions" ], - "summary": "List all dispatches for an incident", - "description": "Returns all notification dispatches for the given incident that belong to the authenticated org's policies. Each dispatch includes delivery records for all associated channels.", - "operationId": "listByIncident", + "summary": "Update an assertion on a monitor", + "operationId": "update_10", "parameters": [ { - "name": "incident_id", - "in": "query", - "description": "UUID of the incident to inspect", + "name": "monitorId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "assertionId", + "in": "path", "required": true, "schema": { "type": "string", @@ -9859,13 +9779,23 @@ } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateAssertionRequest" + } + } + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultNotificationDispatchDto" + "$ref": "#/components/schemas/SingleValueResponseMonitorAssertionDto" } } } @@ -9951,19 +9881,25 @@ } } } - } - }, - "/api/v1/notification-dispatches/{id}": { - "get": { + }, + "delete": { "tags": [ - "Notification Dispatches" + "Monitor Assertions" ], - "summary": "Get a single dispatch with full escalation and delivery history", - "description": "Returns the dispatch state including current escalation step, acknowledgment info, and all delivery attempts made across every step.", - "operationId": "getById_3", + "summary": "Remove an assertion from a monitor", + "operationId": "remove_1", "parameters": [ { - "name": "id", + "name": "monitorId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "assertionId", "in": "path", "required": true, "schema": { @@ -9973,15 +9909,8 @@ } ], "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseNotificationDispatchDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -10066,17 +9995,16 @@ } } }, - "/api/v1/notification-dispatches/{id}/acknowledge": { - "post": { + "/api/v1/monitors/{monitorId}/auth": { + "put": { "tags": [ - "Notification Dispatches" + "Monitor Auth" ], - "summary": "Acknowledge a notification dispatch", - "description": "Marks the dispatch as acknowledged. The dispatch must be in DELIVERED or ESCALATING state. Sets acknowledgedAt, acknowledgedBy (actor email), and acknowledgedVia (DASHBOARD).", - "operationId": "acknowledge", + "summary": "Update authentication config for a monitor", + "operationId": "update_9", "parameters": [ { - "name": "id", + "name": "monitorId", "in": "path", "required": true, "schema": { @@ -10085,13 +10013,23 @@ } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateMonitorAuthRequest" + } + } + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseNotificationDispatchDto" + "$ref": "#/components/schemas/SingleValueResponseMonitorAuthDto" } } } @@ -10177,22 +10115,41 @@ } } } - } - }, - "/api/v1/notification-policies": { - "get": { + }, + "post": { "tags": [ - "Notification Policies" + "Monitor Auth" ], - "summary": "List all notification policies for the authenticated org", - "operationId": "list_7", + "summary": "Set authentication config for a monitor", + "operationId": "set", + "parameters": [ + { + "name": "monitorId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetMonitorAuthRequest" + } + } + }, + "required": true + }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultNotificationPolicyDto" + "$ref": "#/components/schemas/SingleValueResponseMonitorAuthDto" } } } @@ -10279,32 +10236,26 @@ } } }, - "post": { + "delete": { "tags": [ - "Notification Policies" + "Monitor Auth" ], - "summary": "Create a notification policy with match rules and escalation chain", - "operationId": "create_8", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateNotificationPolicyRequest" - } + "summary": "Remove authentication config from a monitor", + "operationId": "remove", + "parameters": [ + { + "name": "monitorId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" } - }, - "required": true - }, + } + ], "responses": { - "201": { - "description": "Created", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseNotificationPolicyDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -10389,17 +10340,19 @@ } } }, - "/api/v1/notification-policies/{id}": { + "/api/v1/monitors/{monitorId}/policy": { "get": { "tags": [ - "Notification Policies" + "Incident Policies" ], - "summary": "Get a notification policy by ID", - "operationId": "getById_1", + "summary": "Get incident policy for a monitor", + "description": "Returns the trigger rules, confirmation settings, and recovery settings for the given monitor.", + "operationId": "get_5", "parameters": [ { - "name": "id", + "name": "monitorId", "in": "path", + "description": "Monitor UUID", "required": true, "schema": { "type": "string", @@ -10409,11 +10362,11 @@ ], "responses": { "200": { - "description": "OK", + "description": "Policy found", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseNotificationPolicyDto" + "$ref": "#/components/schemas/IncidentPolicyDto" } } } @@ -10449,11 +10402,11 @@ } }, "404": { - "description": "Not found — the requested resource does not exist", + "description": "Monitor or policy not found", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseIncidentPolicyDto" } } } @@ -10502,14 +10455,16 @@ }, "put": { "tags": [ - "Notification Policies" + "Incident Policies" ], - "summary": "Update a notification policy", - "operationId": "update_7", + "summary": "Update incident policy for a monitor", + "description": "Replaces the trigger rules, confirmation settings, and recovery settings. All fields are validated before saving.", + "operationId": "update_8", "parameters": [ { - "name": "id", + "name": "monitorId", "in": "path", + "description": "Monitor UUID", "required": true, "schema": { "type": "string", @@ -10521,7 +10476,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateNotificationPolicyRequest" + "$ref": "#/components/schemas/UpdateIncidentPolicyRequest" } } }, @@ -10529,21 +10484,21 @@ }, "responses": { "200": { - "description": "OK", + "description": "Policy updated", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseNotificationPolicyDto" + "$ref": "#/components/schemas/IncidentPolicyDto" } } } }, "400": { - "description": "Bad request — the payload failed validation", + "description": "Validation error in JSONB shape", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseIncidentPolicyDto" } } } @@ -10569,11 +10524,11 @@ } }, "404": { - "description": "Not found — the requested resource does not exist", + "description": "Monitor or policy not found", "content": { - "application/json": { + "*/*": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/SingleValueResponseIncidentPolicyDto" } } } @@ -10619,27 +10574,36 @@ } } } - }, - "delete": { + } + }, + "/api/v1/monitors/bulk": { + "post": { "tags": [ - "Notification Policies" + "Monitors" ], - "summary": "Delete a notification policy", - "operationId": "delete_6", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" + "summary": "Bulk action on monitors", + "description": "Applies PAUSE, RESUME, DELETE, ADD_TAG, or REMOVE_TAG to a list of monitors. Returns a partial-success response indicating which monitors succeeded and which failed.", + "operationId": "bulkAction", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkMonitorActionRequest" + } } - } - ], + }, + "required": true + }, "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseBulkMonitorActionResult" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -10724,31 +10688,31 @@ } } }, - "/api/v1/notification-policies/{id}/dispatches": { - "get": { + "/api/v1/monitors/test": { + "post": { "tags": [ - "Notification Policies" + "Monitors" ], - "summary": "List all dispatches (firing history) for a notification policy", - "operationId": "listDispatches", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" + "summary": "Ad-hoc monitor test", + "description": "Executes a one-off check from an inline config without saving the monitor. Runs synchronously and returns status code, response time, assertion results, body preview, and headers. MULTI_STEP_API and BROWSER are rejected with MONITOR_CODE_CHECK_TEST_UNAVAILABLE until fleet dry-run is available.", + "operationId": "testAdHoc", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MonitorTestRequest" + } } - } - ], + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultNotificationDispatchDto" + "$ref": "#/components/schemas/SingleValueResponseMonitorTestResultDto" } } } @@ -10836,17 +10800,19 @@ } } }, - "/api/v1/notification-policies/{id}/test": { - "post": { + "/api/v1/notification-dispatches": { + "get": { "tags": [ - "Notification Policies" + "Notification Dispatches" ], - "summary": "Dry-run: evaluate a policy's match rules against a supplied incident context", - "operationId": "test_1", + "summary": "List all dispatches for an incident", + "description": "Returns all notification dispatches for the given incident that belong to the authenticated org's policies. Each dispatch includes delivery records for all associated channels.", + "operationId": "listByIncident", "parameters": [ { - "name": "id", - "in": "path", + "name": "incident_id", + "in": "query", + "description": "UUID of the incident to inspect", "required": true, "schema": { "type": "string", @@ -10854,22 +10820,13 @@ } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestNotificationPolicyRequest" - } - } - } - }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseTestMatchResult" + "$ref": "#/components/schemas/TableValueResultNotificationDispatchDto" } } } @@ -10957,41 +10914,135 @@ } } }, - "/api/v1/notifications": { + "/api/v1/notification-dispatches/{id}": { "get": { "tags": [ - "Notifications" + "Notification Dispatches" ], - "summary": "List notifications for the current user", - "operationId": "list_16", + "summary": "Get a single dispatch with full escalation and delivery history", + "description": "Returns the dispatch state including current escalation step, acknowledgment info, and all delivery attempts made across every step.", + "operationId": "getById_3", "parameters": [ { - "name": "unreadOnly", - "in": "query", - "required": false, + "name": "id", + "in": "path", + "required": true, "schema": { - "type": "boolean", - "default": false + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseNotificationDispatchDto" + } + } } }, - { - "name": "page", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "default": 0 + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } } }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/notification-dispatches/{id}/acknowledge": { + "post": { + "tags": [ + "Notification Dispatches" + ], + "summary": "Acknowledge a notification dispatch", + "description": "Marks the dispatch as acknowledged. The dispatch must be in DELIVERED or ESCALATING state. Sets acknowledgedAt, acknowledgedBy (actor email), and acknowledgedVia (DASHBOARD).", + "operationId": "acknowledge", + "parameters": [ { - "name": "size", - "in": "query", - "required": false, + "name": "id", + "in": "path", + "required": true, "schema": { - "type": "integer", - "format": "int32", - "default": 20 + "type": "string", + "format": "uuid" } } ], @@ -11001,7 +11052,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultNotificationDto" + "$ref": "#/components/schemas/SingleValueResponseNotificationDispatchDto" } } } @@ -11089,27 +11140,35 @@ } } }, - "/api/v1/notifications/{id}/read": { - "put": { + "/api/v1/notification-dispatches/{id}/unacknowledge": { + "post": { "tags": [ - "Notifications" + "Notification Dispatches" ], - "summary": "Mark a notification as read", - "operationId": "markRead", + "summary": "Unacknowledge a notification dispatch", + "description": "Reverses a mistaken acknowledgment without reopening the incident. Allowed only from ACKNOWLEDGED. Clears ack fields, stays on the current escalation step, restores nextEscalationAt, and resumes escalation (ESCALATING if more steps remain, else DELIVERED). MEMBER+.", + "operationId": "unacknowledge", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { - "type": "integer", - "format": "int64" + "type": "string", + "format": "uuid" } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseNotificationDispatchDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -11194,16 +11253,23 @@ } } }, - "/api/v1/notifications/read-all": { - "put": { + "/api/v1/notification-policies": { + "get": { "tags": [ - "Notifications" + "Notification Policies" ], - "summary": "Mark all notifications as read", - "operationId": "markAllRead", + "summary": "List all notification policies for the authenticated org", + "operationId": "list_7", "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultNotificationPolicyDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -11286,22 +11352,30 @@ } } } - } - }, - "/api/v1/notifications/unread-count": { - "get": { + }, + "post": { "tags": [ - "Notifications" + "Notification Policies" ], - "summary": "Get unread notification count", - "operationId": "unreadCount", + "summary": "Create a notification policy with match rules and escalation chain", + "operationId": "create_8", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateNotificationPolicyRequest" + } + } + }, + "required": true + }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseLong" + "$ref": "#/components/schemas/SingleValueResponseNotificationPolicyDto" } } } @@ -11389,20 +11463,31 @@ } } }, - "/api/v1/org": { + "/api/v1/notification-policies/{id}": { "get": { "tags": [ - "Organizations" + "Notification Policies" + ], + "summary": "Get a notification policy by ID", + "operationId": "getById_1", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "Get the current organization", - "operationId": "get_4", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseOrganizationDto" + "$ref": "#/components/schemas/SingleValueResponseNotificationPolicyDto" } } } @@ -11491,15 +11576,26 @@ }, "put": { "tags": [ - "Organizations" + "Notification Policies" + ], + "summary": "Update a notification policy", + "operationId": "update_7", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "Update the current organization", - "operationId": "update_6", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateOrgDetailsRequest" + "$ref": "#/components/schemas/UpdateNotificationPolicyRequest" } } }, @@ -11511,7 +11607,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseOrganizationDto" + "$ref": "#/components/schemas/SingleValueResponseNotificationPolicyDto" } } } @@ -11597,25 +11693,27 @@ } } } - } - }, - "/api/v1/resource-groups": { - "get": { + }, + "delete": { "tags": [ - "Resource Groups" + "Notification Policies" ], - "summary": "List all resource groups for the authenticated org with health summaries", - "operationId": "list_6", - "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/TableValueResultResourceGroupDto" - } - } + "summary": "Delete a notification policy", + "operationId": "delete_6", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" } + } + ], + "responses": { + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -11698,30 +11796,33 @@ } } } - }, - "post": { + } + }, + "/api/v1/notification-policies/{id}/dispatches": { + "get": { "tags": [ - "Resource Groups" + "Notification Policies" ], - "summary": "Create a new resource group", - "operationId": "create_7", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateResourceGroupRequest" - } + "summary": "List all dispatches (firing history) for a notification policy", + "operationId": "listDispatches", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" } - }, - "required": true - }, + } + ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseResourceGroupDto" + "$ref": "#/components/schemas/TableValueResultNotificationDispatchDto" } } } @@ -11809,14 +11910,13 @@ } } }, - "/api/v1/resource-groups/{id}": { - "get": { + "/api/v1/notification-policies/{id}/test": { + "post": { "tags": [ - "Resource Groups" + "Notification Policies" ], - "summary": "Get a resource group by id with member statuses and inherited settings", - "description": "Pass includeMetrics=true to enrich each member with 24h uptime, chart data, and latency metrics.", - "operationId": "get_3", + "summary": "Dry-run: evaluate a policy's match rules against a supplied incident context", + "operationId": "test_1", "parameters": [ { "name": "id", @@ -11826,24 +11926,24 @@ "type": "string", "format": "uuid" } - }, - { - "name": "includeMetrics", - "in": "query", - "required": false, - "schema": { - "type": "boolean", - "default": false - } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestNotificationPolicyRequest" + } + } + } + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseResourceGroupDto" + "$ref": "#/components/schemas/SingleValueResponseTestMatchResult" } } } @@ -11929,41 +12029,53 @@ } } } - }, - "put": { + } + }, + "/api/v1/notifications": { + "get": { "tags": [ - "Resource Groups" + "Notifications" ], - "summary": "Update a resource group's name, description, alert policy, inherited settings, and health threshold", - "operationId": "update_5", + "summary": "List notifications for the current user", + "operationId": "list_17", "parameters": [ { - "name": "id", - "in": "path", - "required": true, + "name": "unreadOnly", + "in": "query", + "required": false, "schema": { - "type": "string", - "format": "uuid" + "type": "boolean", + "default": false } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateResourceGroupRequest" - } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 0 } }, - "required": true - }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 20 + } + } + ], "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseResourceGroupDto" + "$ref": "#/components/schemas/TableValueResultNotificationDto" } } } @@ -12049,21 +12161,23 @@ } } } - }, - "delete": { + } + }, + "/api/v1/notifications/{id}/read": { + "put": { "tags": [ - "Resource Groups" + "Notifications" ], - "summary": "Delete a resource group (cascades to member rows)", - "operationId": "delete_5", + "summary": "Mark a notification as read", + "operationId": "markRead", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "integer", + "format": "int64" } } ], @@ -12154,35 +12268,16 @@ } } }, - "/api/v1/resource-groups/{id}/health": { - "get": { + "/api/v1/notifications/read-all": { + "put": { "tags": [ - "Resource Groups" - ], - "summary": "Get the detailed health breakdown for a resource group", - "description": "Returns member counts, worst-of status, and threshold-based health evaluation. The thresholdStatus field is populated only when a health threshold is configured.", - "operationId": "getHealth", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } + "Notifications" ], + "summary": "Mark all notifications as read", + "operationId": "markAllRead", "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseResourceGroupHealthDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -12267,41 +12362,20 @@ } } }, - "/api/v1/resource-groups/{id}/members": { - "post": { + "/api/v1/notifications/unread-count": { + "get": { "tags": [ - "Resource Groups" - ], - "summary": "Add a monitor or service member to a resource group", - "operationId": "addMember_1", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } + "Notifications" ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddResourceGroupMemberRequest" - } - } - }, - "required": true - }, + "summary": "Get unread notification count", + "operationId": "unreadCount", "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseResourceGroupMemberDto" + "$ref": "#/components/schemas/SingleValueResponseLong" } } } @@ -12389,36 +12463,23 @@ } } }, - "/api/v1/resource-groups/{id}/members/{memberId}": { - "delete": { + "/api/v1/org": { + "get": { "tags": [ - "Resource Groups" - ], - "summary": "Remove a member from a resource group", - "operationId": "removeMember_1", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "memberId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } + "Organizations" ], + "summary": "Get the current organization", + "operationId": "get_4", "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseOrganizationDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -12501,22 +12562,30 @@ } } } - } - }, - "/api/v1/secrets": { - "get": { + }, + "put": { "tags": [ - "Secrets" + "Organizations" ], - "summary": "List secrets", - "operationId": "list_5", + "summary": "Update the current organization", + "operationId": "update_6", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateOrgDetailsRequest" + } + } + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultSecretDto" + "$ref": "#/components/schemas/SingleValueResponseOrganizationDto" } } } @@ -12602,30 +12671,22 @@ } } } - }, - "post": { + } + }, + "/api/v1/resource-groups": { + "get": { "tags": [ - "Secrets" + "Resource Groups" ], - "summary": "Create secret", - "operationId": "create_6", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSecretRequest" - } - } - }, - "required": true - }, + "summary": "List all resource groups for the authenticated org with health summaries", + "operationId": "list_6", "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseSecretDto" + "$ref": "#/components/schemas/TableValueResultResourceGroupDto" } } } @@ -12711,42 +12772,30 @@ } } } - } - }, - "/api/v1/secrets/{key}": { - "put": { + }, + "post": { "tags": [ - "Secrets" - ], - "summary": "Update secret", - "operationId": "update_4", - "parameters": [ - { - "name": "key", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } + "Resource Groups" ], + "summary": "Create a new resource group", + "operationId": "create_7", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateSecretRequest" + "$ref": "#/components/schemas/CreateResourceGroupRequest" } } }, "required": true }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseSecretDto" + "$ref": "#/components/schemas/SingleValueResponseResourceGroupDto" } } } @@ -12832,26 +12881,46 @@ } } } - }, - "delete": { + } + }, + "/api/v1/resource-groups/{id}": { + "get": { "tags": [ - "Secrets" + "Resource Groups" ], - "summary": "Delete secret", - "operationId": "delete_4", + "summary": "Get a resource group by id with member statuses and inherited settings", + "description": "Pass includeMetrics=true to enrich each member with 24h uptime, chart data, and latency metrics.", + "operationId": "get_3", "parameters": [ { - "name": "key", + "name": "id", "in": "path", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" + } + }, + { + "name": "includeMetrics", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseResourceGroupDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -12934,22 +13003,41 @@ } } } - } - }, - "/api/v1/service-subscriptions": { - "get": { + }, + "put": { "tags": [ - "Service Subscriptions" + "Resource Groups" ], - "summary": "List all service subscriptions for the organization", - "operationId": "list_15", + "summary": "Update a resource group's name, description, alert policy, inherited settings, and health threshold", + "operationId": "update_5", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateResourceGroupRequest" + } + } + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultServiceSubscriptionDto" + "$ref": "#/components/schemas/SingleValueResponseResourceGroupDto" } } } @@ -13035,15 +13123,13 @@ } } } - } - }, - "/api/v1/service-subscriptions/{id}": { - "get": { + }, + "delete": { "tags": [ - "Service Subscriptions" + "Resource Groups" ], - "summary": "Get a subscription by its ID", - "operationId": "get_10", + "summary": "Delete a resource group (cascades to member rows)", + "operationId": "delete_5", "parameters": [ { "name": "id", @@ -13056,15 +13142,8 @@ } ], "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseServiceSubscriptionDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -13147,14 +13226,16 @@ } } } - }, - "delete": { + } + }, + "/api/v1/resource-groups/{id}/health": { + "get": { "tags": [ - "Service Subscriptions" + "Resource Groups" ], - "summary": "Remove a subscription by its ID", - "description": "Removes a specific subscription (whole-service or component-level). No-op if not found.", - "operationId": "unsubscribe_1", + "summary": "Get the detailed health breakdown for a resource group", + "description": "Returns member counts, worst-of status, and threshold-based health evaluation. The thresholdStatus field is populated only when a health threshold is configured.", + "operationId": "getHealth", "parameters": [ { "name": "id", @@ -13167,8 +13248,15 @@ } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseResourceGroupHealthDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -13253,14 +13341,14 @@ } } }, - "/api/v1/service-subscriptions/{id}/alert-sensitivity": { - "patch": { + "/api/v1/resource-groups/{id}/matched-policies": { + "get": { "tags": [ - "Service Subscriptions" + "Resource Groups" ], - "summary": "Update alert sensitivity for a subscription", - "description": "Controls which external incidents trigger alerts and whether they page anyone: ALL (any status change, paged), INCIDENTS_ONLY (real vendor incidents, paged), MAJOR_ONLY (only DOWN-level incidents, paged), AWARENESS (real vendor incidents tracked silently — visible on the dashboard but no alert channels fire; default for new subscriptions).", - "operationId": "updateAlertSensitivity", + "summary": "List notification policies that match this resource group", + "description": "Policies whose match rules evaluate true for a DEGRADED or DOWN group-origin INCIDENT_CREATED context on this resource group (includes paused)", + "operationId": "listMatchedPolicies", "parameters": [ { "name": "id", @@ -13272,23 +13360,13 @@ } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAlertSensitivityRequest" - } - } - }, - "required": true - }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseServiceSubscriptionDto" + "$ref": "#/components/schemas/TableValueResultNotificationPolicyDto" } } } @@ -13376,21 +13454,21 @@ } } }, - "/api/v1/service-subscriptions/{slug}": { + "/api/v1/resource-groups/{id}/members": { "post": { "tags": [ - "Service Subscriptions" + "Resource Groups" ], - "summary": "Subscribe to a service or a component of a service", - "description": "Idempotent — returns the existing subscription if an identical one exists. Omit the request body or set componentId to null for a whole-service subscription. When alertSensitivity is omitted, new subscriptions default to AWARENESS (silent tracking — the incident appears on the dashboard but no alert channels fire). PATCH /alert-sensitivity to opt in to paging. Free tier: max 10 subscriptions. Paid tier: unlimited.", - "operationId": "subscribe_1", + "summary": "Add a monitor or service member to a resource group", + "operationId": "addMember_1", "parameters": [ { - "name": "slug", + "name": "id", "in": "path", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], @@ -13398,10 +13476,11 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ServiceSubscribeRequest" + "$ref": "#/components/schemas/AddResourceGroupMemberRequest" } } - } + }, + "required": true }, "responses": { "201": { @@ -13409,7 +13488,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseServiceSubscriptionDto" + "$ref": "#/components/schemas/SingleValueResponseResourceGroupMemberDto" } } } @@ -13497,90 +13576,36 @@ } } }, - "/api/v1/services": { - "get": { + "/api/v1/resource-groups/{id}/members/{memberId}": { + "delete": { "tags": [ - "Status Data" + "Resource Groups" ], - "summary": "List all enabled services (cursor-paginated)", - "operationId": "listServices", + "summary": "Remove a member from a resource group", + "operationId": "removeMember_1", "parameters": [ { - "name": "category", - "in": "query", - "description": "Filter by category (exact match)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "status", - "in": "query", - "description": "Filter by current overall_status (exact match)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "published", - "in": "query", - "description": "Filter by published status for pSEO pages", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "search", - "in": "query", - "description": "Case-insensitive substring match on service name or slug", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "sort", - "in": "query", - "description": "Result ordering: 'recent' (default, newest first) or 'curated' (curated/recognizable first)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "cursor", - "in": "query", - "description": "Opaque cursor from a previous response", - "required": false, + "name": "id", + "in": "path", + "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } }, { - "name": "limit", - "in": "query", - "description": "Page size (1–100, default 20)", - "required": false, + "name": "memberId", + "in": "path", + "required": true, "schema": { - "type": "integer", - "format": "int32", - "default": 20 + "type": "string", + "format": "uuid" } } ], "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/CursorPageServiceCatalogDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -13665,51 +13690,20 @@ } } }, - "/api/v1/services/{slugOrId}": { + "/api/v1/secrets": { "get": { "tags": [ - "Status Data" - ], - "summary": "Get a single service by slug or UUID with current status, components, and recent incidents", - "description": "When ``summary=true``, the inline ``components`` list is trimmed to groups + showcase leaves + currently-impacted leaves + ungrouped leaves, and a ``componentsSummary`` block is added with the trimmed counts. Powers SSR for vendors with hundreds of components (Snowflake, Cloudflare, DigitalOcean) without OOM-ing the renderer. Default false for full back-compat.", - "operationId": "getService", - "parameters": [ - { - "name": "slugOrId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "summary", - "in": "query", - "description": "Return a curated subset of components (groups + showcase + impacted + ungrouped) and a componentsSummary block; default false", - "required": false, - "schema": { - "type": "boolean", - "default": false - } - }, - { - "name": "publishedOnly", - "in": "query", - "description": "Resolve only published services (curated public pSEO set); 404 otherwise. Default false", - "required": false, - "schema": { - "type": "boolean", - "default": false - } - } + "Secrets" ], + "summary": "List secrets", + "operationId": "list_5", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseServiceDetailDto" + "$ref": "#/components/schemas/TableValueResultSecretDto" } } } @@ -13795,43 +13789,30 @@ } } } - } - }, - "/api/v1/services/{slugOrId}/components": { - "get": { + }, + "post": { "tags": [ - "Status Data" + "Secrets" ], - "summary": "List active components for a service with current status and inline uptime", - "description": "When ``groupId`` is supplied, only direct children of that group are returned — used by the pSEO renderer to lazy-load the leaves under a group that summary mode trimmed. Without ``groupId`` the response includes every active component for the service.", - "operationId": "getComponents", - "parameters": [ - { - "name": "slugOrId", - "in": "path", - "required": true, - "schema": { - "type": "string" + "summary": "Create secret", + "operationId": "create_6", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSecretRequest" + } } }, - { - "name": "groupId", - "in": "query", - "description": "Restrict result to direct children of this group component id", - "required": false, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], + "required": true + }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultServiceComponentDto" + "$ref": "#/components/schemas/SingleValueResponseSecretDto" } } } @@ -13919,75 +13900,40 @@ } } }, - "/api/v1/services/{slugOrId}/components/{componentId}/uptime": { - "get": { + "/api/v1/secrets/{key}": { + "put": { "tags": [ - "Status Data" + "Secrets" ], - "summary": "Get daily uptime data for a component", - "description": "Pass either ``period`` (preset window) or an explicit ``from``/``to`` calendar window (ISO yyyy-MM-dd, max 730 days, ``to`` defaults to today). When both are supplied, the explicit window wins.", - "operationId": "getComponentUptime", + "summary": "Update secret", + "operationId": "update_4", "parameters": [ { - "name": "slugOrId", + "name": "key", "in": "path", "required": true, "schema": { "type": "string" } - }, - { - "name": "componentId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "period", - "in": "query", - "description": "Preset time window (used when ``from`` is omitted)", - "required": false, - "schema": { - "type": "string", - "enum": [ - "7d", - "30d", - "90d", - "1y" - ] - } - }, - { - "name": "from", - "in": "query", - "description": "Explicit window start (ISO date); overrides ``period``", - "required": false, - "schema": { - "type": "string", - "format": "date" - } - }, - { - "name": "to", - "in": "query", - "description": "Explicit window end (ISO date); defaults to today", - "required": false, - "schema": { - "type": "string", - "format": "date" - } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSecretRequest" + } + } + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultComponentUptimeDayDto" + "$ref": "#/components/schemas/SingleValueResponseSecretDto" } } } @@ -14073,68 +14019,124 @@ } } } - } - }, - "/api/v1/services/{slugOrId}/components/uptime": { - "get": { + }, + "delete": { "tags": [ - "Status Data" + "Secrets" ], - "summary": "Batch daily uptime data for all leaf components", - "description": "Returns daily uptime for every active non-group component with uptime data, keyed by component ID. Replaces N individual per-component uptime calls with a single request. Supports either a preset ``period`` or an explicit ``from``/``to`` window (ISO yyyy-MM-dd, max 730 days). The explicit window wins when both are supplied — this is what powers the sliding 90-day navigator on the public uptime history page.", - "operationId": "getBatchComponentUptime", + "summary": "Delete secret", + "operationId": "delete_4", "parameters": [ { - "name": "slugOrId", + "name": "key", "in": "path", "required": true, "schema": { "type": "string" } + } + ], + "responses": { + "204": { + "description": "No Content" }, - { - "name": "period", - "in": "query", - "description": "Preset time window (used when ``from`` is omitted)", - "required": false, - "schema": { - "type": "string", - "enum": [ - "7d", - "30d", - "90d", - "1y" - ] + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } } }, - { - "name": "from", - "in": "query", - "description": "Explicit window start (ISO date); overrides ``period``", - "required": false, - "schema": { - "type": "string", - "format": "date" + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } } }, - { - "name": "to", - "in": "query", - "description": "Explicit window end (ISO date); defaults to today", - "required": false, - "schema": { - "type": "string", - "format": "date" + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } } } + } + } + }, + "/api/v1/service-subscriptions": { + "get": { + "tags": [ + "Service Subscriptions" ], + "summary": "List all service subscriptions for the organization", + "operationId": "list_16", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseBatchComponentUptimeDto" + "$ref": "#/components/schemas/TableValueResultServiceSubscriptionDto" } } } @@ -14222,31 +14224,21 @@ } } }, - "/api/v1/services/{slugOrId}/days/{date}": { + "/api/v1/service-subscriptions/{id}": { "get": { "tags": [ - "Status Data" + "Service Subscriptions" ], - "summary": "One-day rollup for a service: aggregated uptime, per-component impacts, and overlapping incidents", - "description": "Powers the click/hover-to-expand panel under each uptime bar on the public status page. Single round-trip — components, sums, and overlapping incidents (with affected component names) are returned in one response.", - "operationId": "getServiceDayDetail", + "summary": "Get a subscription by its ID", + "operationId": "get_11", "parameters": [ { - "name": "slugOrId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "date", + "name": "id", "in": "path", - "description": "UTC calendar day in ISO format (YYYY-MM-DD)", "required": true, "schema": { "type": "string", - "format": "date" + "format": "uuid" } } ], @@ -14256,7 +14248,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseServiceDayDetailDto" + "$ref": "#/components/schemas/SingleValueResponseServiceSubscriptionDto" } } } @@ -14342,66 +14334,28 @@ } } } - } - }, - "/api/v1/services/{slugOrId}/incidents": { - "get": { + }, + "delete": { "tags": [ - "Status Data" + "Service Subscriptions" ], - "summary": "List incident history for a service (paginated)", - "operationId": "listIncidents_1", + "summary": "Remove a subscription by its ID", + "description": "Removes a specific subscription (whole-service or component-level). No-op if not found.", + "operationId": "unsubscribe_1", "parameters": [ { - "name": "slugOrId", + "name": "id", "in": "path", "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "from", - "in": "query", - "description": "Earliest start date (ISO 8601 date)", - "required": false, - "schema": { - "type": "string", - "format": "date" - } - }, - { - "name": "status", - "in": "query", - "description": "Filter: active (unresolved), resolved, or omit for all", - "required": false, "schema": { "type": "string", - "enum": [ - "active", - "resolved" - ] - } - }, - { - "name": "pageable", - "in": "query", - "required": true, - "schema": { - "$ref": "#/components/schemas/Pageable" + "format": "uuid" } } ], "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/TableValueResultServiceIncidentDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -14486,24 +14440,17 @@ } } }, - "/api/v1/services/{slugOrId}/incidents/{incidentId}": { - "get": { + "/api/v1/service-subscriptions/{id}/alert-sensitivity": { + "patch": { "tags": [ - "Status Data" + "Service Subscriptions" ], - "summary": "Get incident detail with full update timeline", - "operationId": "getIncident_1", + "summary": "Update alert sensitivity for a subscription", + "description": "Controls which external incidents trigger alerts and whether they page anyone: ALL (any status change, paged), INCIDENTS_ONLY (real vendor incidents, paged), MAJOR_ONLY (only DOWN-level incidents, paged), AWARENESS (real vendor incidents tracked silently — visible on the dashboard but no alert channels fire; default for new subscriptions).", + "operationId": "updateAlertSensitivity", "parameters": [ { - "name": "slugOrId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "incidentId", + "name": "id", "in": "path", "required": true, "schema": { @@ -14512,13 +14459,23 @@ } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateAlertSensitivityRequest" + } + } + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseServiceIncidentDetailDto" + "$ref": "#/components/schemas/SingleValueResponseServiceSubscriptionDto" } } } @@ -14606,17 +14563,17 @@ } } }, - "/api/v1/services/{slugOrId}/live-status": { - "get": { + "/api/v1/service-subscriptions/{slug}": { + "post": { "tags": [ - "Status Data" + "Service Subscriptions" ], - "summary": "Lightweight live-status snapshot for polling", - "description": "Returns only the current overall status, component statuses, and active incident count. Designed for frequent polling with minimal payload.", - "operationId": "getServiceLiveStatus", + "summary": "Subscribe to a service or a component of a service", + "description": "Idempotent — returns the existing subscription if an identical one exists. Omit the request body or set componentId to null for a whole-service subscription. When alertSensitivity is omitted, new subscriptions default to AWARENESS (silent tracking — the incident appears on the dashboard but no alert channels fire). PATCH /alert-sensitivity to opt in to paging. Free tier: max 10 subscriptions. Paid tier: unlimited.", + "operationId": "subscribe_1", "parameters": [ { - "name": "slugOrId", + "name": "slug", "in": "path", "required": true, "schema": { @@ -14624,13 +14581,22 @@ } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceSubscribeRequest" + } + } + } + }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseServiceLiveStatusDto" + "$ref": "#/components/schemas/SingleValueResponseServiceSubscriptionDto" } } } @@ -14718,18 +14684,19 @@ } } }, - "/api/v1/services/{slugOrId}/maintenances": { + "/api/v1/services": { "get": { "tags": [ "Status Data" ], - "summary": "List scheduled maintenances for a service", - "operationId": "getScheduledMaintenances", + "summary": "List all enabled services (cursor-paginated)", + "operationId": "listServices", "parameters": [ { - "name": "slugOrId", - "in": "path", - "required": true, + "name": "category", + "in": "query", + "description": "Filter by category (exact match)", + "required": false, "schema": { "type": "string" } @@ -14737,13 +14704,66 @@ { "name": "status", "in": "query", - "description": "Filter by status (e.g. scheduled, in_progress, verifying, completed)", + "description": "Filter by current overall_status (exact match)", "required": false, "schema": { - "type": "array", - "items": { - "type": "string" - } + "type": "string" + } + }, + { + "name": "published", + "in": "query", + "description": "Filter by published status for pSEO pages", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "slaPublished", + "in": "query", + "description": "Filter by SLA page publication status", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "search", + "in": "query", + "description": "Case-insensitive substring match on service name or slug", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "sort", + "in": "query", + "description": "Result ordering: 'recent' (default, newest first) or 'curated' (curated/recognizable first)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "cursor", + "in": "query", + "description": "Opaque cursor from a previous response", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Page size (1–100, default 20)", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 20 } } ], @@ -14753,7 +14773,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultScheduledMaintenanceDto" + "$ref": "#/components/schemas/CursorPageServiceCatalogDto" } } } @@ -14841,13 +14861,14 @@ } } }, - "/api/v1/services/{slugOrId}/poll-results": { + "/api/v1/services/{slugOrId}": { "get": { "tags": [ "Status Data" ], - "summary": "List poll results for a service (cursor-paginated)", - "operationId": "listPollResults", + "summary": "Get a single service by slug or UUID with current status, components, and recent incidents", + "description": "When ``summary=true``, the inline ``components`` list is trimmed to groups + showcase leaves + currently-impacted leaves + ungrouped leaves, and a ``componentsSummary`` block is added with the trimmed counts. Powers SSR for vendors with hundreds of components (Snowflake, Cloudflare, DigitalOcean) without OOM-ing the renderer. Default false for full back-compat.", + "operationId": "getService", "parameters": [ { "name": "slugOrId", @@ -14858,23 +14879,23 @@ } }, { - "name": "cursor", + "name": "summary", "in": "query", - "description": "ISO 8601 timestamp cursor from a previous response", + "description": "Return a curated subset of components (groups + showcase + impacted + ungrouped) and a componentsSummary block; default false", "required": false, "schema": { - "type": "string" + "type": "boolean", + "default": false } }, { - "name": "limit", + "name": "publishedOnly", "in": "query", - "description": "Page size (1–100, default 50)", + "description": "Resolve only published services (curated public pSEO set); 404 otherwise. Default false", "required": false, "schema": { - "type": "integer", - "format": "int32", - "default": 50 + "type": "boolean", + "default": false } } ], @@ -14884,7 +14905,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/CursorPageServicePollResultDto" + "$ref": "#/components/schemas/SingleValueResponseServiceDetailDto" } } } @@ -14972,13 +14993,14 @@ } } }, - "/api/v1/services/{slugOrId}/poll-summary": { + "/api/v1/services/{slugOrId}/components": { "get": { "tags": [ "Status Data" ], - "summary": "Get aggregated poll metrics and chart data for a service", - "operationId": "getPollSummary", + "summary": "List active components for a service with current status and inline uptime", + "description": "When ``groupId`` is supplied, only direct children of that group are returned — used by the pSEO renderer to lazy-load the leaves under a group that summary mode trimmed. Without ``groupId`` the response includes every active component for the service. Supports pagination via ``page``/``size`` and case-insensitive name search via ``search``.", + "operationId": "getComponents", "parameters": [ { "name": "slugOrId", @@ -14989,17 +15011,42 @@ } }, { - "name": "window", + "name": "groupId", "in": "query", - "description": "Time window", + "description": "Restrict result to direct children of this group component id", "required": false, "schema": { "type": "string", - "enum": [ - "24h", - "7d", - "30d" - ] + "format": "uuid" + } + }, + { + "name": "search", + "in": "query", + "description": "Case-insensitive substring match on component name", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "page", + "in": "query", + "description": "Zero-based page index", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "size", + "in": "query", + "description": "Page size (default 25, max 100)", + "required": false, + "schema": { + "type": "integer", + "format": "int32" } } ], @@ -15009,7 +15056,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseServicePollSummaryDto" + "$ref": "#/components/schemas/TableValueResultServiceComponentDto" } } } @@ -15097,14 +15144,14 @@ } } }, - "/api/v1/services/{slugOrId}/uptime": { + "/api/v1/services/{slugOrId}/components/{componentId}/uptime": { "get": { "tags": [ "Status Data" ], - "summary": "Get uptime statistics for a service", - "description": "Uptime data aggregated across active non-group components.", - "operationId": "getServiceUptime", + "summary": "Get daily uptime data for a component", + "description": "Pass either ``period`` (preset window) or an explicit ``from``/``to`` calendar window (ISO yyyy-MM-dd, max 730 days, ``to`` defaults to today). When both are supplied, the explicit window wins.", + "operationId": "getComponentUptime", "parameters": [ { "name": "slugOrId", @@ -15114,36 +15161,48 @@ "type": "string" } }, + { + "name": "componentId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, { "name": "period", "in": "query", - "description": "Time window", + "description": "Preset time window (used when ``from`` is omitted)", "required": false, "schema": { "type": "string", "enum": [ - "24h", "7d", "30d", "90d", - "1y", - "2y", - "all" + "1y" ] } }, { - "name": "granularity", + "name": "from", "in": "query", - "description": "Bucket granularity", + "description": "Explicit window start (ISO date); overrides ``period``", "required": false, "schema": { "type": "string", - "enum": [ - "hourly", - "daily", - "monthly" - ] + "format": "date" + } + }, + { + "name": "to", + "in": "query", + "description": "Explicit window end (ISO date); defaults to today", + "required": false, + "schema": { + "type": "string", + "format": "date" } } ], @@ -15153,7 +15212,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseServiceUptimeResponse" + "$ref": "#/components/schemas/TableValueResultComponentUptimeDayDto" } } } @@ -15238,61 +15297,59 @@ } } } - }, - "security": [ - { - "BearerAuth": [] - } - ] + } } }, - "/api/v1/services/incidents": { + "/api/v1/services/{slugOrId}/components/uptime": { "get": { "tags": [ "Status Data" ], - "summary": "List vendor incidents across all services (paginated)", - "description": "Cross-service vendor incident feed ordered by start date descending.", - "operationId": "listCrossServiceIncidents", + "summary": "Batch daily uptime data for all leaf components", + "description": "Returns daily uptime for every active non-group component with uptime data, keyed by component ID. Replaces N individual per-component uptime calls with a single request. Supports either a preset ``period`` or an explicit ``from``/``to`` window (ISO yyyy-MM-dd, max 730 days). The explicit window wins when both are supplied — this is what powers the sliding 90-day navigator on the public uptime history page.", + "operationId": "getBatchComponentUptime", "parameters": [ { - "name": "from", - "in": "query", - "description": "Earliest start date (ISO 8601 date)", - "required": false, + "name": "slugOrId", + "in": "path", + "required": true, "schema": { - "type": "string", - "format": "date" + "type": "string" } }, { - "name": "status", + "name": "period", "in": "query", - "description": "Filter: active (unresolved), resolved, or omit for all", + "description": "Preset time window (used when ``from`` is omitted)", "required": false, "schema": { "type": "string", "enum": [ - "active", - "resolved" + "7d", + "30d", + "90d", + "1y" ] } }, { - "name": "category", + "name": "from", "in": "query", - "description": "Filter by service category", + "description": "Explicit window start (ISO date); overrides ``period``", "required": false, "schema": { - "type": "string" + "type": "string", + "format": "date" } }, { - "name": "pageable", + "name": "to", "in": "query", - "required": true, + "description": "Explicit window end (ISO date); defaults to today", + "required": false, "schema": { - "$ref": "#/components/schemas/Pageable" + "type": "string", + "format": "date" } } ], @@ -15302,7 +15359,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultServiceIncidentDto" + "$ref": "#/components/schemas/SingleValueResponseBatchComponentUptimeDto" } } } @@ -15390,23 +15447,31 @@ } } }, - "/api/v1/services/summary": { + "/api/v1/services/{slugOrId}/days/{date}": { "get": { "tags": [ "Status Data" ], - "summary": "Global status summary across all services", - "description": "Returns aggregate counts of services by status and a list of services currently experiencing issues.", - "operationId": "getGlobalStatusSummary", + "summary": "One-day rollup for a service: aggregated uptime, per-component impacts, and overlapping incidents", + "description": "Powers the click/hover-to-expand panel under each uptime bar on the public status page. Single round-trip — components, sums, and overlapping incidents (with affected component names) are returned in one response.", + "operationId": "getServiceDayDetail", "parameters": [ { - "name": "publishedOnly", - "in": "query", - "description": "Aggregate only published services (curated public pSEO set); default false", - "required": false, + "name": "slugOrId", + "in": "path", + "required": true, "schema": { - "type": "boolean", - "default": false + "type": "string" + } + }, + { + "name": "date", + "in": "path", + "description": "UTC calendar day in ISO format (YYYY-MM-DD)", + "required": true, + "schema": { + "type": "string", + "format": "date" } } ], @@ -15416,7 +15481,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseGlobalStatusSummaryDto" + "$ref": "#/components/schemas/SingleValueResponseServiceDayDetailDto" } } } @@ -15504,129 +15569,61 @@ } } }, - "/api/v1/status-pages": { + "/api/v1/services/{slugOrId}/incidents": { "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "List status pages for the workspace", - "operationId": "list_4", - "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/TableValueResultStatusPageDto" - } - } - } - }, - "400": { - "description": "Bad request — the payload failed validation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden — the actor lacks permission for this resource", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Not found — the requested resource does not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "409": { - "description": "Conflict — the request collides with current resource state", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } + "summary": "List incident history for a service (paginated)", + "operationId": "listIncidents_1", + "parameters": [ + { + "name": "slugOrId", + "in": "path", + "required": true, + "schema": { + "type": "string" } }, - "500": { - "description": "Internal server error — see the message field for details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } + { + "name": "from", + "in": "query", + "description": "Earliest start date (ISO 8601 date)", + "required": false, + "schema": { + "type": "string", + "format": "date" } }, - "502": { - "description": "Bad gateway — an upstream provider returned an error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } + { + "name": "status", + "in": "query", + "description": "Filter: active (unresolved), resolved, or omit for all", + "required": false, + "schema": { + "type": "string", + "enum": [ + "active", + "resolved" + ] } }, - "503": { - "description": "Service unavailable — try again shortly", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } + { + "name": "pageable", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/Pageable" } } - } - }, - "post": { - "tags": [ - "Status Pages" ], - "summary": "Create a status page", - "operationId": "create_5", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateStatusPageRequest" - } - } - }, - "required": true - }, "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageDto" + "$ref": "#/components/schemas/TableValueResultServiceIncidentDto" } } } @@ -15714,16 +15711,24 @@ } } }, - "/api/v1/status-pages/{id}": { + "/api/v1/services/{slugOrId}/incidents/{incidentId}": { "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "Get a status page", - "operationId": "get_2", + "summary": "Get incident detail with full update timeline", + "operationId": "getIncident_1", "parameters": [ { - "name": "id", + "name": "slugOrId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "incidentId", "in": "path", "required": true, "schema": { @@ -15738,7 +15743,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageDto" + "$ref": "#/components/schemas/SingleValueResponseServiceIncidentDetailDto" } } } @@ -15824,41 +15829,33 @@ } } } - }, - "put": { + } + }, + "/api/v1/services/{slugOrId}/live-status": { + "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "Update a status page", - "operationId": "update_3", + "summary": "Lightweight live-status snapshot for polling", + "description": "Returns only the current overall status, component statuses, and active incident count. Designed for frequent polling with minimal payload.", + "operationId": "getServiceLiveStatus", "parameters": [ { - "name": "id", + "name": "slugOrId", "in": "path", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "string" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateStatusPageRequest" - } - } - }, - "required": true - }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageDto" + "$ref": "#/components/schemas/SingleValueResponseServiceLiveStatusDto" } } } @@ -15944,27 +15941,47 @@ } } } - }, - "delete": { + } + }, + "/api/v1/services/{slugOrId}/maintenances": { + "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "Delete a status page", - "operationId": "delete_3", + "summary": "List scheduled maintenances for a service", + "operationId": "getScheduledMaintenances", "parameters": [ { - "name": "id", + "name": "slugOrId", "in": "path", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "description": "Filter by status (e.g. scheduled, in_progress, verifying, completed)", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultScheduledMaintenanceDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -16049,21 +16066,40 @@ } } }, - "/api/v1/status-pages/{id}/components": { + "/api/v1/services/{slugOrId}/poll-results": { "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "List all components", - "operationId": "listComponents", + "summary": "List poll results for a service (cursor-paginated)", + "operationId": "listPollResults", "parameters": [ { - "name": "id", + "name": "slugOrId", "in": "path", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "string" + } + }, + { + "name": "cursor", + "in": "query", + "description": "ISO 8601 timestamp cursor from a previous response", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Page size (1–100, default 50)", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 50 } } ], @@ -16073,7 +16109,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultStatusPageComponentDto" + "$ref": "#/components/schemas/CursorPageServicePollResultDto" } } } @@ -16159,41 +16195,46 @@ } } } - }, - "post": { + } + }, + "/api/v1/services/{slugOrId}/poll-summary": { + "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "Add a component to the status page", - "operationId": "createComponent", + "summary": "Get aggregated poll metrics and chart data for a service", + "operationId": "getPollSummary", "parameters": [ { - "name": "id", + "name": "slugOrId", "in": "path", "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "window", + "in": "query", + "description": "Time window", + "required": false, "schema": { "type": "string", - "format": "uuid" + "enum": [ + "24h", + "7d", + "30d" + ] } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateStatusPageComponentRequest" - } - } - }, - "required": true - }, "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentDto" + "$ref": "#/components/schemas/SingleValueResponseServicePollSummaryDto" } } } @@ -16281,50 +16322,94 @@ } } }, - "/api/v1/status-pages/{id}/components/{componentId}": { - "put": { + "/api/v1/services/{slugOrId}/status-events": { + "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "Update a component", - "operationId": "updateComponent", + "summary": "List curated vendor status events for a service", + "description": "Reverse-chronological merge of vendor incidents, maintenances, and rolled-up component transitions for the Dependencies Detail rail. Optional JWT + x-phelm-org-id annotates incident.opened rows with the caller's linked internal incident.", + "operationId": "listStatusEvents", "parameters": [ { - "name": "id", + "name": "slugOrId", "in": "path", "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "types", + "in": "query", + "description": "Comma-separated type buckets: incident, maintenance, component (default: all)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "period", + "in": "query", + "description": "Preset window", + "required": false, "schema": { "type": "string", - "format": "uuid" + "enum": [ + "7d", + "30d", + "90d" + ] } }, { - "name": "componentId", - "in": "path", - "required": true, + "name": "from", + "in": "query", + "description": "Explicit lower bound (ISO 8601); overrides period", + "required": false, "schema": { "type": "string", - "format": "uuid" + "format": "date-time" } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateStatusPageComponentRequest" - } + }, + { + "name": "to", + "in": "query", + "description": "Explicit upper bound (ISO 8601); default now", + "required": false, + "schema": { + "type": "string", + "format": "date-time" } }, - "required": true - }, + { + "name": "cursor", + "in": "query", + "description": "Opaque cursor from a previous response", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Page size (1–100, default 50)", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 50 + } + } + ], "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentDto" + "$ref": "#/components/schemas/CursorPageStatusEventDto" } } } @@ -16410,36 +16495,68 @@ } } } - }, - "delete": { + } + }, + "/api/v1/services/{slugOrId}/uptime": { + "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "Remove a component from the status page", - "operationId": "deleteComponent", + "summary": "Get uptime statistics for a service", + "description": "Uptime data aggregated across active non-group components.", + "operationId": "getServiceUptime", "parameters": [ { - "name": "id", + "name": "slugOrId", "in": "path", "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "period", + "in": "query", + "description": "Time window", + "required": false, "schema": { "type": "string", - "format": "uuid" + "enum": [ + "24h", + "7d", + "30d", + "90d", + "1y", + "2y", + "all" + ] } }, { - "name": "componentId", - "in": "path", - "required": true, + "name": "granularity", + "in": "query", + "description": "Bucket granularity", + "required": false, "schema": { "type": "string", - "format": "uuid" + "enum": [ + "hourly", + "daily", + "monthly" + ] } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseServiceUptimeResponse" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -16521,43 +16638,61 @@ } } } - } + }, + "security": [ + { + "BearerAuth": [] + } + ] } }, - "/api/v1/status-pages/{id}/components/{componentId}/uptime": { + "/api/v1/services/incidents": { "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "Get component uptime history (daily rollups)", - "operationId": "componentUptime_1", + "summary": "List vendor incidents across all services (paginated)", + "description": "Cross-service vendor incident feed ordered by start date descending.", + "operationId": "listCrossServiceIncidents", "parameters": [ { - "name": "id", - "in": "path", - "required": true, + "name": "from", + "in": "query", + "description": "Earliest start date (ISO 8601 date)", + "required": false, "schema": { "type": "string", - "format": "uuid" + "format": "date" } }, { - "name": "componentId", - "in": "path", - "required": true, + "name": "status", + "in": "query", + "description": "Filter: active (unresolved), resolved, or omit for all", + "required": false, "schema": { "type": "string", - "format": "uuid" + "enum": [ + "active", + "resolved" + ] } }, { - "name": "days", + "name": "category", "in": "query", + "description": "Filter by service category", "required": false, "schema": { - "type": "integer", - "format": "int32", - "default": 90 + "type": "string" + } + }, + { + "name": "pageable", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/Pageable" } } ], @@ -16567,7 +16702,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultComponentUptimeDayDto" + "$ref": "#/components/schemas/TableValueResultServiceIncidentDto" } } } @@ -16655,38 +16790,37 @@ } } }, - "/api/v1/status-pages/{id}/components/reorder": { - "put": { + "/api/v1/services/summary": { + "get": { "tags": [ - "Status Pages" + "Status Data" ], - "summary": "Batch reorder components (and optionally move between groups)", - "operationId": "reorderComponents", + "summary": "Global status summary across all services", + "description": "Returns aggregate counts of services by status and a list of services currently experiencing issues.", + "operationId": "getGlobalStatusSummary", "parameters": [ { - "name": "id", - "in": "path", - "required": true, + "name": "publishedOnly", + "in": "query", + "description": "Aggregate only published services (curated public pSEO set); default false", + "required": false, "schema": { - "type": "string", - "format": "uuid" + "type": "boolean", + "default": false } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReorderComponentsRequest" + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseGlobalStatusSummaryDto" + } } } }, - "required": true - }, - "responses": { - "204": { - "description": "No Content" - }, "400": { "description": "Bad request — the payload failed validation", "content": { @@ -16770,31 +16904,20 @@ } } }, - "/api/v1/status-pages/{id}/domains": { + "/api/v1/status-pages": { "get": { "tags": [ "Status Pages" ], - "summary": "List custom domains", - "operationId": "listDomains", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], + "summary": "List status pages for the workspace", + "operationId": "list_4", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultStatusPageCustomDomainDto" + "$ref": "#/components/schemas/TableValueResultStatusPageDto" } } } @@ -16885,24 +17008,13 @@ "tags": [ "Status Pages" ], - "summary": "Add a custom domain", - "operationId": "addDomain", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], + "summary": "Create a status page", + "operationId": "create_5", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AddCustomDomainRequest" + "$ref": "#/components/schemas/CreateStatusPageRequest" } } }, @@ -16914,7 +17026,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageCustomDomainDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageDto" } } } @@ -17002,13 +17114,13 @@ } } }, - "/api/v1/status-pages/{id}/domains/{domainId}": { - "delete": { + "/api/v1/status-pages/{id}": { + "get": { "tags": [ "Status Pages" ], - "summary": "Remove a custom domain", - "operationId": "removeDomain", + "summary": "Get a status page", + "operationId": "get_2", "parameters": [ { "name": "id", @@ -17018,20 +17130,18 @@ "type": "string", "format": "uuid" } - }, - { - "name": "domainId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseStatusPageDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -17114,15 +17224,13 @@ } } } - } - }, - "/api/v1/status-pages/{id}/domains/{domainId}/primary": { - "post": { + }, + "put": { "tags": [ "Status Pages" ], - "summary": "Mark a verified custom domain as the page's primary host", - "operationId": "setPrimaryDomain", + "summary": "Update a status page", + "operationId": "update_3", "parameters": [ { "name": "id", @@ -17132,24 +17240,25 @@ "type": "string", "format": "uuid" } - }, - { - "name": "domainId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateStatusPageRequest" + } + } + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageCustomDomainDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageDto" } } } @@ -17235,15 +17344,13 @@ } } } - } - }, - "/api/v1/status-pages/{id}/domains/{domainId}/verify": { - "post": { + }, + "delete": { "tags": [ "Status Pages" ], - "summary": "Trigger domain verification check", - "operationId": "verifyDomain", + "summary": "Delete a status page", + "operationId": "delete_3", "parameters": [ { "name": "id", @@ -17253,27 +17360,11 @@ "type": "string", "format": "uuid" } - }, - { - "name": "domainId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } } ], "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageCustomDomainDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -17358,13 +17449,13 @@ } } }, - "/api/v1/status-pages/{id}/groups": { + "/api/v1/status-pages/{id}/components": { "get": { "tags": [ "Status Pages" ], - "summary": "List component groups with nested components", - "operationId": "listGroups", + "summary": "List all components", + "operationId": "listComponents", "parameters": [ { "name": "id", @@ -17382,7 +17473,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultStatusPageComponentGroupDto" + "$ref": "#/components/schemas/TableValueResultStatusPageComponentDto" } } } @@ -17473,8 +17564,8 @@ "tags": [ "Status Pages" ], - "summary": "Create a component group", - "operationId": "createGroup", + "summary": "Add a component to the status page", + "operationId": "createComponent", "parameters": [ { "name": "id", @@ -17490,7 +17581,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateStatusPageComponentGroupRequest" + "$ref": "#/components/schemas/CreateStatusPageComponentRequest" } } }, @@ -17502,7 +17593,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentGroupDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentDto" } } } @@ -17590,13 +17681,13 @@ } } }, - "/api/v1/status-pages/{id}/groups/{groupId}": { + "/api/v1/status-pages/{id}/components/{componentId}": { "put": { "tags": [ "Status Pages" ], - "summary": "Update a component group", - "operationId": "updateGroup", + "summary": "Update a component", + "operationId": "updateComponent", "parameters": [ { "name": "id", @@ -17608,7 +17699,7 @@ } }, { - "name": "groupId", + "name": "componentId", "in": "path", "required": true, "schema": { @@ -17621,7 +17712,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateStatusPageComponentGroupRequest" + "$ref": "#/components/schemas/UpdateStatusPageComponentRequest" } } }, @@ -17633,7 +17724,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentGroupDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentDto" } } } @@ -17724,8 +17815,8 @@ "tags": [ "Status Pages" ], - "summary": "Delete a component group (components become ungrouped)", - "operationId": "deleteGroup", + "summary": "Remove a component from the status page", + "operationId": "deleteComponent", "parameters": [ { "name": "id", @@ -17737,7 +17828,7 @@ } }, { - "name": "groupId", + "name": "componentId", "in": "path", "required": true, "schema": { @@ -17833,13 +17924,14 @@ } } }, - "/api/v1/status-pages/{id}/incidents": { + "/api/v1/status-pages/{id}/components/{componentId}/measured-uptime": { "get": { "tags": [ "Status Pages" ], - "summary": "List incidents for this status page (filterable by status, paginated)", - "operationId": "listIncidents", + "summary": "Get measured (check-based) component uptime history", + "description": "Additive measured daily uptime for MONITOR components (ASK-SP-2 / CHG-2). Reads time-bounded check_results_daily rollups for the linked monitor. Response source is always measured. Does not change legacy GET …/uptime incident-window semantics. days default 90, max 365.", + "operationId": "componentMeasuredUptime", "parameters": [ { "name": "id", @@ -17851,28 +17943,22 @@ } }, { - "name": "status", - "in": "query", - "required": false, + "name": "componentId", + "in": "path", + "required": true, "schema": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "INVESTIGATING", - "IDENTIFIED", - "MONITORING", - "RESOLVED" - ] - } + "type": "string", + "format": "uuid" } }, { - "name": "pageable", + "name": "days", "in": "query", - "required": true, + "required": false, "schema": { - "$ref": "#/components/schemas/Pageable" + "type": "integer", + "format": "int32", + "default": 90 } } ], @@ -17882,7 +17968,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultStatusPageIncidentDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageMeasuredComponentUptimeDto" } } } @@ -17968,13 +18054,16 @@ } } } - }, - "post": { + } + }, + "/api/v1/status-pages/{id}/components/{componentId}/override": { + "put": { "tags": [ "Status Pages" ], - "summary": "Create a status page incident (manual)", - "operationId": "createIncident", + "summary": "Set a timed human status override on a component", + "description": "ASK-SP-1 / CHG-1. Effective currentStatus reflects the override until expiry or clear, unless an active incident takes precedence (incident > override > binding). Max expiry horizon is 24 hours.", + "operationId": "setComponentOverride", "parameters": [ { "name": "id", @@ -17984,25 +18073,34 @@ "type": "string", "format": "uuid" } + }, + { + "name": "componentId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } } ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateStatusPageIncidentRequest" + "$ref": "#/components/schemas/SetStatusPageComponentOverrideRequest" } } }, "required": true }, "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentDto" } } } @@ -18088,15 +18186,13 @@ } } } - } - }, - "/api/v1/status-pages/{id}/incidents/{incidentId}": { - "get": { + }, + "delete": { "tags": [ "Status Pages" ], - "summary": "Get incident details with timeline", - "operationId": "getIncident", + "summary": "Clear a timed human status override on a component", + "operationId": "clearComponentOverride", "parameters": [ { "name": "id", @@ -18108,7 +18204,7 @@ } }, { - "name": "incidentId", + "name": "componentId", "in": "path", "required": true, "schema": { @@ -18123,7 +18219,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentDto" } } } @@ -18209,13 +18305,16 @@ } } } - }, - "put": { + } + }, + "/api/v1/status-pages/{id}/components/{componentId}/uptime": { + "get": { "tags": [ "Status Pages" ], - "summary": "Update an incident", - "operationId": "updateIncident", + "summary": "Get component uptime history from published incident windows", + "description": "Legacy incident-window rollup (source semantics: incident_window). Daily % is derived from published status-page incident windows, not probe checks. For measured check-based uptime use GET …/measured-uptime (ASK-SP-2 / CHG-2).", + "operationId": "componentUptime_1", "parameters": [ { "name": "id", @@ -18227,32 +18326,32 @@ } }, { - "name": "incidentId", + "name": "componentId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } + }, + { + "name": "days", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 90 + } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateStatusPageIncidentRequest" - } - } - }, - "required": true - }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" + "$ref": "#/components/schemas/TableValueResultComponentUptimeDayDto" } } } @@ -18338,13 +18437,15 @@ } } } - }, - "delete": { + } + }, + "/api/v1/status-pages/{id}/components/reorder": { + "put": { "tags": [ "Status Pages" ], - "summary": "Delete an incident", - "operationId": "deleteIncident", + "summary": "Batch reorder components (and optionally move between groups)", + "operationId": "reorderComponents", "parameters": [ { "name": "id", @@ -18354,131 +18455,18 @@ "type": "string", "format": "uuid" } - }, - { - "name": "incidentId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } } ], - "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "Bad request — the payload failed validation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden — the actor lacks permission for this resource", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Not found — the requested resource does not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "409": { - "description": "Conflict — the request collides with current resource state", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error — see the message field for details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "502": { - "description": "Bad gateway — an upstream provider returned an error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "503": { - "description": "Service unavailable — try again shortly", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReorderComponentsRequest" } } - } - } - } - }, - "/api/v1/status-pages/{id}/incidents/{incidentId}/dismiss": { - "post": { - "tags": [ - "Status Pages" - ], - "summary": "Dismiss a draft incident (deletes it permanently)", - "operationId": "dismissIncident", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } }, - { - "name": "incidentId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], + "required": true + }, "responses": { "204": { "description": "No Content" @@ -18566,13 +18554,13 @@ } } }, - "/api/v1/status-pages/{id}/incidents/{incidentId}/publish": { - "post": { + "/api/v1/status-pages/{id}/domains": { + "get": { "tags": [ "Status Pages" ], - "summary": "Publish a draft incident (sets publishedAt, applies component statuses, notifies subscribers)", - "operationId": "publishIncident", + "summary": "List custom domains", + "operationId": "listDomains", "parameters": [ { "name": "id", @@ -18582,33 +18570,15 @@ "type": "string", "format": "uuid" } - }, - { - "name": "incidentId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PublishStatusPageIncidentRequest" - } - } - } - }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" + "$ref": "#/components/schemas/TableValueResultStatusPageCustomDomainDto" } } } @@ -18694,15 +18664,13 @@ } } } - } - }, - "/api/v1/status-pages/{id}/incidents/{incidentId}/updates": { + }, "post": { "tags": [ "Status Pages" ], - "summary": "Post an incident timeline update", - "operationId": "postIncidentUpdate", + "summary": "Add a custom domain", + "operationId": "addDomain", "parameters": [ { "name": "id", @@ -18712,22 +18680,13 @@ "type": "string", "format": "uuid" } - }, - { - "name": "incidentId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } } ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateStatusPageIncidentUpdateRequest" + "$ref": "#/components/schemas/AddCustomDomainRequest" } } }, @@ -18739,7 +18698,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageCustomDomainDto" } } } @@ -18827,13 +18786,13 @@ } } }, - "/api/v1/status-pages/{id}/layout/reorder": { - "put": { + "/api/v1/status-pages/{id}/domains/{domainId}": { + "delete": { "tags": [ "Status Pages" ], - "summary": "Reorder page-level layout: groups and ungrouped components share one ordering", - "operationId": "reorderLayout", + "summary": "Remove a custom domain", + "operationId": "removeDomain", "parameters": [ { "name": "id", @@ -18843,18 +18802,17 @@ "type": "string", "format": "uuid" } + }, + { + "name": "domainId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReorderPageLayoutRequest" - } - } - }, - "required": true - }, "responses": { "204": { "description": "No Content" @@ -18942,13 +18900,13 @@ } } }, - "/api/v1/status-pages/{id}/subscribers": { - "get": { + "/api/v1/status-pages/{id}/domains/{domainId}/primary": { + "post": { "tags": [ "Status Pages" ], - "summary": "List confirmed subscribers (paginated)", - "operationId": "listSubscribers", + "summary": "Mark a verified custom domain as the page's primary host", + "operationId": "setPrimaryDomain", "parameters": [ { "name": "id", @@ -18960,11 +18918,12 @@ } }, { - "name": "pageable", - "in": "query", + "name": "domainId", + "in": "path", "required": true, "schema": { - "$ref": "#/components/schemas/Pageable" + "type": "string", + "format": "uuid" } } ], @@ -18974,7 +18933,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultStatusPageSubscriberDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageCustomDomainDto" } } } @@ -19060,13 +19019,15 @@ } } } - }, + } + }, + "/api/v1/status-pages/{id}/domains/{domainId}/verify": { "post": { "tags": [ "Status Pages" ], - "summary": "Add a subscriber (immediately confirmed, skips double opt-in)", - "operationId": "addSubscriber", + "summary": "Trigger domain verification check", + "operationId": "verifyDomain", "parameters": [ { "name": "id", @@ -19076,25 +19037,24 @@ "type": "string", "format": "uuid" } + }, + { + "name": "domainId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AdminAddSubscriberRequest" - } - } - }, - "required": true - }, "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseStatusPageSubscriberDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageCustomDomainDto" } } } @@ -19182,13 +19142,13 @@ } } }, - "/api/v1/status-pages/{id}/subscribers/{subscriberId}": { - "delete": { + "/api/v1/status-pages/{id}/groups": { + "get": { "tags": [ "Status Pages" ], - "summary": "Remove a subscriber", - "operationId": "removeSubscriber", + "summary": "List component groups with nested components", + "operationId": "listGroups", "parameters": [ { "name": "id", @@ -19198,119 +19158,6 @@ "type": "string", "format": "uuid" } - }, - { - "name": "subscriberId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "204": { - "description": "No Content" - }, - "400": { - "description": "Bad request — the payload failed validation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized — missing or invalid credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Forbidden — the actor lacks permission for this resource", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Not found — the requested resource does not exist", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "409": { - "description": "Conflict — the request collides with current resource state", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error — see the message field for details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "502": { - "description": "Bad gateway — an upstream provider returned an error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "503": { - "description": "Service unavailable — try again shortly", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - } - }, - "/api/v1/tags": { - "get": { - "tags": [ - "Tags" - ], - "summary": "List tags for the authenticated organization", - "operationId": "list_3", - "parameters": [ - { - "name": "pageable", - "in": "query", - "required": true, - "schema": { - "$ref": "#/components/schemas/Pageable" - } } ], "responses": { @@ -19319,7 +19166,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultTagDto" + "$ref": "#/components/schemas/TableValueResultStatusPageComponentGroupDto" } } } @@ -19408,15 +19255,26 @@ }, "post": { "tags": [ - "Tags" + "Status Pages" + ], + "summary": "Create a component group", + "operationId": "createGroup", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "Create a new tag", - "operationId": "create_4", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTagRequest" + "$ref": "#/components/schemas/CreateStatusPageComponentGroupRequest" } } }, @@ -19428,7 +19286,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseTagDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentGroupDto" } } } @@ -19516,13 +19374,13 @@ } } }, - "/api/v1/tags/{id}": { - "get": { + "/api/v1/status-pages/{id}/groups/{groupId}": { + "put": { "tags": [ - "Tags" + "Status Pages" ], - "summary": "Get a tag by ID", - "operationId": "getById", + "summary": "Update a component group", + "operationId": "updateGroup", "parameters": [ { "name": "id", @@ -19532,15 +19390,34 @@ "type": "string", "format": "uuid" } + }, + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateStatusPageComponentGroupRequest" + } + } + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseTagDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageComponentGroupDto" } } } @@ -19627,12 +19504,12 @@ } } }, - "put": { + "delete": { "tags": [ - "Tags" + "Status Pages" ], - "summary": "Update a tag's name and/or color", - "operationId": "update_2", + "summary": "Delete a component group (components become ungrouped)", + "operationId": "deleteGroup", "parameters": [ { "name": "id", @@ -19642,28 +19519,20 @@ "type": "string", "format": "uuid" } + }, + { + "name": "groupId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTagRequest" - } - } - }, - "required": true - }, "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseTagDto" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -19746,13 +19615,15 @@ } } } - }, - "delete": { + } + }, + "/api/v1/status-pages/{id}/incidents": { + "get": { "tags": [ - "Tags" + "Status Pages" ], - "summary": "Delete a tag (cascades to all monitor associations)", - "operationId": "delete_2", + "summary": "List incidents for this status page (filterable by status / scheduled, paginated)", + "operationId": "listIncidents", "parameters": [ { "name": "id", @@ -19762,11 +19633,52 @@ "type": "string", "format": "uuid" } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "INVESTIGATING", + "IDENTIFIED", + "MONITORING", + "RESOLVED" + ] + } + } + }, + { + "name": "scheduled", + "in": "query", + "description": "When true, only scheduled maintenance; when false, only non-scheduled incidents; omit for both", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "pageable", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/Pageable" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultStatusPageIncidentDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -19849,23 +19761,41 @@ } } } - } - }, - "/api/v1/vaults/rotate": { + }, "post": { "tags": [ - "Vault" + "Status Pages" ], - "summary": "Rotate DEK", - "description": "Generates a new Data Encryption Key, re-encrypts all secrets and alert-channel configs, and bumps the vault version. Admin-only. Pipeline DEK caches expire within ~10 minutes.", - "operationId": "rotateDek", + "summary": "Create a status page incident (manual)", + "operationId": "createIncident", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateStatusPageIncidentRequest" + } + } + }, + "required": true + }, "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseDekRotationResultDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" } } } @@ -19953,20 +19883,30 @@ } } }, - "/api/v1/webhooks": { + "/api/v1/status-pages/{id}/incidents/{incidentId}": { "get": { "tags": [ - "Webhooks" + "Status Pages" ], - "summary": "List webhook endpoints for the authenticated org", - "operationId": "list_2", + "summary": "Get incident details with timeline", + "operationId": "getIncident", "parameters": [ { - "name": "pageable", - "in": "query", + "name": "id", + "in": "path", "required": true, "schema": { - "$ref": "#/components/schemas/Pageable" + "type": "string", + "format": "uuid" + } + }, + { + "name": "incidentId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" } } ], @@ -19976,7 +19916,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultWebhookEndpointDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" } } } @@ -20063,29 +20003,49 @@ } } }, - "post": { + "put": { "tags": [ - "Webhooks" + "Status Pages" + ], + "summary": "Update an incident", + "operationId": "updateIncident", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "incidentId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "Register a new webhook endpoint", - "operationId": "create_3", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateWebhookEndpointRequest" + "$ref": "#/components/schemas/UpdateStatusPageIncidentRequest" } } }, "required": true }, "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseWebhookEndpointDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" } } } @@ -20171,15 +20131,13 @@ } } } - } - }, - "/api/v1/webhooks/{id}": { - "get": { + }, + "delete": { "tags": [ - "Webhooks" + "Status Pages" ], - "summary": "Get a single webhook endpoint", - "operationId": "get_1", + "summary": "Delete an incident", + "operationId": "deleteIncident", "parameters": [ { "name": "id", @@ -20189,19 +20147,135 @@ "type": "string", "format": "uuid" } + }, + { + "name": "incidentId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request — the payload failed validation", "content": { - "*/*": { + "application/json": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseWebhookEndpointDto" + "$ref": "#/components/schemas/ErrorResponse" } } } }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/status-pages/{id}/incidents/{incidentId}/dismiss": { + "post": { + "tags": [ + "Status Pages" + ], + "summary": "Dismiss a draft incident (soft-deletes: resolves without publishing)", + "operationId": "dismissIncident", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "incidentId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, "400": { "description": "Bad request — the payload failed validation", "content": { @@ -20283,13 +20357,15 @@ } } } - }, - "put": { + } + }, + "/api/v1/status-pages/{id}/incidents/{incidentId}/publish": { + "post": { "tags": [ - "Webhooks" + "Status Pages" ], - "summary": "Update a webhook endpoint", - "operationId": "update_1", + "summary": "Publish a draft incident (sets publishedAt, applies component statuses, notifies subscribers)", + "operationId": "publishIncident", "parameters": [ { "name": "id", @@ -20299,17 +20375,25 @@ "type": "string", "format": "uuid" } + }, + { + "name": "incidentId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } } ], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateWebhookEndpointRequest" + "$ref": "#/components/schemas/PublishStatusPageIncidentRequest" } } - }, - "required": true + } }, "responses": { "200": { @@ -20317,7 +20401,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseWebhookEndpointDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" } } } @@ -20403,13 +20487,15 @@ } } } - }, - "delete": { + } + }, + "/api/v1/status-pages/{id}/incidents/{incidentId}/updates": { + "post": { "tags": [ - "Webhooks" + "Status Pages" ], - "summary": "Delete a webhook endpoint", - "operationId": "delete_1", + "summary": "Post an incident timeline update", + "operationId": "postIncidentUpdate", "parameters": [ { "name": "id", @@ -20419,11 +20505,37 @@ "type": "string", "format": "uuid" } + }, + { + "name": "incidentId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateStatusPageIncidentUpdateRequest" + } + } + }, + "required": true + }, "responses": { - "204": { - "description": "No Content" + "201": { + "description": "Created", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -20508,13 +20620,13 @@ } } }, - "/api/v1/webhooks/{id}/deliveries": { - "get": { + "/api/v1/status-pages/{id}/incidents/{incidentId}/updates/{updateId}": { + "patch": { "tags": [ - "Webhooks" + "Status Pages" ], - "summary": "List recent deliveries for a webhook endpoint", - "operationId": "listDeliveries", + "summary": "Edit an existing incident timeline update body", + "operationId": "patchIncidentUpdate", "parameters": [ { "name": "id", @@ -20526,23 +20638,41 @@ } }, { - "name": "limit", - "in": "query", - "required": false, + "name": "incidentId", + "in": "path", + "required": true, "schema": { - "type": "integer", - "format": "int32", - "default": 20 + "type": "string", + "format": "uuid" + } + }, + { + "name": "updateId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateStatusPageIncidentUpdateRequest" + } + } + }, + "required": true + }, "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultWebhookDeliveryDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageIncidentUpdateDto" } } } @@ -20630,13 +20760,13 @@ } } }, - "/api/v1/webhooks/{id}/test": { - "post": { + "/api/v1/status-pages/{id}/layout/reorder": { + "put": { "tags": [ - "Webhooks" + "Status Pages" ], - "summary": "Send a test delivery to a webhook endpoint", - "operationId": "test", + "summary": "Reorder page-level layout: groups and ungrouped components share one ordering", + "operationId": "reorderLayout", "parameters": [ { "name": "id", @@ -20652,21 +20782,15 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TestWebhookEndpointRequest" + "$ref": "#/components/schemas/ReorderPageLayoutRequest" } } - } + }, + "required": true }, "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseWebhookTestResult" - } - } - } + "204": { + "description": "No Content" }, "400": { "description": "Bad request — the payload failed validation", @@ -20751,21 +20875,55 @@ } } }, - "/api/v1/webhooks/events": { + "/api/v1/status-pages/{id}/notification-deliveries": { "get": { "tags": [ - "Webhooks" + "Status Pages" + ], + "summary": "List notification delivery receipts", + "description": "Returns delivery rows for this status page (newest first). Optional filters: incidentId, eventType.", + "operationId": "listNotificationDeliveries", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "incidentId", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "eventType", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "SUBSCRIPTION_CONFIRMATION", + "INCIDENT_CREATED", + "INCIDENT_UPDATED", + "INCIDENT_RESOLVED" + ] + } + } ], - "summary": "List all available webhook event types", - "description": "Returns the full catalog of supported outbound webhook event types with their surface grouping and human-readable descriptions. Use this to populate subscription checkboxes when creating or updating a webhook endpoint.", - "operationId": "listEvents", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/WebhookEventCatalogResponse" + "$ref": "#/components/schemas/TableValueResultStatusPageNotificationDeliveryDto" } } } @@ -20853,20 +21011,40 @@ } } }, - "/api/v1/webhooks/signing-secret": { + "/api/v1/status-pages/{id}/notification-deliveries/{deliveryId}": { "get": { "tags": [ - "Webhooks" + "Status Pages" + ], + "summary": "Get a notification delivery receipt", + "operationId": "getNotificationDelivery", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "Get signing secret metadata for the authenticated org", - "operationId": "getSigningSecretInfo", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseWebhookSigningSecretDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageNotificationDeliveryDto" } } } @@ -20954,20 +21132,41 @@ } } }, - "/api/v1/webhooks/signing-secret/rotate": { + "/api/v1/status-pages/{id}/notification-deliveries/{deliveryId}/retry": { "post": { "tags": [ - "Webhooks" + "Status Pages" + ], + "summary": "Retry a failed notification delivery", + "description": "Queues a FAILED delivery for another attempt. Refuses terminal attempt_count (~5). Idempotent when already RETRY_PENDING.", + "operationId": "retryNotificationDelivery", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "Generate or rotate the organization webhook signing secret", - "operationId": "rotateSigningSecret", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseString" + "$ref": "#/components/schemas/SingleValueResponseStatusPageNotificationDeliveryDto" } } } @@ -21055,14 +21254,23 @@ } } }, - "/api/v1/workspaces": { + "/api/v1/status-pages/{id}/subscribers": { "get": { "tags": [ - "Workspaces" + "Status Pages" ], - "summary": "List workspaces", - "operationId": "list_1", + "summary": "List subscribers including awaiting confirmation (paginated)", + "operationId": "listSubscribers", "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, { "name": "pageable", "in": "query", @@ -21078,7 +21286,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/TableValueResultWorkspaceDto" + "$ref": "#/components/schemas/TableValueResultStatusPageSubscriberDto" } } } @@ -21167,15 +21375,26 @@ }, "post": { "tags": [ - "Workspaces" + "Status Pages" + ], + "summary": "Add a subscriber; requireConfirmation=true for EMAIL double opt-in, omit/false confirms immediately", + "operationId": "addSubscriber", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } ], - "summary": "Create workspace", - "operationId": "create_2", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateWorkspaceRequest" + "$ref": "#/components/schemas/AdminAddSubscriberRequest" } } }, @@ -21187,7 +21406,7 @@ "content": { "*/*": { "schema": { - "$ref": "#/components/schemas/SingleValueResponseWorkspaceDto" + "$ref": "#/components/schemas/SingleValueResponseStatusPageSubscriberDto" } } } @@ -21275,34 +21494,2127 @@ } } }, - "/api/v1/workspaces/{workspaceId}": { - "get": { + "/api/v1/status-pages/{id}/subscribers/{subscriberId}": { + "delete": { "tags": [ - "Workspaces" + "Status Pages" ], - "summary": "Get workspace by ID", - "operationId": "get", + "summary": "Remove a subscriber", + "operationId": "removeSubscriber", "parameters": [ { - "name": "workspaceId", + "name": "id", "in": "path", "required": true, "schema": { - "type": "integer", - "format": "int32" + "type": "string", + "format": "uuid" + } + }, + { + "name": "subscriberId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" } } ], "responses": { - "200": { - "description": "OK", - "content": { - "*/*": { - "schema": { - "$ref": "#/components/schemas/SingleValueResponseWorkspaceDto" - } - } - } + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/tags": { + "get": { + "tags": [ + "Tags" + ], + "summary": "List tags for the authenticated organization", + "operationId": "list_3", + "parameters": [ + { + "name": "pageable", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/Pageable" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultTagDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "post": { + "tags": [ + "Tags" + ], + "summary": "Create a new tag", + "operationId": "create_4", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTagRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Created", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseTagDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/tags/{id}": { + "get": { + "tags": [ + "Tags" + ], + "summary": "Get a tag by ID", + "operationId": "getById", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseTagDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "put": { + "tags": [ + "Tags" + ], + "summary": "Update a tag's name and/or color", + "operationId": "update_2", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTagRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseTagDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Tags" + ], + "summary": "Delete a tag (cascades to all monitor associations)", + "operationId": "delete_2", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/vaults/rotate": { + "post": { + "tags": [ + "Vault" + ], + "summary": "Rotate DEK", + "description": "Generates a new Data Encryption Key, re-encrypts all secrets and alert-channel configs, and bumps the vault version. Admin-only. Pipeline DEK caches expire within ~10 minutes.", + "operationId": "rotateDek", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseDekRotationResultDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/webhooks": { + "get": { + "tags": [ + "Webhooks" + ], + "summary": "List webhook endpoints for the authenticated org", + "operationId": "list_2", + "parameters": [ + { + "name": "pageable", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/Pageable" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultWebhookEndpointDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "post": { + "tags": [ + "Webhooks" + ], + "summary": "Register a new webhook endpoint", + "operationId": "create_3", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateWebhookEndpointRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Created", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseWebhookEndpointDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/webhooks/{id}": { + "get": { + "tags": [ + "Webhooks" + ], + "summary": "Get a single webhook endpoint", + "operationId": "get_1", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseWebhookEndpointDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "put": { + "tags": [ + "Webhooks" + ], + "summary": "Update a webhook endpoint", + "operationId": "update_1", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateWebhookEndpointRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseWebhookEndpointDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Webhooks" + ], + "summary": "Delete a webhook endpoint", + "operationId": "delete_1", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/webhooks/{id}/deliveries": { + "get": { + "tags": [ + "Webhooks" + ], + "summary": "List recent deliveries for a webhook endpoint", + "operationId": "listDeliveries", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 20 + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultWebhookDeliveryDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/webhooks/{id}/test": { + "post": { + "tags": [ + "Webhooks" + ], + "summary": "Send a test delivery to a webhook endpoint", + "operationId": "test", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestWebhookEndpointRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseWebhookTestResult" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/webhooks/events": { + "get": { + "tags": [ + "Webhooks" + ], + "summary": "List all available webhook event types", + "description": "Returns the full catalog of supported outbound webhook event types with their surface grouping and human-readable descriptions. Use this to populate subscription checkboxes when creating or updating a webhook endpoint.", + "operationId": "listEvents", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/WebhookEventCatalogResponse" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/webhooks/signing-secret": { + "get": { + "tags": [ + "Webhooks" + ], + "summary": "Get signing secret metadata for the authenticated org", + "operationId": "getSigningSecretInfo", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseWebhookSigningSecretDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/webhooks/signing-secret/rotate": { + "post": { + "tags": [ + "Webhooks" + ], + "summary": "Generate or rotate the organization webhook signing secret", + "operationId": "rotateSigningSecret", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseString" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/workspaces": { + "get": { + "tags": [ + "Workspaces" + ], + "summary": "List workspaces", + "operationId": "list_1", + "parameters": [ + { + "name": "pageable", + "in": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/Pageable" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/TableValueResultWorkspaceDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "post": { + "tags": [ + "Workspaces" + ], + "summary": "Create workspace", + "operationId": "create_2", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateWorkspaceRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Created", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseWorkspaceDto" + } + } + } + }, + "400": { + "description": "Bad request — the payload failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized — missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden — the actor lacks permission for this resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not found — the requested resource does not exist", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict — the request collides with current resource state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error — see the message field for details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "502": { + "description": "Bad gateway — an upstream provider returned an error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service unavailable — try again shortly", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/v1/workspaces/{workspaceId}": { + "get": { + "tags": [ + "Workspaces" + ], + "summary": "Get workspace by ID", + "operationId": "get", + "parameters": [ + { + "name": "workspaceId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/SingleValueResponseWorkspaceDto" + } + } + } }, "400": { "description": "Bad request — the payload failed validation", @@ -21613,6 +23925,30 @@ }, "components": { "schemas": { + "AcknowledgeAllIncidentsResponse": { + "required": [ + "acknowledged", + "skipped" + ], + "type": "object", + "properties": { + "acknowledged": { + "type": "array", + "description": "Dispatches successfully acknowledged in this request", + "items": { + "$ref": "#/components/schemas/NotificationDispatchDto" + } + }, + "skipped": { + "type": "array", + "description": "Dispatches skipped (already acked or not in an acknowledgeable state)", + "items": { + "$ref": "#/components/schemas/SkippedDispatch" + } + } + }, + "description": "Result of acknowledging all acknowledgeable dispatches for an incident" + }, "AcquireDeployLockRequest": { "required": [ "lockedBy" @@ -21723,16 +24059,47 @@ "description": "Request body for adding a member to a resource group" }, "AdminAddSubscriberRequest": { - "required": [ - "email" - ], "type": "object", "properties": { "email": { - "minLength": 1, + "maxLength": 320, + "minLength": 0, "type": "string", - "description": "Email address to add as a confirmed subscriber", - "format": "email" + "description": "Email for EMAIL channel; legacy clients may send only this", + "format": "email", + "nullable": true + }, + "channel": { + "type": "string", + "description": "Delivery channel (default: EMAIL)", + "nullable": true, + "enum": [ + "EMAIL", + "SMS", + "WEBHOOK" + ] + }, + "destination": { + "maxLength": 2048, + "minLength": 0, + "type": "string", + "description": "Channel destination (email, phone, or webhook URL)", + "nullable": true + }, + "componentIds": { + "type": "array", + "description": "Optional component IDs to scope; null means whole page", + "nullable": true, + "items": { + "type": "string", + "description": "Optional component IDs to scope; null means whole page", + "format": "uuid" + } + }, + "requireConfirmation": { + "type": "boolean", + "description": "When true (EMAIL only), create unconfirmed and send opt-in; null/false confirms immediately", + "nullable": true } } }, @@ -21848,6 +24215,36 @@ "type": "string", "description": "Jira project key", "nullable": true + }, + "phoneNumber": { + "type": "string", + "description": "Recipient phone number in E.164 format (SMS / phone-call channels)", + "nullable": true + }, + "verifiedPhoneNumberId": { + "type": "integer", + "description": "Id of the org verified_phone_number row bound to this channel", + "format": "int64", + "nullable": true + }, + "phoneNumbers": { + "type": "array", + "description": "Deprecated mirror of phoneNumber as a length-1 list for older clients", + "nullable": true, + "items": { + "type": "string", + "description": "Deprecated mirror of phoneNumber as a length-1 list for older clients" + } + }, + "voiceLanguage": { + "type": "string", + "description": "BCP-47 voice language for phone-call TTS (e.g. en-US, de-DE)", + "nullable": true + }, + "preferredLanguage": { + "type": "string", + "description": "Preferred language for SMS/voice (BCP-47, e.g. en-US, de-DE)", + "nullable": true } }, "description": "Non-sensitive alert channel configuration metadata" @@ -21856,6 +24253,7 @@ "required": [ "channelType", "createdAt", + "enabled", "id", "name", "updatedAt" @@ -21894,7 +24292,9 @@ "zapier", "datadog", "jira", - "gitlab" + "gitlab", + "sms", + "phone_call" ] }, "displayConfig": { @@ -21905,6 +24305,10 @@ } ] }, + "enabled": { + "type": "boolean", + "description": "Whether this channel is enabled and will receive alerts" + }, "createdAt": { "type": "string", "description": "Timestamp when the channel was created", @@ -21998,7 +24402,11 @@ "DELIVERED", "RETRY_PENDING", "FAILED", - "CANCELLED" + "CANCELLED", + "SKIPPED_NO_CREDIT", + "SKIPPED_UNVERIFIED", + "SKIPPED_OPTED_OUT", + "SKIPPED_RATE_LIMITED" ] }, "eventType": { @@ -22845,7 +25253,8 @@ "tcp": "#/components/schemas/Tcp", "icmp": "#/components/schemas/Icmp", "dns": "#/components/schemas/Dns", - "mcp_server": "#/components/schemas/McpServer" + "mcp_server": "#/components/schemas/McpServer", + "code": "#/components/schemas/Code" } }, "oneOf": [ @@ -22863,9 +25272,95 @@ }, { "$ref": "#/components/schemas/McpServer" + }, + { + "$ref": "#/components/schemas/Code" + } + ] + }, + "Code": { + "type": "object", + "description": "Code check (browser / multi-step API) specific details", + "properties": { + "check_type": { + "type": "string", + "enum": [ + "code" + ] + }, + "exitCode": { + "type": "integer", + "description": "Container exit code (0 = pass)", + "format": "int32" + }, + "stdoutSnippet": { + "type": "string", + "description": "Truncated stdout from the container", + "nullable": true + }, + "stderrSnippet": { + "type": "string", + "description": "Truncated stderr from the container", + "nullable": true + }, + "steps": { + "type": "array", + "description": "Named steps extracted from Playwright test output", + "nullable": true, + "items": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/CodeCheckStep" + } + ] + } + }, + "failureKind": { + "type": "string", + "description": "Failure classification: timeout, assertion, or error", + "nullable": true + }, + "timedOut": { + "type": "boolean", + "description": "Whether the run hit a step/total/run-budget timeout", + "nullable": true } + }, + "required": [ + "check_type", + "exitCode" ] }, + "CodeCheckStep": { + "required": [ + "name", + "status" + ], + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Step name from test.step() or test() call" + }, + "status": { + "type": "string", + "description": "Step outcome: passed, failed, skipped, or timedOut" + }, + "durationMs": { + "type": "integer", + "description": "Step duration in milliseconds", + "format": "int32", + "nullable": true + }, + "error": { + "type": "string", + "description": "Error message if the step failed", + "nullable": true + } + }, + "description": "A single named step within a code check execution" + }, "ComponentImpact": { "required": [ "componentId", @@ -22934,6 +25429,35 @@ }, "description": "A single component position" }, + "ComponentSample": { + "required": [ + "componentId", + "newStatus" + ], + "type": "object", + "properties": { + "componentId": { + "type": "string", + "description": "Component ID", + "format": "uuid" + }, + "componentName": { + "type": "string", + "description": "Component display name", + "nullable": true + }, + "oldStatus": { + "type": "string", + "description": "Previous status before the flip", + "nullable": true + }, + "newStatus": { + "type": "string", + "description": "New status after the flip" + } + }, + "description": "One component sample inside a transition rollup" + }, "ComponentsSummaryDto": { "required": [ "groupComponentCounts", @@ -22986,6 +25510,33 @@ }, "description": "Current status of each active component" }, + "ComponentTransitionEventDto": { + "required": [ + "componentSample", + "newStatus", + "componentCount" + ], + "type": "object", + "properties": { + "newStatus": { + "type": "string", + "description": "New status that defines this rollup bucket" + }, + "componentCount": { + "type": "integer", + "description": "Total components in the 5-minute rollup bucket", + "format": "int32" + }, + "componentSample": { + "type": "array", + "description": "Up to 5 sample components from the bucket", + "items": { + "$ref": "#/components/schemas/ComponentSample" + } + } + }, + "description": "Rolled-up component status transitions for a status-events rail row" + }, "ComponentUptimeDayDto": { "required": [ "date", @@ -23143,6 +25694,9 @@ { "$ref": "#/components/schemas/PagerDutyChannelConfig" }, + { + "$ref": "#/components/schemas/PhoneCallChannelConfig" + }, { "$ref": "#/components/schemas/PushbulletChannelConfig" }, @@ -23155,6 +25709,9 @@ { "$ref": "#/components/schemas/SlackChannelConfig" }, + { + "$ref": "#/components/schemas/SmsChannelConfig" + }, { "$ref": "#/components/schemas/SplunkOnCallChannelConfig" }, @@ -23491,6 +26048,18 @@ "type": "string", "description": "Detailed description or context for the incident", "nullable": true + }, + "serviceId": { + "type": "string", + "description": "Vendor service to link; optional for Dependencies create CTA", + "format": "uuid", + "nullable": true + }, + "serviceIncidentId": { + "type": "string", + "description": "Vendor incident to link; idempotent if an active org incident already links it", + "format": "uuid", + "nullable": true } } }, @@ -23517,7 +26086,9 @@ "MCP_SERVER", "TCP", "ICMP", - "HEARTBEAT" + "HEARTBEAT", + "BROWSER", + "MULTI_STEP_API" ] }, "config": { @@ -23537,6 +26108,9 @@ { "$ref": "#/components/schemas/McpServerMonitorConfig" }, + { + "$ref": "#/components/schemas/ScriptMonitorConfig" + }, { "$ref": "#/components/schemas/TcpMonitorConfig" } @@ -23859,11 +26433,12 @@ }, "type": { "type": "string", - "description": "Component type: MONITOR, GROUP, or STATIC", + "description": "Component type: MONITOR, GROUP, STATIC, or DEPENDENCY", "enum": [ "MONITOR", "GROUP", - "STATIC" + "STATIC", + "DEPENDENCY" ] }, "monitorId": { @@ -23878,6 +26453,12 @@ "format": "uuid", "nullable": true }, + "serviceSubscriptionId": { + "type": "string", + "description": "Service subscription (Dependency) ID — required when type=DEPENDENCY. Bind an existing org subscription; catalog picks must create the subscription first, then pass its id", + "format": "uuid", + "nullable": true + }, "groupId": { "type": "string", "description": "Component group ID for visual grouping", @@ -23886,7 +26467,7 @@ }, "showUptime": { "type": "boolean", - "description": "Whether to show the uptime bar (default: true)", + "description": "Whether to show the uptime bar (default: true; false for DEPENDENCY)", "nullable": true }, "displayOrder": { @@ -23897,7 +26478,7 @@ }, "excludeFromOverall": { "type": "boolean", - "description": "Exclude from overall status calculation (default: false, use true for third-party deps)", + "description": "Exclude from overall status calculation (default: false; true for DEPENDENCY)", "nullable": true }, "startDate": { @@ -23982,6 +26563,12 @@ "type": "boolean", "description": "Whether to email confirmed subscribers about this incident (default: true)", "nullable": true + }, + "monitoringIncidentId": { + "type": "string", + "description": "Monitoring incident ID to link this status page incident to; null for standalone", + "format": "uuid", + "nullable": true } } }, @@ -24175,6 +26762,72 @@ }, "description": "Create a new workspace within the organization" }, + "CreditPolicy": { + "type": "object", + "properties": { + "summary": { + "type": "string", + "description": "Brief summary of credit policy", + "nullable": true + }, + "maxCreditPercent": { + "type": "integer", + "description": "Max credit as percent of monthly fee", + "format": "int32", + "nullable": true + }, + "claimWindowDays": { + "type": "integer", + "description": "Days to submit a credit claim after eligibility", + "format": "int32", + "nullable": true + }, + "creditApplicationDays": { + "type": "integer", + "description": "Days for credit to be applied after approval", + "format": "int32", + "nullable": true + }, + "tiers": { + "type": "array", + "description": "Credit tiers by uptime threshold", + "nullable": true, + "items": { + "$ref": "#/components/schemas/CreditTier" + } + } + }, + "description": "Service credit policy for SLA violations" + }, + "CreditTier": { + "required": [ + "uptimeRange" + ], + "type": "object", + "properties": { + "uptimeRange": { + "type": "string", + "description": "Uptime range, e.g. '99.1% – 99.98%'" + }, + "creditPercent": { + "type": "integer", + "description": "Credit percent of monthly fee", + "format": "int32", + "nullable": true + }, + "formula": { + "type": "string", + "description": "Credit formula when percent is not a fixed number", + "nullable": true + }, + "notes": { + "type": "string", + "description": "Additional notes on this credit tier", + "nullable": true + } + }, + "description": "Credit tiers by uptime threshold" + }, "CursorPageCheckResultDto": { "required": [ "data", @@ -24201,6 +26854,32 @@ }, "description": "Cursor-paginated response for time-series and append-only data" }, + "CursorPageIncidentActivityEventDto": { + "required": [ + "data", + "hasMore" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "description": "Items on this page", + "items": { + "$ref": "#/components/schemas/IncidentActivityEventDto" + } + }, + "nextCursor": { + "type": "string", + "description": "Opaque cursor for the next page; null when there are no more results", + "nullable": true + }, + "hasMore": { + "type": "boolean", + "description": "Whether more results exist beyond this page" + } + }, + "description": "Cursor-paginated response for time-series and append-only data" + }, "CursorPageServiceCatalogDto": { "required": [ "data", @@ -24253,6 +26932,32 @@ }, "description": "Cursor-paginated response for time-series and append-only data" }, + "CursorPageStatusEventDto": { + "required": [ + "data", + "hasMore" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "description": "Items on this page", + "items": { + "$ref": "#/components/schemas/StatusEventDto" + } + }, + "nextCursor": { + "type": "string", + "description": "Opaque cursor for the next page; null when there are no more results", + "nullable": true + }, + "hasMore": { + "type": "boolean", + "description": "Whether more results exist beyond this page" + } + }, + "description": "Cursor-paginated response for time-series and append-only data" + }, "DashboardOverviewDto": { "required": [ "incidents", @@ -25806,6 +28511,58 @@ "warnMs" ] }, + "IncidentActivityEventDto": { + "required": [ + "at", + "id", + "kind", + "summary" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Stable event ID (source row ID)", + "format": "uuid" + }, + "at": { + "type": "string", + "description": "When the event occurred (ISO 8601)", + "format": "date-time" + }, + "kind": { + "type": "string", + "description": "Activity event kind in the merged incident activity stream", + "enum": [ + "update", + "dispatch", + "delivery", + "forensic_transition", + "status_page_update" + ] + }, + "actor": { + "type": "string", + "description": "Actor label when known (user email, system, etc.)", + "nullable": true + }, + "summary": { + "type": "string", + "description": "Human-readable summary of the event" + }, + "payload": { + "type": "object", + "additionalProperties": { + "type": "object", + "description": "Kind-specific structured fields", + "nullable": true + }, + "description": "Kind-specific structured fields", + "nullable": true + } + }, + "description": "Merged incident activity event (updates, dispatches, deliveries, forensics, SP updates)" + }, "IncidentDetailDto": { "required": [ "incident", @@ -25828,6 +28585,14 @@ "items": { "$ref": "#/components/schemas/LinkedStatusPageIncidentDto" } + }, + "trigger": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/IncidentTriggerDto" + } + ] } } }, @@ -25842,7 +28607,8 @@ "updatedAt", "organizationId", "reopenCount", - "statusPageVisible" + "statusPageVisible", + "suppressDispatch" ], "type": "object", "properties": { @@ -25925,6 +28691,10 @@ "type": "boolean", "description": "Whether this incident is visible on the status page" }, + "suppressDispatch": { + "type": "boolean", + "description": "When true, alert channels are suppressed (AWARENESS silent tracking); false means Alerted" + }, "serviceIncidentId": { "type": "string", "description": "Linked vendor service incident ID; null for monitor incidents", @@ -25966,6 +28736,11 @@ "AUTO_RESOLVED" ] }, + "resolutionNote": { + "type": "string", + "description": "Body from the most recent resolve update; null when not currently resolved, auto-resolved without a note, or no resolve update body was provided", + "nullable": true + }, "startedAt": { "type": "string", "description": "Timestamp when the incident was detected or created", @@ -26052,10 +28827,160 @@ "type": "string", "description": "Detection engine semver that evaluated the rule. Omitted from JSON when null, treat missing as null.", "nullable": true + }, + "displayKey": { + "type": "string", + "description": "Org-scoped human-readable incident code, e.g. \"ABC-42\". Null on incidents created by pre-INC-keys API pods before the sweep; treat missing as unknown and fall back to the id", + "nullable": true + }, + "alertCollapsedByResourceGroupIds": { + "type": "array", + "description": "Sticky union of resource-group IDs that suppressed a paging dispatch for this member incident; null when never written / legacy", + "nullable": true, + "items": { + "type": "string", + "description": "Sticky union of resource-group IDs that suppressed a paging dispatch for this member incident; null when never written / legacy", + "format": "uuid" + } + }, + "peakFailingMemberCount": { + "type": "integer", + "description": "Peak non-operational member count while this RESOURCE_GROUP incident was open; null otherwise", + "format": "int32", + "nullable": true + }, + "failingMembersAtPeak": { + "type": "array", + "description": "Frozen failing members at peakFailingMemberCount; null when not a group incident or never snapshotted", + "nullable": true, + "items": { + "$ref": "#/components/schemas/IncidentFailingMemberSnapshotDto" + } } }, "description": "Incident triggered by a monitor check failure or manual creation" }, + "IncidentEventDto": { + "required": [ + "incidentId", + "title" + ], + "type": "object", + "properties": { + "incidentId": { + "type": "string", + "description": "Vendor catalog incident ID", + "format": "uuid" + }, + "externalId": { + "type": "string", + "description": "Vendor-supplied external incident ID", + "nullable": true + }, + "title": { + "type": "string", + "description": "Incident title from the vendor status page" + }, + "impact": { + "type": "string", + "description": "Vendor impact level (major, minor, none)", + "nullable": true + }, + "status": { + "type": "string", + "description": "Vendor lifecycle status (only set on incident.update rows)", + "nullable": true + }, + "body": { + "type": "string", + "description": "Update body text (only set on incident.update rows)", + "nullable": true + }, + "shortlink": { + "type": "string", + "description": "Short public URL for the vendor incident", + "nullable": true + }, + "startedAt": { + "type": "string", + "description": "When the vendor incident started", + "format": "date-time", + "nullable": true + }, + "resolvedAt": { + "type": "string", + "description": "When the vendor incident resolved", + "format": "date-time", + "nullable": true + }, + "detectedAt": { + "type": "string", + "description": "When DevHelm first detected the incident", + "format": "date-time", + "nullable": true + }, + "vendorCreatedAt": { + "type": "string", + "description": "Vendor-reported creation timestamp", + "format": "date-time", + "nullable": true + }, + "durationSeconds": { + "type": "integer", + "description": "Total duration in seconds (set on incident.resolved)", + "format": "int64", + "nullable": true + }, + "affectedComponentIds": { + "type": "array", + "description": "Affected component IDs from the vendor incident join", + "nullable": true, + "items": { + "type": "string", + "description": "Affected component IDs from the vendor incident join", + "format": "uuid" + } + } + }, + "description": "Vendor incident fields for a status-events rail row" + }, + "IncidentFailingMemberSnapshotDto": { + "required": [ + "memberType", + "name" + ], + "type": "object", + "properties": { + "memberType": { + "type": "string", + "description": "Member type: monitor or service" + }, + "monitorId": { + "type": "string", + "description": "Monitor ID when memberType is monitor", + "format": "uuid", + "nullable": true + }, + "serviceId": { + "type": "string", + "description": "Service ID when memberType is service", + "format": "uuid", + "nullable": true + }, + "name": { + "minLength": 1, + "type": "string", + "description": "Frozen display name at snapshot time" + }, + "membershipId": { + "type": "string", + "description": "Membership row ID when available", + "format": "uuid", + "nullable": true + } + }, + "description": "Frozen failing member identity at peak failing count for a resource-group incident" + }, "IncidentFilterParams": { "type": "object", "properties": { @@ -26106,7 +29031,7 @@ }, "resourceGroupId": { "type": "string", - "description": "Only return incidents whose monitor belongs to this resource group", + "description": "Only return incidents owned by this resource group (incidents.resource_group_id)", "format": "uuid", "nullable": true }, @@ -26122,6 +29047,12 @@ "format": "uuid", "nullable": true }, + "excludeId": { + "type": "string", + "description": "Exclude this incident ID from results (related-incident lists)", + "format": "uuid", + "nullable": true + }, "startedFrom": { "type": "string", "description": "Earliest startedAt to include (inclusive, ISO 8601)", @@ -26414,6 +29345,59 @@ } } }, + "IncidentTriggerDto": { + "required": [ + "source" + ], + "type": "object", + "properties": { + "ruleType": { + "type": "string", + "description": "Trigger rule type (consecutive_failures, failures_in_window, response_time); null when unknown", + "nullable": true + }, + "ruleIndex": { + "type": "integer", + "description": "0-based index into the policy trigger_rules array; null when unknown", + "format": "int32", + "nullable": true + }, + "count": { + "type": "integer", + "description": "Observed failing_streak or failures_in_window from forensics; null when unavailable", + "format": "int32", + "nullable": true + }, + "threshold": { + "type": "integer", + "description": "Rule required count or threshold_ms from forensics; null when unavailable", + "format": "int32", + "nullable": true + }, + "lastError": { + "type": "string", + "description": "failure_reason from the triggering check result; null when unavailable", + "nullable": true + }, + "firstFailedCheckAt": { + "type": "string", + "description": "Earliest failing check timestamp in the confirm window when computable; null otherwise", + "format": "date-time", + "nullable": true + }, + "source": { + "minLength": 1, + "type": "string", + "description": "Where the enrichment came from: forensics, checks, or none (STATUS_DATA/manual/no data)", + "enum": [ + "forensics", + "checks", + "none" + ] + } + }, + "description": "Honest trigger metadata for the incident origin tooltip / TTD strip" + }, "IncidentUpdateDto": { "required": [ "createdAt", @@ -26592,6 +29576,7 @@ }, "InviteDto": { "required": [ + "createdAt", "email", "expiresAt", "roleOffered", @@ -26617,6 +29602,11 @@ "MEMBER" ] }, + "createdAt": { + "type": "string", + "description": "Timestamp when the invite was created", + "format": "date-time" + }, "expiresAt": { "type": "string", "description": "Timestamp when the invite expires", @@ -26789,8 +29779,11 @@ }, "LinkedStatusPageIncidentDto": { "required": [ + "connectionMode", "id", "impact", + "pageIncidentMode", + "spIncidentId", "status", "statusPageId", "statusPageName", @@ -26802,23 +29795,34 @@ "properties": { "id": { "type": "string", + "description": "Status page incident ID (same value as spIncidentId; kept for backwards compatibility)", + "format": "uuid" + }, + "spIncidentId": { + "type": "string", + "description": "Status page incident ID (alias for id) — use this when the outer context is a monitoring incident", "format": "uuid" }, "statusPageId": { "type": "string", + "description": "Parent status page ID", "format": "uuid" }, "statusPageName": { - "type": "string" + "type": "string", + "description": "Parent status page display name" }, "statusPageSlug": { - "type": "string" + "type": "string", + "description": "Parent status page URL slug" }, "title": { - "type": "string" + "type": "string", + "description": "Customer-facing incident title" }, "status": { "type": "string", + "description": "Current lifecycle status (INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED)", "enum": [ "INVESTIGATING", "IDENTIFIED", @@ -26828,6 +29832,7 @@ }, "impact": { "type": "string", + "description": "Impact level (NONE, MINOR, MAJOR, CRITICAL)", "enum": [ "NONE", "MINOR", @@ -26836,12 +29841,31 @@ ] }, "scheduled": { - "type": "boolean" + "type": "boolean", + "description": "Scheduled maintenance flag" }, "publishedAt": { "type": "string", + "description": "Publish time; null while draft", "format": "date-time", "nullable": true + }, + "connectionMode": { + "type": "string", + "description": "Whether the linked SPI was created by automation (AUTO) or by a human/API caller (MANUAL)", + "enum": [ + "AUTO", + "MANUAL" + ] + }, + "pageIncidentMode": { + "type": "string", + "description": "Incident mode of the parent status page at read time (MANUAL, REVIEW, AUTOMATIC)", + "enum": [ + "MANUAL", + "REVIEW", + "AUTOMATIC" + ] } } }, @@ -26869,6 +29893,79 @@ }, "description": "A component affected by a scheduled maintenance window" }, + "MaintenanceEventDto": { + "required": [ + "externalId", + "maintenanceId", + "status", + "title" + ], + "type": "object", + "properties": { + "maintenanceId": { + "type": "string", + "description": "Vendor catalog maintenance ID", + "format": "uuid" + }, + "externalId": { + "type": "string", + "description": "Vendor-supplied external maintenance ID" + }, + "title": { + "type": "string", + "description": "Maintenance title from the vendor status page" + }, + "status": { + "type": "string", + "description": "Lifecycle status: scheduled, in_progress, verifying, completed" + }, + "impact": { + "type": "string", + "description": "Vendor impact level", + "nullable": true + }, + "shortlink": { + "type": "string", + "description": "Short public URL for the vendor maintenance", + "nullable": true + }, + "scheduledFor": { + "type": "string", + "description": "Scheduled start; null for undated maintenance", + "format": "date-time", + "nullable": true + }, + "scheduledUntil": { + "type": "string", + "description": "Scheduled end", + "format": "date-time", + "nullable": true + }, + "startedAt": { + "type": "string", + "description": "When maintenance actually started", + "format": "date-time", + "nullable": true + }, + "completedAt": { + "type": "string", + "description": "When maintenance completed", + "format": "date-time", + "nullable": true + }, + "affectedComponentIds": { + "type": "array", + "description": "Affected component IDs", + "nullable": true, + "items": { + "type": "string", + "description": "Affected component IDs", + "format": "uuid" + } + } + }, + "description": "Vendor maintenance fields for a status-events rail row" + }, "MaintenanceUpdateDto": { "required": [ "id", @@ -27686,7 +30783,9 @@ "MCP_SERVER", "TCP", "ICMP", - "HEARTBEAT" + "HEARTBEAT", + "BROWSER", + "MULTI_STEP_API" ] }, "config": { @@ -27706,6 +30805,9 @@ { "$ref": "#/components/schemas/McpServerMonitorConfig" }, + { + "$ref": "#/components/schemas/ScriptMonitorConfig" + }, { "$ref": "#/components/schemas/TcpMonitorConfig" } @@ -27904,7 +31006,9 @@ "MCP_SERVER", "TCP", "ICMP", - "HEARTBEAT" + "HEARTBEAT", + "BROWSER", + "MULTI_STEP_API" ] }, "config": { @@ -27924,6 +31028,9 @@ { "$ref": "#/components/schemas/McpServerMonitorConfig" }, + { + "$ref": "#/components/schemas/ScriptMonitorConfig" + }, { "$ref": "#/components/schemas/TcpMonitorConfig" } @@ -28087,6 +31194,32 @@ }, "description": "Inline tag creation — creates the tag if it does not already exist" }, + "NoSlaContext": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "description": "Reason no SLA is published", + "nullable": true + }, + "historicalClaim": { + "type": "string", + "description": "Non-binding historical uptime claim", + "nullable": true + }, + "supportSla": { + "type": "string", + "description": "Support response time SLA if different from uptime SLA", + "nullable": true + }, + "enterpriseNote": { + "type": "string", + "description": "Note about enterprise/custom SLA availability", + "nullable": true + } + }, + "description": "Context for vendors with no public SLA" + }, "NotificationDispatchDto": { "required": [ "createdAt", @@ -28159,6 +31292,25 @@ "format": "date-time", "nullable": true }, + "acknowledgedBy": { + "type": "string", + "description": "Actor who acknowledged this dispatch (user email, api-key:, voice:, etc.); null if not acknowledged", + "nullable": true + }, + "acknowledgedVia": { + "type": "string", + "description": "Channel used to acknowledge (DASHBOARD, API, PHONE_CALL, INTERNAL, etc.); null if not acknowledged", + "nullable": true + }, + "matchedRules": { + "type": "array", + "description": "Labels of match rules that caused this dispatch (same wording as TestMatchResult); null on pre-V138 rows; catch-all is [\"(catch-all: no rules defined)\"]", + "nullable": true, + "items": { + "type": "string", + "description": "Labels of match rules that caused this dispatch (same wording as TestMatchResult); null on pre-V138 rows; catch-all is [\"(catch-all: no rules defined)\"]" + } + }, "nextEscalationAt": { "type": "string", "description": "Timestamp when the next escalation step will fire (null if not scheduled)", @@ -28302,6 +31454,46 @@ }, "description": "Org-level notification policy with match rules and escalation chain" }, + "OfficialSla": { + "type": "object", + "properties": { + "percentage": { + "type": "string", + "description": "Advertised uptime percentage, e.g. '99.99%'", + "nullable": true + }, + "scope": { + "type": "string", + "description": "Scope of the SLA, e.g. 'Monthly uptime per region'", + "nullable": true + }, + "measurement": { + "type": "string", + "description": "How the vendor measures uptime for SLA purposes", + "nullable": true + }, + "exclusions": { + "type": "string", + "description": "Summary of exclusions from SLA calculation", + "nullable": true + }, + "appliesToPlans": { + "type": "array", + "description": "Plan names this SLA applies to, e.g. ['Enterprise']", + "nullable": true, + "items": { + "type": "string", + "description": "Plan names this SLA applies to, e.g. ['Enterprise']" + } + }, + "notCovered": { + "type": "string", + "description": "Services/components NOT covered by the SLA", + "nullable": true + } + }, + "description": "The vendor's officially advertised SLA commitment" + }, "OpsGenieChannelConfig": { "required": [ "channelType", @@ -28367,6 +31559,57 @@ }, "description": "Organization account details" }, + "OrgIncidentAnnotationDto": { + "required": [ + "incidentId", + "severity", + "status", + "alerted" + ], + "type": "object", + "properties": { + "incidentId": { + "type": "string", + "description": "Internal org incident ID", + "format": "uuid" + }, + "displayKey": { + "type": "string", + "description": "Human display key (e.g. DEV-42); null until platform INC codes ship", + "nullable": true + }, + "status": { + "type": "string", + "description": "Internal incident lifecycle status", + "enum": [ + "WATCHING", + "TRIGGERED", + "CONFIRMED", + "RESOLVED" + ] + }, + "severity": { + "type": "string", + "description": "Internal incident severity", + "enum": [ + "DOWN", + "DEGRADED", + "MAINTENANCE" + ] + }, + "alerted": { + "type": "boolean", + "description": "Whether alert channels were eligible to fire (false for AWARENESS silent tracking)" + }, + "startedAt": { + "type": "string", + "description": "When the internal incident started", + "format": "date-time", + "nullable": true + } + }, + "description": "Linked internal incident annotation on a vendor status-event row" + }, "OrgInfo": { "required": [ "name", @@ -28463,6 +31706,51 @@ "pageOrder" ] }, + "PhoneCallChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "phone_call" + ] + }, + "phoneNumber": { + "type": "string", + "description": "Recipient phone number in E.164 format, e.g. +14155550123", + "nullable": true + }, + "verifiedPhoneNumberId": { + "type": "integer", + "description": "Id of an org verified_phone_number row; alternative to phoneNumber", + "format": "int64", + "nullable": true + }, + "phoneNumbers": { + "type": "array", + "description": "Deprecated: use phoneNumber. Accepted as a length-1 list for one release; ignored when phoneNumber or id is set", + "nullable": true, + "items": { + "type": "string", + "description": "Deprecated: use phoneNumber. Accepted as a length-1 list for one release; ignored when phoneNumber or id is set", + "nullable": true + } + }, + "voiceLanguage": { + "type": "string", + "description": "TTS voice language/locale (default: en-US). See VoiceLanguage for supported values", + "nullable": true + }, + "preferredLanguage": { + "type": "string", + "description": "Preferred language for TTS and notifications (BCP-47, e.g. en-US, de-DE). Alias for voiceLanguage", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, "PlanInfo": { "required": [ "entitlements", @@ -28595,6 +31883,29 @@ }, "description": "Aggregated poll metrics for a time bucket" }, + "PricingTier": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Tier name, e.g. 'Free', 'Pro', 'Enterprise'" + }, + "slaPercentage": { + "type": "string", + "description": "SLA percentage for this tier, e.g. '99.9%'", + "nullable": true + }, + "priceFrom": { + "type": "string", + "description": "Starting price, e.g. '$0', '$25/mo', 'Custom'", + "nullable": true + } + }, + "description": "Pricing tiers with associated SLA levels" + }, "PublishStatusPageIncidentRequest": { "type": "object", "properties": { @@ -28871,6 +32182,28 @@ }, "description": "Latest check result for a single region" }, + "RelatedIncidentsResponse": { + "required": [ + "data", + "total" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "description": "Related incident rows (newest first, capped by limit)", + "items": { + "$ref": "#/components/schemas/IncidentDto" + } + }, + "total": { + "type": "integer", + "description": "Total matching incidents in the window, excluding the current incident", + "format": "int64" + } + }, + "description": "Related incidents sharing the same origin within a time window" + }, "RemoveMonitorTagsRequest": { "required": [ "tagIds" @@ -28942,6 +32275,49 @@ } } }, + "ResourceGroupDeleteBlockerDto": { + "required": [ + "componentId", + "componentName", + "statusPageId", + "statusPageName", + "statusPageSlug" + ], + "type": "object", + "properties": { + "statusPageId": { + "type": "string", + "description": "Status page that owns the blocking component", + "format": "uuid" + }, + "statusPageName": { + "minLength": 1, + "type": "string", + "description": "Human-readable status page name" + }, + "statusPageSlug": { + "minLength": 1, + "type": "string", + "description": "URL-safe status page slug" + }, + "componentId": { + "type": "string", + "description": "Blocking GROUP-typed status page component ID", + "format": "uuid" + }, + "componentName": { + "minLength": 1, + "type": "string", + "description": "Blocking component display name" + }, + "hostname": { + "type": "string", + "description": "Public hostname when a custom domain is configured; null otherwise", + "nullable": true + } + }, + "description": "Status-page component that references this resource group (blocks delete; public exposure)" + }, "ResourceGroupDto": { "required": [ "createdAt", @@ -29066,6 +32442,22 @@ "$ref": "#/components/schemas/ResourceGroupMemberDto" } }, + "deleteBlockedBy": { + "type": "array", + "description": "Status-page GROUP components that reference this group (delete blockers / public exposure); populated on detail GET only — omitted on list", + "nullable": true, + "items": { + "$ref": "#/components/schemas/ResourceGroupDeleteBlockerDto" + } + }, + "openRegionIncident": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/IncidentDto" + } + ] + }, "managedBy": { "type": "string", "description": "Source that created/owns this group: DASHBOARD, CLI, TERRAFORM, MCP, or API. Null on groups created before this attribution column existed.", @@ -29122,7 +32514,7 @@ }, "activeIncidents": { "type": "integer", - "description": "Number of members with an active incident or non-operational status", + "description": "Number of members currently non-operational (not an incident-row count)", "format": "int32" }, "thresholdStatus": { @@ -29137,9 +32529,21 @@ }, "failingCount": { "type": "integer", - "description": "Number of failing members at time of last evaluation", + "description": "Number of failing members at time of last evaluation; null when no threshold configured", "format": "int32", "nullable": true + }, + "healthBreachedSince": { + "type": "string", + "description": "When the health threshold was first breached in the current cycle; null when not breached", + "format": "date-time", + "nullable": true + }, + "healthEvaluatedAt": { + "type": "string", + "description": "When group health was last evaluated (threshold or stamp-only); null until first evaluation", + "format": "date-time", + "nullable": true } }, "description": "Aggregated health summary for a resource group" @@ -29259,10 +32663,60 @@ "type": "string", "description": "Environment name; monitors only", "nullable": true + }, + "groupMembershipCount": { + "type": "integer", + "description": "Count of resource groups this monitor or service belongs to; detail GET only — omitted on list", + "format": "int32", + "nullable": true + }, + "failingSince": { + "type": "string", + "description": "Start of the current non-operational stretch; null when operational or unknown (services OK); detail GET only — omitted on list", + "format": "date-time", + "nullable": true + }, + "alertCollapsed": { + "type": "boolean", + "description": "True when an active member incident records this group among alertCollapsedByResourceGroupIds; detail GET only — omitted on list", + "nullable": true + }, + "incidentMarks": { + "type": "array", + "description": "Incident marks for the trailing 24h strip; null when metrics omitted or failed; detail GET only — omitted on list", + "nullable": true, + "items": { + "$ref": "#/components/schemas/ResourceGroupMemberIncidentMarkDto" + } } }, "description": "A single member of a resource group with its computed health status" }, + "ResourceGroupMemberIncidentMarkDto": { + "required": [ + "at" + ], + "type": "object", + "properties": { + "at": { + "type": "string", + "description": "Incident startedAt (or first confirmed) within the trailing 24h window", + "format": "date-time" + }, + "incidentId": { + "type": "string", + "description": "Incident ID for navigation; null when unknown", + "format": "uuid", + "nullable": true + }, + "severity": { + "type": "string", + "description": "Optional severity display hint", + "nullable": true + } + }, + "description": "Member incident mark for the trailing 24h uptime strip" + }, "ResponseSizeAssertion": { "type": "object", "properties": { @@ -29601,6 +33055,28 @@ }, "description": "A scheduled maintenance window from a vendor status page" }, + "ScriptMonitorConfig": { + "required": [ + "script" + ], + "type": "object", + "properties": { + "script": { + "maxLength": 65536, + "minLength": 1, + "type": "string", + "description": "Playwright test script source code" + }, + "timeoutSeconds": { + "maximum": 120, + "minimum": 5, + "type": "integer", + "description": "Maximum execution time in seconds (5–120)", + "format": "int32", + "nullable": true + } + } + }, "SecretDto": { "required": [ "createdAt", @@ -29672,6 +33148,34 @@ }, "description": "Admin-editable SEO metadata for pSEO pages" }, + "ServiceBreakdown": { + "required": [ + "service" + ], + "type": "object", + "properties": { + "service": { + "type": "string", + "description": "Sub-service name, e.g. 'EC2', 'S3'" + }, + "slaPercentage": { + "type": "string", + "description": "SLA percentage for this sub-service", + "nullable": true + }, + "scope": { + "type": "string", + "description": "Scope qualifier, e.g. 'Region (Multi-AZ)'", + "nullable": true + }, + "notes": { + "type": "string", + "description": "Additional notes on measurement or conditions", + "nullable": true + } + }, + "description": "Per-service breakdown for vendors with per_service SLA type" + }, "ServiceCatalogDto": { "required": [ "adapterType", @@ -29685,6 +33189,7 @@ "pollingIntervalSeconds", "enabled", "published", + "slaPublished", "componentCount", "activeIncidentCount" ], @@ -29739,6 +33244,10 @@ "published": { "type": "boolean" }, + "slaPublished": { + "type": "boolean", + "description": "Whether the service's SLA page is publicly visible" + }, "overallStatus": { "type": "string", "nullable": true @@ -29959,7 +33468,8 @@ "slug", "updatedAt", "pollingIntervalSeconds", - "enabled" + "enabled", + "slaPublished" ], "type": "object", "properties": { @@ -30062,6 +33572,10 @@ "dataCompleteness": { "type": "string" }, + "slaPublished": { + "type": "boolean", + "description": "Whether the service's SLA page is publicly visible" + }, "seoMetadata": { "nullable": true, "allOf": [ @@ -30070,6 +33584,14 @@ } ] }, + "slaData": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/SlaDataDto" + } + ] + }, "relatedServices": { "type": "array", "nullable": true, @@ -30128,6 +33650,13 @@ "type": "string" } }, + "affectedRegions": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, "updates": { "type": "array", "items": { @@ -30203,6 +33732,13 @@ "type": "string", "format": "date-time", "nullable": true + }, + "affectedRegions": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } } } }, @@ -30566,6 +34102,19 @@ }, "description": "Replace the alert channels linked to a monitor" }, + "SetEnabledRequest": { + "required": [ + "enabled" + ], + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Whether the resource should be enabled" + } + }, + "description": "Request body for toggling a resource's enabled state" + }, "SetMonitorAuthRequest": { "required": [ "config" @@ -30590,6 +34139,49 @@ } } }, + "SetStatusPageComponentOverrideRequest": { + "required": [ + "expiresAt", + "status" + ], + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "Override status while active; takes precedence over binding until expiry/clear", + "enum": [ + "OPERATIONAL", + "DEGRADED_PERFORMANCE", + "PARTIAL_OUTAGE", + "MAJOR_OUTAGE", + "UNDER_MAINTENANCE" + ] + }, + "reason": { + "maxLength": 2000, + "minLength": 0, + "type": "string", + "description": "Optional operator reason shown in the builder", + "nullable": true + }, + "expiresAt": { + "type": "string", + "description": "When the override expires (must be in the future, at most 24h from now)", + "format": "date-time" + } + } + }, + "SingleValueResponseAcknowledgeAllIncidentsResponse": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AcknowledgeAllIncidentsResponse" + } + } + }, "SingleValueResponseAlertChannelDto": { "required": [ "data" @@ -31101,6 +34693,39 @@ } } }, + "SingleValueResponseStatusPageIncidentUpdateDto": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/StatusPageIncidentUpdateDto" + } + } + }, + "SingleValueResponseStatusPageMeasuredComponentUptimeDto": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/StatusPageMeasuredComponentUptimeDto" + } + } + }, + "SingleValueResponseStatusPageNotificationDeliveryDto": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/StatusPageNotificationDeliveryDto" + } + } + }, "SingleValueResponseStatusPageSubscriberDto": { "required": [ "data" @@ -31211,6 +34836,39 @@ } } }, + "SkippedDispatch": { + "required": [ + "id", + "reason", + "status" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Dispatch identifier", + "format": "uuid" + }, + "status": { + "type": "string", + "description": "Current dispatch status", + "enum": [ + "PENDING", + "DISPATCHING", + "DELIVERED", + "ESCALATING", + "ACKNOWLEDGED", + "COMPLETED" + ] + }, + "reason": { + "minLength": 1, + "type": "string", + "description": "Why this dispatch was skipped" + } + }, + "description": "A dispatch that was not acknowledged by ack-all" + }, "SlackChannelConfig": { "required": [ "channelType", @@ -31236,6 +34894,146 @@ } } }, + "SlaDataDto": { + "type": "object", + "properties": { + "slaType": { + "type": "string", + "description": "SLA pattern: plan_gated, per_service, no_public_sla, or universal", + "nullable": true + }, + "officialSla": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OfficialSla" + } + ] + }, + "serviceBreakdown": { + "type": "array", + "description": "Per-service breakdown for vendors with per_service SLA type", + "nullable": true, + "items": { + "$ref": "#/components/schemas/ServiceBreakdown" + } + }, + "pricingTiers": { + "type": "array", + "description": "Pricing tiers with associated SLA levels", + "nullable": true, + "items": { + "$ref": "#/components/schemas/PricingTier" + } + }, + "creditPolicy": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/CreditPolicy" + } + ] + }, + "noSlaContext": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/NoSlaContext" + } + ] + }, + "sourceUrls": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/SourceUrls" + } + ] + }, + "lastResearched": { + "type": "string", + "description": "ISO date when this data was last manually researched", + "nullable": true + }, + "researchNotes": { + "type": "string", + "description": "Freeform operator notes about the research", + "nullable": true + } + }, + "description": "Researched vendor SLA/pricing data for pSEO SLA report pages" + }, + "SmsChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "sms" + ] + }, + "phoneNumber": { + "type": "string", + "description": "Recipient phone number in E.164 format, e.g. +14155550123", + "nullable": true + }, + "verifiedPhoneNumberId": { + "type": "integer", + "description": "Id of an org verified_phone_number row; alternative to phoneNumber", + "format": "int64", + "nullable": true + }, + "phoneNumbers": { + "type": "array", + "description": "Deprecated: use phoneNumber. Accepted as a length-1 list for one release; ignored when phoneNumber or id is set", + "nullable": true, + "items": { + "type": "string", + "description": "Deprecated: use phoneNumber. Accepted as a length-1 list for one release; ignored when phoneNumber or id is set", + "nullable": true + } + }, + "preferredLanguage": { + "type": "string", + "description": "Preferred language for SMS body (BCP-47, e.g. en-US, de-DE). Default: en-US", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "SourceUrls": { + "type": "object", + "properties": { + "slaPage": { + "type": "string", + "description": "URL to vendor's SLA page", + "nullable": true + }, + "pricingPage": { + "type": "string", + "description": "URL to vendor's pricing page", + "nullable": true + }, + "tosPage": { + "type": "string", + "description": "URL to vendor's Terms of Service", + "nullable": true + }, + "statusPage": { + "type": "string", + "description": "URL to vendor's status page", + "nullable": true + }, + "allSlasPage": { + "type": "string", + "description": "URL to vendor's all-services SLA listing", + "nullable": true + } + }, + "description": "Source URLs for SLA, pricing, and ToS pages" + }, "SplunkOnCallChannelConfig": { "required": [ "channelType", @@ -31332,6 +35130,72 @@ } } }, + "StatusEventDto": { + "required": [ + "at", + "id", + "type" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Stable row ID (incident/update/maintenance UUID or transition bucket key)", + "format": "uuid" + }, + "type": { + "type": "string", + "description": "Status event row type on the Dependencies Detail rail", + "enum": [ + "incident.opened", + "incident.update", + "incident.resolved", + "maintenance.scheduled", + "maintenance.started", + "maintenance.completed", + "component.transition" + ] + }, + "at": { + "type": "string", + "description": "Canonical timestamp used for reverse-chronological ordering", + "format": "date-time" + }, + "incident": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/IncidentEventDto" + } + ] + }, + "maintenance": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/MaintenanceEventDto" + } + ] + }, + "component": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/ComponentTransitionEventDto" + } + ] + }, + "orgAnnotation": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OrgIncidentAnnotationDto" + } + ] + } + }, + "description": "Curated vendor status-event row for the Dependencies Detail rail" + }, "StatusPageBranding": { "type": "object", "properties": { @@ -31482,7 +35346,8 @@ "enum": [ "MONITOR", "GROUP", - "STATIC" + "STATIC", + "DEPENDENCY" ] }, "monitorId": { @@ -31495,8 +35360,25 @@ "format": "uuid", "nullable": true }, + "serviceSubscriptionId": { + "type": "string", + "description": "Service subscription (Dependency) id when type=DEPENDENCY", + "format": "uuid", + "nullable": true + }, + "serviceSlug": { + "type": "string", + "description": "Slug of the subscribed catalog service (denormalized for display)", + "nullable": true + }, + "serviceName": { + "type": "string", + "description": "Display name of the subscribed catalog service (denormalized for display)", + "nullable": true + }, "currentStatus": { "type": "string", + "description": "Effective display status (incident > active override > binding)", "enum": [ "OPERATIONAL", "DEGRADED_PERFORMANCE", @@ -31505,6 +35387,35 @@ "UNDER_MAINTENANCE" ] }, + "overrideStatus": { + "type": "string", + "description": "Active timed override status; null when unset or expired", + "nullable": true, + "enum": [ + "OPERATIONAL", + "DEGRADED_PERFORMANCE", + "PARTIAL_OUTAGE", + "MAJOR_OUTAGE", + "UNDER_MAINTENANCE" + ] + }, + "overrideReason": { + "type": "string", + "description": "Optional operator reason for the active override", + "nullable": true + }, + "overrideExpiresAt": { + "type": "string", + "description": "When the active override expires; null when unset or expired", + "format": "date-time", + "nullable": true + }, + "overrideActor": { + "type": "integer", + "description": "User id who set the override; null for API-key actors or when inactive", + "format": "int32", + "nullable": true + }, "showUptime": { "type": "boolean" }, @@ -31754,6 +35665,14 @@ "UNDER_MAINTENANCE" ] }, + "openIncident": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/StatusPageOpenIncidentSummaryDto" + } + ] + }, "managedBy": { "type": "string", "description": "Source that created/owns this status page: DASHBOARD, CLI, TERRAFORM, MCP, or API. Null on pages created before this attribution column existed.", @@ -31968,10 +35887,238 @@ } } }, + "StatusPageMeasuredComponentUptimeDto": { + "required": [ + "componentId", + "days", + "monitorId", + "source" + ], + "type": "object", + "properties": { + "source": { + "type": "string", + "description": "Uptime source discriminator; always measured for this resource", + "enum": [ + "incident_window", + "measured" + ] + }, + "componentId": { + "type": "string", + "description": "Status-page component ID", + "format": "uuid" + }, + "monitorId": { + "type": "string", + "description": "Linked monitor whose check rollups feed this series", + "format": "uuid" + }, + "trackingSince": { + "type": "string", + "description": "ISO-8601 date bars start (Camp A tracking-since); null only if unresolved", + "nullable": true + }, + "days": { + "type": "array", + "description": "Dense daily buckets from tracking start through today (oldest → newest)", + "items": { + "$ref": "#/components/schemas/StatusPageMeasuredUptimeDayDto" + } + } + }, + "description": "Measured (check-based) daily uptime for a MONITOR status-page component" + }, + "StatusPageMeasuredUptimeDayDto": { + "required": [ + "date", + "totalChecks", + "passedChecks" + ], + "type": "object", + "properties": { + "date": { + "type": "string", + "description": "Start-of-day timestamp for this bucket (UTC midnight, ISO 8601)", + "format": "date-time" + }, + "totalChecks": { + "type": "integer", + "description": "Total probe checks recorded that day across regions", + "format": "int64" + }, + "passedChecks": { + "type": "integer", + "description": "Checks that passed that day across regions", + "format": "int64" + }, + "uptimePercentage": { + "type": "number", + "description": "passedChecks / totalChecks × 100; null when totalChecks is 0", + "format": "double", + "nullable": true + } + }, + "description": "One UTC day of measured (check-based) uptime for a MONITOR status-page component" + }, + "StatusPageNotificationDeliveryDto": { + "required": [ + "channel", + "createdAt", + "eventType", + "id", + "status", + "statusPageId", + "subscriberId", + "attemptCount" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Delivery receipt ID", + "format": "uuid" + }, + "statusPageId": { + "type": "string", + "description": "Status page that owns this delivery", + "format": "uuid" + }, + "subscriberId": { + "type": "string", + "description": "Subscriber this delivery targeted", + "format": "uuid" + }, + "destination": { + "type": "string", + "description": "Subscriber destination (email, phone, or webhook URL)", + "nullable": true + }, + "channel": { + "type": "string", + "description": "Delivery channel from the subscriber (EMAIL, SMS, WEBHOOK)" + }, + "incidentId": { + "type": "string", + "description": "Related status-page incident ID, if any", + "format": "uuid", + "nullable": true + }, + "incidentUpdateId": { + "type": "string", + "description": "Related incident update ID, if any", + "format": "uuid", + "nullable": true + }, + "eventType": { + "type": "string", + "description": "Notification event type that triggered this delivery", + "enum": [ + "SUBSCRIPTION_CONFIRMATION", + "INCIDENT_CREATED", + "INCIDENT_UPDATED", + "INCIDENT_RESOLVED" + ] + }, + "status": { + "type": "string", + "description": "Current delivery status", + "enum": [ + "PENDING", + "DELIVERED", + "RETRY_PENDING", + "FAILED", + "CANCELLED", + "SKIPPED_NO_CREDIT", + "SKIPPED_UNVERIFIED", + "SKIPPED_OPTED_OUT", + "SKIPPED_RATE_LIMITED" + ] + }, + "attemptCount": { + "type": "integer", + "description": "Number of delivery attempts made", + "format": "int32" + }, + "lastAttemptAt": { + "type": "string", + "description": "When the last attempt was made", + "format": "date-time", + "nullable": true + }, + "nextRetryAt": { + "type": "string", + "description": "When the next retry is scheduled; null if not retrying", + "format": "date-time", + "nullable": true + }, + "deliveredAt": { + "type": "string", + "description": "When delivery was confirmed; null if not delivered", + "format": "date-time", + "nullable": true + }, + "errorMessage": { + "type": "string", + "description": "Error summary from the last failed attempt", + "nullable": true + }, + "createdAt": { + "type": "string", + "description": "When the delivery row was created", + "format": "date-time" + } + }, + "description": "Delivery receipt for a status page subscriber notification" + }, + "StatusPageOpenIncidentSummaryDto": { + "required": [ + "startedAt", + "status", + "title", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Incident id for dashboard CTAs that open the matching drawer", + "format": "uuid", + "nullable": true + }, + "title": { + "minLength": 1, + "type": "string", + "description": "Incident title shown on the list card live row" + }, + "status": { + "type": "string", + "description": "Lifecycle status of the open incident", + "enum": [ + "INVESTIGATING", + "IDENTIFIED", + "MONITORING", + "RESOLVED" + ] + }, + "startedAt": { + "type": "string", + "description": "When the incident started (ISO 8601)", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "description": "When the incident was last updated (ISO 8601)", + "format": "date-time" + } + }, + "description": "Newest open status-page incident; omitted from JSON when none" + }, "StatusPageSubscriberDto": { "required": [ + "channel", "createdAt", - "email", + "destination", "id", "confirmed" ], @@ -31979,16 +36126,44 @@ "properties": { "id": { "type": "string", + "description": "Subscriber id", "format": "uuid" }, "email": { - "type": "string" + "type": "string", + "description": "Email when channel is EMAIL; null for other channels", + "nullable": true + }, + "channel": { + "type": "string", + "description": "Delivery channel (EMAIL, SMS, WEBHOOK)", + "enum": [ + "EMAIL", + "SMS", + "WEBHOOK" + ] + }, + "destination": { + "type": "string", + "description": "Channel destination (email, phone, or webhook URL)" + }, + "componentIds": { + "type": "array", + "description": "Scoped component IDs; null means whole page", + "nullable": true, + "items": { + "type": "string", + "description": "Scoped component IDs; null means whole page", + "format": "uuid" + } }, "confirmed": { - "type": "boolean" + "type": "boolean", + "description": "Whether the subscriber has confirmed opt-in" }, "createdAt": { "type": "string", + "description": "When the subscriber was created", "format": "date-time" } } @@ -33008,6 +37183,38 @@ } } }, + "TableValueResultStatusPageNotificationDeliveryDto": { + "required": [ + "data", + "hasNext", + "hasPrev" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StatusPageNotificationDeliveryDto" + } + }, + "hasNext": { + "type": "boolean" + }, + "hasPrev": { + "type": "boolean" + }, + "totalElements": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "totalPages": { + "type": "integer", + "format": "int32", + "nullable": true + } + } + }, "TableValueResultStatusPageSubscriberDto": { "required": [ "data", @@ -33072,6 +37279,70 @@ } } }, + "TableValueResultTestChannelResult": { + "required": [ + "data", + "hasNext", + "hasPrev" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TestChannelResult" + } + }, + "hasNext": { + "type": "boolean" + }, + "hasPrev": { + "type": "boolean" + }, + "totalElements": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "totalPages": { + "type": "integer", + "format": "int32", + "nullable": true + } + } + }, + "TableValueResultVoiceLanguageDto": { + "required": [ + "data", + "hasNext", + "hasPrev" + ], + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VoiceLanguageDto" + } + }, + "hasNext": { + "type": "boolean" + }, + "hasPrev": { + "type": "boolean" + }, + "totalElements": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "totalPages": { + "type": "integer", + "format": "int32", + "nullable": true + } + } + }, "TableValueResultWebhookDeliveryDto": { "required": [ "data", @@ -33413,6 +37684,9 @@ { "$ref": "#/components/schemas/PagerDutyChannelConfig" }, + { + "$ref": "#/components/schemas/PhoneCallChannelConfig" + }, { "$ref": "#/components/schemas/PushbulletChannelConfig" }, @@ -33425,6 +37699,9 @@ { "$ref": "#/components/schemas/SlackChannelConfig" }, + { + "$ref": "#/components/schemas/SmsChannelConfig" + }, { "$ref": "#/components/schemas/SplunkOnCallChannelConfig" }, @@ -33491,6 +37768,29 @@ }, "description": "Result of a dry-run match evaluation against a notification policy" }, + "TestMonitorNotificationsRequest": { + "type": "object", + "properties": { + "channelIds": { + "type": "array", + "description": "Channel IDs to test; null or empty tests all channels attached to the monitor", + "nullable": true, + "items": { + "type": "string", + "description": "Channel IDs to test; null or empty tests all channels attached to the monitor", + "format": "uuid" + } + }, + "includeResolved": { + "type": "boolean", + "description": "Whether to include a resolved notification in the test (default: false)" + } + }, + "description": "Request to send test notifications through a monitor's alert channels", + "required": [ + "includeResolved" + ] + }, "TestNotificationPolicyRequest": { "type": "object", "properties": { @@ -33564,7 +37864,7 @@ "properties": { "dns_ms": { "type": "integer", - "description": "DNS resolution time in milliseconds", + "description": "Legacy DNS phase; null for new checks (no longer measured)", "format": "int32", "nullable": true, "example": 12 @@ -33753,64 +38053,70 @@ "config": { "oneOf": [ { - "$ref": "#/components/schemas/DatadogChannelConfig" + "$ref": "#/components/schemas/UpdateDatadogChannelConfig" }, { - "$ref": "#/components/schemas/DiscordChannelConfig" + "$ref": "#/components/schemas/UpdateDiscordChannelConfig" }, { - "$ref": "#/components/schemas/EmailChannelConfig" + "$ref": "#/components/schemas/UpdateEmailChannelConfig" }, { - "$ref": "#/components/schemas/GitLabChannelConfig" + "$ref": "#/components/schemas/UpdateGitLabChannelConfig" }, { - "$ref": "#/components/schemas/GoogleChatChannelConfig" + "$ref": "#/components/schemas/UpdateGoogleChatChannelConfig" }, { - "$ref": "#/components/schemas/IncidentIoChannelConfig" + "$ref": "#/components/schemas/UpdateIncidentIoChannelConfig" }, { - "$ref": "#/components/schemas/JiraChannelConfig" + "$ref": "#/components/schemas/UpdateJiraChannelConfig" }, { - "$ref": "#/components/schemas/LinearChannelConfig" + "$ref": "#/components/schemas/UpdateLinearChannelConfig" }, { - "$ref": "#/components/schemas/MattermostChannelConfig" + "$ref": "#/components/schemas/UpdateMattermostChannelConfig" }, { - "$ref": "#/components/schemas/OpsGenieChannelConfig" + "$ref": "#/components/schemas/UpdateOpsGenieChannelConfig" }, { - "$ref": "#/components/schemas/PagerDutyChannelConfig" + "$ref": "#/components/schemas/UpdatePagerDutyChannelConfig" }, { - "$ref": "#/components/schemas/PushbulletChannelConfig" + "$ref": "#/components/schemas/UpdatePhoneCallChannelConfig" }, { - "$ref": "#/components/schemas/PushoverChannelConfig" + "$ref": "#/components/schemas/UpdatePushbulletChannelConfig" }, { - "$ref": "#/components/schemas/RootlyChannelConfig" + "$ref": "#/components/schemas/UpdatePushoverChannelConfig" }, { - "$ref": "#/components/schemas/SlackChannelConfig" + "$ref": "#/components/schemas/UpdateRootlyChannelConfig" }, { - "$ref": "#/components/schemas/SplunkOnCallChannelConfig" + "$ref": "#/components/schemas/UpdateSlackChannelConfig" }, { - "$ref": "#/components/schemas/TeamsChannelConfig" + "$ref": "#/components/schemas/UpdateSmsChannelConfig" }, { - "$ref": "#/components/schemas/TelegramChannelConfig" + "$ref": "#/components/schemas/UpdateSplunkOnCallChannelConfig" }, { - "$ref": "#/components/schemas/WebhookChannelConfig" + "$ref": "#/components/schemas/UpdateTeamsChannelConfig" }, { - "$ref": "#/components/schemas/ZapierChannelConfig" + "$ref": "#/components/schemas/UpdateTelegramChannelConfig" + }, + { + "$ref": "#/components/schemas/UpdateWebhookChannelConfig" + }, + { + "$ref": "#/components/schemas/UpdateZapierChannelConfig" } ] }, @@ -33825,6 +38131,11 @@ "MCP", "API" ] + }, + "enabled": { + "type": "boolean", + "description": "Whether this channel is enabled (default: true); null preserves current value", + "nullable": true } } }, @@ -34004,32 +38315,183 @@ } } }, - "UpdateEnvironmentRequest": { + "UpdateDatadogChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "datadog" + ] + }, + "apiKey": { + "type": "string", + "description": "Datadog API key", + "nullable": true + }, + "site": { + "type": "string", + "description": "Datadog site region (e.g. datadoghq.com, datadoghq.eu, us3.datadoghq.com)", + "nullable": true + }, + "tags": { + "type": "string", + "description": "Comma-separated tags to attach to events", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "UpdateDiscordChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "discord" + ] + }, + "webhookUrl": { + "type": "string", + "description": "Discord webhook URL", + "nullable": true + }, + "mentionRoleId": { + "type": "string", + "description": "Optional Discord role ID to mention in notifications", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "UpdateEmailChannelConfig": { + "required": [ + "channelType", + "recipients" + ], + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "email" + ] + }, + "recipients": { + "minItems": 1, + "type": "array", + "description": "Email addresses to send notifications to", + "items": { + "type": "string", + "description": "Email addresses to send notifications to", + "format": "email" + } + } + } + }, + "UpdateEnvironmentRequest": { + "type": "object", + "properties": { + "name": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "New environment name; null preserves current", + "nullable": true + }, + "variables": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "Replace all variables; null preserves current", + "nullable": true + }, + "description": "Replace all variables; null preserves current", + "nullable": true + }, + "isDefault": { + "type": "boolean", + "description": "Whether this is the default environment; null preserves current", + "nullable": true + } + } + }, + "UpdateGitLabChannelConfig": { + "required": [ + "channelType", + "endpointUrl" + ], + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "gitlab" + ] + }, + "endpointUrl": { + "minLength": 1, + "type": "string", + "description": "GitLab alert integration endpoint URL" + }, + "authorizationKey": { + "type": "string", + "description": "Authorization key from GitLab alert integration settings", + "nullable": true + } + } + }, + "UpdateGoogleChatChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "google_chat" + ] + }, + "webhookUrl": { + "type": "string", + "description": "Google Chat space webhook URL", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "UpdateIncidentIoChannelConfig": { "type": "object", "properties": { - "name": { - "maxLength": 100, - "minLength": 0, + "channelType": { "type": "string", - "description": "New environment name; null preserves current", + "enum": [ + "incident_io" + ] + }, + "apiKey": { + "type": "string", + "description": "incident.io API key with 'Create incidents' permission", "nullable": true }, - "variables": { - "type": "object", - "additionalProperties": { - "type": "string", - "description": "Replace all variables; null preserves current", - "nullable": true - }, - "description": "Replace all variables; null preserves current", + "severityId": { + "type": "string", + "description": "Severity ID for created incidents (from List Severities API)", "nullable": true }, - "isDefault": { - "type": "boolean", - "description": "Whether this is the default environment; null preserves current", + "visibility": { + "type": "string", + "description": "Incident visibility: public or private (default: public)", "nullable": true } - } + }, + "required": [ + "channelType" + ] }, "UpdateIncidentPolicyRequest": { "required": [ @@ -34056,6 +38518,100 @@ }, "description": "Request body for updating an incident policy" }, + "UpdateIncidentRequest": { + "type": "object", + "properties": { + "title": { + "maxLength": 2147483647, + "minLength": 1, + "type": "string", + "description": "New title; null preserves current (min 1 char if present)", + "nullable": true + }, + "severity": { + "type": "string", + "description": "New severity: DOWN, DEGRADED, or MAINTENANCE; null preserves current", + "nullable": true, + "enum": [ + "DOWN", + "DEGRADED", + "MAINTENANCE" + ] + } + } + }, + "UpdateJiraChannelConfig": { + "required": [ + "channelType", + "domain", + "email", + "projectKey" + ], + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "jira" + ] + }, + "domain": { + "minLength": 1, + "type": "string", + "description": "Atlassian instance domain (e.g. yourteam.atlassian.net)" + }, + "email": { + "minLength": 1, + "type": "string", + "description": "Atlassian account email for API authentication" + }, + "apiToken": { + "type": "string", + "description": "Atlassian API token", + "nullable": true + }, + "projectKey": { + "minLength": 1, + "type": "string", + "description": "Jira project key where issues are created (e.g. OPS)" + }, + "issueType": { + "type": "string", + "description": "Issue type name (e.g. Bug, Task, Incident)", + "nullable": true + } + } + }, + "UpdateLinearChannelConfig": { + "required": [ + "channelType", + "teamId" + ], + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "linear" + ] + }, + "apiKey": { + "type": "string", + "description": "Linear API key", + "nullable": true + }, + "teamId": { + "minLength": 1, + "type": "string", + "description": "Team ID to create issues in" + }, + "labelId": { + "type": "string", + "description": "Label ID to attach to created issues", + "nullable": true + } + } + }, "UpdateMaintenanceWindowRequest": { "required": [ "endsAt", @@ -34100,6 +38656,35 @@ } } }, + "UpdateMattermostChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "mattermost" + ] + }, + "webhookUrl": { + "type": "string", + "description": "Mattermost incoming webhook URL", + "nullable": true + }, + "channel": { + "type": "string", + "description": "Override channel (if webhook allows)", + "nullable": true + }, + "iconUrl": { + "type": "string", + "description": "Custom bot icon URL", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, "UpdateMonitorAuthRequest": { "required": [ "config" @@ -34152,6 +38737,9 @@ { "$ref": "#/components/schemas/McpServerMonitorConfig" }, + { + "$ref": "#/components/schemas/ScriptMonitorConfig" + }, { "$ref": "#/components/schemas/TcpMonitorConfig" } @@ -34291,6 +38879,30 @@ }, "description": "Request body for updating a notification policy (null fields are preserved)" }, + "UpdateOpsGenieChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "opsgenie" + ] + }, + "apiKey": { + "type": "string", + "description": "OpsGenie API key for alert creation", + "nullable": true + }, + "region": { + "type": "string", + "description": "OpsGenie API region: us or eu", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, "UpdateOrgDetailsRequest": { "required": [ "email", @@ -34333,6 +38945,133 @@ } } }, + "UpdatePagerDutyChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "pagerduty" + ] + }, + "routingKey": { + "type": "string", + "description": "PagerDuty Events API v2 routing (integration) key", + "nullable": true + }, + "severityOverride": { + "type": "string", + "description": "Override PagerDuty severity mapping", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "UpdatePhoneCallChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "phone_call" + ] + }, + "phoneNumber": { + "type": "string", + "description": "Recipient phone number in E.164 format; null preserves current", + "nullable": true + }, + "verifiedPhoneNumberId": { + "type": "integer", + "description": "Id of an org verified_phone_number row; null preserves current when phoneNumber also null", + "format": "int64", + "nullable": true + }, + "phoneNumbers": { + "type": "array", + "description": "Deprecated: use phoneNumber", + "nullable": true, + "items": { + "type": "string", + "description": "Deprecated: use phoneNumber", + "nullable": true + } + }, + "voiceLanguage": { + "type": "string", + "description": "TTS voice language/locale (default: en-US). See VoiceLanguage for supported values", + "nullable": true + }, + "preferredLanguage": { + "type": "string", + "description": "Preferred language for TTS and notifications (BCP-47, e.g. en-US, de-DE). Alias for voiceLanguage", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "UpdatePushbulletChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "pushbullet" + ] + }, + "accessToken": { + "type": "string", + "description": "Pushbullet access token", + "nullable": true + }, + "deviceIden": { + "type": "string", + "description": "Target device identifier (broadcasts to all if empty)", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "UpdatePushoverChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "pushover" + ] + }, + "userKey": { + "type": "string", + "description": "Pushover user or group key", + "nullable": true + }, + "appToken": { + "type": "string", + "description": "Pushover application API token", + "nullable": true + }, + "priority": { + "type": "string", + "description": "Notification priority override (-2 to 2)", + "nullable": true + }, + "sound": { + "type": "string", + "description": "Notification sound override", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, "UpdateResourceGroupRequest": { "required": [ "name" @@ -34451,6 +39190,30 @@ }, "description": "Request body for updating a resource group" }, + "UpdateRootlyChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "rootly" + ] + }, + "apiKey": { + "type": "string", + "description": "Rootly API token with incident creation permission", + "nullable": true + }, + "severity": { + "type": "string", + "description": "Severity slug override (e.g. sev0, sev1)", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, "UpdateSecretRequest": { "required": [ "value" @@ -34465,6 +39228,95 @@ } } }, + "UpdateSlackChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "slack" + ] + }, + "webhookUrl": { + "type": "string", + "description": "Slack incoming webhook URL", + "nullable": true + }, + "mentionText": { + "type": "string", + "description": "Optional mention text included in notifications, e.g. @channel", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "UpdateSmsChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "sms" + ] + }, + "phoneNumber": { + "type": "string", + "description": "Recipient phone number in E.164 format; null preserves current", + "nullable": true + }, + "verifiedPhoneNumberId": { + "type": "integer", + "description": "Id of an org verified_phone_number row; null preserves current when phoneNumber also null", + "format": "int64", + "nullable": true + }, + "phoneNumbers": { + "type": "array", + "description": "Deprecated: use phoneNumber", + "nullable": true, + "items": { + "type": "string", + "description": "Deprecated: use phoneNumber", + "nullable": true + } + }, + "preferredLanguage": { + "type": "string", + "description": "Preferred language for SMS body (BCP-47, e.g. en-US, de-DE). Default: en-US", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "UpdateSplunkOnCallChannelConfig": { + "required": [ + "channelType", + "routingKey" + ], + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "splunk_oncall" + ] + }, + "apiKey": { + "type": "string", + "description": "Splunk On-Call REST API key", + "nullable": true + }, + "routingKey": { + "minLength": 1, + "type": "string", + "description": "Routing key for alert routing" + } + } + }, "UpdateStatusPageComponentGroupRequest": { "type": "object", "properties": { @@ -34595,10 +39447,57 @@ "postmortemUrl": { "maxLength": 2048, "minLength": 0, - "pattern": "^https?://.*", + "pattern": "^$|^https?://.*", "type": "string", "description": "URL to an external postmortem document; empty string clears", "nullable": true + }, + "published": { + "type": "boolean", + "description": "Whether the incident is published on the public page; null preserves current. true publishes (sets publishedAt); false unpublishes (clears publishedAt)", + "nullable": true + }, + "scheduledFor": { + "type": "string", + "description": "New maintenance window start; null preserves current. Only for scheduled incidents", + "format": "date-time", + "nullable": true + }, + "scheduledUntil": { + "type": "string", + "description": "New maintenance window end; null preserves current. Only for scheduled incidents", + "format": "date-time", + "nullable": true + }, + "autoResolve": { + "type": "boolean", + "description": "Whether the window auto-completes at scheduledUntil; null preserves current", + "nullable": true + } + } + }, + "UpdateStatusPageIncidentUpdateRequest": { + "required": [ + "body" + ], + "type": "object", + "properties": { + "body": { + "maxLength": 10000, + "minLength": 0, + "type": "string", + "description": "Replacement update body in markdown" + }, + "status": { + "type": "string", + "description": "Replacement lifecycle status for this update; null preserves current", + "nullable": true, + "enum": [ + "INVESTIGATING", + "IDENTIFIED", + "MONITORING", + "RESOLVED" + ] } } }, @@ -34685,6 +39584,84 @@ }, "description": "Request body for updating a tag; null fields are left unchanged" }, + "UpdateTeamsChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "teams" + ] + }, + "webhookUrl": { + "type": "string", + "description": "Microsoft Teams incoming webhook URL", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, + "UpdateTelegramChannelConfig": { + "required": [ + "channelType", + "chatId" + ], + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "telegram" + ] + }, + "botToken": { + "type": "string", + "description": "Telegram bot token from @BotFather", + "nullable": true + }, + "chatId": { + "minLength": 1, + "type": "string", + "description": "Chat, group, or channel ID to send alerts to" + } + } + }, + "UpdateWebhookChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "webhook" + ] + }, + "url": { + "type": "string", + "description": "Webhook endpoint URL that receives alert payloads", + "nullable": true + }, + "signingSecret": { + "type": "string", + "description": "HMAC secret for X-DevHelm-Signature header; omit for unsigned delivery", + "nullable": true + }, + "customHeaders": { + "type": "object", + "additionalProperties": { + "type": "string", + "description": "Additional HTTP headers to include in webhook requests", + "nullable": true + }, + "description": "Additional HTTP headers to include in webhook requests", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, "UpdateWebhookEndpointRequest": { "type": "object", "properties": { @@ -34745,6 +39722,25 @@ }, "description": "Update workspace details" }, + "UpdateZapierChannelConfig": { + "type": "object", + "properties": { + "channelType": { + "type": "string", + "enum": [ + "zapier" + ] + }, + "webhookUrl": { + "type": "string", + "description": "Zapier/n8n/Make catch webhook URL", + "nullable": true + } + }, + "required": [ + "channelType" + ] + }, "UptimeBucketDto": { "required": [ "timestamp", @@ -34809,14 +39805,48 @@ "format": "double", "nullable": true, "example": 312 + }, + "p50LatencyMs": { + "type": "number", + "description": "50th-percentile (median) latency in milliseconds; null when no data", + "format": "double", + "nullable": true, + "example": 128 + }, + "incidentCount": { + "type": "integer", + "description": "Number of incidents that started within the requested window", + "format": "int64", + "example": 2 } }, "description": "Uptime statistics aggregated from continuous aggregates", "required": [ "totalChecks", - "passedChecks" + "passedChecks", + "incidentCount" ] }, + "VoiceLanguageDto": { + "required": [ + "code", + "label" + ], + "type": "object", + "properties": { + "code": { + "minLength": 1, + "type": "string", + "description": "BCP-47 locale code, e.g. en-US" + }, + "label": { + "minLength": 1, + "type": "string", + "description": "Human-readable label, e.g. English (US)" + } + }, + "description": "Supported TTS voice language for phone call alerts" + }, "WebhookChannelConfig": { "required": [ "channelType", @@ -34837,7 +39867,7 @@ }, "signingSecret": { "type": "string", - "description": "Optional HMAC signing secret for payload verification", + "description": "HMAC secret for X-DevHelm-Signature header; omit for unsigned delivery", "nullable": true }, "customHeaders": { diff --git a/src/devhelm/_generated.py b/src/devhelm/_generated.py index 21bb287..b2ee995 100644 --- a/src/devhelm/_generated.py +++ b/src/devhelm/_generated.py @@ -86,14 +86,47 @@ class AddResourceGroupMemberRequest(BaseModel): ] +class Channel(StrEnum): + email = "EMAIL" + sms = "SMS" + webhook = "WEBHOOK" + + class AdminAddSubscriberRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) email: Annotated[ - EmailStr, + EmailStr | None, Field( - description="Email address to add as a confirmed subscriber", min_length=1 + description="Email for EMAIL channel; legacy clients may send only this", + max_length=320, + min_length=0, ), - ] + ] = None + channel: Annotated[ + Channel | None, Field(description="Delivery channel (default: EMAIL)") + ] = None + destination: Annotated[ + str | None, + Field( + description="Channel destination (email, phone, or webhook URL)", + max_length=2048, + min_length=0, + ), + ] = None + component_ids: Annotated[ + list[UUID] | None, + Field( + alias="componentIds", + description="Optional component IDs to scope; null means whole page", + ), + ] = None + require_confirmation: Annotated[ + bool | None, + Field( + alias="requireConfirmation", + description="When true (EMAIL only), create unconfirmed and send opt-in; null/false confirms immediately", + ), + ] = None class Status(StrEnum): @@ -173,6 +206,41 @@ class AlertChannelDisplayConfig(BaseModel): project_key: Annotated[ str | None, Field(alias="projectKey", description="Jira project key") ] = None + phone_number: Annotated[ + str | None, + Field( + alias="phoneNumber", + description="Recipient phone number in E.164 format (SMS / phone-call channels)", + ), + ] = None + verified_phone_number_id: Annotated[ + int | None, + Field( + alias="verifiedPhoneNumberId", + description="Id of the org verified_phone_number row bound to this channel", + ), + ] = None + phone_numbers: Annotated[ + list[str] | None, + Field( + alias="phoneNumbers", + description="Deprecated mirror of phoneNumber as a length-1 list for older clients", + ), + ] = None + voice_language: Annotated[ + str | None, + Field( + alias="voiceLanguage", + description="BCP-47 voice language for phone-call TTS (e.g. en-US, de-DE)", + ), + ] = None + preferred_language: Annotated[ + str | None, + Field( + alias="preferredLanguage", + description="Preferred language for SMS/voice (BCP-47, e.g. en-US, de-DE)", + ), + ] = None class AlertChannelDto(BaseModel): @@ -189,6 +257,10 @@ class AlertChannelDto(BaseModel): display_config: Annotated[ AlertChannelDisplayConfig | None, Field(alias="displayConfig") ] = None + enabled: Annotated[ + bool, + Field(description="Whether this channel is enabled and will receive alerts"), + ] created_at: Annotated[ AwareDatetime, Field(alias="createdAt", description="Timestamp when the channel was created"), @@ -549,6 +621,21 @@ class ChartBucketDto(BaseModel): ] = None +class CodeCheckStep(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + name: Annotated[str, Field(description="Step name from test.step() or test() call")] + status: Annotated[ + str, Field(description="Step outcome: passed, failed, skipped, or timedOut") + ] + duration_ms: Annotated[ + int | None, + Field(alias="durationMs", description="Step duration in milliseconds"), + ] = None + error: Annotated[ + str | None, Field(description="Error message if the step failed") + ] = None + + class ComponentImpact(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) component_id: Annotated[ @@ -601,6 +688,23 @@ class ComponentPosition(BaseModel): ] = None +class ComponentSample(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + component_id: Annotated[ + UUID, Field(alias="componentId", description="Component ID") + ] + component_name: Annotated[ + str | None, Field(alias="componentName", description="Component display name") + ] = None + old_status: Annotated[ + str | None, + Field(alias="oldStatus", description="Previous status before the flip"), + ] = None + new_status: Annotated[ + str, Field(alias="newStatus", description="New status after the flip") + ] + + class ComponentsSummaryDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) total_count: Annotated[ @@ -638,6 +742,30 @@ class ComponentStatusDto(BaseModel): ] +class ComponentTransitionEventDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + new_status: Annotated[ + str, + Field( + alias="newStatus", description="New status that defines this rollup bucket" + ), + ] + component_count: Annotated[ + int, + Field( + alias="componentCount", + description="Total components in the 5-minute rollup bucket", + ), + ] + component_sample: Annotated[ + list[ComponentSample], + Field( + alias="componentSample", + description="Up to 5 sample components from the bucket", + ), + ] + + class ComponentUptimeSummaryDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) day: Annotated[ @@ -834,6 +962,20 @@ class CreateManualIncidentRequest(BaseModel): str | None, Field(description="Detailed description or context for the incident"), ] = None + service_id: Annotated[ + UUID | None, + Field( + alias="serviceId", + description="Vendor service to link; optional for Dependencies create CTA", + ), + ] = None + service_incident_id: Annotated[ + UUID | None, + Field( + alias="serviceIncidentId", + description="Vendor incident to link; idempotent if an active org incident already links it", + ), + ] = None class Type(StrEnum): @@ -843,6 +985,8 @@ class Type(StrEnum): tcp = "TCP" icmp = "ICMP" heartbeat = "HEARTBEAT" + browser = "BROWSER" + multi_step_api = "MULTI_STEP_API" class HealthThresholdType(StrEnum): @@ -896,6 +1040,7 @@ class Type1(StrEnum): monitor = "MONITOR" group = "GROUP" static = "STATIC" + dependency = "DEPENDENCY" class CreateStatusPageComponentRequest(BaseModel): @@ -912,7 +1057,8 @@ class CreateStatusPageComponentRequest(BaseModel): ), ] = None type: Annotated[ - Type1, Field(description="Component type: MONITOR, GROUP, or STATIC") + Type1, + Field(description="Component type: MONITOR, GROUP, STATIC, or DEPENDENCY"), ] monitor_id: Annotated[ UUID | None, @@ -925,6 +1071,13 @@ class CreateStatusPageComponentRequest(BaseModel): description="Resource group ID (required when type=GROUP)", ), ] = None + service_subscription_id: Annotated[ + UUID | None, + Field( + alias="serviceSubscriptionId", + description="Service subscription (Dependency) ID — required when type=DEPENDENCY. Bind an existing org subscription; catalog picks must create the subscription first, then pass its id", + ), + ] = None group_id: Annotated[ UUID | None, Field(alias="groupId", description="Component group ID for visual grouping"), @@ -933,7 +1086,7 @@ class CreateStatusPageComponentRequest(BaseModel): bool | None, Field( alias="showUptime", - description="Whether to show the uptime bar (default: true)", + description="Whether to show the uptime bar (default: true; false for DEPENDENCY)", ), ] = None display_order: Annotated[ @@ -944,7 +1097,7 @@ class CreateStatusPageComponentRequest(BaseModel): bool | None, Field( alias="excludeFromOverall", - description="Exclude from overall status calculation (default: false, use true for third-party deps)", + description="Exclude from overall status calculation (default: false; true for DEPENDENCY)", ), ] = None start_date: Annotated[ @@ -1023,6 +1176,13 @@ class CreateStatusPageIncidentRequest(BaseModel): description="Whether to email confirmed subscribers about this incident (default: true)", ), ] = None + monitoring_incident_id: Annotated[ + UUID | None, + Field( + alias="monitoringIncidentId", + description="Monitoring incident ID to link this status page incident to; null for standalone", + ), + ] = None class CreateStatusPageIncidentUpdateRequest(BaseModel): @@ -1121,6 +1281,25 @@ class CreateWorkspaceRequest(BaseModel): name: Annotated[str, Field(description="Workspace name", min_length=1)] +class CreditTier(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + uptime_range: Annotated[ + str, + Field(alias="uptimeRange", description="Uptime range, e.g. '99.1% – 99.98%'"), + ] + credit_percent: Annotated[ + int | None, + Field(alias="creditPercent", description="Credit percent of monthly fee"), + ] = None + formula: Annotated[ + str | None, + Field(description="Credit formula when percent is not a fixed number"), + ] = None + notes: Annotated[ + str | None, Field(description="Additional notes on this credit tier") + ] = None + + class DatadogChannelConfig(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) channel_type: Annotated[Literal["datadog"], Field(alias="channelType")] = "datadog" @@ -2050,279 +2229,167 @@ class IcmpResponseTimeWarnAssertion(BaseModel): ] -class IncidentDto(BaseModel): +class IncidentActivityEventDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) - id: Annotated[UUID, Field(description="Unique incident identifier")] - monitor_id: Annotated[ - UUID | None, - Field( - alias="monitorId", - description="Monitor that triggered the incident; null for service or manual incidents", - ), - ] = None - organization_id: Annotated[ - int, - Field( - alias="organizationId", description="Organization this incident belongs to" - ), - ] - source: Annotated[ - str, Field(description="Incident origin: MONITOR, SERVICE, or MANUAL") + id: Annotated[UUID, Field(description="Stable event ID (source row ID)")] + at: Annotated[ + AwareDatetime, Field(description="When the event occurred (ISO 8601)") ] - status: Annotated[ - str, Field(description="Current lifecycle status (OPEN, RESOLVED, etc.)") + kind: Annotated[ + str, + Field(description="Activity event kind in the merged incident activity stream"), ] - severity: Annotated[ - str, Field(description="Severity level: DOWN, DEGRADED, or MAINTENANCE") + actor: Annotated[ + str | None, + Field(description="Actor label when known (user email, system, etc.)"), + ] = None + summary: Annotated[str, Field(description="Human-readable summary of the event")] + payload: Annotated[ + dict[str, dict[str, Any]] | None, + Field(description="Kind-specific structured fields"), + ] = None + + +class IncidentEventDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + incident_id: Annotated[ + UUID, Field(alias="incidentId", description="Vendor catalog incident ID") ] + external_id: Annotated[ + str | None, + Field(alias="externalId", description="Vendor-supplied external incident ID"), + ] = None title: Annotated[ + str, Field(description="Incident title from the vendor status page") + ] + impact: Annotated[ + str | None, Field(description="Vendor impact level (major, minor, none)") + ] = None + status: Annotated[ + str | None, + Field(description="Vendor lifecycle status (only set on incident.update rows)"), + ] = None + body: Annotated[ str | None, + Field(description="Update body text (only set on incident.update rows)"), + ] = None + shortlink: Annotated[ + str | None, Field(description="Short public URL for the vendor incident") + ] = None + started_at: Annotated[ + AwareDatetime | None, + Field(alias="startedAt", description="When the vendor incident started"), + ] = None + resolved_at: Annotated[ + AwareDatetime | None, + Field(alias="resolvedAt", description="When the vendor incident resolved"), + ] = None + detected_at: Annotated[ + AwareDatetime | None, Field( - description="Short summary of the incident; null for auto-generated incidents" + alias="detectedAt", description="When DevHelm first detected the incident" ), ] = None - triggered_by_rule: Annotated[ - str | None, + vendor_created_at: Annotated[ + AwareDatetime | None, Field( - alias="triggeredByRule", - description="Human-readable description of the trigger rule that fired", + alias="vendorCreatedAt", description="Vendor-reported creation timestamp" ), ] = None - affected_regions: Annotated[ - list[str], + duration_seconds: Annotated[ + int | None, Field( - alias="affectedRegions", - description="Probe regions that observed the failure", + alias="durationSeconds", + description="Total duration in seconds (set on incident.resolved)", ), - ] - reopen_count: Annotated[ - int, + ] = None + affected_component_ids: Annotated[ + list[UUID] | None, Field( - alias="reopenCount", - description="Number of times this incident has been reopened", + alias="affectedComponentIds", + description="Affected component IDs from the vendor incident join", ), + ] = None + + +class IncidentFailingMemberSnapshotDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + member_type: Annotated[ + str, Field(alias="memberType", description="Member type: monitor or service") ] - created_by_user_id: Annotated[ - int | None, + monitor_id: Annotated[ + UUID | None, + Field(alias="monitorId", description="Monitor ID when memberType is monitor"), + ] = None + service_id: Annotated[ + UUID | None, + Field(alias="serviceId", description="Service ID when memberType is service"), + ] = None + name: Annotated[ + str, Field(description="Frozen display name at snapshot time", min_length=1) + ] + membership_id: Annotated[ + UUID | None, + Field(alias="membershipId", description="Membership row ID when available"), + ] = None + + +class Status5(StrEnum): + watching = "WATCHING" + triggered = "TRIGGERED" + confirmed = "CONFIRMED" + resolved = "RESOLVED" + + +class Source(StrEnum): + automatic = "AUTOMATIC" + manual = "MANUAL" + monitors = "MONITORS" + status_data = "STATUS_DATA" + resource_group = "RESOURCE_GROUP" + + +class IncidentFilterParams(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + status: Annotated[ + Status5 | None, Field( - alias="createdByUserId", - description="User who created the incident (manual incidents only)", + description="Filter by incident lifecycle status; null returns every status" ), ] = None - status_page_visible: Annotated[ - bool, + severity: Annotated[ + Severity1 | None, + Field(description="Filter by severity; null returns every severity"), + ] = None + source: Annotated[ + Source | None, Field( - alias="statusPageVisible", - description="Whether this incident is visible on the status page", + description="Filter by where the incident originated (auto, manual, third-party)" ), - ] - service_incident_id: Annotated[ + ] = None + monitor_id: Annotated[ UUID | None, Field( - alias="serviceIncidentId", - description="Linked vendor service incident ID; null for monitor incidents", + alias="monitorId", + description="Only return incidents tied to this monitor ID", ), ] = None service_id: Annotated[ UUID | None, Field( alias="serviceId", - description="Linked service catalog ID; null for monitor incidents", + description="Only return incidents tied to this service ID (third-party services)", ), ] = None - external_ref: Annotated[ - str | None, + resource_group_id: Annotated[ + UUID | None, Field( - alias="externalRef", - description="External reference ID (e.g. PagerDuty incident ID)", + alias="resourceGroupId", + description="Only return incidents owned by this resource group (incidents.resource_group_id)", ), ] = None - affected_components: Annotated[ - list[str] | None, - Field( - alias="affectedComponents", - description="Service components affected by this incident", - ), - ] = None - shortlink: Annotated[ - str | None, Field(description="Short URL linking to the incident details") - ] = None - resolution_reason: Annotated[ - str | None, - Field( - alias="resolutionReason", - description="How the incident was resolved (AUTO_RECOVERED, MANUAL, etc.)", - ), - ] = None - started_at: Annotated[ - AwareDatetime | None, - Field( - alias="startedAt", - description="Timestamp when the incident was detected or created", - ), - ] = None - confirmed_at: Annotated[ - AwareDatetime | None, - Field( - alias="confirmedAt", - description="Timestamp when the incident was confirmed (multi-region confirmation)", - ), - ] = None - resolved_at: Annotated[ - AwareDatetime | None, - Field( - alias="resolvedAt", description="Timestamp when the incident was resolved" - ), - ] = None - cooldown_until: Annotated[ - AwareDatetime | None, - Field( - alias="cooldownUntil", - description="Cooldown window end; new incidents suppressed until this time", - ), - ] = None - created_at: Annotated[ - AwareDatetime, - Field( - alias="createdAt", - description="Timestamp when the incident record was created", - ), - ] - updated_at: Annotated[ - AwareDatetime, - Field( - alias="updatedAt", - description="Timestamp when the incident was last updated", - ), - ] - monitor_name: Annotated[ - str | None, - Field( - alias="monitorName", - description="Name of the associated monitor; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", - ), - ] = None - service_name: Annotated[ - str | None, - Field( - alias="serviceName", - description="Name of the associated service; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", - ), - ] = None - service_slug: Annotated[ - str | None, - Field( - alias="serviceSlug", - description="Slug of the associated service; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", - ), - ] = None - monitor_type: Annotated[ - str | None, - Field( - alias="monitorType", - description="Type of the associated monitor; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", - ), - ] = None - resource_group_id: Annotated[ - UUID | None, - Field( - alias="resourceGroupId", - description="Resource group that owns this incident; null when not group-managed", - ), - ] = None - resource_group_name: Annotated[ - str | None, - Field( - alias="resourceGroupName", - description="Name of the resource group; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", - ), - ] = None - triggering_check_id: Annotated[ - UUID | None, - Field( - alias="triggeringCheckId", - description="Scheduler-minted check execution ID whose result confirmed this incident; joins to check_results, rule_evaluations, and incident_state_transitions. Omitted from JSON (undefined to SDKs) when null, treat missing as null.", - ), - ] = None - triggered_by_rule_snapshot_hash_hex: Annotated[ - str | None, - Field( - alias="triggeredByRuleSnapshotHashHex", - description="Hex SHA-256 of the canonical policy snapshot that fired; combined with triggeredByRuleIndex points to the exact TriggerRule. Omitted from JSON when null, treat missing as null.", - ), - ] = None - triggered_by_rule_index: Annotated[ - int | None, - Field( - alias="triggeredByRuleIndex", - description="Index of the fired rule inside the policy's trigger_rules array. Omitted from JSON when null, treat missing as null.", - ), - ] = None - engine_version: Annotated[ - str | None, - Field( - alias="engineVersion", - description="Detection engine semver that evaluated the rule. Omitted from JSON when null, treat missing as null.", - ), - ] = None - - -class Status5(StrEnum): - watching = "WATCHING" - triggered = "TRIGGERED" - confirmed = "CONFIRMED" - resolved = "RESOLVED" - - -class Source(StrEnum): - automatic = "AUTOMATIC" - manual = "MANUAL" - monitors = "MONITORS" - status_data = "STATUS_DATA" - resource_group = "RESOURCE_GROUP" - - -class IncidentFilterParams(BaseModel): - model_config = ConfigDict(extra="forbid", populate_by_name=True) - status: Annotated[ - Status5 | None, - Field( - description="Filter by incident lifecycle status; null returns every status" - ), - ] = None - severity: Annotated[ - Severity1 | None, - Field(description="Filter by severity; null returns every severity"), - ] = None - source: Annotated[ - Source | None, - Field( - description="Filter by where the incident originated (auto, manual, third-party)" - ), - ] = None - monitor_id: Annotated[ - UUID | None, - Field( - alias="monitorId", - description="Only return incidents tied to this monitor ID", - ), - ] = None - service_id: Annotated[ - UUID | None, - Field( - alias="serviceId", - description="Only return incidents tied to this service ID (third-party services)", - ), - ] = None - resource_group_id: Annotated[ - UUID | None, - Field( - alias="resourceGroupId", - description="Only return incidents whose monitor belongs to this resource group", - ), - ] = None - tag_id: Annotated[ - UUID | None, + tag_id: Annotated[ + UUID | None, Field( alias="tagId", description="Only return incidents whose monitor carries this tag", @@ -2335,6 +2402,13 @@ class IncidentFilterParams(BaseModel): description="Only return incidents whose monitor lives in this environment", ), ] = None + exclude_id: Annotated[ + UUID | None, + Field( + alias="excludeId", + description="Exclude this incident ID from results (related-incident lists)", + ), + ] = None started_from: Annotated[ AwareDatetime | None, Field( @@ -2415,6 +2489,57 @@ class IncidentsSummaryDto(BaseModel): mttr30d: float | None = None +class IncidentTriggerDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + rule_type: Annotated[ + str | None, + Field( + alias="ruleType", + description="Trigger rule type (consecutive_failures, failures_in_window, response_time); null when unknown", + ), + ] = None + rule_index: Annotated[ + int | None, + Field( + alias="ruleIndex", + description="0-based index into the policy trigger_rules array; null when unknown", + ), + ] = None + count: Annotated[ + int | None, + Field( + description="Observed failing_streak or failures_in_window from forensics; null when unavailable" + ), + ] = None + threshold: Annotated[ + int | None, + Field( + description="Rule required count or threshold_ms from forensics; null when unavailable" + ), + ] = None + last_error: Annotated[ + str | None, + Field( + alias="lastError", + description="failure_reason from the triggering check result; null when unavailable", + ), + ] = None + first_failed_check_at: Annotated[ + AwareDatetime | None, + Field( + alias="firstFailedCheckAt", + description="Earliest failing check timestamp in the confirm window when computable; null otherwise", + ), + ] = None + source: Annotated[ + str, + Field( + description="Where the enrichment came from: forensics, checks, or none (STATUS_DATA/manual/no data)", + min_length=1, + ), + ] + + class IncidentUpdateDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) id: UUID @@ -2453,6 +2578,10 @@ class InviteDto(BaseModel): description="Role that will be assigned to the invitee on acceptance", ), ] + created_at: Annotated[ + AwareDatetime, + Field(alias="createdAt", description="Timestamp when the invite was created"), + ] expires_at: Annotated[ AwareDatetime, Field(alias="expiresAt", description="Timestamp when the invite expires"), @@ -2564,24 +2693,115 @@ class LinearChannelConfig(BaseModel): class LinkedStatusPageIncidentDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) - id: UUID - status_page_id: Annotated[UUID, Field(alias="statusPageId")] - status_page_name: Annotated[str, Field(alias="statusPageName")] - status_page_slug: Annotated[str, Field(alias="statusPageSlug")] - title: str - status: str - impact: str - scheduled: bool - published_at: Annotated[AwareDatetime | None, Field(alias="publishedAt")] = None - - -class MaintenanceComponentRef(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - id: Annotated[UUID, Field(description="Component identifier")] - name: Annotated[str, Field(description="Component name")] + id: Annotated[ + UUID, + Field( + description="Status page incident ID (same value as spIncidentId; kept for backwards compatibility)" + ), + ] + sp_incident_id: Annotated[ + UUID, + Field( + alias="spIncidentId", + description="Status page incident ID (alias for id) — use this when the outer context is a monitoring incident", + ), + ] + status_page_id: Annotated[ + UUID, Field(alias="statusPageId", description="Parent status page ID") + ] + status_page_name: Annotated[ + str, + Field(alias="statusPageName", description="Parent status page display name"), + ] + status_page_slug: Annotated[ + str, Field(alias="statusPageSlug", description="Parent status page URL slug") + ] + title: Annotated[str, Field(description="Customer-facing incident title")] status: Annotated[ - str, Field(description="Component status at the time of the maintenance update") + str, + Field( + description="Current lifecycle status (INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED)" + ), ] + impact: Annotated[ + str, Field(description="Impact level (NONE, MINOR, MAJOR, CRITICAL)") + ] + scheduled: Annotated[bool, Field(description="Scheduled maintenance flag")] + published_at: Annotated[ + AwareDatetime | None, + Field(alias="publishedAt", description="Publish time; null while draft"), + ] = None + connection_mode: Annotated[ + str, + Field( + alias="connectionMode", + description="Whether the linked SPI was created by automation (AUTO) or by a human/API caller (MANUAL)", + ), + ] + page_incident_mode: Annotated[ + str, + Field( + alias="pageIncidentMode", + description="Incident mode of the parent status page at read time (MANUAL, REVIEW, AUTOMATIC)", + ), + ] + + +class MaintenanceComponentRef(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: Annotated[UUID, Field(description="Component identifier")] + name: Annotated[str, Field(description="Component name")] + status: Annotated[ + str, Field(description="Component status at the time of the maintenance update") + ] + + +class MaintenanceEventDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + maintenance_id: Annotated[ + UUID, Field(alias="maintenanceId", description="Vendor catalog maintenance ID") + ] + external_id: Annotated[ + str, + Field( + alias="externalId", description="Vendor-supplied external maintenance ID" + ), + ] + title: Annotated[ + str, Field(description="Maintenance title from the vendor status page") + ] + status: Annotated[ + str, + Field( + description="Lifecycle status: scheduled, in_progress, verifying, completed" + ), + ] + impact: Annotated[str | None, Field(description="Vendor impact level")] = None + shortlink: Annotated[ + str | None, Field(description="Short public URL for the vendor maintenance") + ] = None + scheduled_for: Annotated[ + AwareDatetime | None, + Field( + alias="scheduledFor", + description="Scheduled start; null for undated maintenance", + ), + ] = None + scheduled_until: Annotated[ + AwareDatetime | None, Field(alias="scheduledUntil", description="Scheduled end") + ] = None + started_at: Annotated[ + AwareDatetime | None, + Field(alias="startedAt", description="When maintenance actually started"), + ] = None + completed_at: Annotated[ + AwareDatetime | None, + Field(alias="completedAt", description="When maintenance completed"), + ] = None + affected_component_ids: Annotated[ + list[UUID] | None, + Field(alias="affectedComponentIds", description="Affected component IDs"), + ] = None class MaintenanceUpdateDto(BaseModel): @@ -2946,6 +3166,8 @@ class Type3(StrEnum): tcp = "TCP" icmp = "ICMP" heartbeat = "HEARTBEAT" + browser = "BROWSER" + multi_step_api = "MULTI_STEP_API" class MonitorTestResultDto(BaseModel): @@ -2979,6 +3201,33 @@ class NewTagRequest(BaseModel): ] = None +class NoSlaContext(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + reason: Annotated[str | None, Field(description="Reason no SLA is published")] = ( + None + ) + historical_claim: Annotated[ + str | None, + Field( + alias="historicalClaim", description="Non-binding historical uptime claim" + ), + ] = None + support_sla: Annotated[ + str | None, + Field( + alias="supportSla", + description="Support response time SLA if different from uptime SLA", + ), + ] = None + enterprise_note: Annotated[ + str | None, + Field( + alias="enterpriseNote", + description="Note about enterprise/custom SLA availability", + ), + ] = None + + class NotificationDispatchDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) id: Annotated[UUID, Field(description="Unique dispatch record identifier")] @@ -3028,6 +3277,27 @@ class NotificationDispatchDto(BaseModel): description="Timestamp when this dispatch was acknowledged (null if not acknowledged)", ), ] = None + acknowledged_by: Annotated[ + str | None, + Field( + alias="acknowledgedBy", + description="Actor who acknowledged this dispatch (user email, api-key:, voice:, etc.); null if not acknowledged", + ), + ] = None + acknowledged_via: Annotated[ + str | None, + Field( + alias="acknowledgedVia", + description="Channel used to acknowledge (DASHBOARD, API, PHONE_CALL, INTERNAL, etc.); null if not acknowledged", + ), + ] = None + matched_rules: Annotated[ + list[str] | None, + Field( + alias="matchedRules", + description='Labels of match rules that caused this dispatch (same wording as TestMatchResult); null on pre-V138 rows; catch-all is ["(catch-all: no rules defined)"]', + ), + ] = None next_escalation_at: Annotated[ AwareDatetime | None, Field( @@ -3095,6 +3365,36 @@ class NotificationDto(BaseModel): ] +class OfficialSla(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + percentage: Annotated[ + str | None, Field(description="Advertised uptime percentage, e.g. '99.99%'") + ] = None + scope: Annotated[ + str | None, + Field(description="Scope of the SLA, e.g. 'Monthly uptime per region'"), + ] = None + measurement: Annotated[ + str | None, Field(description="How the vendor measures uptime for SLA purposes") + ] = None + exclusions: Annotated[ + str | None, Field(description="Summary of exclusions from SLA calculation") + ] = None + applies_to_plans: Annotated[ + list[str] | None, + Field( + alias="appliesToPlans", + description="Plan names this SLA applies to, e.g. ['Enterprise']", + ), + ] = None + not_covered: Annotated[ + str | None, + Field( + alias="notCovered", description="Services/components NOT covered by the SLA" + ), + ] = None + + class OpsGenieChannelConfig(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) channel_type: Annotated[Literal["opsgenie"], Field(alias="channelType")] = ( @@ -3129,6 +3429,32 @@ class OrganizationDto(BaseModel): ] = None +class OrgIncidentAnnotationDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + incident_id: Annotated[ + UUID, Field(alias="incidentId", description="Internal org incident ID") + ] + display_key: Annotated[ + str | None, + Field( + alias="displayKey", + description="Human display key (e.g. DEV-42); null until platform INC codes ship", + ), + ] = None + status: Annotated[str, Field(description="Internal incident lifecycle status")] + severity: Annotated[str, Field(description="Internal incident severity")] + alerted: Annotated[ + bool, + Field( + description="Whether alert channels were eligible to fire (false for AWARENESS silent tracking)" + ), + ] + started_at: Annotated[ + AwareDatetime | None, + Field(alias="startedAt", description="When the internal incident started"), + ] = None + + class OrgInfo(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) id: Annotated[int, Field(description="Organization ID")] @@ -3181,6 +3507,48 @@ class PageSection(BaseModel): ] +class PhoneCallChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["phone_call"], Field(alias="channelType")] = ( + "phone_call" + ) + phone_number: Annotated[ + str | None, + Field( + alias="phoneNumber", + description="Recipient phone number in E.164 format, e.g. +14155550123", + ), + ] = None + verified_phone_number_id: Annotated[ + int | None, + Field( + alias="verifiedPhoneNumberId", + description="Id of an org verified_phone_number row; alternative to phoneNumber", + ), + ] = None + phone_numbers: Annotated[ + list[str] | None, + Field( + alias="phoneNumbers", + description="Deprecated: use phoneNumber. Accepted as a length-1 list for one release; ignored when phoneNumber or id is set", + ), + ] = None + voice_language: Annotated[ + str | None, + Field( + alias="voiceLanguage", + description="TTS voice language/locale (default: en-US). See VoiceLanguage for supported values", + ), + ] = None + preferred_language: Annotated[ + str | None, + Field( + alias="preferredLanguage", + description="Preferred language for TTS and notifications (BCP-47, e.g. en-US, de-DE). Alias for voiceLanguage", + ), + ] = None + + class Tier(StrEnum): free = "FREE" starter = "STARTER" @@ -3286,6 +3654,27 @@ class PollChartBucketDto(BaseModel): ] +class PricingTier(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + name: Annotated[ + str, Field(description="Tier name, e.g. 'Free', 'Pro', 'Enterprise'") + ] + sla_percentage: Annotated[ + str | None, + Field( + alias="slaPercentage", + description="SLA percentage for this tier, e.g. '99.9%'", + ), + ] = None + price_from: Annotated[ + str | None, + Field( + alias="priceFrom", + description="Starting price, e.g. '$0', '$25/mo', 'Custom'", + ), + ] = None + + class Status6(StrEnum): investigating = "INVESTIGATING" identified = "IDENTIFIED" @@ -3527,6 +3916,54 @@ class ResolveIncidentRequest(BaseModel): ] = None +class ResourceGroupDeleteBlockerDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + status_page_id: Annotated[ + UUID, + Field( + alias="statusPageId", + description="Status page that owns the blocking component", + ), + ] + status_page_name: Annotated[ + str, + Field( + alias="statusPageName", + description="Human-readable status page name", + min_length=1, + ), + ] + status_page_slug: Annotated[ + str, + Field( + alias="statusPageSlug", + description="URL-safe status page slug", + min_length=1, + ), + ] + component_id: Annotated[ + UUID, + Field( + alias="componentId", + description="Blocking GROUP-typed status page component ID", + ), + ] + component_name: Annotated[ + str, + Field( + alias="componentName", + description="Blocking component display name", + min_length=1, + ), + ] + hostname: Annotated[ + str | None, + Field( + description="Public hostname when a custom domain is configured; null otherwise" + ), + ] = None + + class ResourceGroupHealthDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) status: Annotated[ @@ -3547,7 +3984,7 @@ class ResourceGroupHealthDto(BaseModel): int, Field( alias="activeIncidents", - description="Number of members with an active incident or non-operational status", + description="Number of members currently non-operational (not an incident-row count)", ), ] threshold_status: Annotated[ @@ -3561,121 +3998,53 @@ class ResourceGroupHealthDto(BaseModel): int | None, Field( alias="failingCount", - description="Number of failing members at time of last evaluation", + description="Number of failing members at time of last evaluation; null when no threshold configured", ), ] = None - - -class ResourceGroupMemberDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - id: Annotated[UUID, Field(description="Unique group member record identifier")] - group_id: Annotated[ - UUID, - Field(alias="groupId", description="Resource group this member belongs to"), - ] - member_type: Annotated[ - str, - Field(alias="memberType", description="Type of member: 'monitor' or 'service'"), - ] - monitor_id: Annotated[ - UUID | None, + health_breached_since: Annotated[ + AwareDatetime | None, Field( - alias="monitorId", - description="Monitor ID; set when memberType is 'monitor'", + alias="healthBreachedSince", + description="When the health threshold was first breached in the current cycle; null when not breached", ), ] = None - service_id: Annotated[ - UUID | None, + health_evaluated_at: Annotated[ + AwareDatetime | None, Field( - alias="serviceId", - description="Service ID; set when memberType is 'service'", + alias="healthEvaluatedAt", + description="When group health was last evaluated (threshold or stamp-only); null until first evaluation", ), ] = None - name: Annotated[ - str | None, - Field(description="Display name of the referenced monitor or service"), - ] = None - slug: Annotated[ - str | None, + + +class ResourceGroupMemberIncidentMarkDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + at: Annotated[ + AwareDatetime, Field( - description="Slug identifier for the service (services only); used for icons and uptime API calls" + description="Incident startedAt (or first confirmed) within the trailing 24h window" ), - ] = None - subscription_id: Annotated[ + ] + incident_id: Annotated[ UUID | None, Field( - alias="subscriptionId", - description="Subscription ID for the service (services only); used to link to the dependency detail page", + alias="incidentId", + description="Incident ID for navigation; null when unknown", ), ] = None - status: Annotated[str, Field(description="Computed health status for this member")] - effective_frequency: Annotated[ - str | None, - Field( - alias="effectiveFrequency", - description="Effective check frequency label showing the group default when the monitor inherits it; null for services or when no group default is configured", - ), + severity: Annotated[ + str | None, Field(description="Optional severity display hint") ] = None - created_at: Annotated[ - AwareDatetime, + + +class ResponseSizeAssertion(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + type: Literal["response_size"] = "response_size" + max_bytes: Annotated[ + int, Field( - alias="createdAt", - description="Timestamp when the member was added to the group", - ), - ] - uptime24h: Annotated[ - float | None, - Field(description="24h uptime percentage; populated when includeMetrics=true"), - ] = None - chart_data: Annotated[ - list[float] | None, - Field( - alias="chartData", - description="Uptime tick values (0-100) for last-24h mini chart; populated when includeMetrics=true", - ), - ] = None - avg_latency_ms: Annotated[ - float | None, - Field( - alias="avgLatencyMs", - description="Average latency in ms (monitors only); populated when includeMetrics=true", - ), - ] = None - p95_latency_ms: Annotated[ - float | None, - Field( - alias="p95LatencyMs", - description="P95 latency in ms (monitors only); populated when includeMetrics=true", - ), - ] = None - last_checked_at: Annotated[ - AwareDatetime | None, - Field( - alias="lastCheckedAt", - description="Timestamp of the most recent health check; populated when includeMetrics=true", - ), - ] = None - monitor_type: Annotated[ - str | None, - Field( - alias="monitorType", - description="Monitor type (HTTP, DNS, TCP, ICMP, HEARTBEAT, MCP); monitors only", - ), - ] = None - environment_name: Annotated[ - str | None, - Field(alias="environmentName", description="Environment name; monitors only"), - ] = None - - -class ResponseSizeAssertion(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - type: Literal["response_size"] = "response_size" - max_bytes: Annotated[ - int, - Field( - alias="maxBytes", - description="Maximum response body size in bytes before the check fails", + alias="maxBytes", + description="Maximum response body size in bytes before the check fails", ), ] @@ -3930,6 +4299,27 @@ class ScheduledMaintenanceDto(BaseModel): ] +class ScriptMonitorConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + script: Annotated[ + str, + Field( + description="Playwright test script source code", + max_length=65536, + min_length=1, + ), + ] + timeout_seconds: Annotated[ + int | None, + Field( + alias="timeoutSeconds", + description="Maximum execution time in seconds (5–120)", + ge=5, + le=120, + ), + ] = None + + class SecretDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) id: Annotated[UUID, Field(description="Unique secret identifier")] @@ -3986,6 +4376,21 @@ class SeoMetadataDto(BaseModel): ] = None +class ServiceBreakdown(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + service: Annotated[str, Field(description="Sub-service name, e.g. 'EC2', 'S3'")] + sla_percentage: Annotated[ + str | None, + Field(alias="slaPercentage", description="SLA percentage for this sub-service"), + ] = None + scope: Annotated[ + str | None, Field(description="Scope qualifier, e.g. 'Region (Multi-AZ)'") + ] = None + notes: Annotated[ + str | None, Field(description="Additional notes on measurement or conditions") + ] = None + + class ServiceCatalogDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) id: UUID @@ -4006,6 +4411,13 @@ class ServiceCatalogDto(BaseModel): ] enabled: bool published: bool + sla_published: Annotated[ + bool, + Field( + alias="slaPublished", + description="Whether the service's SLA page is publicly visible", + ), + ] overall_status: Annotated[str | None, Field(alias="overallStatus")] = None created_at: Annotated[AwareDatetime, Field(alias="createdAt")] updated_at: Annotated[AwareDatetime, Field(alias="updatedAt")] @@ -4147,6 +4559,7 @@ class ServiceIncidentDto(BaseModel): vendor_created_at: Annotated[ AwareDatetime | None, Field(alias="vendorCreatedAt") ] = None + affected_regions: Annotated[list[str] | None, Field(alias="affectedRegions")] = None class ServiceIncidentUpdateDto(BaseModel): @@ -4388,11 +4801,51 @@ class SetAlertChannelsRequest(BaseModel): ] +class SetEnabledRequest(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + enabled: Annotated[ + bool, Field(description="Whether the resource should be enabled") + ] + + class SetMonitorAuthRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) config: ApiKeyAuthConfig | BasicAuthConfig | BearerAuthConfig | HeaderAuthConfig +class Status7(StrEnum): + operational = "OPERATIONAL" + degraded_performance = "DEGRADED_PERFORMANCE" + partial_outage = "PARTIAL_OUTAGE" + major_outage = "MAJOR_OUTAGE" + under_maintenance = "UNDER_MAINTENANCE" + + +class SetStatusPageComponentOverrideRequest(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + status: Annotated[ + Status7, + Field( + description="Override status while active; takes precedence over binding until expiry/clear" + ), + ] + reason: Annotated[ + str | None, + Field( + description="Optional operator reason shown in the builder", + max_length=2000, + min_length=0, + ), + ] = None + expires_at: Annotated[ + AwareDatetime, + Field( + alias="expiresAt", + description="When the override expires (must be in the future, at most 24h from now)", + ), + ] + + class SingleValueResponseAlertChannelDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: AlertChannelDto @@ -4478,11 +4931,6 @@ class SingleValueResponseResourceGroupHealthDto(BaseModel): data: ResourceGroupHealthDto -class SingleValueResponseResourceGroupMemberDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: ResourceGroupMemberDto - - class SingleValueResponseResultSummaryDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: ResultSummaryDto @@ -4518,6 +4966,24 @@ class SingleValueResponseString(BaseModel): data: str +class Status8(StrEnum): + pending = "PENDING" + dispatching = "DISPATCHING" + delivered = "DELIVERED" + escalating = "ESCALATING" + acknowledged = "ACKNOWLEDGED" + completed = "COMPLETED" + + +class SkippedDispatch(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: Annotated[UUID, Field(description="Dispatch identifier")] + status: Annotated[Status8, Field(description="Current dispatch status")] + reason: Annotated[ + str, Field(description="Why this dispatch was skipped", min_length=1) + ] + + class SlackChannelConfig(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) channel_type: Annotated[Literal["slack"], Field(alias="channelType")] = "slack" @@ -4536,6 +5002,63 @@ class SlackChannelConfig(BaseModel): ] = None +class SmsChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["sms"], Field(alias="channelType")] = "sms" + phone_number: Annotated[ + str | None, + Field( + alias="phoneNumber", + description="Recipient phone number in E.164 format, e.g. +14155550123", + ), + ] = None + verified_phone_number_id: Annotated[ + int | None, + Field( + alias="verifiedPhoneNumberId", + description="Id of an org verified_phone_number row; alternative to phoneNumber", + ), + ] = None + phone_numbers: Annotated[ + list[str] | None, + Field( + alias="phoneNumbers", + description="Deprecated: use phoneNumber. Accepted as a length-1 list for one release; ignored when phoneNumber or id is set", + ), + ] = None + preferred_language: Annotated[ + str | None, + Field( + alias="preferredLanguage", + description="Preferred language for SMS body (BCP-47, e.g. en-US, de-DE). Default: en-US", + ), + ] = None + + +class SourceUrls(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + sla_page: Annotated[ + str | None, Field(alias="slaPage", description="URL to vendor's SLA page") + ] = None + pricing_page: Annotated[ + str | None, + Field(alias="pricingPage", description="URL to vendor's pricing page"), + ] = None + tos_page: Annotated[ + str | None, + Field(alias="tosPage", description="URL to vendor's Terms of Service"), + ] = None + status_page: Annotated[ + str | None, Field(alias="statusPage", description="URL to vendor's status page") + ] = None + all_slas_page: Annotated[ + str | None, + Field( + alias="allSlasPage", description="URL to vendor's all-services SLA listing" + ), + ] = None + + class SplunkOnCallChannelConfig(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) channel_type: Annotated[Literal["splunk_oncall"], Field(alias="channelType")] = ( @@ -4600,6 +5123,31 @@ class StatusCodeAssertion(BaseModel): ] +class StatusEventDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: Annotated[ + UUID, + Field( + description="Stable row ID (incident/update/maintenance UUID or transition bucket key)" + ), + ] + type: Annotated[ + str, Field(description="Status event row type on the Dependencies Detail rail") + ] + at: Annotated[ + AwareDatetime, + Field( + description="Canonical timestamp used for reverse-chronological ordering" + ), + ] + incident: IncidentEventDto | None = None + maintenance: MaintenanceEventDto | None = None + component: ComponentTransitionEventDto | None = None + org_annotation: Annotated[ + OrgIncidentAnnotationDto | None, Field(alias="orgAnnotation") + ] = None + + class StatusPageBranding(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) logo_url: Annotated[ @@ -4743,7 +5291,62 @@ class StatusPageComponentDto(BaseModel): type: str monitor_id: Annotated[UUID | None, Field(alias="monitorId")] = None resource_group_id: Annotated[UUID | None, Field(alias="resourceGroupId")] = None - current_status: Annotated[str, Field(alias="currentStatus")] + service_subscription_id: Annotated[ + UUID | None, + Field( + alias="serviceSubscriptionId", + description="Service subscription (Dependency) id when type=DEPENDENCY", + ), + ] = None + service_slug: Annotated[ + str | None, + Field( + alias="serviceSlug", + description="Slug of the subscribed catalog service (denormalized for display)", + ), + ] = None + service_name: Annotated[ + str | None, + Field( + alias="serviceName", + description="Display name of the subscribed catalog service (denormalized for display)", + ), + ] = None + current_status: Annotated[ + str, + Field( + alias="currentStatus", + description="Effective display status (incident > active override > binding)", + ), + ] + override_status: Annotated[ + str | None, + Field( + alias="overrideStatus", + description="Active timed override status; null when unset or expired", + ), + ] = None + override_reason: Annotated[ + str | None, + Field( + alias="overrideReason", + description="Optional operator reason for the active override", + ), + ] = None + override_expires_at: Annotated[ + AwareDatetime | None, + Field( + alias="overrideExpiresAt", + description="When the active override expires; null when unset or expired", + ), + ] = None + override_actor: Annotated[ + int | None, + Field( + alias="overrideActor", + description="User id who set the override; null for API-key actors or when inactive", + ), + ] = None show_uptime: Annotated[bool, Field(alias="showUptime")] display_order: Annotated[int, Field(alias="displayOrder")] page_order: Annotated[int, Field(alias="pageOrder")] @@ -4787,32 +5390,6 @@ class StatusPageCustomDomainDto(BaseModel): primary: bool -class StatusPageDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - id: UUID - organization_id: Annotated[int, Field(alias="organizationId")] - workspace_id: Annotated[int, Field(alias="workspaceId")] - name: Annotated[str, Field(min_length=1)] - slug: Annotated[str, Field(min_length=1)] - description: str | None = None - branding: StatusPageBranding - visibility: str - enabled: bool - incident_mode: Annotated[str, Field(alias="incidentMode")] - component_count: Annotated[int | None, Field(alias="componentCount")] = None - subscriber_count: Annotated[int | None, Field(alias="subscriberCount")] = None - overall_status: Annotated[str | None, Field(alias="overallStatus")] = None - managed_by: Annotated[ - str | None, - Field( - alias="managedBy", - description="Source that created/owns this status page: DASHBOARD, CLI, TERRAFORM, MCP, or API. Null on pages created before this attribution column existed.", - ), - ] = None - created_at: Annotated[AwareDatetime, Field(alias="createdAt")] - updated_at: Annotated[AwareDatetime, Field(alias="updatedAt")] - - class StatusPageIncidentComponentDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) status_page_component_id: Annotated[UUID, Field(alias="statusPageComponentId")] @@ -4831,12 +5408,163 @@ class StatusPageIncidentUpdateDto(BaseModel): created_at: Annotated[AwareDatetime, Field(alias="createdAt")] -class StatusPageSubscriberDto(BaseModel): +class StatusPageMeasuredUptimeDayDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) - id: UUID - email: str - confirmed: bool - created_at: Annotated[AwareDatetime, Field(alias="createdAt")] + date: Annotated[ + AwareDatetime, + Field( + description="Start-of-day timestamp for this bucket (UTC midnight, ISO 8601)" + ), + ] + total_checks: Annotated[ + int, + Field( + alias="totalChecks", + description="Total probe checks recorded that day across regions", + ), + ] + passed_checks: Annotated[ + int, + Field( + alias="passedChecks", + description="Checks that passed that day across regions", + ), + ] + uptime_percentage: Annotated[ + float | None, + Field( + alias="uptimePercentage", + description="passedChecks / totalChecks × 100; null when totalChecks is 0", + ), + ] = None + + +class StatusPageNotificationDeliveryDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: Annotated[UUID, Field(description="Delivery receipt ID")] + status_page_id: Annotated[ + UUID, + Field(alias="statusPageId", description="Status page that owns this delivery"), + ] + subscriber_id: Annotated[ + UUID, + Field(alias="subscriberId", description="Subscriber this delivery targeted"), + ] + destination: Annotated[ + str | None, + Field(description="Subscriber destination (email, phone, or webhook URL)"), + ] = None + channel: Annotated[ + str, + Field(description="Delivery channel from the subscriber (EMAIL, SMS, WEBHOOK)"), + ] + incident_id: Annotated[ + UUID | None, + Field( + alias="incidentId", description="Related status-page incident ID, if any" + ), + ] = None + incident_update_id: Annotated[ + UUID | None, + Field( + alias="incidentUpdateId", description="Related incident update ID, if any" + ), + ] = None + event_type: Annotated[ + str, + Field( + alias="eventType", + description="Notification event type that triggered this delivery", + ), + ] + status: Annotated[str, Field(description="Current delivery status")] + attempt_count: Annotated[ + int, Field(alias="attemptCount", description="Number of delivery attempts made") + ] + last_attempt_at: Annotated[ + AwareDatetime | None, + Field(alias="lastAttemptAt", description="When the last attempt was made"), + ] = None + next_retry_at: Annotated[ + AwareDatetime | None, + Field( + alias="nextRetryAt", + description="When the next retry is scheduled; null if not retrying", + ), + ] = None + delivered_at: Annotated[ + AwareDatetime | None, + Field( + alias="deliveredAt", + description="When delivery was confirmed; null if not delivered", + ), + ] = None + error_message: Annotated[ + str | None, + Field( + alias="errorMessage", + description="Error summary from the last failed attempt", + ), + ] = None + created_at: Annotated[ + AwareDatetime, + Field(alias="createdAt", description="When the delivery row was created"), + ] + + +class StatusPageOpenIncidentSummaryDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: Annotated[ + UUID | None, + Field( + description="Incident id for dashboard CTAs that open the matching drawer" + ), + ] = None + title: Annotated[ + str, + Field( + description="Incident title shown on the list card live row", min_length=1 + ), + ] + status: Annotated[str, Field(description="Lifecycle status of the open incident")] + started_at: Annotated[ + AwareDatetime, + Field(alias="startedAt", description="When the incident started (ISO 8601)"), + ] + updated_at: Annotated[ + AwareDatetime, + Field( + alias="updatedAt", + description="When the incident was last updated (ISO 8601)", + ), + ] + + +class StatusPageSubscriberDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: Annotated[UUID, Field(description="Subscriber id")] + email: Annotated[ + str | None, + Field(description="Email when channel is EMAIL; null for other channels"), + ] = None + channel: Annotated[str, Field(description="Delivery channel (EMAIL, SMS, WEBHOOK)")] + destination: Annotated[ + str, Field(description="Channel destination (email, phone, or webhook URL)") + ] + component_ids: Annotated[ + list[UUID] | None, + Field( + alias="componentIds", + description="Scoped component IDs; null means whole page", + ), + ] = None + confirmed: Annotated[ + bool, Field(description="Whether the subscriber has confirmed opt-in") + ] + created_at: Annotated[ + AwareDatetime, + Field(alias="createdAt", description="When the subscriber was created"), + ] class Summary(BaseModel): @@ -4900,15 +5628,6 @@ class TableValueResultEnvironmentDto(BaseModel): total_pages: Annotated[int | None, Field(alias="totalPages")] = None -class TableValueResultIncidentDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: list[IncidentDto] - has_next: Annotated[bool, Field(alias="hasNext")] - has_prev: Annotated[bool, Field(alias="hasPrev")] - total_elements: Annotated[int | None, Field(alias="totalElements")] = None - total_pages: Annotated[int | None, Field(alias="totalPages")] = None - - class TableValueResultInviteDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: list[InviteDto] @@ -5035,9 +5754,9 @@ class TableValueResultStatusPageCustomDomainDto(BaseModel): total_pages: Annotated[int | None, Field(alias="totalPages")] = None -class TableValueResultStatusPageDto(BaseModel): +class TableValueResultStatusPageNotificationDeliveryDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: list[StatusPageDto] + data: list[StatusPageNotificationDeliveryDto] has_next: Annotated[bool, Field(alias="hasNext")] has_prev: Annotated[bool, Field(alias="hasPrev")] total_elements: Annotated[int | None, Field(alias="totalElements")] = None @@ -5188,6 +5907,24 @@ class TestMatchResult(BaseModel): ] +class TestMonitorNotificationsRequest(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + channel_ids: Annotated[ + list[UUID] | None, + Field( + alias="channelIds", + description="Channel IDs to test; null or empty tests all channels attached to the monitor", + ), + ] = None + include_resolved: Annotated[ + bool, + Field( + alias="includeResolved", + description="Whether to include a resolved notification in the test (default: false)", + ), + ] + + class TestNotificationPolicyRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) severity: Annotated[ @@ -5261,7 +5998,10 @@ class TimingPhasesDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) dns_ms: Annotated[ int | None, - Field(description="DNS resolution time in milliseconds", examples=[12]), + Field( + description="Legacy DNS phase; null for new checks (no longer measured)", + examples=[12], + ), ] = None tcp_ms: Annotated[ int | None, Field(description="TCP connect time in milliseconds", examples=[18]) @@ -5489,6 +6229,47 @@ class UpdateAssertionRequest(BaseModel): ] = None +class UpdateDatadogChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["datadog"], Field(alias="channelType")] = "datadog" + api_key: Annotated[ + str | None, Field(alias="apiKey", description="Datadog API key") + ] = None + site: Annotated[ + str | None, + Field( + description="Datadog site region (e.g. datadoghq.com, datadoghq.eu, us3.datadoghq.com)" + ), + ] = None + tags: Annotated[ + str | None, Field(description="Comma-separated tags to attach to events") + ] = None + + +class UpdateDiscordChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["discord"], Field(alias="channelType")] = "discord" + webhook_url: Annotated[ + str | None, Field(alias="webhookUrl", description="Discord webhook URL") + ] = None + mention_role_id: Annotated[ + str | None, + Field( + alias="mentionRoleId", + description="Optional Discord role ID to mention in notifications", + ), + ] = None + + +class UpdateEmailChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["email"], Field(alias="channelType")] = "email" + recipients: Annotated[ + list[EmailStr], + Field(description="Email addresses to send notifications to", min_length=1), + ] + + class UpdateEnvironmentRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) name: Annotated[ @@ -5512,75 +6293,237 @@ class UpdateEnvironmentRequest(BaseModel): ] = None -class UpdateIncidentPolicyRequest(BaseModel): - model_config = ConfigDict(extra="forbid", populate_by_name=True) - trigger_rules: Annotated[ - list[TriggerRule], +class UpdateGitLabChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["gitlab"], Field(alias="channelType")] = "gitlab" + endpoint_url: Annotated[ + str, Field( - alias="triggerRules", - description="Array of trigger rules; at least one required", + alias="endpointUrl", + description="GitLab alert integration endpoint URL", min_length=1, ), ] - confirmation: ConfirmationPolicy - recovery: RecoveryPolicy - - -class UpdateMaintenanceWindowRequest(BaseModel): - model_config = ConfigDict(extra="forbid", populate_by_name=True) - monitor_id: Annotated[ - UUID | None, + authorization_key: Annotated[ + str | None, Field( - alias="monitorId", - description="Monitor this window applies to; null switches the window to org-wide", + alias="authorizationKey", + description="Authorization key from GitLab alert integration settings", ), ] = None - starts_at: Annotated[ - AwareDatetime, - Field(alias="startsAt", description="Updated start time (ISO 8601)"), - ] - ends_at: Annotated[ - AwareDatetime, Field(alias="endsAt", description="Updated end time (ISO 8601)") - ] - repeat_rule: Annotated[ + + +class UpdateGoogleChatChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["google_chat"], Field(alias="channelType")] = ( + "google_chat" + ) + webhook_url: Annotated[ str | None, - Field( - alias="repeatRule", - description="Reserved: iCal RRULE for recurring windows (stored but not yet honored); null clears it", - max_length=100, - min_length=0, - ), + Field(alias="webhookUrl", description="Google Chat space webhook URL"), ] = None - reason: Annotated[ + + +class UpdateIncidentIoChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["incident_io"], Field(alias="channelType")] = ( + "incident_io" + ) + api_key: Annotated[ str | None, Field( - description="Updated reason (max 500 chars); null clears the existing reason", - max_length=500, - min_length=0, + alias="apiKey", + description="incident.io API key with 'Create incidents' permission", ), ] = None - suppress_alerts: Annotated[ - bool | None, + severity_id: Annotated[ + str | None, Field( - alias="suppressAlerts", - description="Whether to suppress alerts during this window; null defaults to true", + alias="severityId", + description="Severity ID for created incidents (from List Severities API)", ), ] = None + visibility: Annotated[ + str | None, + Field(description="Incident visibility: public or private (default: public)"), + ] = None -class UpdateMonitorAuthRequest(BaseModel): +class UpdateIncidentPolicyRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) - config: ApiKeyAuthConfig | BasicAuthConfig | BearerAuthConfig | HeaderAuthConfig + trigger_rules: Annotated[ + list[TriggerRule], + Field( + alias="triggerRules", + description="Array of trigger rules; at least one required", + min_length=1, + ), + ] + confirmation: ConfirmationPolicy + recovery: RecoveryPolicy -class UpdateOrgDetailsRequest(BaseModel): +class Severity5(StrEnum): + down = "DOWN" + degraded = "DEGRADED" + maintenance = "MAINTENANCE" + + +class UpdateIncidentRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) - name: Annotated[ - str, + title: Annotated[ + str | None, Field( - description="New organization name (max 200 chars)", - max_length=200, - min_length=0, + description="New title; null preserves current (min 1 char if present)", + max_length=2147483647, + min_length=1, + ), + ] = None + severity: Annotated[ + Severity5 | None, + Field( + description="New severity: DOWN, DEGRADED, or MAINTENANCE; null preserves current" + ), + ] = None + + +class UpdateJiraChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["jira"], Field(alias="channelType")] = "jira" + domain: Annotated[ + str, + Field( + description="Atlassian instance domain (e.g. yourteam.atlassian.net)", + min_length=1, + ), + ] + email: Annotated[ + str, + Field( + description="Atlassian account email for API authentication", min_length=1 + ), + ] + api_token: Annotated[ + str | None, Field(alias="apiToken", description="Atlassian API token") + ] = None + project_key: Annotated[ + str, + Field( + alias="projectKey", + description="Jira project key where issues are created (e.g. OPS)", + min_length=1, + ), + ] + issue_type: Annotated[ + str | None, + Field( + alias="issueType", description="Issue type name (e.g. Bug, Task, Incident)" + ), + ] = None + + +class UpdateLinearChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["linear"], Field(alias="channelType")] = "linear" + api_key: Annotated[ + str | None, Field(alias="apiKey", description="Linear API key") + ] = None + team_id: Annotated[ + str, + Field(alias="teamId", description="Team ID to create issues in", min_length=1), + ] + label_id: Annotated[ + str | None, + Field(alias="labelId", description="Label ID to attach to created issues"), + ] = None + + +class UpdateMaintenanceWindowRequest(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + monitor_id: Annotated[ + UUID | None, + Field( + alias="monitorId", + description="Monitor this window applies to; null switches the window to org-wide", + ), + ] = None + starts_at: Annotated[ + AwareDatetime, + Field(alias="startsAt", description="Updated start time (ISO 8601)"), + ] + ends_at: Annotated[ + AwareDatetime, Field(alias="endsAt", description="Updated end time (ISO 8601)") + ] + repeat_rule: Annotated[ + str | None, + Field( + alias="repeatRule", + description="Reserved: iCal RRULE for recurring windows (stored but not yet honored); null clears it", + max_length=100, + min_length=0, + ), + ] = None + reason: Annotated[ + str | None, + Field( + description="Updated reason (max 500 chars); null clears the existing reason", + max_length=500, + min_length=0, + ), + ] = None + suppress_alerts: Annotated[ + bool | None, + Field( + alias="suppressAlerts", + description="Whether to suppress alerts during this window; null defaults to true", + ), + ] = None + + +class UpdateMattermostChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["mattermost"], Field(alias="channelType")] = ( + "mattermost" + ) + webhook_url: Annotated[ + str | None, + Field(alias="webhookUrl", description="Mattermost incoming webhook URL"), + ] = None + channel: Annotated[ + str | None, Field(description="Override channel (if webhook allows)") + ] = None + icon_url: Annotated[ + str | None, Field(alias="iconUrl", description="Custom bot icon URL") + ] = None + + +class UpdateMonitorAuthRequest(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + config: ApiKeyAuthConfig | BasicAuthConfig | BearerAuthConfig | HeaderAuthConfig + + +class UpdateOpsGenieChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["opsgenie"], Field(alias="channelType")] = ( + "opsgenie" + ) + api_key: Annotated[ + str | None, + Field(alias="apiKey", description="OpsGenie API key for alert creation"), + ] = None + region: Annotated[ + str | None, Field(description="OpsGenie API region: us or eu") + ] = None + + +class UpdateOrgDetailsRequest(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + name: Annotated[ + str, + Field( + description="New organization name (max 200 chars)", + max_length=200, + min_length=0, ), ] email: Annotated[ @@ -5614,6 +6557,102 @@ class UpdateOrgDetailsRequest(BaseModel): ] = None +class UpdatePagerDutyChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["pagerduty"], Field(alias="channelType")] = ( + "pagerduty" + ) + routing_key: Annotated[ + str | None, + Field( + alias="routingKey", + description="PagerDuty Events API v2 routing (integration) key", + ), + ] = None + severity_override: Annotated[ + str | None, + Field( + alias="severityOverride", description="Override PagerDuty severity mapping" + ), + ] = None + + +class UpdatePhoneCallChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["phone_call"], Field(alias="channelType")] = ( + "phone_call" + ) + phone_number: Annotated[ + str | None, + Field( + alias="phoneNumber", + description="Recipient phone number in E.164 format; null preserves current", + ), + ] = None + verified_phone_number_id: Annotated[ + int | None, + Field( + alias="verifiedPhoneNumberId", + description="Id of an org verified_phone_number row; null preserves current when phoneNumber also null", + ), + ] = None + phone_numbers: Annotated[ + list[str] | None, + Field(alias="phoneNumbers", description="Deprecated: use phoneNumber"), + ] = None + voice_language: Annotated[ + str | None, + Field( + alias="voiceLanguage", + description="TTS voice language/locale (default: en-US). See VoiceLanguage for supported values", + ), + ] = None + preferred_language: Annotated[ + str | None, + Field( + alias="preferredLanguage", + description="Preferred language for TTS and notifications (BCP-47, e.g. en-US, de-DE). Alias for voiceLanguage", + ), + ] = None + + +class UpdatePushbulletChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["pushbullet"], Field(alias="channelType")] = ( + "pushbullet" + ) + access_token: Annotated[ + str | None, Field(alias="accessToken", description="Pushbullet access token") + ] = None + device_iden: Annotated[ + str | None, + Field( + alias="deviceIden", + description="Target device identifier (broadcasts to all if empty)", + ), + ] = None + + +class UpdatePushoverChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["pushover"], Field(alias="channelType")] = ( + "pushover" + ) + user_key: Annotated[ + str | None, Field(alias="userKey", description="Pushover user or group key") + ] = None + app_token: Annotated[ + str | None, + Field(alias="appToken", description="Pushover application API token"), + ] = None + priority: Annotated[ + str | None, Field(description="Notification priority override (-2 to 2)") + ] = None + sound: Annotated[str | None, Field(description="Notification sound override")] = ( + None + ) + + class UpdateResourceGroupRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) name: Annotated[ @@ -5718,6 +6757,21 @@ class UpdateResourceGroupRequest(BaseModel): ] = None +class UpdateRootlyChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["rootly"], Field(alias="channelType")] = "rootly" + api_key: Annotated[ + str | None, + Field( + alias="apiKey", + description="Rootly API token with incident creation permission", + ), + ] = None + severity: Annotated[ + str | None, Field(description="Severity slug override (e.g. sev0, sev1)") + ] = None + + class UpdateSecretRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) value: Annotated[ @@ -5730,42 +6784,105 @@ class UpdateSecretRequest(BaseModel): ] -class UpdateStatusPageComponentGroupRequest(BaseModel): - model_config = ConfigDict(extra="forbid", populate_by_name=True) - name: Annotated[ +class UpdateSlackChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["slack"], Field(alias="channelType")] = "slack" + webhook_url: Annotated[ + str | None, Field(alias="webhookUrl", description="Slack incoming webhook URL") + ] = None + mention_text: Annotated[ str | None, Field( - description="New group name; null preserves current", - max_length=255, - min_length=0, + alias="mentionText", + description="Optional mention text included in notifications, e.g. @channel", ), ] = None - description: Annotated[ + + +class UpdateSmsChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["sms"], Field(alias="channelType")] = "sms" + phone_number: Annotated[ str | None, Field( - description="New description; null preserves current, empty string clears", - max_length=500, - min_length=0, + alias="phoneNumber", + description="Recipient phone number in E.164 format; null preserves current", ), ] = None - display_order: Annotated[ + verified_phone_number_id: Annotated[ int | None, Field( - alias="displayOrder", - description="New position in the group list; null preserves current", + alias="verifiedPhoneNumberId", + description="Id of an org verified_phone_number row; null preserves current when phoneNumber also null", ), ] = None - default_open: Annotated[ - bool | None, + phone_numbers: Annotated[ + list[str] | None, + Field(alias="phoneNumbers", description="Deprecated: use phoneNumber"), + ] = None + preferred_language: Annotated[ + str | None, Field( - alias="defaultOpen", - description="Initial expand/collapse state on first page load; null preserves current. Renderer may auto-expand on active incidents", + alias="preferredLanguage", + description="Preferred language for SMS body (BCP-47, e.g. en-US, de-DE). Default: en-US", ), ] = None -class UpdateStatusPageComponentRequest(BaseModel): - model_config = ConfigDict(extra="forbid", populate_by_name=True) +class UpdateSplunkOnCallChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["splunk_oncall"], Field(alias="channelType")] = ( + "splunk_oncall" + ) + api_key: Annotated[ + str | None, Field(alias="apiKey", description="Splunk On-Call REST API key") + ] = None + routing_key: Annotated[ + str, + Field( + alias="routingKey", + description="Routing key for alert routing", + min_length=1, + ), + ] + + +class UpdateStatusPageComponentGroupRequest(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + name: Annotated[ + str | None, + Field( + description="New group name; null preserves current", + max_length=255, + min_length=0, + ), + ] = None + description: Annotated[ + str | None, + Field( + description="New description; null preserves current, empty string clears", + max_length=500, + min_length=0, + ), + ] = None + display_order: Annotated[ + int | None, + Field( + alias="displayOrder", + description="New position in the group list; null preserves current", + ), + ] = None + default_open: Annotated[ + bool | None, + Field( + alias="defaultOpen", + description="Initial expand/collapse state on first page load; null preserves current. Renderer may auto-expand on active incidents", + ), + ] = None + + +class UpdateStatusPageComponentRequest(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) name: Annotated[ str | None, Field( @@ -5826,6 +6943,13 @@ class UpdateStatusPageComponentRequest(BaseModel): ] = None +class Status9(StrEnum): + investigating = "INVESTIGATING" + identified = "IDENTIFIED" + monitoring = "MONITORING" + resolved = "RESOLVED" + + class UpdateStatusPageIncidentRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) title: Annotated[ @@ -5837,7 +6961,7 @@ class UpdateStatusPageIncidentRequest(BaseModel): ), ] = None status: Annotated[ - Status6 | None, Field(description="New status; null preserves current") + Status9 | None, Field(description="New status; null preserves current") ] = None impact: Annotated[ Impact | None, Field(description="New impact level; null preserves current") @@ -5863,7 +6987,52 @@ class UpdateStatusPageIncidentRequest(BaseModel): description="URL to an external postmortem document; empty string clears", max_length=2048, min_length=0, - pattern="^https?://.*", + pattern="^$|^https?://.*", + ), + ] = None + published: Annotated[ + bool | None, + Field( + description="Whether the incident is published on the public page; null preserves current. true publishes (sets publishedAt); false unpublishes (clears publishedAt)" + ), + ] = None + scheduled_for: Annotated[ + AwareDatetime | None, + Field( + alias="scheduledFor", + description="New maintenance window start; null preserves current. Only for scheduled incidents", + ), + ] = None + scheduled_until: Annotated[ + AwareDatetime | None, + Field( + alias="scheduledUntil", + description="New maintenance window end; null preserves current. Only for scheduled incidents", + ), + ] = None + auto_resolve: Annotated[ + bool | None, + Field( + alias="autoResolve", + description="Whether the window auto-completes at scheduledUntil; null preserves current", + ), + ] = None + + +class UpdateStatusPageIncidentUpdateRequest(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + body: Annotated[ + str, + Field( + description="Replacement update body in markdown", + max_length=10000, + min_length=0, + ), + ] + status: Annotated[ + Status9 | None, + Field( + description="Replacement lifecycle status for this update; null preserves current" ), ] = None @@ -5922,6 +7091,57 @@ class UpdateTagRequest(BaseModel): ] = None +class UpdateTeamsChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["teams"], Field(alias="channelType")] = "teams" + webhook_url: Annotated[ + str | None, + Field(alias="webhookUrl", description="Microsoft Teams incoming webhook URL"), + ] = None + + +class UpdateTelegramChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["telegram"], Field(alias="channelType")] = ( + "telegram" + ) + bot_token: Annotated[ + str | None, + Field(alias="botToken", description="Telegram bot token from @BotFather"), + ] = None + chat_id: Annotated[ + str, + Field( + alias="chatId", + description="Chat, group, or channel ID to send alerts to", + min_length=1, + ), + ] + + +class UpdateWebhookChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["webhook"], Field(alias="channelType")] = "webhook" + url: Annotated[ + str | None, + Field(description="Webhook endpoint URL that receives alert payloads"), + ] = None + signing_secret: Annotated[ + str | None, + Field( + alias="signingSecret", + description="HMAC secret for X-DevHelm-Signature header; omit for unsigned delivery", + ), + ] = None + custom_headers: Annotated[ + dict[str, str] | None, + Field( + alias="customHeaders", + description="Additional HTTP headers to include in webhook requests", + ), + ] = None + + class UpdateWebhookEndpointRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) url: Annotated[ @@ -5960,6 +7180,15 @@ class UpdateWorkspaceRequest(BaseModel): ] +class UpdateZapierChannelConfig(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + channel_type: Annotated[Literal["zapier"], Field(alias="channelType")] = "zapier" + webhook_url: Annotated[ + str | None, + Field(alias="webhookUrl", description="Zapier/n8n/Make catch webhook URL"), + ] = None + + class UptimeBucketDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) timestamp: Annotated[ @@ -6029,6 +7258,32 @@ class UptimeDto(BaseModel): examples=[312], ), ] = None + p50_latency_ms: Annotated[ + float | None, + Field( + alias="p50LatencyMs", + description="50th-percentile (median) latency in milliseconds; null when no data", + examples=[128], + ), + ] = None + incident_count: Annotated[ + int, + Field( + alias="incidentCount", + description="Number of incidents that started within the requested window", + examples=[2], + ), + ] + + +class VoiceLanguageDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + code: Annotated[ + str, Field(description="BCP-47 locale code, e.g. en-US", min_length=1) + ] + label: Annotated[ + str, Field(description="Human-readable label, e.g. English (US)", min_length=1) + ] class WebhookChannelConfig(BaseModel): @@ -6045,7 +7300,7 @@ class WebhookChannelConfig(BaseModel): str | None, Field( alias="signingSecret", - description="Optional HMAC signing secret for payload verification", + description="HMAC secret for X-DevHelm-Signature header; omit for unsigned delivery", ), ] = None custom_headers: Annotated[ @@ -6201,6 +7456,20 @@ class ZapierChannelConfig(BaseModel): ] +class AcknowledgeAllIncidentsResponse(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + acknowledged: Annotated[ + list[NotificationDispatchDto], + Field(description="Dispatches successfully acknowledged in this request"), + ] + skipped: Annotated[ + list[SkippedDispatch], + Field( + description="Dispatches skipped (already acked or not in an acknowledgeable state)" + ), + ] + + class AddMonitorTagsRequest(BaseModel): model_config = ConfigDict(extra="forbid", populate_by_name=True) tag_ids: Annotated[ @@ -6278,6 +7547,40 @@ class BulkMonitorActionResult(BaseModel): ] +class Code(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + check_type: Literal["code"] = "code" + exit_code: Annotated[ + int, Field(alias="exitCode", description="Container exit code (0 = pass)") + ] + stdout_snippet: Annotated[ + str | None, + Field(alias="stdoutSnippet", description="Truncated stdout from the container"), + ] = None + stderr_snippet: Annotated[ + str | None, + Field(alias="stderrSnippet", description="Truncated stderr from the container"), + ] = None + steps: Annotated[ + list[CodeCheckStep] | None, + Field(description="Named steps extracted from Playwright test output"), + ] = None + failure_kind: Annotated[ + str | None, + Field( + alias="failureKind", + description="Failure classification: timeout, assertion, or error", + ), + ] = None + timed_out: Annotated[ + bool | None, + Field( + alias="timedOut", + description="Whether the run hit a step/total/run-budget timeout", + ), + ] = None + + class ComponentUptimeDayDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) date: Annotated[ @@ -6342,10 +7645,12 @@ class CreateAlertChannelRequest(BaseModel): | MattermostChannelConfig | OpsGenieChannelConfig | PagerDutyChannelConfig + | PhoneCallChannelConfig | PushbulletChannelConfig | PushoverChannelConfig | RootlyChannelConfig | SlackChannelConfig + | SmsChannelConfig | SplunkOnCallChannelConfig | TeamsChannelConfig | TelegramChannelConfig @@ -6434,6 +7739,7 @@ class CreateMonitorRequest(BaseModel): | HttpMonitorConfig | IcmpMonitorConfig | McpServerMonitorConfig + | ScriptMonitorConfig | TcpMonitorConfig ) frequency_seconds: Annotated[ @@ -6600,189 +7906,507 @@ class CreateStatusPageRequest(BaseModel): slug: Annotated[ str, Field( - description="URL slug (lowercase, hyphens, globally unique)", - max_length=63, - min_length=3, - pattern="^[a-z0-9][a-z0-9-]*[a-z0-9]$", + description="URL slug (lowercase, hyphens, globally unique)", + max_length=63, + min_length=3, + pattern="^[a-z0-9][a-z0-9-]*[a-z0-9]$", + ), + ] + description: Annotated[ + str | None, + Field( + description="Optional description shown below the page header", + max_length=500, + min_length=0, + ), + ] = None + branding: StatusPageBranding | None = None + visibility: Annotated[ + Visibility | None, + Field( + description="Page visibility: PUBLIC, PASSWORD, or IP_RESTRICTED (default: PUBLIC)" + ), + ] = None + enabled: Annotated[ + bool | None, Field(description="Whether the page is enabled (default: true)") + ] = None + incident_mode: Annotated[ + IncidentMode | None, + Field( + alias="incidentMode", + description="Incident mode: MANUAL, REVIEW, or AUTOMATIC (default: AUTOMATIC)", + ), + ] = None + managed_by: Annotated[ + ManagedBy | None, + Field( + alias="managedBy", + description="Source creating this page: DASHBOARD, CLI, TERRAFORM, MCP, or API. Defaults to API when omitted.", + ), + ] = None + + +class CreditPolicy(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + summary: Annotated[ + str | None, Field(description="Brief summary of credit policy") + ] = None + max_credit_percent: Annotated[ + int | None, + Field( + alias="maxCreditPercent", description="Max credit as percent of monthly fee" + ), + ] = None + claim_window_days: Annotated[ + int | None, + Field( + alias="claimWindowDays", + description="Days to submit a credit claim after eligibility", + ), + ] = None + credit_application_days: Annotated[ + int | None, + Field( + alias="creditApplicationDays", + description="Days for credit to be applied after approval", + ), + ] = None + tiers: Annotated[ + list[CreditTier] | None, Field(description="Credit tiers by uptime threshold") + ] = None + + +class CursorPageIncidentActivityEventDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: Annotated[ + list[IncidentActivityEventDto], Field(description="Items on this page") + ] + next_cursor: Annotated[ + str | None, + Field( + alias="nextCursor", + description="Opaque cursor for the next page; null when there are no more results", + ), + ] = None + has_more: Annotated[ + bool, + Field( + alias="hasMore", description="Whether more results exist beyond this page" + ), + ] + + +class CursorPageServiceCatalogDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: Annotated[list[ServiceCatalogDto], Field(description="Items on this page")] + next_cursor: Annotated[ + str | None, + Field( + alias="nextCursor", + description="Opaque cursor for the next page; null when there are no more results", + ), + ] = None + has_more: Annotated[ + bool, + Field( + alias="hasMore", description="Whether more results exist beyond this page" + ), + ] + + +class CursorPageServicePollResultDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: Annotated[list[ServicePollResultDto], Field(description="Items on this page")] + next_cursor: Annotated[ + str | None, + Field( + alias="nextCursor", + description="Opaque cursor for the next page; null when there are no more results", + ), + ] = None + has_more: Annotated[ + bool, + Field( + alias="hasMore", description="Whether more results exist beyond this page" + ), + ] + + +class CursorPageStatusEventDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: Annotated[list[StatusEventDto], Field(description="Items on this page")] + next_cursor: Annotated[ + str | None, + Field( + alias="nextCursor", + description="Opaque cursor for the next page; null when there are no more results", + ), + ] = None + has_more: Annotated[ + bool, + Field( + alias="hasMore", description="Whether more results exist beyond this page" + ), + ] + + +class DashboardOverviewDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + monitors: MonitorsSummaryDto + incidents: IncidentsSummaryDto + + +class EscalationChain(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + steps: Annotated[ + list[EscalationStep], + Field( + description="Ordered escalation steps, evaluated in sequence", min_length=1 + ), + ] + on_resolve: Annotated[ + str | None, + Field(alias="onResolve", description="Action when the incident resolves"), + ] = None + on_reopen: Annotated[ + str | None, + Field(alias="onReopen", description="Action when a resolved incident reopens"), + ] = None + + +class GlobalStatusSummaryDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + total_services: Annotated[ + int, + Field( + alias="totalServices", description="Total number of services in the catalog" + ), + ] + operational_count: Annotated[ + int, + Field( + alias="operationalCount", + description="Number of services currently fully operational", + ), + ] + degraded_count: Annotated[ + int, + Field( + alias="degradedCount", description="Number of services with degraded status" + ), + ] + partial_outage_count: Annotated[ + int, + Field( + alias="partialOutageCount", + description="Number of services with partial outage", + ), + ] + major_outage_count: Annotated[ + int, + Field( + alias="majorOutageCount", description="Number of services with major outage" + ), + ] + maintenance_count: Annotated[ + int, + Field( + alias="maintenanceCount", + description="Number of services currently under maintenance", + ), + ] + unknown_count: Annotated[ + int, + Field( + alias="unknownCount", + description="Number of services with unknown or null status", + ), + ] + active_incident_count: Annotated[ + int, + Field( + alias="activeIncidentCount", + description="Total number of active incidents across all services", + ), + ] + services_with_issues: Annotated[ + list[ServiceCatalogDto], + Field( + alias="servicesWithIssues", + description="Services that are not fully operational", + ), + ] + + +class Http(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + check_type: Literal["http"] = "http" + timing: TimingPhasesDto | None = None + body_truncated: Annotated[ + bool | None, + Field( + alias="bodyTruncated", + description="Whether the response body was truncated before storage", + ), + ] = None + + +class IncidentDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: Annotated[UUID, Field(description="Unique incident identifier")] + monitor_id: Annotated[ + UUID | None, + Field( + alias="monitorId", + description="Monitor that triggered the incident; null for service or manual incidents", + ), + ] = None + organization_id: Annotated[ + int, + Field( + alias="organizationId", description="Organization this incident belongs to" + ), + ] + source: Annotated[ + str, Field(description="Incident origin: MONITOR, SERVICE, or MANUAL") + ] + status: Annotated[ + str, Field(description="Current lifecycle status (OPEN, RESOLVED, etc.)") + ] + severity: Annotated[ + str, Field(description="Severity level: DOWN, DEGRADED, or MAINTENANCE") + ] + title: Annotated[ + str | None, + Field( + description="Short summary of the incident; null for auto-generated incidents" + ), + ] = None + triggered_by_rule: Annotated[ + str | None, + Field( + alias="triggeredByRule", + description="Human-readable description of the trigger rule that fired", + ), + ] = None + affected_regions: Annotated[ + list[str], + Field( + alias="affectedRegions", + description="Probe regions that observed the failure", + ), + ] + reopen_count: Annotated[ + int, + Field( + alias="reopenCount", + description="Number of times this incident has been reopened", + ), + ] + created_by_user_id: Annotated[ + int | None, + Field( + alias="createdByUserId", + description="User who created the incident (manual incidents only)", + ), + ] = None + status_page_visible: Annotated[ + bool, + Field( + alias="statusPageVisible", + description="Whether this incident is visible on the status page", + ), + ] + suppress_dispatch: Annotated[ + bool, + Field( + alias="suppressDispatch", + description="When true, alert channels are suppressed (AWARENESS silent tracking); false means Alerted", + ), + ] + service_incident_id: Annotated[ + UUID | None, + Field( + alias="serviceIncidentId", + description="Linked vendor service incident ID; null for monitor incidents", + ), + ] = None + service_id: Annotated[ + UUID | None, + Field( + alias="serviceId", + description="Linked service catalog ID; null for monitor incidents", ), - ] - description: Annotated[ + ] = None + external_ref: Annotated[ str | None, Field( - description="Optional description shown below the page header", - max_length=500, - min_length=0, + alias="externalRef", + description="External reference ID (e.g. PagerDuty incident ID)", ), ] = None - branding: StatusPageBranding | None = None - visibility: Annotated[ - Visibility | None, + affected_components: Annotated[ + list[str] | None, Field( - description="Page visibility: PUBLIC, PASSWORD, or IP_RESTRICTED (default: PUBLIC)" + alias="affectedComponents", + description="Service components affected by this incident", ), ] = None - enabled: Annotated[ - bool | None, Field(description="Whether the page is enabled (default: true)") + shortlink: Annotated[ + str | None, Field(description="Short URL linking to the incident details") ] = None - incident_mode: Annotated[ - IncidentMode | None, + resolution_reason: Annotated[ + str | None, Field( - alias="incidentMode", - description="Incident mode: MANUAL, REVIEW, or AUTOMATIC (default: AUTOMATIC)", + alias="resolutionReason", + description="How the incident was resolved (AUTO_RECOVERED, MANUAL, etc.)", ), ] = None - managed_by: Annotated[ - ManagedBy | None, + resolution_note: Annotated[ + str | None, Field( - alias="managedBy", - description="Source creating this page: DASHBOARD, CLI, TERRAFORM, MCP, or API. Defaults to API when omitted.", + alias="resolutionNote", + description="Body from the most recent resolve update; null when not currently resolved, auto-resolved without a note, or no resolve update body was provided", ), ] = None - - -class CursorPageServiceCatalogDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: Annotated[list[ServiceCatalogDto], Field(description="Items on this page")] - next_cursor: Annotated[ - str | None, + started_at: Annotated[ + AwareDatetime | None, Field( - alias="nextCursor", - description="Opaque cursor for the next page; null when there are no more results", + alias="startedAt", + description="Timestamp when the incident was detected or created", ), ] = None - has_more: Annotated[ - bool, + confirmed_at: Annotated[ + AwareDatetime | None, Field( - alias="hasMore", description="Whether more results exist beyond this page" + alias="confirmedAt", + description="Timestamp when the incident was confirmed (multi-region confirmation)", ), - ] - - -class CursorPageServicePollResultDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: Annotated[list[ServicePollResultDto], Field(description="Items on this page")] - next_cursor: Annotated[ - str | None, + ] = None + resolved_at: Annotated[ + AwareDatetime | None, Field( - alias="nextCursor", - description="Opaque cursor for the next page; null when there are no more results", + alias="resolvedAt", description="Timestamp when the incident was resolved" ), ] = None - has_more: Annotated[ - bool, + cooldown_until: Annotated[ + AwareDatetime | None, Field( - alias="hasMore", description="Whether more results exist beyond this page" + alias="cooldownUntil", + description="Cooldown window end; new incidents suppressed until this time", + ), + ] = None + created_at: Annotated[ + AwareDatetime, + Field( + alias="createdAt", + description="Timestamp when the incident record was created", ), ] - - -class DashboardOverviewDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - monitors: MonitorsSummaryDto - incidents: IncidentsSummaryDto - - -class EscalationChain(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - steps: Annotated[ - list[EscalationStep], + updated_at: Annotated[ + AwareDatetime, Field( - description="Ordered escalation steps, evaluated in sequence", min_length=1 + alias="updatedAt", + description="Timestamp when the incident was last updated", ), ] - on_resolve: Annotated[ + monitor_name: Annotated[ str | None, - Field(alias="onResolve", description="Action when the incident resolves"), + Field( + alias="monitorName", + description="Name of the associated monitor; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", + ), ] = None - on_reopen: Annotated[ + service_name: Annotated[ str | None, - Field(alias="onReopen", description="Action when a resolved incident reopens"), + Field( + alias="serviceName", + description="Name of the associated service; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", + ), ] = None - - -class GlobalStatusSummaryDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - total_services: Annotated[ - int, + service_slug: Annotated[ + str | None, Field( - alias="totalServices", description="Total number of services in the catalog" + alias="serviceSlug", + description="Slug of the associated service; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", ), - ] - operational_count: Annotated[ - int, + ] = None + monitor_type: Annotated[ + str | None, Field( - alias="operationalCount", - description="Number of services currently fully operational", + alias="monitorType", + description="Type of the associated monitor; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", ), - ] - degraded_count: Annotated[ - int, + ] = None + resource_group_id: Annotated[ + UUID | None, Field( - alias="degradedCount", description="Number of services with degraded status" + alias="resourceGroupId", + description="Resource group that owns this incident; null when not group-managed", ), - ] - partial_outage_count: Annotated[ - int, + ] = None + resource_group_name: Annotated[ + str | None, Field( - alias="partialOutageCount", - description="Number of services with partial outage", + alias="resourceGroupName", + description="Name of the resource group; populated on list responses. Omitted from JSON (undefined to SDKs) on detail responses, treat missing as null.", ), - ] - major_outage_count: Annotated[ - int, + ] = None + triggering_check_id: Annotated[ + UUID | None, Field( - alias="majorOutageCount", description="Number of services with major outage" + alias="triggeringCheckId", + description="Scheduler-minted check execution ID whose result confirmed this incident; joins to check_results, rule_evaluations, and incident_state_transitions. Omitted from JSON (undefined to SDKs) when null, treat missing as null.", ), - ] - maintenance_count: Annotated[ - int, + ] = None + triggered_by_rule_snapshot_hash_hex: Annotated[ + str | None, Field( - alias="maintenanceCount", - description="Number of services currently under maintenance", + alias="triggeredByRuleSnapshotHashHex", + description="Hex SHA-256 of the canonical policy snapshot that fired; combined with triggeredByRuleIndex points to the exact TriggerRule. Omitted from JSON when null, treat missing as null.", ), - ] - unknown_count: Annotated[ - int, + ] = None + triggered_by_rule_index: Annotated[ + int | None, Field( - alias="unknownCount", - description="Number of services with unknown or null status", + alias="triggeredByRuleIndex", + description="Index of the fired rule inside the policy's trigger_rules array. Omitted from JSON when null, treat missing as null.", ), - ] - active_incident_count: Annotated[ - int, + ] = None + engine_version: Annotated[ + str | None, Field( - alias="activeIncidentCount", - description="Total number of active incidents across all services", + alias="engineVersion", + description="Detection engine semver that evaluated the rule. Omitted from JSON when null, treat missing as null.", ), - ] - services_with_issues: Annotated[ - list[ServiceCatalogDto], + ] = None + display_key: Annotated[ + str | None, Field( - alias="servicesWithIssues", - description="Services that are not fully operational", + alias="displayKey", + description='Org-scoped human-readable incident code, e.g. "ABC-42". Null on incidents created by pre-INC-keys API pods before the sweep; treat missing as unknown and fall back to the id', ), - ] - - -class Http(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - check_type: Literal["http"] = "http" - timing: TimingPhasesDto | None = None - body_truncated: Annotated[ - bool | None, + ] = None + alert_collapsed_by_resource_group_ids: Annotated[ + list[UUID] | None, Field( - alias="bodyTruncated", - description="Whether the response body was truncated before storage", + alias="alertCollapsedByResourceGroupIds", + description="Sticky union of resource-group IDs that suppressed a paging dispatch for this member incident; null when never written / legacy", ), ] = None - - -class IncidentDetailDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - incident: IncidentDto - updates: list[IncidentUpdateDto] - status_page_incidents: Annotated[ - list[LinkedStatusPageIncidentDto] | None, Field(alias="statusPageIncidents") + peak_failing_member_count: Annotated[ + int | None, + Field( + alias="peakFailingMemberCount", + description="Peak non-operational member count while this RESOURCE_GROUP incident was open; null otherwise", + ), + ] = None + failing_members_at_peak: Annotated[ + list[IncidentFailingMemberSnapshotDto] | None, + Field( + alias="failingMembersAtPeak", + description="Frozen failing members at peakFailingMemberCount; null when not a group incident or never snapshotted", + ), ] = None @@ -7001,13 +8625,9 @@ class MonitorAssertionDto(BaseModel): class MonitorDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) """Note: ``currentStatus`` was removed from this DTO. Inspect ``enabled`` and the incident-policy API to derive a live status for a monitor instead.""" model_config = ConfigDict(extra="ignore", populate_by_name=True) - """Note: ``currentStatus`` was removed from this DTO. Inspect ``enabled`` and the incident-policy API to derive a live status for a monitor instead.""" - - model_config = ConfigDict(extra="forbid", populate_by_name=True) id: Annotated[UUID, Field(description="Unique monitor identifier")] organization_id: Annotated[ int, @@ -7025,6 +8645,7 @@ class MonitorDto(BaseModel): | HttpMonitorConfig | IcmpMonitorConfig | McpServerMonitorConfig + | ScriptMonitorConfig | TcpMonitorConfig ) frequency_seconds: Annotated[ @@ -7101,6 +8722,7 @@ class MonitorTestRequest(BaseModel): | HttpMonitorConfig | IcmpMonitorConfig | McpServerMonitorConfig + | ScriptMonitorConfig | TcpMonitorConfig ) assertions: Annotated[ @@ -7181,152 +8803,147 @@ class NotificationPolicyDto(BaseModel): ] -class ResourceGroupDto(BaseModel): +class RelatedIncidentsResponse(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) - id: Annotated[UUID, Field(description="Unique resource group identifier")] - organization_id: Annotated[ + data: Annotated[ + list[IncidentDto], + Field(description="Related incident rows (newest first, capped by limit)"), + ] + total: Annotated[ int, - Field(alias="organizationId", description="Organization this group belongs to"), + Field( + description="Total matching incidents in the window, excluding the current incident" + ), + ] + + +class ResourceGroupMemberDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: Annotated[UUID, Field(description="Unique group member record identifier")] + group_id: Annotated[ + UUID, + Field(alias="groupId", description="Resource group this member belongs to"), + ] + member_type: Annotated[ + str, + Field(alias="memberType", description="Type of member: 'monitor' or 'service'"), ] - name: Annotated[str, Field(description="Human-readable group name", min_length=1)] - slug: Annotated[str, Field(description="URL-safe group identifier", min_length=1)] - description: Annotated[ - str | None, Field(description="Optional group description") - ] = None - alert_policy_id: Annotated[ + monitor_id: Annotated[ UUID | None, Field( - alias="alertPolicyId", - description="Notification policy applied to this group", - ), - ] = None - default_frequency: Annotated[ - int | None, - Field( - alias="defaultFrequency", - description="Default check frequency in seconds for member monitors", + alias="monitorId", + description="Monitor ID; set when memberType is 'monitor'", ), ] = None - default_regions: Annotated[ - list[str] | None, + service_id: Annotated[ + UUID | None, Field( - alias="defaultRegions", description="Default regions for member monitors" + alias="serviceId", + description="Service ID; set when memberType is 'service'", ), ] = None - default_retry_strategy: Annotated[ - RetryStrategy | None, Field(alias="defaultRetryStrategy") + name: Annotated[ + str | None, + Field(description="Display name of the referenced monitor or service"), ] = None - default_alert_channels: Annotated[ - list[UUID] | None, + slug: Annotated[ + str | None, Field( - alias="defaultAlertChannels", - description="Default alert channel IDs for member monitors", + description="Slug identifier for the service (services only); used for icons and uptime API calls" ), ] = None - default_environment_id: Annotated[ + subscription_id: Annotated[ UUID | None, Field( - alias="defaultEnvironmentId", - description="Default environment ID for member monitors", + alias="subscriptionId", + description="Subscription ID for the service (services only); used to link to the dependency detail page", ), ] = None - health_threshold_type: Annotated[ + status: Annotated[str, Field(description="Computed health status for this member")] + effective_frequency: Annotated[ str | None, Field( - alias="healthThresholdType", - description="Health threshold type: COUNT or PERCENTAGE", + alias="effectiveFrequency", + description="Effective check frequency label showing the group default when the monitor inherits it; null for services or when no group default is configured", ), ] = None - health_threshold_value: Annotated[ + created_at: Annotated[ + AwareDatetime, + Field( + alias="createdAt", + description="Timestamp when the member was added to the group", + ), + ] + uptime24h: Annotated[ float | None, - Field(alias="healthThresholdValue", description="Health threshold value"), + Field(description="24h uptime percentage; populated when includeMetrics=true"), ] = None - suppress_member_alerts: Annotated[ - bool, + chart_data: Annotated[ + list[float] | None, Field( - alias="suppressMemberAlerts", - description="When true, member-level incidents skip notification dispatch; only group alerts fire", + alias="chartData", + description="Uptime tick values (0-100) for last-24h mini chart; populated when includeMetrics=true", ), - ] - confirmation_delay_seconds: Annotated[ - int | None, + ] = None + avg_latency_ms: Annotated[ + float | None, Field( - alias="confirmationDelaySeconds", - description="Seconds to wait after health threshold breach before creating group incident", + alias="avgLatencyMs", + description="Average latency in ms (monitors only); populated when includeMetrics=true", ), ] = None - recovery_cooldown_minutes: Annotated[ - int | None, + p95_latency_ms: Annotated[ + float | None, Field( - alias="recoveryCooldownMinutes", - description="Cooldown minutes after group incident resolves before a new one can open", + alias="p95LatencyMs", + description="P95 latency in ms (monitors only); populated when includeMetrics=true", ), ] = None - health: ResourceGroupHealthDto - members: Annotated[ - list[ResourceGroupMemberDto] | None, + last_checked_at: Annotated[ + AwareDatetime | None, Field( - description="Member list with individual statuses; populated on detail GET only" + alias="lastCheckedAt", + description="Timestamp of the most recent health check; populated when includeMetrics=true", ), ] = None - managed_by: Annotated[ + monitor_type: Annotated[ str | None, Field( - alias="managedBy", - description="Source that created/owns this group: DASHBOARD, CLI, TERRAFORM, MCP, or API. Null on groups created before this attribution column existed.", + alias="monitorType", + description="Monitor type (HTTP, DNS, TCP, ICMP, HEARTBEAT, MCP); monitors only", ), ] = None - created_at: Annotated[ - AwareDatetime, - Field(alias="createdAt", description="Timestamp when the group was created"), - ] - updated_at: Annotated[ - AwareDatetime, + environment_name: Annotated[ + str | None, + Field(alias="environmentName", description="Environment name; monitors only"), + ] = None + group_membership_count: Annotated[ + int | None, Field( - alias="updatedAt", description="Timestamp when the group was last updated" + alias="groupMembershipCount", + description="Count of resource groups this monitor or service belongs to; detail GET only — omitted on list", ), - ] - - -class ServiceDetailDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - id: UUID - slug: str - name: str - category: str | None = None - official_status_url: Annotated[str | None, Field(alias="officialStatusUrl")] = None - developer_context: Annotated[str | None, Field(alias="developerContext")] = None - logo_url: Annotated[str | None, Field(alias="logoUrl")] = None - adapter_type: Annotated[str, Field(alias="adapterType")] - polling_interval_seconds: Annotated[int, Field(alias="pollingIntervalSeconds")] - lifecycle_status: Annotated[ - str, + ] = None + failing_since: Annotated[ + AwareDatetime | None, Field( - alias="lifecycleStatus", - description="Service lifecycle state: ACTIVE, DEGRADED, DEPRECATED, or RETIRED", + alias="failingSince", + description="Start of the current non-operational stretch; null when operational or unknown (services OK); detail GET only — omitted on list", ), - ] - enabled: bool - created_at: Annotated[AwareDatetime, Field(alias="createdAt")] - updated_at: Annotated[AwareDatetime, Field(alias="updatedAt")] - current_status: Annotated[ServiceStatusDto | None, Field(alias="currentStatus")] = ( - None - ) - recent_incidents: Annotated[ - list[ServiceIncidentDto], Field(alias="recentIncidents") - ] - components: list[ServiceComponentDto] - components_summary: Annotated[ - ComponentsSummaryDto | None, Field(alias="componentsSummary") ] = None - uptime: ComponentUptimeSummaryDto | None = None - active_maintenances: Annotated[ - list[ScheduledMaintenanceDto], Field(alias="activeMaintenances") - ] - data_completeness: Annotated[str, Field(alias="dataCompleteness")] - seo_metadata: Annotated[SeoMetadataDto | None, Field(alias="seoMetadata")] = None - related_services: Annotated[ - list[ServiceCatalogDto] | None, Field(alias="relatedServices") + alert_collapsed: Annotated[ + bool | None, + Field( + alias="alertCollapsed", + description="True when an active member incident records this group among alertCollapsedByResourceGroupIds; detail GET only — omitted on list", + ), + ] = None + incident_marks: Annotated[ + list[ResourceGroupMemberIncidentMarkDto] | None, + Field( + alias="incidentMarks", + description="Incident marks for the trailing 24h strip; null when metrics omitted or failed; detail GET only — omitted on list", + ), ] = None @@ -7343,6 +8960,7 @@ class ServiceIncidentDetailDto(BaseModel): affected_components: Annotated[ list[str] | None, Field(alias="affectedComponents") ] = None + affected_regions: Annotated[list[str] | None, Field(alias="affectedRegions")] = None updates: list[ServiceIncidentUpdateDto] @@ -7373,6 +8991,11 @@ class ServiceUptimeResponse(BaseModel): ] = None +class SingleValueResponseAcknowledgeAllIncidentsResponse(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: AcknowledgeAllIncidentsResponse + + class SingleValueResponseAuthMeResponse(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: AuthMeResponse @@ -7393,11 +9016,6 @@ class SingleValueResponseGlobalStatusSummaryDto(BaseModel): data: GlobalStatusSummaryDto -class SingleValueResponseIncidentDetailDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: IncidentDetailDto - - class SingleValueResponseIncidentPolicyDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: IncidentPolicyDto @@ -7428,14 +9046,9 @@ class SingleValueResponseNotificationPolicyDto(BaseModel): data: NotificationPolicyDto -class SingleValueResponseResourceGroupDto(BaseModel): - model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: ResourceGroupDto - - -class SingleValueResponseServiceDetailDto(BaseModel): +class SingleValueResponseResourceGroupMemberDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: ServiceDetailDto + data: ResourceGroupMemberDto class SingleValueResponseServiceIncidentDetailDto(BaseModel): @@ -7463,9 +9076,14 @@ class SingleValueResponseStatusPageCustomDomainDto(BaseModel): data: StatusPageCustomDomainDto -class SingleValueResponseStatusPageDto(BaseModel): +class SingleValueResponseStatusPageIncidentUpdateDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: StatusPageDto + data: StatusPageIncidentUpdateDto + + +class SingleValueResponseStatusPageNotificationDeliveryDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: StatusPageNotificationDeliveryDto class SingleValueResponseStatusPageSubscriberDto(BaseModel): @@ -7513,6 +9131,77 @@ class SingleValueResponseWorkspaceDto(BaseModel): data: WorkspaceDto +class SlaDataDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + sla_type: Annotated[ + str | None, + Field( + alias="slaType", + description="SLA pattern: plan_gated, per_service, no_public_sla, or universal", + ), + ] = None + official_sla: Annotated[OfficialSla | None, Field(alias="officialSla")] = None + service_breakdown: Annotated[ + list[ServiceBreakdown] | None, + Field( + alias="serviceBreakdown", + description="Per-service breakdown for vendors with per_service SLA type", + ), + ] = None + pricing_tiers: Annotated[ + list[PricingTier] | None, + Field( + alias="pricingTiers", description="Pricing tiers with associated SLA levels" + ), + ] = None + credit_policy: Annotated[CreditPolicy | None, Field(alias="creditPolicy")] = None + no_sla_context: Annotated[NoSlaContext | None, Field(alias="noSlaContext")] = None + source_urls: Annotated[SourceUrls | None, Field(alias="sourceUrls")] = None + last_researched: Annotated[ + str | None, + Field( + alias="lastResearched", + description="ISO date when this data was last manually researched", + ), + ] = None + research_notes: Annotated[ + str | None, + Field( + alias="researchNotes", + description="Freeform operator notes about the research", + ), + ] = None + + +class StatusPageDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: UUID + organization_id: Annotated[int, Field(alias="organizationId")] + workspace_id: Annotated[int, Field(alias="workspaceId")] + name: Annotated[str, Field(min_length=1)] + slug: Annotated[str, Field(min_length=1)] + description: str | None = None + branding: StatusPageBranding + visibility: str + enabled: bool + incident_mode: Annotated[str, Field(alias="incidentMode")] + component_count: Annotated[int | None, Field(alias="componentCount")] = None + subscriber_count: Annotated[int | None, Field(alias="subscriberCount")] = None + overall_status: Annotated[str | None, Field(alias="overallStatus")] = None + open_incident: Annotated[ + StatusPageOpenIncidentSummaryDto | None, Field(alias="openIncident") + ] = None + managed_by: Annotated[ + str | None, + Field( + alias="managedBy", + description="Source that created/owns this status page: DASHBOARD, CLI, TERRAFORM, MCP, or API. Null on pages created before this attribution column existed.", + ), + ] = None + created_at: Annotated[AwareDatetime, Field(alias="createdAt")] + updated_at: Annotated[AwareDatetime, Field(alias="updatedAt")] + + class StatusPageIncidentDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) id: UUID @@ -7536,9 +9225,42 @@ class StatusPageIncidentDto(BaseModel): affected_components: Annotated[ list[StatusPageIncidentComponentDto] | None, Field(alias="affectedComponents") ] = None - updates: list[StatusPageIncidentUpdateDto] | None = None - created_at: Annotated[AwareDatetime, Field(alias="createdAt")] - updated_at: Annotated[AwareDatetime, Field(alias="updatedAt")] + updates: list[StatusPageIncidentUpdateDto] | None = None + created_at: Annotated[AwareDatetime, Field(alias="createdAt")] + updated_at: Annotated[AwareDatetime, Field(alias="updatedAt")] + + +class StatusPageMeasuredComponentUptimeDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + source: Annotated[ + str, + Field( + description="Uptime source discriminator; always measured for this resource" + ), + ] + component_id: Annotated[ + UUID, Field(alias="componentId", description="Status-page component ID") + ] + monitor_id: Annotated[ + UUID, + Field( + alias="monitorId", + description="Linked monitor whose check rollups feed this series", + ), + ] + tracking_since: Annotated[ + str | None, + Field( + alias="trackingSince", + description="ISO-8601 date bars start (Camp A tracking-since); null only if unresolved", + ), + ] = None + days: Annotated[ + list[StatusPageMeasuredUptimeDayDto], + Field( + description="Dense daily buckets from tracking start through today (oldest → newest)" + ), + ] class TableValueResultComponentUptimeDayDto(BaseModel): @@ -7550,6 +9272,15 @@ class TableValueResultComponentUptimeDayDto(BaseModel): total_pages: Annotated[int | None, Field(alias="totalPages")] = None +class TableValueResultIncidentDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: list[IncidentDto] + has_next: Annotated[bool, Field(alias="hasNext")] + has_prev: Annotated[bool, Field(alias="hasPrev")] + total_elements: Annotated[int | None, Field(alias="totalElements")] = None + total_pages: Annotated[int | None, Field(alias="totalPages")] = None + + class TableValueResultIncidentStateTransitionDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: list[IncidentStateTransitionDto] @@ -7595,9 +9326,9 @@ class TableValueResultNotificationPolicyDto(BaseModel): total_pages: Annotated[int | None, Field(alias="totalPages")] = None -class TableValueResultResourceGroupDto(BaseModel): +class TableValueResultStatusPageDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) - data: list[ResourceGroupDto] + data: list[StatusPageDto] has_next: Annotated[bool, Field(alias="hasNext")] has_prev: Annotated[bool, Field(alias="hasPrev")] total_elements: Annotated[int | None, Field(alias="totalElements")] = None @@ -7622,6 +9353,24 @@ class TableValueResultTagDto(BaseModel): total_pages: Annotated[int | None, Field(alias="totalPages")] = None +class TableValueResultTestChannelResult(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: list[TestChannelResult] + has_next: Annotated[bool, Field(alias="hasNext")] + has_prev: Annotated[bool, Field(alias="hasPrev")] + total_elements: Annotated[int | None, Field(alias="totalElements")] = None + total_pages: Annotated[int | None, Field(alias="totalPages")] = None + + +class TableValueResultVoiceLanguageDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: list[VoiceLanguageDto] + has_next: Annotated[bool, Field(alias="hasNext")] + has_prev: Annotated[bool, Field(alias="hasPrev")] + total_elements: Annotated[int | None, Field(alias="totalElements")] = None + total_pages: Annotated[int | None, Field(alias="totalPages")] = None + + class TableValueResultWebhookDeliveryDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: list[WebhookDeliveryDto] @@ -7663,10 +9412,12 @@ class TestAlertChannelRequest(BaseModel): | MattermostChannelConfig | OpsGenieChannelConfig | PagerDutyChannelConfig + | PhoneCallChannelConfig | PushbulletChannelConfig | PushoverChannelConfig | RootlyChannelConfig | SlackChannelConfig + | SmsChannelConfig | SplunkOnCallChannelConfig | TeamsChannelConfig | TelegramChannelConfig @@ -7687,26 +9438,28 @@ class UpdateAlertChannelRequest(BaseModel): ), ] config: Annotated[ - DatadogChannelConfig - | DiscordChannelConfig - | EmailChannelConfig - | GitLabChannelConfig - | GoogleChatChannelConfig - | IncidentIoChannelConfig - | JiraChannelConfig - | LinearChannelConfig - | MattermostChannelConfig - | OpsGenieChannelConfig - | PagerDutyChannelConfig - | PushbulletChannelConfig - | PushoverChannelConfig - | RootlyChannelConfig - | SlackChannelConfig - | SplunkOnCallChannelConfig - | TeamsChannelConfig - | TelegramChannelConfig - | WebhookChannelConfig - | ZapierChannelConfig, + UpdateDatadogChannelConfig + | UpdateDiscordChannelConfig + | UpdateEmailChannelConfig + | UpdateGitLabChannelConfig + | UpdateGoogleChatChannelConfig + | UpdateIncidentIoChannelConfig + | UpdateJiraChannelConfig + | UpdateLinearChannelConfig + | UpdateMattermostChannelConfig + | UpdateOpsGenieChannelConfig + | UpdatePagerDutyChannelConfig + | UpdatePhoneCallChannelConfig + | UpdatePushbulletChannelConfig + | UpdatePushoverChannelConfig + | UpdateRootlyChannelConfig + | UpdateSlackChannelConfig + | UpdateSmsChannelConfig + | UpdateSplunkOnCallChannelConfig + | UpdateTeamsChannelConfig + | UpdateTelegramChannelConfig + | UpdateWebhookChannelConfig + | UpdateZapierChannelConfig, Field(discriminator="channel_type"), ] managed_by: Annotated[ @@ -7716,6 +9469,12 @@ class UpdateAlertChannelRequest(BaseModel): description="New attribution source: DASHBOARD, CLI, TERRAFORM, MCP, or API; null preserves current value.", ), ] = None + enabled: Annotated[ + bool | None, + Field( + description="Whether this channel is enabled (default: true); null preserves current value" + ), + ] = None class UpdateMonitorRequest(BaseModel): @@ -7734,6 +9493,7 @@ class UpdateMonitorRequest(BaseModel): | HttpMonitorConfig | IcmpMonitorConfig | McpServerMonitorConfig + | ScriptMonitorConfig | TcpMonitorConfig | None ) = None @@ -7907,9 +9667,9 @@ class CheckTraceDto(BaseModel): ] = None -class CheckTypeDetailsDto(RootModel[Http | Tcp | Icmp | Dns | McpServer]): +class CheckTypeDetailsDto(RootModel[Http | Tcp | Icmp | Dns | McpServer | Code]): root: Annotated[ - Http | Tcp | Icmp | Dns | McpServer, + Http | Tcp | Icmp | Dns | McpServer | Code, Field( description="Check-type-specific details — polymorphic by check_type discriminator", discriminator="check_type", @@ -7946,6 +9706,183 @@ class CreateNotificationPolicyRequest(BaseModel): ] = 0 +class IncidentDetailDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + incident: IncidentDto + updates: list[IncidentUpdateDto] + status_page_incidents: Annotated[ + list[LinkedStatusPageIncidentDto] | None, Field(alias="statusPageIncidents") + ] = None + trigger: IncidentTriggerDto | None = None + + +class ResourceGroupDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: Annotated[UUID, Field(description="Unique resource group identifier")] + organization_id: Annotated[ + int, + Field(alias="organizationId", description="Organization this group belongs to"), + ] + name: Annotated[str, Field(description="Human-readable group name", min_length=1)] + slug: Annotated[str, Field(description="URL-safe group identifier", min_length=1)] + description: Annotated[ + str | None, Field(description="Optional group description") + ] = None + alert_policy_id: Annotated[ + UUID | None, + Field( + alias="alertPolicyId", + description="Notification policy applied to this group", + ), + ] = None + default_frequency: Annotated[ + int | None, + Field( + alias="defaultFrequency", + description="Default check frequency in seconds for member monitors", + ), + ] = None + default_regions: Annotated[ + list[str] | None, + Field( + alias="defaultRegions", description="Default regions for member monitors" + ), + ] = None + default_retry_strategy: Annotated[ + RetryStrategy | None, Field(alias="defaultRetryStrategy") + ] = None + default_alert_channels: Annotated[ + list[UUID] | None, + Field( + alias="defaultAlertChannels", + description="Default alert channel IDs for member monitors", + ), + ] = None + default_environment_id: Annotated[ + UUID | None, + Field( + alias="defaultEnvironmentId", + description="Default environment ID for member monitors", + ), + ] = None + health_threshold_type: Annotated[ + str | None, + Field( + alias="healthThresholdType", + description="Health threshold type: COUNT or PERCENTAGE", + ), + ] = None + health_threshold_value: Annotated[ + float | None, + Field(alias="healthThresholdValue", description="Health threshold value"), + ] = None + suppress_member_alerts: Annotated[ + bool, + Field( + alias="suppressMemberAlerts", + description="When true, member-level incidents skip notification dispatch; only group alerts fire", + ), + ] + confirmation_delay_seconds: Annotated[ + int | None, + Field( + alias="confirmationDelaySeconds", + description="Seconds to wait after health threshold breach before creating group incident", + ), + ] = None + recovery_cooldown_minutes: Annotated[ + int | None, + Field( + alias="recoveryCooldownMinutes", + description="Cooldown minutes after group incident resolves before a new one can open", + ), + ] = None + health: ResourceGroupHealthDto + members: Annotated[ + list[ResourceGroupMemberDto] | None, + Field( + description="Member list with individual statuses; populated on detail GET only" + ), + ] = None + delete_blocked_by: Annotated[ + list[ResourceGroupDeleteBlockerDto] | None, + Field( + alias="deleteBlockedBy", + description="Status-page GROUP components that reference this group (delete blockers / public exposure); populated on detail GET only — omitted on list", + ), + ] = None + open_region_incident: Annotated[ + IncidentDto | None, Field(alias="openRegionIncident") + ] = None + managed_by: Annotated[ + str | None, + Field( + alias="managedBy", + description="Source that created/owns this group: DASHBOARD, CLI, TERRAFORM, MCP, or API. Null on groups created before this attribution column existed.", + ), + ] = None + created_at: Annotated[ + AwareDatetime, + Field(alias="createdAt", description="Timestamp when the group was created"), + ] + updated_at: Annotated[ + AwareDatetime, + Field( + alias="updatedAt", description="Timestamp when the group was last updated" + ), + ] + + +class ServiceDetailDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + id: UUID + slug: str + name: str + category: str | None = None + official_status_url: Annotated[str | None, Field(alias="officialStatusUrl")] = None + developer_context: Annotated[str | None, Field(alias="developerContext")] = None + logo_url: Annotated[str | None, Field(alias="logoUrl")] = None + adapter_type: Annotated[str, Field(alias="adapterType")] + polling_interval_seconds: Annotated[int, Field(alias="pollingIntervalSeconds")] + lifecycle_status: Annotated[ + str, + Field( + alias="lifecycleStatus", + description="Service lifecycle state: ACTIVE, DEGRADED, DEPRECATED, or RETIRED", + ), + ] + enabled: bool + created_at: Annotated[AwareDatetime, Field(alias="createdAt")] + updated_at: Annotated[AwareDatetime, Field(alias="updatedAt")] + current_status: Annotated[ServiceStatusDto | None, Field(alias="currentStatus")] = ( + None + ) + recent_incidents: Annotated[ + list[ServiceIncidentDto], Field(alias="recentIncidents") + ] + components: list[ServiceComponentDto] + components_summary: Annotated[ + ComponentsSummaryDto | None, Field(alias="componentsSummary") + ] = None + uptime: ComponentUptimeSummaryDto | None = None + active_maintenances: Annotated[ + list[ScheduledMaintenanceDto], Field(alias="activeMaintenances") + ] + data_completeness: Annotated[str, Field(alias="dataCompleteness")] + sla_published: Annotated[ + bool, + Field( + alias="slaPublished", + description="Whether the service's SLA page is publicly visible", + ), + ] + seo_metadata: Annotated[SeoMetadataDto | None, Field(alias="seoMetadata")] = None + sla_data: Annotated[SlaDataDto | None, Field(alias="slaData")] = None + related_services: Annotated[ + list[ServiceCatalogDto] | None, Field(alias="relatedServices") + ] = None + + class SingleValueResponseBatchComponentUptimeDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: BatchComponentUptimeDto @@ -7956,11 +9893,36 @@ class SingleValueResponseCheckTraceDto(BaseModel): data: CheckTraceDto +class SingleValueResponseIncidentDetailDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: IncidentDetailDto + + +class SingleValueResponseResourceGroupDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: ResourceGroupDto + + +class SingleValueResponseServiceDetailDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: ServiceDetailDto + + +class SingleValueResponseStatusPageDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: StatusPageDto + + class SingleValueResponseStatusPageIncidentDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: StatusPageIncidentDto +class SingleValueResponseStatusPageMeasuredComponentUptimeDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: StatusPageMeasuredComponentUptimeDto + + class TableValueResultAuditEventDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) data: list[AuditEventDto] @@ -7970,6 +9932,15 @@ class TableValueResultAuditEventDto(BaseModel): total_pages: Annotated[int | None, Field(alias="totalPages")] = None +class TableValueResultResourceGroupDto(BaseModel): + model_config = ConfigDict(extra="ignore", populate_by_name=True) + data: list[ResourceGroupDto] + has_next: Annotated[bool, Field(alias="hasNext")] + has_prev: Annotated[bool, Field(alias="hasPrev")] + total_elements: Annotated[int | None, Field(alias="totalElements")] = None + total_pages: Annotated[int | None, Field(alias="totalPages")] = None + + class CheckResultDetailsDto(BaseModel): model_config = ConfigDict(extra="ignore", populate_by_name=True) status_code: Annotated[