{
  "openapi": "3.1.0",
  "info": {
    "title": "UpButler API",
    "version": "1.0.0",
    "description": "Agent-first uptime monitoring, status pages and incident communication. Every endpoint is also available as an MCP tool at /mcp. Authenticate with \"Authorization: Bearer ub_live_...\". Errors are {\"error\":{\"code\",\"message\",\"hint?\",\"details?\"}}. POST requests accept an Idempotency-Key header.",
    "contact": {
      "name": "UpButler",
      "url": "https://upbutler.com",
      "email": "support@upbutler.com"
    }
  },
  "servers": [
    {
      "url": "https://upbutler.com"
    }
  ],
  "security": [
    {
      "bearer": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "ub_live_..."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "hint": {
                "type": "string"
              },
              "details": {}
            },
            "required": [
              "code",
              "message"
            ]
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Agents"
    },
    {
      "name": "Monitors"
    },
    {
      "name": "Status pages"
    },
    {
      "name": "Components"
    },
    {
      "name": "Incidents"
    },
    {
      "name": "Alerts"
    },
    {
      "name": "Public status"
    },
    {
      "name": "Workspace"
    },
    {
      "name": "Events"
    },
    {
      "name": "Billing"
    },
    {
      "name": "Import"
    },
    {
      "name": "On-call"
    },
    {
      "name": "Account"
    },
    {
      "name": "Deploys"
    },
    {
      "name": "Digest"
    }
  ],
  "paths": {
    "/api/v1/agent/bootstrap": {
      "post": {
        "operationId": "agent.bootstrap",
        "summary": "Create a workspace + API key with no human in the loop",
        "description": "For autonomous agents. Returns an API key immediately and a claim URL. Give the claim URL to your human: unclaimed workspaces are deleted after 7 days, and email features unlock once claimed. Rate-limited per IP.",
        "tags": [
          "Agents"
        ],
        "security": [],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "agentName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "description": "Who you are, e.g. \"claude-code\" or \"deploy-bot\""
                  },
                  "workspaceName": {
                    "type": "string",
                    "maxLength": 80
                  }
                },
                "required": [
                  "agentName"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/services": {
      "post": {
        "operationId": "services.add",
        "summary": "Plug in a service: monitor + status page component in one call",
        "description": "The fastest path: creates a monitor for the URL (or a heartbeat when you pass periodSec), creates the status page if needed (statusPage = slug or name), and adds a component that follows the monitor. Returns everything you need, including heartbeat ping URLs.",
        "tags": [
          "Agents"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Human-friendly name, e.g. \"Search API\""
                  },
                  "description": {
                    "description": "null or \"\" clears it",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "kind": {
                    "description": "Inferred when omitted: url → http, host+port → tcp, periodSec → heartbeat",
                    "type": "string",
                    "enum": [
                      "http",
                      "tcp",
                      "dns",
                      "heartbeat",
                      "manifest",
                      "script",
                      "browser"
                    ]
                  },
                  "url": {
                    "description": "http/manifest: URL to check",
                    "type": "string",
                    "maxLength": 2000,
                    "format": "uri"
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "GET",
                      "HEAD",
                      "POST",
                      "PUT",
                      "PATCH",
                      "DELETE",
                      "OPTIONS"
                    ]
                  },
                  "headers": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 4000
                    }
                  },
                  "body": {
                    "description": "null clears it",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 100000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "followRedirects": {
                    "type": "boolean"
                  },
                  "expectedStatus": {
                    "description": "e.g. \"200-299\" (default), \"200,204\", \"401\"",
                    "type": "string",
                    "maxLength": 100
                  },
                  "keyword": {
                    "description": "http: response body must contain this text",
                    "type": "string",
                    "maxLength": 500
                  },
                  "keywordAbsent": {
                    "description": "http: response body must NOT contain this text",
                    "type": "string",
                    "maxLength": 500
                  },
                  "degradedAfterMs": {
                    "description": "Mark degraded when slower than this (null clears)",
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 50,
                        "maximum": 120000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "sslExpiryDays": {
                    "description": "Mark degraded when the TLS cert expires within N days (null clears)",
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 365
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "host": {
                    "description": "tcp/dns host",
                    "type": "string",
                    "maxLength": 255
                  },
                  "port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535
                  },
                  "recordType": {
                    "type": "string",
                    "enum": [
                      "A",
                      "AAAA",
                      "CNAME",
                      "MX",
                      "TXT",
                      "NS"
                    ]
                  },
                  "expected": {
                    "description": "dns: values that must be present",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 500
                    }
                  },
                  "periodSec": {
                    "description": "heartbeat: expected ping interval",
                    "type": "integer",
                    "minimum": 30,
                    "maximum": 2678400
                  },
                  "graceSec": {
                    "description": "heartbeat: extra time before alerting",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 86400
                  },
                  "code": {
                    "description": "script/browser: test code",
                    "type": "string",
                    "maxLength": 50000
                  },
                  "viewport": {
                    "type": "object",
                    "properties": {
                      "width": {
                        "type": "integer",
                        "minimum": 320,
                        "maximum": 3840
                      },
                      "height": {
                        "type": "integer",
                        "minimum": 240,
                        "maximum": 2160
                      }
                    },
                    "required": [
                      "width",
                      "height"
                    ]
                  },
                  "assertions": {
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": "string",
                          "enum": [
                            "status",
                            "latency",
                            "header",
                            "body",
                            "json",
                            "ssl_days"
                          ]
                        },
                        "path": {
                          "type": "string",
                          "maxLength": 300
                        },
                        "op": {
                          "type": "string",
                          "enum": [
                            "eq",
                            "neq",
                            "lt",
                            "lte",
                            "gt",
                            "gte",
                            "contains",
                            "not_contains",
                            "matches",
                            "exists",
                            "not_exists"
                          ]
                        },
                        "value": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 2000
                            },
                            {
                              "type": "number"
                            },
                            {
                              "type": "boolean"
                            }
                          ]
                        },
                        "severity": {
                          "type": "string",
                          "enum": [
                            "down",
                            "degraded"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "op"
                      ]
                    }
                  },
                  "intervalSec": {
                    "description": "Seconds between checks (default 60, limited by plan)",
                    "type": "integer",
                    "minimum": 10,
                    "maximum": 86400
                  },
                  "timeoutMs": {
                    "type": "integer",
                    "minimum": 1000,
                    "maximum": 120000
                  },
                  "failureThreshold": {
                    "description": "Consecutive failures before DOWN (default 2)",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  },
                  "recoveryThreshold": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  },
                  "channelIds": {
                    "description": "Alert channels. Default: channels marked as default",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "reminderMinutes": {
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 10080
                    }
                  },
                  "ai": {
                    "description": "AI incident analysis (default true)",
                    "type": "boolean"
                  },
                  "tags": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 40
                    }
                  },
                  "paused": {
                    "type": "boolean"
                  },
                  "regions": {
                    "description": "Check regions (GET /api/v1/regions). With several, a round only counts as DOWN when a majority of regions agree. Default: main region only",
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^[a-z0-9][a-z0-9-]{0,39}$"
                    }
                  },
                  "statusPage": {
                    "description": "Status page slug or id; created (by name) if it does not exist. Omit to only monitor.",
                    "type": "string",
                    "maxLength": 100
                  },
                  "group": {
                    "description": "Component group on the status page, e.g. \"APIs\"",
                    "type": "string",
                    "maxLength": 80
                  },
                  "componentName": {
                    "description": "Public name (defaults to name)",
                    "type": "string",
                    "maxLength": 100
                  }
                },
                "required": [
                  "name"
                ]
              },
              "example": {
                "name": "Search API",
                "url": "https://api.example.com/health",
                "statusPage": "acme",
                "group": "APIs"
              }
            }
          }
        }
      }
    },
    "/api/v1/heartbeat/{token}": {
      "post": {
        "operationId": "heartbeat.ping",
        "summary": "Send a heartbeat (no API key needed — the token is the secret)",
        "description": "Call at least every periodSec. status=down (or POST to /hb/{token}/fail) reports an explicit failure and alerts immediately. Short form: GET/POST https://upbutler.com/hb/{token}.",
        "tags": [
          "Agents"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "up",
                      "down",
                      "degraded"
                    ]
                  },
                  "message": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "durationMs": {
                    "description": "How long the job took",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/push/{token}": {
      "post": {
        "operationId": "components.push",
        "summary": "Push one component status by its push token (no API key needed)",
        "tags": [
          "Agents"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "description": "operational | degraded | partial_outage | major_outage | maintenance, or ok/up/fail/down/true/false",
                    "type": [
                      "string",
                      "boolean",
                      "number"
                    ]
                  },
                  "message": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "confirmed": {
                    "description": "Skip blip protection: the sender already confirmed this status",
                    "type": "boolean"
                  },
                  "observedAt": {
                    "description": "When this status was observed; re-sending the same observation does not count as a new confirmation"
                  }
                },
                "required": [
                  "status"
                ]
              },
              "example": {
                "status": "degraded",
                "message": "p95 latency above 2s"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/agent/whoami": {
      "get": {
        "operationId": "agent.whoami",
        "summary": "Identify the calling key",
        "tags": [
          "Agents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors": {
      "get": {
        "operationId": "monitors.list",
        "summary": "List monitors",
        "description": "All monitors in the workspace with their current state and last check.",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "up",
                "down",
                "degraded",
                "pending",
                "paused"
              ]
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "post": {
        "operationId": "monitors.create",
        "summary": "Create a monitor",
        "description": "Create an uptime monitor. Minimal input is {\"name\",\"url\"}. Kinds: http (status/keyword/JSON/latency/TLS assertions), tcp, dns, heartbeat (your job pings us), manifest (one JSON endpoint reporting many components), script, browser.",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Human-friendly name, e.g. \"Search API\""
                  },
                  "description": {
                    "description": "null or \"\" clears it",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "kind": {
                    "description": "Inferred when omitted: url → http, host+port → tcp, periodSec → heartbeat",
                    "type": "string",
                    "enum": [
                      "http",
                      "tcp",
                      "dns",
                      "heartbeat",
                      "manifest",
                      "script",
                      "browser"
                    ]
                  },
                  "url": {
                    "description": "http/manifest: URL to check",
                    "type": "string",
                    "maxLength": 2000,
                    "format": "uri"
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "GET",
                      "HEAD",
                      "POST",
                      "PUT",
                      "PATCH",
                      "DELETE",
                      "OPTIONS"
                    ]
                  },
                  "headers": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 4000
                    }
                  },
                  "body": {
                    "description": "null clears it",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 100000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "followRedirects": {
                    "type": "boolean"
                  },
                  "expectedStatus": {
                    "description": "e.g. \"200-299\" (default), \"200,204\", \"401\"",
                    "type": "string",
                    "maxLength": 100
                  },
                  "keyword": {
                    "description": "http: response body must contain this text",
                    "type": "string",
                    "maxLength": 500
                  },
                  "keywordAbsent": {
                    "description": "http: response body must NOT contain this text",
                    "type": "string",
                    "maxLength": 500
                  },
                  "degradedAfterMs": {
                    "description": "Mark degraded when slower than this (null clears)",
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 50,
                        "maximum": 120000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "sslExpiryDays": {
                    "description": "Mark degraded when the TLS cert expires within N days (null clears)",
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 365
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "host": {
                    "description": "tcp/dns host",
                    "type": "string",
                    "maxLength": 255
                  },
                  "port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535
                  },
                  "recordType": {
                    "type": "string",
                    "enum": [
                      "A",
                      "AAAA",
                      "CNAME",
                      "MX",
                      "TXT",
                      "NS"
                    ]
                  },
                  "expected": {
                    "description": "dns: values that must be present",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 500
                    }
                  },
                  "periodSec": {
                    "description": "heartbeat: expected ping interval",
                    "type": "integer",
                    "minimum": 30,
                    "maximum": 2678400
                  },
                  "graceSec": {
                    "description": "heartbeat: extra time before alerting",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 86400
                  },
                  "code": {
                    "description": "script/browser: test code",
                    "type": "string",
                    "maxLength": 50000
                  },
                  "viewport": {
                    "type": "object",
                    "properties": {
                      "width": {
                        "type": "integer",
                        "minimum": 320,
                        "maximum": 3840
                      },
                      "height": {
                        "type": "integer",
                        "minimum": 240,
                        "maximum": 2160
                      }
                    },
                    "required": [
                      "width",
                      "height"
                    ]
                  },
                  "assertions": {
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": "string",
                          "enum": [
                            "status",
                            "latency",
                            "header",
                            "body",
                            "json",
                            "ssl_days"
                          ]
                        },
                        "path": {
                          "type": "string",
                          "maxLength": 300
                        },
                        "op": {
                          "type": "string",
                          "enum": [
                            "eq",
                            "neq",
                            "lt",
                            "lte",
                            "gt",
                            "gte",
                            "contains",
                            "not_contains",
                            "matches",
                            "exists",
                            "not_exists"
                          ]
                        },
                        "value": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 2000
                            },
                            {
                              "type": "number"
                            },
                            {
                              "type": "boolean"
                            }
                          ]
                        },
                        "severity": {
                          "type": "string",
                          "enum": [
                            "down",
                            "degraded"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "op"
                      ]
                    }
                  },
                  "intervalSec": {
                    "description": "Seconds between checks (default 60, limited by plan)",
                    "type": "integer",
                    "minimum": 10,
                    "maximum": 86400
                  },
                  "timeoutMs": {
                    "type": "integer",
                    "minimum": 1000,
                    "maximum": 120000
                  },
                  "failureThreshold": {
                    "description": "Consecutive failures before DOWN (default 2)",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  },
                  "recoveryThreshold": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  },
                  "channelIds": {
                    "description": "Alert channels. Default: channels marked as default",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "reminderMinutes": {
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 10080
                    }
                  },
                  "ai": {
                    "description": "AI incident analysis (default true)",
                    "type": "boolean"
                  },
                  "tags": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 40
                    }
                  },
                  "paused": {
                    "type": "boolean"
                  },
                  "regions": {
                    "description": "Check regions (GET /api/v1/regions). With several, a round only counts as DOWN when a majority of regions agree. Default: main region only",
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^[a-z0-9][a-z0-9-]{0,39}$"
                    }
                  }
                },
                "required": [
                  "name"
                ]
              },
              "example": {
                "name": "Search API",
                "url": "https://api.example.com/health",
                "keyword": "\"ok\"",
                "intervalSec": 60
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/{id}": {
      "get": {
        "operationId": "monitors.get",
        "summary": "Get a monitor with recent checks and stats",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Monitor id (mon_...)"
            },
            "description": "Monitor id (mon_...)"
          },
          {
            "name": "checks",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 200
            }
          }
        ]
      },
      "patch": {
        "operationId": "monitors.update",
        "summary": "Update a monitor",
        "description": "Partial update; any create field may be sent. Set paused=true/false to pause or resume.",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Human-friendly name, e.g. \"Search API\""
                  },
                  "description": {
                    "description": "null or \"\" clears it",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "kind": {
                    "description": "Inferred when omitted: url → http, host+port → tcp, periodSec → heartbeat",
                    "type": "string",
                    "enum": [
                      "http",
                      "tcp",
                      "dns",
                      "heartbeat",
                      "manifest",
                      "script",
                      "browser"
                    ]
                  },
                  "url": {
                    "description": "http/manifest: URL to check",
                    "type": "string",
                    "maxLength": 2000,
                    "format": "uri"
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "GET",
                      "HEAD",
                      "POST",
                      "PUT",
                      "PATCH",
                      "DELETE",
                      "OPTIONS"
                    ]
                  },
                  "headers": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 4000
                    }
                  },
                  "body": {
                    "description": "null clears it",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 100000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "followRedirects": {
                    "type": "boolean"
                  },
                  "expectedStatus": {
                    "description": "e.g. \"200-299\" (default), \"200,204\", \"401\"",
                    "type": "string",
                    "maxLength": 100
                  },
                  "keyword": {
                    "description": "http: response body must contain this text",
                    "type": "string",
                    "maxLength": 500
                  },
                  "keywordAbsent": {
                    "description": "http: response body must NOT contain this text",
                    "type": "string",
                    "maxLength": 500
                  },
                  "degradedAfterMs": {
                    "description": "Mark degraded when slower than this (null clears)",
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 50,
                        "maximum": 120000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "sslExpiryDays": {
                    "description": "Mark degraded when the TLS cert expires within N days (null clears)",
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 365
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "host": {
                    "description": "tcp/dns host",
                    "type": "string",
                    "maxLength": 255
                  },
                  "port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535
                  },
                  "recordType": {
                    "type": "string",
                    "enum": [
                      "A",
                      "AAAA",
                      "CNAME",
                      "MX",
                      "TXT",
                      "NS"
                    ]
                  },
                  "expected": {
                    "description": "dns: values that must be present",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 500
                    }
                  },
                  "periodSec": {
                    "description": "heartbeat: expected ping interval",
                    "type": "integer",
                    "minimum": 30,
                    "maximum": 2678400
                  },
                  "graceSec": {
                    "description": "heartbeat: extra time before alerting",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 86400
                  },
                  "code": {
                    "description": "script/browser: test code",
                    "type": "string",
                    "maxLength": 50000
                  },
                  "viewport": {
                    "type": "object",
                    "properties": {
                      "width": {
                        "type": "integer",
                        "minimum": 320,
                        "maximum": 3840
                      },
                      "height": {
                        "type": "integer",
                        "minimum": 240,
                        "maximum": 2160
                      }
                    },
                    "required": [
                      "width",
                      "height"
                    ]
                  },
                  "assertions": {
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": "string",
                          "enum": [
                            "status",
                            "latency",
                            "header",
                            "body",
                            "json",
                            "ssl_days"
                          ]
                        },
                        "path": {
                          "type": "string",
                          "maxLength": 300
                        },
                        "op": {
                          "type": "string",
                          "enum": [
                            "eq",
                            "neq",
                            "lt",
                            "lte",
                            "gt",
                            "gte",
                            "contains",
                            "not_contains",
                            "matches",
                            "exists",
                            "not_exists"
                          ]
                        },
                        "value": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 2000
                            },
                            {
                              "type": "number"
                            },
                            {
                              "type": "boolean"
                            }
                          ]
                        },
                        "severity": {
                          "type": "string",
                          "enum": [
                            "down",
                            "degraded"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "op"
                      ]
                    }
                  },
                  "intervalSec": {
                    "description": "Seconds between checks (default 60, limited by plan)",
                    "type": "integer",
                    "minimum": 10,
                    "maximum": 86400
                  },
                  "timeoutMs": {
                    "type": "integer",
                    "minimum": 1000,
                    "maximum": 120000
                  },
                  "failureThreshold": {
                    "description": "Consecutive failures before DOWN (default 2)",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  },
                  "recoveryThreshold": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  },
                  "channelIds": {
                    "description": "Alert channels. Default: channels marked as default",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "reminderMinutes": {
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 10080
                    }
                  },
                  "ai": {
                    "description": "AI incident analysis (default true)",
                    "type": "boolean"
                  },
                  "tags": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 40
                    }
                  },
                  "paused": {
                    "type": "boolean"
                  },
                  "regions": {
                    "description": "Check regions (GET /api/v1/regions). With several, a round only counts as DOWN when a majority of regions agree. Default: main region only",
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^[a-z0-9][a-z0-9-]{0,39}$"
                    }
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Monitor id (mon_...)"
            },
            "description": "Monitor id (mon_...)"
          }
        ]
      },
      "delete": {
        "operationId": "monitors.delete",
        "summary": "Delete a monitor and its history",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Monitor id (mon_...)"
            },
            "description": "Monitor id (mon_...)"
          }
        ]
      }
    },
    "/api/v1/monitors/{id}/check": {
      "post": {
        "operationId": "monitors.check",
        "summary": "Run a check right now",
        "description": "Runs the monitor immediately and returns the full result with evidence. Does not change monitor state unless apply=true.",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "apply": {
                    "description": "Feed the result into the state machine (may open/resolve incidents)",
                    "type": "boolean"
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Monitor id (mon_...)"
            },
            "description": "Monitor id (mon_...)"
          }
        ]
      }
    },
    "/api/v1/monitors/{id}/checks": {
      "get": {
        "operationId": "monitors.checks",
        "summary": "List checks (raw results, 30 days)",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Monitor id (mon_...)"
            },
            "description": "Monitor id (mon_...)"
          },
          {
            "name": "outcome",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "up",
                "degraded",
                "down"
              ]
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "evidence",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "boolean",
                "string"
              ]
            }
          }
        ]
      }
    },
    "/api/v1/checks/{id}": {
      "get": {
        "operationId": "checks.get",
        "summary": "Get one check with full evidence",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/pages": {
      "get": {
        "operationId": "pages.list",
        "summary": "List status pages",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "pages.create",
        "summary": "Create a status page",
        "description": "Theme presets: midnight, grid, daylight, paper. Add components afterwards with POST /pages/{pageId}/components.",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "slug": {
                    "type": "string",
                    "pattern": "^[a-z0-9](?:[a-z0-9-]{1,46}[a-z0-9])?$"
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "customDomain": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^(?=.{4,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "visibility": {
                    "type": "string",
                    "enum": [
                      "public",
                      "private"
                    ]
                  },
                  "theme": {
                    "type": "object",
                    "properties": {
                      "preset": {
                        "type": "string",
                        "maxLength": 30
                      },
                      "mode": {
                        "type": "string",
                        "enum": [
                          "dark",
                          "light"
                        ]
                      },
                      "accent": {
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "tokens": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        }
                      },
                      "fontSans": {
                        "type": "string",
                        "maxLength": 40
                      },
                      "fontMono": {
                        "type": "string",
                        "maxLength": 40
                      },
                      "radius": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 24
                      },
                      "customCss": {
                        "type": "string",
                        "maxLength": 50000
                      }
                    }
                  },
                  "branding": {
                    "type": "object",
                    "properties": {
                      "logoUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 1000
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "logoDarkUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 1000
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "logoText": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 60
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "faviconUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 1000
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "websiteUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 500,
                            "format": "uri"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "supportUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 500,
                            "format": "uri"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "headerLinks": {
                        "maxItems": 8,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 60
                            },
                            "url": {
                              "type": "string",
                              "maxLength": 500,
                              "format": "uri"
                            }
                          },
                          "required": [
                            "label",
                            "url"
                          ]
                        }
                      },
                      "footerLinks": {
                        "maxItems": 20,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 60
                            },
                            "url": {
                              "type": "string",
                              "maxLength": 500,
                              "format": "uri"
                            }
                          },
                          "required": [
                            "label",
                            "url"
                          ]
                        }
                      },
                      "footerText": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 300
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "hidePoweredBy": {
                        "type": "boolean"
                      }
                    }
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "uptimeDays": {
                        "type": "integer",
                        "minimum": 7,
                        "maximum": 90
                      },
                      "showUptimePercent": {
                        "type": "boolean"
                      },
                      "showResponseTimes": {
                        "description": "Allow public response-time charts (components opt in with showResponseTimes)",
                        "type": "boolean"
                      },
                      "language": {
                        "description": "Public page + subscriber email language; auto = visitor Accept-Language",
                        "type": "string",
                        "enum": [
                          "auto",
                          "en",
                          "de",
                          "fr",
                          "es",
                          "it",
                          "pt",
                          "nl",
                          "el",
                          "pl",
                          "tr",
                          "ja"
                        ]
                      },
                      "autoIncidents": {
                        "type": "boolean"
                      },
                      "incidentMinStatus": {
                        "description": "Lowest component status that opens an automatic incident",
                        "type": "string",
                        "enum": [
                          "degraded",
                          "partial_outage",
                          "major_outage"
                        ]
                      },
                      "aiPublicUpdates": {
                        "type": "boolean"
                      },
                      "aiGuidelines": {
                        "description": "Rules for AI-written public text, e.g. \"Never mention internal infrastructure\"",
                        "type": "string",
                        "maxLength": 2000
                      },
                      "aiAvoidTerms": {
                        "description": "AI public text containing any of these is replaced by a neutral template",
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 2,
                          "maxLength": 60
                        }
                      },
                      "subscriptions": {
                        "type": "object",
                        "properties": {
                          "email": {
                            "type": "boolean"
                          },
                          "webhook": {
                            "type": "boolean"
                          },
                          "slack": {
                            "type": "boolean"
                          },
                          "rss": {
                            "type": "boolean"
                          }
                        }
                      },
                      "timezone": {
                        "type": "string",
                        "maxLength": 60
                      }
                    }
                  },
                  "seo": {
                    "type": "object",
                    "properties": {
                      "title": {
                        "type": "string",
                        "maxLength": 120
                      },
                      "description": {
                        "type": "string",
                        "maxLength": 300
                      },
                      "noindex": {
                        "type": "boolean"
                      }
                    }
                  }
                },
                "required": [
                  "name"
                ]
              },
              "example": {
                "name": "Acme Status",
                "slug": "acme",
                "theme": {
                  "preset": "midnight",
                  "accent": "#22c55e"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pages/{pageId}": {
      "get": {
        "operationId": "pages.get",
        "summary": "Get a status page with components",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Status page id (pg_...) or slug"
            },
            "description": "Status page id (pg_...) or slug"
          }
        ]
      },
      "patch": {
        "operationId": "pages.update",
        "summary": "Update page settings, theme, branding or domain",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "slug": {
                    "type": "string",
                    "pattern": "^[a-z0-9](?:[a-z0-9-]{1,46}[a-z0-9])?$"
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "customDomain": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^(?=.{4,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "visibility": {
                    "type": "string",
                    "enum": [
                      "public",
                      "private"
                    ]
                  },
                  "theme": {
                    "type": "object",
                    "properties": {
                      "preset": {
                        "type": "string",
                        "maxLength": 30
                      },
                      "mode": {
                        "type": "string",
                        "enum": [
                          "dark",
                          "light"
                        ]
                      },
                      "accent": {
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "tokens": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        }
                      },
                      "fontSans": {
                        "type": "string",
                        "maxLength": 40
                      },
                      "fontMono": {
                        "type": "string",
                        "maxLength": 40
                      },
                      "radius": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 24
                      },
                      "customCss": {
                        "type": "string",
                        "maxLength": 50000
                      }
                    }
                  },
                  "branding": {
                    "type": "object",
                    "properties": {
                      "logoUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 1000
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "logoDarkUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 1000
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "logoText": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 60
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "faviconUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 1000
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "websiteUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 500,
                            "format": "uri"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "supportUrl": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 500,
                            "format": "uri"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "headerLinks": {
                        "maxItems": 8,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 60
                            },
                            "url": {
                              "type": "string",
                              "maxLength": 500,
                              "format": "uri"
                            }
                          },
                          "required": [
                            "label",
                            "url"
                          ]
                        }
                      },
                      "footerLinks": {
                        "maxItems": 20,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 60
                            },
                            "url": {
                              "type": "string",
                              "maxLength": 500,
                              "format": "uri"
                            }
                          },
                          "required": [
                            "label",
                            "url"
                          ]
                        }
                      },
                      "footerText": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 300
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "hidePoweredBy": {
                        "type": "boolean"
                      }
                    }
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "uptimeDays": {
                        "type": "integer",
                        "minimum": 7,
                        "maximum": 90
                      },
                      "showUptimePercent": {
                        "type": "boolean"
                      },
                      "showResponseTimes": {
                        "description": "Allow public response-time charts (components opt in with showResponseTimes)",
                        "type": "boolean"
                      },
                      "language": {
                        "description": "Public page + subscriber email language; auto = visitor Accept-Language",
                        "type": "string",
                        "enum": [
                          "auto",
                          "en",
                          "de",
                          "fr",
                          "es",
                          "it",
                          "pt",
                          "nl",
                          "el",
                          "pl",
                          "tr",
                          "ja"
                        ]
                      },
                      "autoIncidents": {
                        "type": "boolean"
                      },
                      "incidentMinStatus": {
                        "description": "Lowest component status that opens an automatic incident",
                        "type": "string",
                        "enum": [
                          "degraded",
                          "partial_outage",
                          "major_outage"
                        ]
                      },
                      "aiPublicUpdates": {
                        "type": "boolean"
                      },
                      "aiGuidelines": {
                        "description": "Rules for AI-written public text, e.g. \"Never mention internal infrastructure\"",
                        "type": "string",
                        "maxLength": 2000
                      },
                      "aiAvoidTerms": {
                        "description": "AI public text containing any of these is replaced by a neutral template",
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 2,
                          "maxLength": 60
                        }
                      },
                      "subscriptions": {
                        "type": "object",
                        "properties": {
                          "email": {
                            "type": "boolean"
                          },
                          "webhook": {
                            "type": "boolean"
                          },
                          "slack": {
                            "type": "boolean"
                          },
                          "rss": {
                            "type": "boolean"
                          }
                        }
                      },
                      "timezone": {
                        "type": "string",
                        "maxLength": 60
                      }
                    }
                  },
                  "seo": {
                    "type": "object",
                    "properties": {
                      "title": {
                        "type": "string",
                        "maxLength": 120
                      },
                      "description": {
                        "type": "string",
                        "maxLength": 300
                      },
                      "noindex": {
                        "type": "boolean"
                      }
                    }
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Status page id (pg_...) or slug"
            },
            "description": "Status page id (pg_...) or slug"
          }
        ]
      },
      "delete": {
        "operationId": "pages.delete",
        "summary": "Delete a status page, its components and subscribers",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Status page id (pg_...) or slug"
            },
            "description": "Status page id (pg_...) or slug"
          }
        ]
      }
    },
    "/api/v1/pages/{pageId}/domain/verify": {
      "post": {
        "operationId": "pages.verifyDomain",
        "summary": "Check the custom domain DNS now",
        "description": "Verified when the domain CNAMEs to the target shown in pages.get dns.value (or resolves to the same IPs).",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Status page id (pg_...) or slug"
            },
            "description": "Status page id (pg_...) or slug"
          }
        ]
      }
    },
    "/api/v1/pages/{pageId}/preview": {
      "get": {
        "operationId": "pages.preview",
        "summary": "Get the rendered public status data (as visitors see it)",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Status page id (pg_...) or slug"
            },
            "description": "Status page id (pg_...) or slug"
          }
        ]
      }
    },
    "/api/v1/pages/{pageId}/groups": {
      "put": {
        "operationId": "pages.groups",
        "summary": "Replace the ordered list of component groups",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "groups": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 80
                        },
                        "description": {
                          "type": "string",
                          "maxLength": 300
                        },
                        "collapsed": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "name"
                      ]
                    }
                  }
                },
                "required": [
                  "groups"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Status page id (pg_...) or slug"
            },
            "description": "Status page id (pg_...) or slug"
          }
        ]
      }
    },
    "/api/v1/pages/{pageId}/subscribers": {
      "get": {
        "operationId": "pages.subscribers",
        "summary": "List subscribers of a status page",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Status page id (pg_...) or slug"
            },
            "description": "Status page id (pg_...) or slug"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "active",
                "unsubscribed",
                "disabled"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            }
          }
        ]
      }
    },
    "/api/v1/subscribers/{id}": {
      "delete": {
        "operationId": "subscribers.delete",
        "summary": "Remove a subscriber",
        "tags": [
          "Status pages"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/pages/{pageId}/components": {
      "post": {
        "operationId": "components.create",
        "summary": "Add a component to a status page",
        "description": "A component is a row on the status page. Its status comes from one of: monitorIds (follows monitors), push=true (you POST statuses to its push URL), manifest {monitorId,key} (read from a manifest monitor), or manual (default).",
        "tags": [
          "Components"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "key": {
                    "description": "Stable machine key used by pushes and manifests (default: slug of name)",
                    "type": "string",
                    "pattern": "^[a-z0-9][a-z0-9_.-]{0,62}$"
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "group": {
                    "description": "Group name or id; created if it does not exist",
                    "type": "string",
                    "maxLength": 80
                  },
                  "monitorIds": {
                    "description": "Status follows these monitors",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "aggregate": {
                    "type": "string",
                    "enum": [
                      "worst",
                      "majority"
                    ]
                  },
                  "push": {
                    "description": "Status is pushed via the component push URL",
                    "type": "boolean"
                  },
                  "pushTtlSec": {
                    "description": "Become \"unknown\" when no push arrives for this long (null clears it)",
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 60,
                        "maximum": 604800
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "manual": {
                    "description": "Switch the component to manual status (set via overrides/incidents)",
                    "type": "boolean"
                  },
                  "manifest": {
                    "description": "Status read from a manifest monitor key",
                    "type": "object",
                    "properties": {
                      "monitorId": {
                        "type": "string"
                      },
                      "key": {
                        "type": "string",
                        "maxLength": 120
                      }
                    },
                    "required": [
                      "monitorId",
                      "key"
                    ]
                  },
                  "showUptime": {
                    "type": "boolean"
                  },
                  "showResponseTimes": {
                    "description": "Public response-time chart (monitor-backed components only; page setting showResponseTimes must be on)",
                    "type": "boolean"
                  },
                  "hidden": {
                    "type": "boolean"
                  },
                  "order": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  },
                  "confirmations": {
                    "description": "Push/manifest: consecutive fresh bad reports before a worse status shows (default 2; 1 = immediate)",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  }
                },
                "required": [
                  "name"
                ]
              },
              "example": {
                "name": "Search API",
                "group": "APIs",
                "monitorIds": [
                  "mon_..."
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Status page id (pg_...) or slug"
            },
            "description": "Status page id (pg_...) or slug"
          }
        ]
      }
    },
    "/api/v1/components/{id}": {
      "patch": {
        "operationId": "components.update",
        "summary": "Update a component (name, group, source, visibility)",
        "tags": [
          "Components"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "key": {
                    "description": "Stable machine key used by pushes and manifests (default: slug of name)",
                    "type": "string",
                    "pattern": "^[a-z0-9][a-z0-9_.-]{0,62}$"
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "group": {
                    "description": "Group name or id; created if it does not exist",
                    "type": "string",
                    "maxLength": 80
                  },
                  "monitorIds": {
                    "description": "Status follows these monitors",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "aggregate": {
                    "type": "string",
                    "enum": [
                      "worst",
                      "majority"
                    ]
                  },
                  "push": {
                    "description": "Status is pushed via the component push URL",
                    "type": "boolean"
                  },
                  "pushTtlSec": {
                    "description": "Become \"unknown\" when no push arrives for this long (null clears it)",
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 60,
                        "maximum": 604800
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "manual": {
                    "description": "Switch the component to manual status (set via overrides/incidents)",
                    "type": "boolean"
                  },
                  "manifest": {
                    "description": "Status read from a manifest monitor key",
                    "type": "object",
                    "properties": {
                      "monitorId": {
                        "type": "string"
                      },
                      "key": {
                        "type": "string",
                        "maxLength": 120
                      }
                    },
                    "required": [
                      "monitorId",
                      "key"
                    ]
                  },
                  "showUptime": {
                    "type": "boolean"
                  },
                  "showResponseTimes": {
                    "description": "Public response-time chart (monitor-backed components only; page setting showResponseTimes must be on)",
                    "type": "boolean"
                  },
                  "hidden": {
                    "type": "boolean"
                  },
                  "order": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  },
                  "confirmations": {
                    "description": "Push/manifest: consecutive fresh bad reports before a worse status shows (default 2; 1 = immediate)",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "delete": {
        "operationId": "components.delete",
        "summary": "Delete a component",
        "tags": [
          "Components"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/components/{id}/override": {
      "post": {
        "operationId": "components.override",
        "summary": "Manually set (or clear) a component status",
        "description": "Overrides win over automatic status until cleared with status=null. For outages prefer creating an incident, which also notifies subscribers.",
        "tags": [
          "Components"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "operational",
                          "degraded",
                          "partial_outage",
                          "major_outage",
                          "maintenance"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 300
                  }
                },
                "required": [
                  "status"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/pages/{pageId}/status": {
      "post": {
        "operationId": "pages.push",
        "summary": "Push statuses for many components at once",
        "description": "Body: {\"statuses\": {\"<component key>\": \"operational\" | {\"status\": \"major_outage\", \"message\": \"...\"}}}. Accepts ok/up/fail/down/true/false too. Failing components open (or join) an automatic incident when the page has autoIncidents on; recovery resolves it.",
        "tags": [
          "Components"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "statuses": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "statuses"
                ]
              },
              "example": {
                "statuses": {
                  "search": "operational",
                  "billing": {
                    "status": "degraded",
                    "message": "Stripe latency"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "pageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Status page id (pg_...) or slug"
            },
            "description": "Status page id (pg_...) or slug"
          }
        ]
      }
    },
    "/api/v1/incidents": {
      "get": {
        "operationId": "incidents.list",
        "summary": "List incidents and maintenance",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "open",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Only unresolved",
              "type": [
                "boolean",
                "string"
              ]
            },
            "description": "Only unresolved"
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "incident",
                "maintenance"
              ]
            }
          },
          {
            "name": "pageId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "monitorId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ]
      },
      "post": {
        "operationId": "incidents.create",
        "summary": "Report an incident",
        "description": "Declare an incident (agents: use this when you detect a problem yourself). Affected components switch to the given status and page subscribers are notified. Set polish=true to have AI rewrite rough notes into a clear public update.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "message": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000,
                    "description": "First public update"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "investigating",
                      "identified",
                      "monitoring"
                    ]
                  },
                  "impact": {
                    "type": "string",
                    "enum": [
                      "none",
                      "minor",
                      "major",
                      "critical"
                    ]
                  },
                  "pageIds": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "components": {
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "componentId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "operational",
                            "degraded",
                            "partial_outage",
                            "major_outage",
                            "maintenance"
                          ]
                        }
                      },
                      "required": [
                        "componentId",
                        "status"
                      ]
                    },
                    "description": "Affected components and their status during the incident"
                  },
                  "public": {
                    "description": "Show on status pages (default: true when pages/components are given)",
                    "type": "boolean"
                  },
                  "polish": {
                    "type": "boolean"
                  },
                  "notify": {
                    "description": "Notify subscribers (default true)",
                    "type": "boolean"
                  }
                },
                "required": [
                  "title",
                  "message"
                ]
              },
              "example": {
                "title": "Elevated API errors",
                "message": "We are seeing 5xx errors on search and are investigating.",
                "components": [
                  {
                    "componentId": "cmp_...",
                    "status": "partial_outage"
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/incidents/{id}": {
      "get": {
        "operationId": "incidents.get",
        "summary": "Get an incident with its timeline and AI reports",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/incidents/{id}/updates": {
      "post": {
        "operationId": "incidents.update",
        "summary": "Post an incident update",
        "description": "Adds a timeline update, optionally changing status and component impact. status=resolved resolves the incident.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "message": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "investigating",
                      "identified",
                      "monitoring",
                      "resolved",
                      "scheduled",
                      "in_progress",
                      "completed"
                    ]
                  },
                  "components": {
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "componentId": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "operational",
                            "degraded",
                            "partial_outage",
                            "major_outage",
                            "maintenance"
                          ]
                        }
                      },
                      "required": [
                        "componentId",
                        "status"
                      ]
                    },
                    "description": "Affected components and their status during the incident"
                  },
                  "public": {
                    "description": "false = internal note (not shown or sent to subscribers)",
                    "type": "boolean"
                  },
                  "polish": {
                    "type": "boolean"
                  },
                  "notify": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "message"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/incidents/{id}/resolve": {
      "post": {
        "operationId": "incidents.resolve",
        "summary": "Resolve an incident",
        "description": "Without a message, UpButler writes the resolution note (AI recovery summary when available).",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "message": {
                    "type": "string",
                    "maxLength": 10000
                  },
                  "polish": {
                    "type": "boolean"
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/incidents/{id}/analyze": {
      "post": {
        "operationId": "incidents.analyze",
        "summary": "Generate (or regenerate) the AI report for an incident",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/maintenance": {
      "post": {
        "operationId": "maintenance.create",
        "summary": "Schedule maintenance",
        "description": "Components show \"Under maintenance\" during the window; it starts and completes automatically. Subscribers are notified.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "message": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                  },
                  "scheduledStart": {},
                  "scheduledEnd": {},
                  "pageIds": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "componentIds": {
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "notify": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "title",
                  "message",
                  "scheduledStart",
                  "scheduledEnd"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/channels": {
      "get": {
        "operationId": "channels.list",
        "summary": "List alert channels",
        "tags": [
          "Alerts"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "channels.create",
        "summary": "Create an alert channel",
        "description": "Where your team (or your agent) gets alerted. Webhook channels receive Standard Webhooks-signed JSON (headers webhook-id, webhook-timestamp, webhook-signature); the signing secret is returned once in the response.",
        "tags": [
          "Alerts"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "email",
                      "webhook",
                      "slack",
                      "discord",
                      "telegram"
                    ]
                  },
                  "emails": {
                    "description": "email: recipients",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email",
                      "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                    }
                  },
                  "url": {
                    "description": "webhook/slack/discord: URL",
                    "type": "string",
                    "maxLength": 1000,
                    "format": "uri"
                  },
                  "headers": {
                    "description": "webhook: extra headers",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {
                      "type": "string"
                    }
                  },
                  "botToken": {
                    "description": "telegram: bot token",
                    "type": "string",
                    "maxLength": 200
                  },
                  "chatId": {
                    "description": "telegram: chat id",
                    "type": "string",
                    "maxLength": 100
                  },
                  "events": {
                    "description": "Event types to receive (default: alerts). One of: monitor.down, monitor.up, monitor.degraded, monitor.reminder, incident.created, incident.updated, incident.resolved, maintenance.scheduled, maintenance.started, maintenance.updated, maintenance.completed, incident.acknowledged, incident.escalated, incident.unacknowledged, component.status_changed, monitor.created, monitor.deleted, deploy.created, digest.weekly, test.ping, or \"*\"",
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "isDefault": {
                    "description": "Attach to new monitors automatically (default true)",
                    "type": "boolean"
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "name",
                  "type"
                ]
              },
              "example": {
                "name": "Ops agent",
                "type": "webhook",
                "url": "https://agent.example.com/hooks/upbutler"
              }
            }
          }
        }
      }
    },
    "/api/v1/channels/{id}": {
      "patch": {
        "operationId": "channels.update",
        "summary": "Update an alert channel",
        "tags": [
          "Alerts"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "email",
                      "webhook",
                      "slack",
                      "discord",
                      "telegram"
                    ]
                  },
                  "emails": {
                    "description": "email: recipients",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email",
                      "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                    }
                  },
                  "url": {
                    "description": "webhook/slack/discord: URL",
                    "type": "string",
                    "maxLength": 1000,
                    "format": "uri"
                  },
                  "headers": {
                    "description": "webhook: extra headers",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {
                      "type": "string"
                    }
                  },
                  "botToken": {
                    "description": "telegram: bot token",
                    "type": "string",
                    "maxLength": 200
                  },
                  "chatId": {
                    "description": "telegram: chat id",
                    "type": "string",
                    "maxLength": 100
                  },
                  "events": {
                    "description": "Event types to receive (default: alerts). One of: monitor.down, monitor.up, monitor.degraded, monitor.reminder, incident.created, incident.updated, incident.resolved, maintenance.scheduled, maintenance.started, maintenance.updated, maintenance.completed, incident.acknowledged, incident.escalated, incident.unacknowledged, component.status_changed, monitor.created, monitor.deleted, deploy.created, digest.weekly, test.ping, or \"*\"",
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "isDefault": {
                    "description": "Attach to new monitors automatically (default true)",
                    "type": "boolean"
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "rotateSecret": {
                    "type": "boolean"
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "delete": {
        "operationId": "channels.delete",
        "summary": "Delete an alert channel",
        "tags": [
          "Alerts"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/channels/{id}/test": {
      "post": {
        "operationId": "channels.test",
        "summary": "Send a test notification",
        "tags": [
          "Alerts"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/public/pages/{slug}": {
      "get": {
        "operationId": "public.status",
        "summary": "Public status of a page (no auth)",
        "description": "Overall status, components with 90-day uptime, active incidents and maintenance. Safe to poll every 30s.",
        "tags": [
          "Public status"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "history",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Include per-day uptime bars (default true)",
              "type": [
                "boolean",
                "string"
              ]
            },
            "description": "Include per-day uptime bars (default true)"
          }
        ]
      }
    },
    "/api/v1/public/pages/{slug}/incidents": {
      "get": {
        "operationId": "public.incidents",
        "summary": "Public incident history of a page",
        "tags": [
          "Public status"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            }
          }
        ]
      }
    },
    "/api/v1/public/pages/{slug}/incidents/{id}": {
      "get": {
        "operationId": "public.incident",
        "summary": "One public incident with its updates",
        "tags": [
          "Public status"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/public/pages/{slug}/subscribers": {
      "post": {
        "operationId": "public.subscribe",
        "summary": "Subscribe to a status page (email, webhook, Slack or Discord)",
        "description": "Agents: subscribe with {\"type\":\"webhook\",\"url\":\"https://your-agent/hook\"} to receive signed incident.*, maintenance.* and component.status_changed events and automate downtime handling. We first POST {\"type\":\"subscription.verify\",\"challenge\":\"...\"} and your endpoint must echo the challenge. The response contains the signing secret (Standard Webhooks) and a manage token for unsubscribing. Optionally limit to components (ids or keys).",
        "tags": [
          "Public status"
        ],
        "security": [],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "email",
                      "webhook",
                      "slack",
                      "discord"
                    ]
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "url": {
                    "type": "string",
                    "maxLength": 1000,
                    "format": "uri"
                  },
                  "components": {
                    "description": "Component ids or keys; omit for everything",
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "agent": {
                    "description": "Name of the subscribing agent (shown to the page owner)",
                    "type": "string",
                    "maxLength": 80
                  },
                  "incident": {
                    "description": "Incident id: only that incident's updates, until it is resolved (\"subscribe to this incident\")",
                    "type": "string",
                    "maxLength": 60
                  },
                  "language": {
                    "description": "Email language (en, de, fr, es, it, pt, nl, el, pl, tr, ja); default = page language or Accept-Language",
                    "type": "string",
                    "maxLength": 10
                  }
                },
                "required": [
                  "type"
                ]
              },
              "example": {
                "type": "webhook",
                "url": "https://my-agent.example.com/upbutler",
                "components": [
                  "reddit"
                ],
                "agent": "scraper-orchestrator"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/public/subscribers/{id}": {
      "get": {
        "operationId": "public.subscriber.get",
        "summary": "View a subscription (requires its manage token)",
        "tags": [
          "Public status"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "patch": {
        "operationId": "public.subscriber.update",
        "summary": "Change which components a subscription follows (requires the manage token)",
        "tags": [
          "Public status"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string"
                  },
                  "components": {
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Component ids or keys; [] = everything"
                  }
                },
                "required": [
                  "token",
                  "components"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "delete": {
        "operationId": "public.unsubscribe",
        "summary": "Unsubscribe (requires the manage token)",
        "tags": [
          "Public status"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/public/pages/{slug}/components/{component}/response-times": {
      "get": {
        "operationId": "public.responseTimes",
        "summary": "Public response-time series of a component (p50/p95)",
        "description": "Only for components the page owner published (page settings.showResponseTimes + component showResponseTimes, monitor-backed). 24h = 30-min buckets and 7d = 3-hour buckets with p50/p95 in ms from raw checks; 30d = daily averages (p95 null). Values are averaged across the component's monitors.",
        "tags": [
          "Public status"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "component",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Component key or id"
            },
            "description": "Component key or id"
          },
          {
            "name": "range",
            "in": "query",
            "required": false,
            "schema": {
              "description": "24h (default), 7d or 30d",
              "type": "string",
              "enum": [
                "24h",
                "7d",
                "30d"
              ]
            },
            "description": "24h (default), 7d or 30d"
          }
        ]
      }
    },
    "/api/v1/workspace": {
      "get": {
        "operationId": "workspace.get",
        "summary": "Current workspace, plan, limits and usage",
        "description": "Useful first call for agents: shows what the key can do and how much quota is left.",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "workspace.update",
        "summary": "Rename the workspace",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/me/workspaces": {
      "get": {
        "operationId": "workspaces.list",
        "summary": "Workspaces of the signed-in user",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "workspaces.create",
        "summary": "Create another workspace",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/me/workspaces/{id}/switch": {
      "post": {
        "operationId": "workspaces.switch",
        "summary": "Switch the dashboard to another workspace",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/members": {
      "get": {
        "operationId": "members.list",
        "summary": "List workspace members and pending invites",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/members/invites": {
      "post": {
        "operationId": "members.invite",
        "summary": "Invite a teammate by email",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "member"
                    ]
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/members/invites/{id}": {
      "delete": {
        "operationId": "members.revokeInvite",
        "summary": "Revoke a pending invite",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/members/{userId}": {
      "delete": {
        "operationId": "members.remove",
        "summary": "Remove a member",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/keys": {
      "get": {
        "operationId": "keys.list",
        "summary": "List API keys",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "keys.create",
        "summary": "Create an API key",
        "description": "The secret is returned once. Give agents their own key (with agent set) so their actions are attributed in incident timelines.",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "read",
                        "write"
                      ]
                    }
                  },
                  "agent": {
                    "description": "Name of the agent using this key, e.g. \"deploy-bot\"",
                    "type": "string",
                    "maxLength": 80
                  },
                  "expiresInDays": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 3650
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/keys/{id}": {
      "delete": {
        "operationId": "keys.revoke",
        "summary": "Revoke an API key",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/events": {
      "get": {
        "operationId": "events.list",
        "summary": "Poll the event stream",
        "description": "Every state change in the workspace (monitor.down/up/degraded, incident.*, maintenance.*, component.status_changed …), newest first. Agents without a public webhook endpoint can poll with ?after=<last event id> to get only new events (oldest first). For push instead of polling, open GET /api/v1/stream (Server-Sent Events, same auth; resume with Last-Event-ID; ?types= filter; ?checks=1 for live check results).",
        "tags": [
          "Events"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "after",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Return events after this id, oldest first",
              "type": "string"
            },
            "description": "Return events after this id, oldest first"
          },
          {
            "name": "types",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Comma-separated event types, e.g. \"monitor.down,monitor.up\"",
              "type": "string"
            },
            "description": "Comma-separated event types, e.g. \"monitor.down,monitor.up\""
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            }
          }
        ]
      }
    },
    "/api/v1/plans": {
      "get": {
        "operationId": "plans.list",
        "summary": "Available plans and limits",
        "tags": [
          "Billing"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/checkout": {
      "post": {
        "operationId": "billing.checkout",
        "summary": "Start a checkout to upgrade the workspace",
        "description": "Returns a Polar checkout URL. Agents: hand this URL to your human — payment needs a person.",
        "tags": [
          "Billing"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plan": {
                    "type": "string",
                    "enum": [
                      "starter",
                      "pro",
                      "business"
                    ]
                  },
                  "interval": {
                    "type": "string",
                    "enum": [
                      "month",
                      "year"
                    ]
                  }
                },
                "required": [
                  "plan"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/portal": {
      "post": {
        "operationId": "billing.portal",
        "summary": "Open the billing portal (invoices, payment method, cancel)",
        "tags": [
          "Billing"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/import/preview": {
      "post": {
        "operationId": "import.preview",
        "summary": "Dry run: what an import would create",
        "description": "Reads your UptimeRobot, Better Stack or Statuspage.io account and returns every item with action create | exists (already imported) | skip (with reason), plus plan-limit warnings. Nothing is written. Statuspage.io works with just a public URL.",
        "tags": [
          "Import"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": [
                      "uptimerobot",
                      "betterstack",
                      "statuspage"
                    ],
                    "description": "Where to import from"
                  },
                  "apiKey": {
                    "description": "UptimeRobot read-only API key, Better Stack Uptime API token, or Statuspage.io API key. Used for this request only and never stored.",
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 500
                  },
                  "pageId": {
                    "description": "Statuspage.io page id (with apiKey)",
                    "type": "string",
                    "maxLength": 100
                  },
                  "url": {
                    "description": "Statuspage.io: any public status page URL (no key needed), e.g. https://www.githubstatus.com",
                    "type": "string",
                    "maxLength": 500
                  },
                  "monitors": {
                    "description": "Import monitors and heartbeats (default true)",
                    "type": "boolean"
                  },
                  "channels": {
                    "description": "Import alert contacts as alert channels (default true)",
                    "type": "boolean"
                  },
                  "pages": {
                    "description": "Import status pages, groups and components (default true)",
                    "type": "boolean"
                  },
                  "incidents": {
                    "description": "Statuspage.io: import past incidents and maintenance (default true)",
                    "type": "boolean"
                  },
                  "mirror": {
                    "description": "Statuspage.io: add a manifest monitor that keeps mirroring their components.json (default false)",
                    "type": "boolean"
                  },
                  "targetPageId": {
                    "description": "Import components into this existing status page instead of creating one",
                    "type": "string"
                  },
                  "exclude": {
                    "description": "Refs from the preview (\"monitor:123\") to leave out",
                    "maxItems": 2000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    }
                  }
                },
                "required": [
                  "source"
                ]
              },
              "example": {
                "source": "statuspage",
                "url": "https://www.githubstatus.com",
                "mirror": true
              }
            }
          }
        }
      }
    },
    "/api/v1/import": {
      "post": {
        "operationId": "import.apply",
        "summary": "Run an import (background job)",
        "description": "Starts the import and returns the job right away; poll import.status. Idempotent: re-running creates only what is new. Credentials are kept in memory for the job and never stored.",
        "tags": [
          "Import"
        ],
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": [
                      "uptimerobot",
                      "betterstack",
                      "statuspage"
                    ],
                    "description": "Where to import from"
                  },
                  "apiKey": {
                    "description": "UptimeRobot read-only API key, Better Stack Uptime API token, or Statuspage.io API key. Used for this request only and never stored.",
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 500
                  },
                  "pageId": {
                    "description": "Statuspage.io page id (with apiKey)",
                    "type": "string",
                    "maxLength": 100
                  },
                  "url": {
                    "description": "Statuspage.io: any public status page URL (no key needed), e.g. https://www.githubstatus.com",
                    "type": "string",
                    "maxLength": 500
                  },
                  "monitors": {
                    "description": "Import monitors and heartbeats (default true)",
                    "type": "boolean"
                  },
                  "channels": {
                    "description": "Import alert contacts as alert channels (default true)",
                    "type": "boolean"
                  },
                  "pages": {
                    "description": "Import status pages, groups and components (default true)",
                    "type": "boolean"
                  },
                  "incidents": {
                    "description": "Statuspage.io: import past incidents and maintenance (default true)",
                    "type": "boolean"
                  },
                  "mirror": {
                    "description": "Statuspage.io: add a manifest monitor that keeps mirroring their components.json (default false)",
                    "type": "boolean"
                  },
                  "targetPageId": {
                    "description": "Import components into this existing status page instead of creating one",
                    "type": "string"
                  },
                  "exclude": {
                    "description": "Refs from the preview (\"monitor:123\") to leave out",
                    "maxItems": 2000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    }
                  }
                },
                "required": [
                  "source"
                ]
              },
              "example": {
                "source": "uptimerobot",
                "apiKey": "ur123456-..."
              }
            }
          }
        }
      }
    },
    "/api/v1/import/jobs/{id}": {
      "get": {
        "operationId": "import.status",
        "summary": "Progress and result of an import job",
        "tags": [
          "Import"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Import job id (imp_...)"
            },
            "description": "Import job id (imp_...)"
          }
        ]
      }
    },
    "/api/v1/import/jobs": {
      "get": {
        "operationId": "import.jobs",
        "summary": "Recent import jobs",
        "tags": [
          "Import"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ]
      }
    },
    "/api/v1/incidents/{id}/ack": {
      "post": {
        "operationId": "incidents.ack",
        "summary": "Acknowledge an incident or a down monitor",
        "description": "Take ownership: stops \"still down\" reminders and escalation, records an internal timeline entry and emits incident.acknowledged to the channels that were alerted. `id` may be an incident id or a monitor id (acknowledges its open incident). Idempotent.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "description": "e.g. \"Looking into it, rolling back deploy\"",
                    "type": "string",
                    "maxLength": 1000
                  }
                },
                "required": []
              },
              "example": {
                "note": "On it, rolling back the last deploy"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Incident id (inc_…) or monitor id (mon_…)"
            },
            "description": "Incident id (inc_…) or monitor id (mon_…)"
          }
        ]
      }
    },
    "/api/v1/incidents/{id}/unack": {
      "post": {
        "operationId": "incidents.unack",
        "summary": "Remove an acknowledgement",
        "description": "Reminders and escalation resume where they stopped.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/oncall/current": {
      "get": {
        "operationId": "oncall.current",
        "summary": "Who is on call right now",
        "description": "For every schedule (or one with scheduleId): the person on call now, until when, and whether it is an override. Agents: use this to decide whom to tell about a problem.",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "scheduleId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/oncall/schedules": {
      "get": {
        "operationId": "oncall.schedules.list",
        "summary": "List on-call schedules",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Include upcoming shifts for this many days",
              "type": "integer",
              "minimum": 0,
              "maximum": 42
            },
            "description": "Include upcoming shifts for this many days"
          }
        ]
      },
      "post": {
        "operationId": "oncall.schedules.create",
        "summary": "Create a weekly on-call rotation (Business plan)",
        "tags": [
          "On-call"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "timezone": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "IANA timezone, e.g. \"Europe/Berlin\""
                  },
                  "handoffDay": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 6,
                    "description": "Handoff weekday: 0 = Monday … 6 = Sunday"
                  },
                  "handoffTime": {
                    "type": "string",
                    "pattern": "^\\d{1,2}:\\d{2}$",
                    "description": "Local handoff time \"HH:MM\" (24h)"
                  },
                  "participants": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Ordered member user ids; each is on call for one week"
                  },
                  "startDay": {
                    "description": "Local date whose rotation week the first participant takes (default: the current week)",
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                  }
                },
                "required": [
                  "name",
                  "timezone",
                  "handoffDay",
                  "handoffTime",
                  "participants"
                ]
              },
              "example": {
                "name": "Primary",
                "timezone": "Europe/Berlin",
                "handoffDay": 0,
                "handoffTime": "09:00",
                "participants": [
                  "usr_…",
                  "usr_…"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/oncall/schedules/{id}": {
      "get": {
        "operationId": "oncall.schedules.get",
        "summary": "Get a schedule with upcoming shifts",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Default 14",
              "type": "integer",
              "minimum": 1,
              "maximum": 42
            },
            "description": "Default 14"
          }
        ]
      },
      "patch": {
        "operationId": "oncall.schedules.update",
        "summary": "Update a schedule",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "timezone": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "IANA timezone, e.g. \"Europe/Berlin\""
                  },
                  "handoffDay": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 6,
                    "description": "Handoff weekday: 0 = Monday … 6 = Sunday"
                  },
                  "handoffTime": {
                    "type": "string",
                    "pattern": "^\\d{1,2}:\\d{2}$",
                    "description": "Local handoff time \"HH:MM\" (24h)"
                  },
                  "participants": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Ordered member user ids; each is on call for one week"
                  },
                  "startDay": {
                    "description": "Local date whose rotation week the first participant takes (default: the current week)",
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "delete": {
        "operationId": "oncall.schedules.delete",
        "summary": "Delete a schedule",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/oncall/schedules/{id}/overrides": {
      "post": {
        "operationId": "oncall.overrides.create",
        "summary": "Put someone on call for a period (override)",
        "description": "Overrides win over the rotation; the most recently created one wins when they overlap.",
        "tags": [
          "On-call"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userId": {
                    "type": "string"
                  },
                  "start": {},
                  "end": {},
                  "note": {
                    "type": "string",
                    "maxLength": 200
                  }
                },
                "required": [
                  "userId",
                  "start",
                  "end"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/oncall/schedules/{id}/overrides/{overrideId}": {
      "delete": {
        "operationId": "oncall.overrides.delete",
        "summary": "Remove an override",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "overrideId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/oncall/members": {
      "get": {
        "operationId": "oncall.members",
        "summary": "Members with their paging contact status",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/escalation-policies": {
      "get": {
        "operationId": "escalation.list",
        "summary": "List escalation policies",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "escalation.create",
        "summary": "Create an escalation policy (Business plan)",
        "description": "Ordered levels: level 1 is paged as soon as an incident opens; each next level after `afterMinutes` if nobody acknowledged. Applies to incidents of `monitorIds`/`pageIds`, or to everything when isDefault. Without any policy, alerts follow each monitor's channels and reminders.",
        "tags": [
          "On-call"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "isDefault": {
                    "description": "Use for incidents no monitor/page-specific policy claims (the first policy becomes default)",
                    "type": "boolean"
                  },
                  "monitorIds": {
                    "maxItems": 250,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "pageIds": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "levels": {
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "afterMinutes": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 1440,
                          "description": "Wait after the previous level (ignored for level 1)"
                        },
                        "targets": {
                          "minItems": 1,
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "oneOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "channel"
                                  },
                                  "id": {
                                    "type": "string",
                                    "description": "Alert channel id"
                                  }
                                },
                                "required": [
                                  "type",
                                  "id"
                                ]
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "schedule"
                                  },
                                  "id": {
                                    "type": "string",
                                    "description": "Schedule id: pages whoever is on call when the level fires"
                                  }
                                },
                                "required": [
                                  "type",
                                  "id"
                                ]
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "user"
                                  },
                                  "id": {
                                    "type": "string",
                                    "description": "Member user id"
                                  }
                                },
                                "required": [
                                  "type",
                                  "id"
                                ]
                              }
                            ]
                          }
                        }
                      },
                      "required": [
                        "afterMinutes",
                        "targets"
                      ]
                    }
                  },
                  "repeat": {
                    "description": "Repeat the whole chain this many times while unacknowledged",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 5
                  },
                  "repeatAfterMinutes": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1440
                  }
                },
                "required": [
                  "name",
                  "levels"
                ]
              },
              "example": {
                "name": "Default",
                "levels": [
                  {
                    "afterMinutes": 0,
                    "targets": [
                      {
                        "type": "schedule",
                        "id": "sch_…"
                      }
                    ]
                  },
                  {
                    "afterMinutes": 15,
                    "targets": [
                      {
                        "type": "channel",
                        "id": "ch_…"
                      }
                    ]
                  }
                ],
                "repeat": 1
              }
            }
          }
        }
      }
    },
    "/api/v1/escalation-policies/{id}": {
      "patch": {
        "operationId": "escalation.update",
        "summary": "Update an escalation policy",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "isDefault": {
                    "description": "Use for incidents no monitor/page-specific policy claims (the first policy becomes default)",
                    "type": "boolean"
                  },
                  "monitorIds": {
                    "maxItems": 250,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "pageIds": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "levels": {
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "afterMinutes": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 1440,
                          "description": "Wait after the previous level (ignored for level 1)"
                        },
                        "targets": {
                          "minItems": 1,
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "oneOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "channel"
                                  },
                                  "id": {
                                    "type": "string",
                                    "description": "Alert channel id"
                                  }
                                },
                                "required": [
                                  "type",
                                  "id"
                                ]
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "schedule"
                                  },
                                  "id": {
                                    "type": "string",
                                    "description": "Schedule id: pages whoever is on call when the level fires"
                                  }
                                },
                                "required": [
                                  "type",
                                  "id"
                                ]
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "user"
                                  },
                                  "id": {
                                    "type": "string",
                                    "description": "Member user id"
                                  }
                                },
                                "required": [
                                  "type",
                                  "id"
                                ]
                              }
                            ]
                          }
                        }
                      },
                      "required": [
                        "afterMinutes",
                        "targets"
                      ]
                    }
                  },
                  "repeat": {
                    "description": "Repeat the whole chain this many times while unacknowledged",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 5
                  },
                  "repeatAfterMinutes": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1440
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "delete": {
        "operationId": "escalation.delete",
        "summary": "Delete an escalation policy",
        "tags": [
          "On-call"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/me/contact": {
      "get": {
        "operationId": "profile.contact.get",
        "summary": "Your paging contact profile",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "profile.contact.update",
        "summary": "Update your paging contact profile",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "description": "Paging email; null = account email",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200,
                        "format": "email",
                        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "telegramChatId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^-?\\d{1,20}$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "phone": {
                    "description": "Stored for future SMS paging",
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^\\+[1-9]\\d{6,14}$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": []
              }
            }
          }
        }
      }
    },
    "/api/v1/me/security": {
      "get": {
        "operationId": "me.security",
        "summary": "Two-factor status, connected sign-in providers and active sessions",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/sessions/{id}": {
      "delete": {
        "operationId": "me.sessions.revoke",
        "summary": "Sign out one session",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 64
            }
          }
        ]
      }
    },
    "/api/v1/me/sessions/revoke-others": {
      "post": {
        "operationId": "me.sessions.revokeOthers",
        "summary": "Sign out every other session",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/2fa/setup": {
      "post": {
        "operationId": "me.2fa.setup",
        "summary": "Start two-factor enrolment (returns secret, otpauth URI and QR SVG)",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/me/2fa/enable": {
      "post": {
        "operationId": "me.2fa.enable",
        "summary": "Confirm enrolment with a code; returns 10 one-time recovery codes",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "minLength": 6,
                    "maxLength": 12
                  }
                },
                "required": [
                  "code"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/me/2fa/disable": {
      "post": {
        "operationId": "me.2fa.disable",
        "summary": "Turn off two-factor authentication",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "minLength": 6,
                    "maxLength": 40,
                    "description": "6-digit code from the authenticator app, or a recovery code"
                  }
                },
                "required": [
                  "code"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/me/2fa/recovery-codes": {
      "post": {
        "operationId": "me.2fa.recoveryCodes",
        "summary": "Replace all recovery codes (old ones stop working)",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "minLength": 6,
                    "maxLength": 40,
                    "description": "6-digit code from the authenticator app, or a recovery code"
                  }
                },
                "required": [
                  "code"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/me/identities/{provider}": {
      "delete": {
        "operationId": "me.identities.unlink",
        "summary": "Disconnect a Google or GitHub sign-in",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "google",
                "github"
              ]
            }
          }
        ]
      }
    },
    "/api/v1/workspace/security": {
      "patch": {
        "operationId": "workspace.security.update",
        "summary": "Require two-factor authentication for every member (owners only)",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "require2fa": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "require2fa"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/audit": {
      "get": {
        "operationId": "audit.list",
        "summary": "Audit log: sign-ins, 2FA changes, keys, members, billing, deletions, domains",
        "description": "Newest first, kept 400 days. Filter by action (exact like \"api_key.created\" or a prefix like \"auth\" / \"member.\"), actor id or time range; page with ?before=<next>. Owners and admins (or keys with the write scope).",
        "tags": [
          "Workspace"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "action",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            }
          },
          {
            "name": "actorId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {}
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {}
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ]
      }
    },
    "/api/v1/regions": {
      "get": {
        "operationId": "regions.list",
        "summary": "List check regions and probe health",
        "description": "Regions monitors can be checked from (use the ids in a monitor's \"regions\"). With several regions a round only counts as DOWN when a majority of the reporting regions agree; regions whose probe is unhealthy are skipped, never counted as failures.",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/{id}/regions": {
      "get": {
        "operationId": "monitors.regions",
        "summary": "Per-region latency and failures for a monitor",
        "tags": [
          "Monitors"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Monitor id (mon_...)"
            },
            "description": "Monitor id (mon_...)"
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 168
            }
          }
        ]
      }
    },
    "/api/v1/deploys": {
      "post": {
        "operationId": "deploys.create",
        "summary": "Record a deploy",
        "description": "Mark a release so incidents can be correlated with it (AI reports, charts, incident timelines). Minimal input {\"version\":\"1.4.2\"} applies to the whole workspace; narrow it with monitorIds, service (matches monitor tags/names) or pageId. Emits deploy.created.",
        "tags": [
          "Deploys"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "version": {
                    "description": "Release version or tag, e.g. \"1.4.2\"",
                    "type": "string",
                    "maxLength": 100
                  },
                  "commit": {
                    "description": "Commit SHA (shown shortened)",
                    "type": "string",
                    "maxLength": 80
                  },
                  "url": {
                    "description": "Link to the release, CI run or PR",
                    "type": "string",
                    "maxLength": 2000,
                    "format": "uri"
                  },
                  "environment": {
                    "description": "e.g. \"production\", \"staging\"",
                    "type": "string",
                    "maxLength": 40
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "service": {
                    "description": "Service name; monitors tagged or named like this are linked automatically",
                    "type": "string",
                    "maxLength": 120
                  },
                  "monitorIds": {
                    "description": "Limit the deploy to these monitors (default: whole workspace)",
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 60
                    }
                  },
                  "monitorId": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "pageId": {
                    "description": "Limit the deploy to one status page",
                    "type": "string",
                    "maxLength": 60
                  },
                  "pageIds": {
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 60
                    }
                  },
                  "at": {
                    "description": "When it went out (ISO 8601, default now)",
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  }
                },
                "required": []
              },
              "example": {
                "version": "1.4.2",
                "commit": "abc1234def",
                "environment": "production",
                "service": "api"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "deploys.list",
        "summary": "List deploys",
        "description": "Newest first. monitorId/pageId include workspace-wide deploys; incidentId returns the deploys from the hour before the incident through its end.",
        "tags": [
          "Deploys"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "monitorId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "incidentId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "until",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            }
          }
        ]
      }
    },
    "/api/v1/deploys/{id}": {
      "delete": {
        "operationId": "deploys.delete",
        "summary": "Delete a deploy marker",
        "tags": [
          "Deploys"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/digest/settings": {
      "get": {
        "operationId": "digest.settings",
        "summary": "Weekly digest settings",
        "description": "Workspace timezone, who receives the Monday 08:00 email, when the next one goes out and the last runs. Webhook channels subscribed to \"digest.weekly\" get the full JSON.",
        "tags": [
          "Digest"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "digest.settings.update",
        "summary": "Change the workspace timezone or your weekly digest opt-in",
        "description": "subscribed applies to the signed-in member (owners are subscribed by default). timezone (IANA, e.g. \"Europe/Berlin\") needs owner/admin and also sets when Monday 08:00 is.",
        "tags": [
          "Digest"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subscribed": {
                    "type": "boolean"
                  },
                  "timezone": {
                    "type": "string",
                    "maxLength": 60
                  }
                },
                "required": []
              }
            }
          }
        }
      }
    },
    "/api/v1/digest/preview": {
      "post": {
        "operationId": "digest.preview",
        "summary": "Build the weekly digest on demand",
        "description": "Returns the digest JSON (same shape as the digest.weekly event) and, with format=html, the rendered email. period=last_week is exactly what Monday's email covers; last_7_days is rolling. ai=true writes the \"what to look at\" section with AI (uses one AI report from the monthly quota); otherwise a rule-based version is returned.",
        "tags": [
          "Digest"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "period": {
                    "type": "string",
                    "enum": [
                      "last_week",
                      "last_7_days"
                    ]
                  },
                  "ai": {
                    "type": "boolean"
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "json",
                      "html"
                    ]
                  }
                },
                "required": []
              }
            }
          }
        }
      }
    },
    "/api/v1/incidents/{id}/postmortem": {
      "post": {
        "operationId": "incidents.postmortem",
        "summary": "Draft a postmortem with AI",
        "description": "Writes a blameless markdown postmortem (summary, impact, timeline from updates, checks and deploy markers, root-cause hypotheses, contributing factors, what went well/poorly, action items) plus a customer-safe summary, and stores it as a new version. Uses one AI report. When AI is unavailable the 503 response carries a template draft in error.details.template.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mode": {
                    "description": "template = return an unsaved fill-in-the-blanks draft without using AI",
                    "type": "string",
                    "enum": [
                      "ai",
                      "template"
                    ]
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "get": {
        "operationId": "incidents.postmortem.get",
        "summary": "Get an incident's postmortem",
        "description": "Current markdown, the public summary, publish state and the version list (history=true includes every version's markdown). 404 when none exists yet.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "history",
            "in": "query",
            "required": false,
            "schema": {
              "type": [
                "boolean",
                "string"
              ]
            }
          }
        ]
      },
      "put": {
        "operationId": "incidents.postmortem.save",
        "summary": "Save an edited postmortem (new version)",
        "description": "Send baseVersion (the version you edited) to get a 409 instead of overwriting someone else's changes.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "markdown": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60000
                  },
                  "publicSummary": {
                    "description": "Customer-safe text used by publish",
                    "type": "string",
                    "maxLength": 5000
                  },
                  "baseVersion": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "markdown"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/incidents/{id}/postmortem/publish": {
      "post": {
        "operationId": "incidents.postmortem.publish",
        "summary": "Publish a post-incident report to status pages",
        "description": "Posts body (default: the postmortem's public summary) as a public update on the resolved incident and notifies subscribers. The text must pass the page's AI policy and may not contain hostnames, IPs or error output.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000
                  },
                  "notify": {
                    "type": "boolean"
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/incident-templates": {
      "get": {
        "operationId": "templates.list",
        "summary": "List incident templates",
        "description": "Reusable title/status/impact/message presets. Bodies support {{component}}, {{duration}}, {{status_page}} and {{title}}. New workspaces start with sensible defaults.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "templates.create",
        "summary": "Create an incident template",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "description": "Shown in the \"Use template\" picker"
                  },
                  "kind": {
                    "description": "Default incident",
                    "type": "string",
                    "enum": [
                      "incident",
                      "maintenance"
                    ]
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "Incident title; placeholders allowed"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "investigating",
                      "identified",
                      "monitoring",
                      "resolved",
                      "scheduled",
                      "in_progress",
                      "completed"
                    ]
                  },
                  "impact": {
                    "type": "string",
                    "enum": [
                      "none",
                      "minor",
                      "major",
                      "critical",
                      "maintenance"
                    ]
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000,
                    "description": "Update text. Placeholders: {{component}}, {{duration}}, {{status_page}}, {{title}}"
                  },
                  "componentIds": {
                    "description": "Components affected by default",
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "componentStatus": {
                    "description": "Status the default components get (default partial_outage)",
                    "type": "string",
                    "enum": [
                      "operational",
                      "degraded",
                      "partial_outage",
                      "major_outage",
                      "maintenance"
                    ]
                  },
                  "order": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  }
                },
                "required": [
                  "name",
                  "title",
                  "body"
                ]
              },
              "example": {
                "name": "Payment provider outage",
                "title": "Payments delayed on {{component}}",
                "status": "identified",
                "impact": "major",
                "body": "Our payment provider is having issues. {{component}} payments may be delayed; no charges are lost."
              }
            }
          }
        }
      }
    },
    "/api/v1/incident-templates/{id}": {
      "patch": {
        "operationId": "templates.update",
        "summary": "Update an incident template",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "description": "Shown in the \"Use template\" picker"
                  },
                  "kind": {
                    "description": "Default incident",
                    "type": "string",
                    "enum": [
                      "incident",
                      "maintenance"
                    ]
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "Incident title; placeholders allowed"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "investigating",
                      "identified",
                      "monitoring",
                      "resolved",
                      "scheduled",
                      "in_progress",
                      "completed"
                    ]
                  },
                  "impact": {
                    "type": "string",
                    "enum": [
                      "none",
                      "minor",
                      "major",
                      "critical",
                      "maintenance"
                    ]
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000,
                    "description": "Update text. Placeholders: {{component}}, {{duration}}, {{status_page}}, {{title}}"
                  },
                  "componentIds": {
                    "description": "Components affected by default",
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "componentStatus": {
                    "description": "Status the default components get (default partial_outage)",
                    "type": "string",
                    "enum": [
                      "operational",
                      "degraded",
                      "partial_outage",
                      "major_outage",
                      "maintenance"
                    ]
                  },
                  "order": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "delete": {
        "operationId": "templates.delete",
        "summary": "Delete an incident template",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/incident-templates/{id}/render": {
      "post": {
        "operationId": "templates.render",
        "summary": "Fill in a template",
        "description": "Returns title, message, status, impact and components ready for POST /incidents or POST /incidents/{id}/updates. With incidentId, the incident's components and duration fill the placeholders; otherwise componentIds (or the template defaults) do.",
        "tags": [
          "Incidents"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "incidentId": {
                    "type": "string"
                  },
                  "componentIds": {
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": []
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    }
  }
}