{"openapi":"3.0.0","info":{"title":"UptimeWarden API v1","version":"1.0.0","description":"\n# UptimeWarden Public API v1\n\nProduction-ready API with granular permission system, time-based data access limits, and comprehensive monitoring capabilities.\n\n## Authentication\n\nAll endpoints require an API token in the Authorization header:\n```\nAuthorization: Bearer YOUR_API_TOKEN\n```\n\n## Rate Limits\n\n- **Monitor operations**: 60-120 requests/minute\n- **Security analysis**: 10 requests/minute\n- **Health predictions**: 60 requests/minute\n\n## Time-Based Restrictions\n\n- **Monitor Results**: Maximum 7 days of historical data\n- **Incidents**: Maximum 30 days of historical data\n\n## Permissions\n\nEach endpoint requires specific permissions. Create API tokens with only the permissions you need:\n\n- `monitors:read` - View monitors\n- `monitors:create` - Create monitors\n- `monitors:delete` - Delete monitors\n- `monitors:results:read` - Access monitor results (7-day limit)\n- `incidents:read` - View incidents (30-day limit)\n- `incidents:update` - Update incident status\n- `incidents:comment` - Add comments to incidents\n- `ssl:status:read` - View SSL certificate status\n- `security:analysis:read` - View security analysis results\n- `security:analysis:monitor` - Run analysis on owned monitors\n- `security:analysis:website` - Run analysis on any website\n- `health:predictions:read` - View AI health predictions\n        ","contact":{"name":"UptimeWarden API Support","url":"https://uptimewarden.online/support"}},"servers":[{"url":"https://app.uptimewarden.online","description":"Production Server"},{"url":"http://localhost:5000","description":"Development Server"}],"tags":[{"name":"API v1 - Monitors","description":"Monitor management endpoints with CRUD operations"},{"name":"API v1 - Incidents","description":"Incident tracking and management (30-day limit)"},{"name":"API v1 - SSL","description":"SSL certificate status and monitoring"},{"name":"API v1 - Security","description":"Security analysis and vulnerability scanning"},{"name":"API v1 - Health Predictions","description":"AI-powered health predictions and anomaly detection"},{"name":"API v1 - References","description":"Read-only lists of what a monitor can reference by public id (escalation policies, webhooks, regions)"},{"name":"Heartbeat","description":"Pings from your jobs. The heartbeat token in the URL is the credential; no API token."}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Create tokens at /api-portal"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","description":"Response data (varies by endpoint)"}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"INTERNAL_ERROR"},"message":{"type":"string","example":"An error occurred"},"details":{"type":"array","items":{"type":"string"}}}}}},"Pagination":{"type":"object","properties":{"page":{"type":"integer","example":1},"limit":{"type":"integer","example":20},"total":{"type":"integer","example":100},"totalPages":{"type":"integer","example":5},"hasNextPage":{"type":"boolean","example":true},"hasPrevPage":{"type":"boolean","example":false}}},"Monitor":{"type":"object","description":"A monitor. No internal ids: publicId is the only id.","properties":{"publicId":{"type":"string","example":"01J9ZP4M3K8Q5R6S7T8V9W0X1Y"},"name":{"type":"string","example":"Production API"},"type":{"type":"string","enum":["http","tcp","udp","ssl","websocket","mcp","grpc","ping","dns","heartbeat"],"description":"Must also be in your plan. Cannot be changed to or from heartbeat.","example":"http"},"url":{"type":"string","description":"Target. Not sent for heartbeat monitors (the server sets heartbeat://<token>).","example":"https://api.example.com/health"},"description":{"type":"string","nullable":true},"interval":{"type":"integer","minimum":30,"default":300,"description":"Check interval in seconds; at least your plan minimum."},"timeout":{"type":"integer","minimum":5,"maximum":300,"default":30,"description":"Seconds."},"isActive":{"type":"boolean","default":true,"description":"Switching a paused monitor on counts against your plan."},"tags":{"type":"array","items":{"type":"string"}},"groups":{"type":"array","items":{"type":"string"},"description":"PATCH only. Group names."},"externalId":{"type":"string","maxLength":255,"nullable":true,"description":"Your stable handle (e.g. Terraform address). PATCH \"\" clears it."},"managedBySource":{"type":"string","default":"manual","example":"terraform"},"region":{"type":"string","description":"Primary region code from GET /api/v1/regions. Choosing one needs regionSelection on your plan.","example":"gwc"},"verificationRegions":{"type":"array","items":{"type":"string"},"description":"Regions that recheck an outage before it is alerted. Active codes only, not the primary, at most maxVerificationRegions - 1. Empty = nearest regions. Must be empty for heartbeat and agent monitors."},"minConfirmingRegions":{"type":"integer","minimum":1,"description":"Regions that must confirm a DOWN. Other than the plan default needs allowConsensusOverride."},"agentId":{"type":"string","nullable":true,"description":"One of your private agents; \"\" or \"server\" = our regions."},"method":{"type":"string","example":"GET","description":"HTTP method."},"customHeaders":{"type":"object","additionalProperties":{"type":"string"}},"requestBody":{"type":"string","nullable":true},"expectedStatusCodes":{"type":"string","example":"200-299"},"expectedBody":{"type":"string","nullable":true,"description":"Keyword the response body must contain."},"contentValidation":{"type":"object","nullable":true},"followRedirects":{"type":"boolean","default":true},"verifySsl":{"type":"boolean","default":true},"enableSsl":{"type":"boolean","default":true},"basicAuthUsername":{"type":"string","nullable":true},"basicAuthPassword":{"type":"string","nullable":true,"description":"Returned only to callers who may edit the monitor."},"bearerToken":{"type":"string","nullable":true,"description":"Returned only to callers who may edit the monitor."},"hostname":{"type":"string","nullable":true},"port":{"type":"integer","nullable":true,"description":"TCP / UDP port."},"grpcProtoFile":{"type":"string","nullable":true},"grpcMethod":{"type":"string","nullable":true},"dnsConfig":{"type":"object","nullable":true,"properties":{"recordType":{"type":"string","enum":["A","AAAA","CNAME","MX","NS","TXT"]},"resolver":{"type":"string"},"expectedAnswers":{"type":"array","items":{"type":"string"}}}},"retryCount":{"type":"integer","nullable":true},"responseTimeThreshold":{"type":"integer","nullable":true,"minimum":50,"maximum":5000,"description":"ms; 0 or null = off."},"sslExpiryDays":{"type":"integer","default":30},"sslAlerts":{"type":"object","properties":{"thirtyDays":{"type":"boolean"},"fifteenDays":{"type":"boolean"},"sevenDays":{"type":"boolean"},"oneDay":{"type":"boolean"}}},"domainMonitoringEnabled":{"type":"boolean","description":"Plan feature (domainMonitoring) and count limit."},"domainExpiryThreshold":{"type":"integer","nullable":true,"description":"Days."},"securityAnalysisEnabled":{"type":"boolean","description":"Plan feature (securityHeaders)."},"securityAnalysisMode":{"type":"string","example":"basic"},"alertTypes":{"type":"array","items":{"type":"string"},"example":["down","recovery"]},"notifications":{"type":"object","description":"Channel × alert type switches, e.g. {\"email\":{\"down\":true,\"recovery\":true},\"sms\":{\"down\":true}}.","additionalProperties":{"type":"object","additionalProperties":{"type":"boolean"}}},"emailAddresses":{"type":"string","description":"Comma-separated."},"phoneNumbers":{"type":"string","nullable":true,"description":"Comma-separated E.164 (SMS)."},"whatsappNumbers":{"type":"string","nullable":true},"voiceNumbers":{"type":"string","nullable":true},"voiceMode":{"type":"string","enum":["sequential","all"],"default":"sequential"},"escalationPolicyId":{"type":"string","nullable":true,"description":"Public id from GET /api/v1/escalation-policies (one you created). PATCH null detaches. On-call is a plan feature.","example":"01J9ZP4M3K8Q5R6S7T8V9W0X1Y"},"selectedWebhookIds":{"type":"array","items":{"type":"string"},"description":"Public ids from GET /api/v1/webhooks (your own). [] detaches all."},"maintenanceWindows":{"type":"array","items":{"type":"object"},"description":"Also managed with /api/v1/monitors/{id}/maintenance."},"heartbeatIntervalSeconds":{"type":"integer","minimum":60,"maximum":2592000,"description":"Heartbeat only. Defaults to interval (at least 60)."},"heartbeatGraceSeconds":{"type":"integer","minimum":0,"maximum":2592000,"default":60},"heartbeatToken":{"type":"string","nullable":true,"description":"Heartbeat monitors, editors only."},"heartbeatUrl":{"type":"string","nullable":true,"description":"POST here on success; POST .../fail (same token) on failure.","example":"https://app.uptimewarden.online/api/heartbeat/01J9ZP4M3K8Q5R6S7T8V9W0X1Y/ping"},"heartbeatLastPingAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"},"lastChecked":{"type":"string","format":"date-time","nullable":true}}},"MonitorCreate":{"type":"object","required":["name","type"],"description":"url is required except for heartbeat monitors. Unknown fields are a 400 naming the field.","properties":{"name":{"type":"string","example":"Production API"},"type":{"type":"string","enum":["http","tcp","udp","ssl","websocket","mcp","grpc","ping","dns","heartbeat"],"description":"Must also be in your plan. Cannot be changed to or from heartbeat.","example":"http"},"url":{"type":"string","description":"Target. Not sent for heartbeat monitors (the server sets heartbeat://<token>).","example":"https://api.example.com/health"},"description":{"type":"string","nullable":true},"interval":{"type":"integer","minimum":30,"default":300,"description":"Check interval in seconds; at least your plan minimum."},"timeout":{"type":"integer","minimum":5,"maximum":300,"default":30,"description":"Seconds."},"isActive":{"type":"boolean","default":true,"description":"Switching a paused monitor on counts against your plan."},"tags":{"type":"array","items":{"type":"string"}},"externalId":{"type":"string","maxLength":255,"nullable":true,"description":"Your stable handle (e.g. Terraform address). PATCH \"\" clears it."},"managedBySource":{"type":"string","default":"manual","example":"terraform"},"region":{"type":"string","description":"Primary region code from GET /api/v1/regions. Choosing one needs regionSelection on your plan.","example":"gwc"},"verificationRegions":{"type":"array","items":{"type":"string"},"description":"Regions that recheck an outage before it is alerted. Active codes only, not the primary, at most maxVerificationRegions - 1. Empty = nearest regions. Must be empty for heartbeat and agent monitors."},"minConfirmingRegions":{"type":"integer","minimum":1,"description":"Regions that must confirm a DOWN. Other than the plan default needs allowConsensusOverride."},"agentId":{"type":"string","nullable":true,"description":"One of your private agents; \"\" or \"server\" = our regions."},"method":{"type":"string","example":"GET","description":"HTTP method."},"customHeaders":{"type":"object","additionalProperties":{"type":"string"}},"requestBody":{"type":"string","nullable":true},"expectedStatusCodes":{"type":"string","example":"200-299"},"expectedBody":{"type":"string","nullable":true,"description":"Keyword the response body must contain."},"contentValidation":{"type":"object","nullable":true},"followRedirects":{"type":"boolean","default":true},"verifySsl":{"type":"boolean","default":true},"enableSsl":{"type":"boolean","default":true},"basicAuthUsername":{"type":"string","nullable":true},"basicAuthPassword":{"type":"string","nullable":true,"description":"Returned only to callers who may edit the monitor."},"bearerToken":{"type":"string","nullable":true,"description":"Returned only to callers who may edit the monitor."},"hostname":{"type":"string","nullable":true},"port":{"type":"integer","nullable":true,"description":"TCP / UDP port."},"grpcProtoFile":{"type":"string","nullable":true},"grpcMethod":{"type":"string","nullable":true},"dnsConfig":{"type":"object","nullable":true,"properties":{"recordType":{"type":"string","enum":["A","AAAA","CNAME","MX","NS","TXT"]},"resolver":{"type":"string"},"expectedAnswers":{"type":"array","items":{"type":"string"}}}},"retryCount":{"type":"integer","nullable":true},"responseTimeThreshold":{"type":"integer","nullable":true,"minimum":50,"maximum":5000,"description":"ms; 0 or null = off."},"sslExpiryDays":{"type":"integer","default":30},"sslAlerts":{"type":"object","properties":{"thirtyDays":{"type":"boolean"},"fifteenDays":{"type":"boolean"},"sevenDays":{"type":"boolean"},"oneDay":{"type":"boolean"}}},"domainMonitoringEnabled":{"type":"boolean","description":"Plan feature (domainMonitoring) and count limit."},"domainExpiryThreshold":{"type":"integer","nullable":true,"description":"Days."},"securityAnalysisEnabled":{"type":"boolean","description":"Plan feature (securityHeaders)."},"securityAnalysisMode":{"type":"string","example":"basic"},"alertTypes":{"type":"array","items":{"type":"string"},"example":["down","recovery"]},"notifications":{"type":"object","description":"Channel × alert type switches, e.g. {\"email\":{\"down\":true,\"recovery\":true},\"sms\":{\"down\":true}}.","additionalProperties":{"type":"object","additionalProperties":{"type":"boolean"}}},"emailAddresses":{"type":"string","description":"Comma-separated."},"phoneNumbers":{"type":"string","nullable":true,"description":"Comma-separated E.164 (SMS)."},"whatsappNumbers":{"type":"string","nullable":true},"voiceNumbers":{"type":"string","nullable":true},"voiceMode":{"type":"string","enum":["sequential","all"],"default":"sequential"},"escalationPolicyId":{"type":"string","nullable":true,"description":"Public id from GET /api/v1/escalation-policies (one you created). PATCH null detaches. On-call is a plan feature.","example":"01J9ZP4M3K8Q5R6S7T8V9W0X1Y"},"selectedWebhookIds":{"type":"array","items":{"type":"string"},"description":"Public ids from GET /api/v1/webhooks (your own). [] detaches all."},"maintenanceWindows":{"type":"array","items":{"type":"object"},"description":"Also managed with /api/v1/monitors/{id}/maintenance."},"heartbeatIntervalSeconds":{"type":"integer","minimum":60,"maximum":2592000,"description":"Heartbeat only. Defaults to interval (at least 60)."},"heartbeatGraceSeconds":{"type":"integer","minimum":0,"maximum":2592000,"default":60}}},"MonitorUpdate":{"type":"object","description":"Partial update: only the fields sent change. Plan gates judge only what changes, against the owner's plan.","properties":{"name":{"type":"string","example":"Production API"},"type":{"type":"string","enum":["http","tcp","udp","ssl","websocket","mcp","grpc","ping","dns","heartbeat"],"description":"Must also be in your plan. Cannot be changed to or from heartbeat.","example":"http"},"url":{"type":"string","description":"Target. Not sent for heartbeat monitors (the server sets heartbeat://<token>).","example":"https://api.example.com/health"},"description":{"type":"string","nullable":true},"interval":{"type":"integer","minimum":30,"default":300,"description":"Check interval in seconds; at least your plan minimum."},"timeout":{"type":"integer","minimum":5,"maximum":300,"default":30,"description":"Seconds."},"isActive":{"type":"boolean","default":true,"description":"Switching a paused monitor on counts against your plan."},"tags":{"type":"array","items":{"type":"string"}},"groups":{"type":"array","items":{"type":"string"},"description":"PATCH only. Group names."},"externalId":{"type":"string","maxLength":255,"nullable":true,"description":"Your stable handle (e.g. Terraform address). PATCH \"\" clears it."},"managedBySource":{"type":"string","default":"manual","example":"terraform"},"region":{"type":"string","description":"Primary region code from GET /api/v1/regions. Choosing one needs regionSelection on your plan.","example":"gwc"},"verificationRegions":{"type":"array","items":{"type":"string"},"description":"Regions that recheck an outage before it is alerted. Active codes only, not the primary, at most maxVerificationRegions - 1. Empty = nearest regions. Must be empty for heartbeat and agent monitors."},"minConfirmingRegions":{"type":"integer","minimum":1,"description":"Regions that must confirm a DOWN. Other than the plan default needs allowConsensusOverride."},"agentId":{"type":"string","nullable":true,"description":"One of your private agents; \"\" or \"server\" = our regions."},"method":{"type":"string","example":"GET","description":"HTTP method."},"customHeaders":{"type":"object","additionalProperties":{"type":"string"}},"requestBody":{"type":"string","nullable":true},"expectedStatusCodes":{"type":"string","example":"200-299"},"expectedBody":{"type":"string","nullable":true,"description":"Keyword the response body must contain."},"contentValidation":{"type":"object","nullable":true},"followRedirects":{"type":"boolean","default":true},"verifySsl":{"type":"boolean","default":true},"enableSsl":{"type":"boolean","default":true},"basicAuthUsername":{"type":"string","nullable":true},"basicAuthPassword":{"type":"string","nullable":true,"description":"Returned only to callers who may edit the monitor."},"bearerToken":{"type":"string","nullable":true,"description":"Returned only to callers who may edit the monitor."},"hostname":{"type":"string","nullable":true},"port":{"type":"integer","nullable":true,"description":"TCP / UDP port."},"grpcProtoFile":{"type":"string","nullable":true},"grpcMethod":{"type":"string","nullable":true},"dnsConfig":{"type":"object","nullable":true,"properties":{"recordType":{"type":"string","enum":["A","AAAA","CNAME","MX","NS","TXT"]},"resolver":{"type":"string"},"expectedAnswers":{"type":"array","items":{"type":"string"}}}},"retryCount":{"type":"integer","nullable":true},"responseTimeThreshold":{"type":"integer","nullable":true,"minimum":50,"maximum":5000,"description":"ms; 0 or null = off."},"sslExpiryDays":{"type":"integer","default":30},"sslAlerts":{"type":"object","properties":{"thirtyDays":{"type":"boolean"},"fifteenDays":{"type":"boolean"},"sevenDays":{"type":"boolean"},"oneDay":{"type":"boolean"}}},"domainMonitoringEnabled":{"type":"boolean","description":"Plan feature (domainMonitoring) and count limit."},"domainExpiryThreshold":{"type":"integer","nullable":true,"description":"Days."},"securityAnalysisEnabled":{"type":"boolean","description":"Plan feature (securityHeaders)."},"securityAnalysisMode":{"type":"string","example":"basic"},"alertTypes":{"type":"array","items":{"type":"string"},"example":["down","recovery"]},"notifications":{"type":"object","description":"Channel × alert type switches, e.g. {\"email\":{\"down\":true,\"recovery\":true},\"sms\":{\"down\":true}}.","additionalProperties":{"type":"object","additionalProperties":{"type":"boolean"}}},"emailAddresses":{"type":"string","description":"Comma-separated."},"phoneNumbers":{"type":"string","nullable":true,"description":"Comma-separated E.164 (SMS)."},"whatsappNumbers":{"type":"string","nullable":true},"voiceNumbers":{"type":"string","nullable":true},"voiceMode":{"type":"string","enum":["sequential","all"],"default":"sequential"},"escalationPolicyId":{"type":"string","nullable":true,"description":"Public id from GET /api/v1/escalation-policies (one you created). PATCH null detaches. On-call is a plan feature.","example":"01J9ZP4M3K8Q5R6S7T8V9W0X1Y"},"selectedWebhookIds":{"type":"array","items":{"type":"string"},"description":"Public ids from GET /api/v1/webhooks (your own). [] detaches all."},"maintenanceWindows":{"type":"array","items":{"type":"object"},"description":"Also managed with /api/v1/monitors/{id}/maintenance."},"heartbeatIntervalSeconds":{"type":"integer","minimum":60,"maximum":2592000,"description":"Heartbeat only. Defaults to interval (at least 60)."},"heartbeatGraceSeconds":{"type":"integer","minimum":0,"maximum":2592000,"default":60}}},"MonitorSummary":{"type":"object","properties":{"publicId":{"type":"string","example":"01J9ZP4M3K8Q5R6S7T8V9W0X1Y"},"name":{"type":"string"},"type":{"type":"string"},"externalId":{"type":"string"},"url":{"type":"string"},"interval":{"type":"integer"},"timeout":{"type":"integer"},"isActive":{"type":"boolean"},"region":{"type":"string"},"hostname":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"managedBySource":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"latestResult":{"type":"object","nullable":true,"properties":{"status":{"type":"string"},"responseTime":{"type":"integer"},"checkedAt":{"type":"string","format":"date-time"}}},"uptime":{"type":"number"},"avgResponseTime":{"type":"number","nullable":true},"recentHistory":{"type":"array","items":{"type":"object"}},"groups":{"type":"array","items":{"type":"string"}}}},"EscalationPolicyRef":{"type":"object","properties":{"publicId":{"type":"string","example":"01J9ZP4M3K8Q5R6S7T8V9W0X1Y"},"name":{"type":"string","example":"Primary on-call"},"stepCount":{"type":"integer","example":2},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WebhookRef":{"type":"object","description":"No target URL, headers or credentials: a Slack/Teams webhook URL is itself a secret.","properties":{"publicId":{"type":"string","example":"01J9ZP4M3K8Q5R6S7T8V9W0X1Y"},"name":{"type":"string","example":"Ops Slack"},"description":{"type":"string","nullable":true},"messageFormat":{"type":"string","nullable":true},"isActive":{"type":"boolean"},"enabledAlertTypes":{"type":"array","items":{"type":"string"}},"enabledMonitorTypes":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"}}},"Region":{"type":"object","properties":{"code":{"type":"string","example":"gwc"},"name":{"type":"string","example":"Germany West Central"},"description":{"type":"string","nullable":true},"isDefault":{"type":"boolean"}}},"MonitorResult":{"type":"object","properties":{"monitorId":{"type":"string","description":"The monitor's public id","example":"01J9ZP4M3K8Q5R6S7T8V9W0X1Y"},"status":{"type":"string","enum":["up","down"],"example":"up"},"responseTime":{"type":"integer","description":"Response time in milliseconds","example":245},"statusCode":{"type":"integer","example":200},"errorMessage":{"type":"string","nullable":true,"example":null},"checkedAt":{"type":"string","format":"date-time","example":"2025-10-18T10:30:00Z"}}},"MonitorStats":{"type":"object","properties":{"uptime":{"type":"number","description":"Uptime percentage","example":99.5},"avgResponseTime":{"type":"number","description":"Average response time in milliseconds","example":245},"totalChecks":{"type":"integer","example":672},"failedChecks":{"type":"integer","example":3},"timeRange":{"type":"string","example":"7d"}}},"Incident":{"type":"object","properties":{"id":{"type":"integer","example":789},"monitorId":{"type":"integer","example":123},"monitorName":{"type":"string","example":"Production API"},"status":{"type":"string","enum":["active","resolved"],"example":"active"},"severity":{"type":"string","enum":["low","medium","high","critical"],"example":"high"},"startedAt":{"type":"string","format":"date-time","example":"2025-10-18T08:15:00Z"},"resolvedAt":{"type":"string","format":"date-time","nullable":true,"example":null},"resolutionMessage":{"type":"string","nullable":true,"example":null},"affectedChecks":{"type":"integer","example":5}}},"IncidentComment":{"type":"object","properties":{"id":{"type":"integer","example":456},"incidentId":{"type":"integer","example":789},"message":{"type":"string","example":"Investigating the issue"},"userId":{"type":"integer","example":1},"createdAt":{"type":"string","format":"date-time","example":"2025-10-18T08:20:00Z"}}},"SSLCertificate":{"type":"object","properties":{"id":{"type":"integer","example":234},"monitorId":{"type":"integer","example":123},"domain":{"type":"string","example":"api.example.com"},"issuer":{"type":"string","example":"Let's Encrypt"},"validFrom":{"type":"string","format":"date-time","example":"2025-01-01T00:00:00Z"},"validUntil":{"type":"string","format":"date-time","example":"2025-04-01T00:00:00Z"},"daysUntilExpiry":{"type":"integer","example":73},"isValid":{"type":"boolean","example":true},"checkedAt":{"type":"string","format":"date-time","example":"2025-10-18T10:30:00Z"}}},"SecurityAnalysis":{"type":"object","properties":{"id":{"type":"integer","example":567},"monitorId":{"type":"integer","example":123},"url":{"type":"string","example":"https://api.example.com"},"securityScore":{"type":"number","description":"Security score out of 100","example":85},"grade":{"type":"string","enum":["A+","A","B","C","D","F"],"example":"A"},"headers":{"type":"object","properties":{"content-security-policy":{"type":"object","properties":{"present":{"type":"boolean","example":true},"value":{"type":"string","example":"default-src 'self'"},"score":{"type":"number","example":10}}},"strict-transport-security":{"type":"object","properties":{"present":{"type":"boolean","example":true},"value":{"type":"string","example":"max-age=31536000"},"score":{"type":"number","example":10}}},"x-frame-options":{"type":"object","properties":{"present":{"type":"boolean","example":true},"value":{"type":"string","example":"DENY"},"score":{"type":"number","example":5}}}}},"vulnerabilities":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["low","medium","high","critical"],"example":"medium"},"title":{"type":"string","example":"Missing X-Content-Type-Options header"},"description":{"type":"string","example":"This header prevents MIME type sniffing"},"recommendation":{"type":"string","example":"Add X-Content-Type-Options: nosniff header"}}}},"analyzedAt":{"type":"string","format":"date-time","example":"2025-10-18T10:30:00Z"}}},"HealthPrediction":{"type":"object","properties":{"id":{"type":"integer","example":890},"monitorId":{"type":"integer","example":123},"predictionType":{"type":"string","enum":["anomaly","trend","forecast"],"example":"anomaly"},"confidence":{"type":"number","description":"Confidence level (0-1)","example":0.87},"prediction":{"type":"object","properties":{"riskLevel":{"type":"string","enum":["low","medium","high","critical"],"example":"medium"},"description":{"type":"string","example":"Response time trending upward"},"metrics":{"type":"object","properties":{"currentAvg":{"type":"number","example":245},"predictedAvg":{"type":"number","example":310},"changePercent":{"type":"number","example":26.5}}},"recommendations":{"type":"array","items":{"type":"string"},"example":["Monitor CPU usage on server","Check database query performance","Review recent code deployments"]}}},"predictedAt":{"type":"string","format":"date-time","example":"2025-10-18T10:30:00Z"}}}}},"paths":{"/api/v1/monitors":{"get":{"summary":"List all monitors","description":"Get all monitors accessible to the API token owner with pagination support","tags":["API v1 - Monitors"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Items per page"},{"in":"query","name":"managedBySource","schema":{"type":"string","example":"terraform"},"description":"Only monitors with this managedBySource"}],"responses":{"200":{"description":"Monitors you own or that are shared with you (summary form; GET /api/v1/monitors/{id} for every field)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/MonitorSummary"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"description":"Unauthorized - Invalid API token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"summary":"Create a new monitor","description":"Creates a monitor with the same validation, defaults and plan limits as the dashboard. Requires monitors:create. Heartbeat monitors get heartbeatToken / heartbeatUrl in the response.","tags":["API v1 - Monitors"],"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorCreate"}}}},"responses":{"201":{"description":"Monitor created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Monitor"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"PLAN_LIMIT_REACHED (count, type, interval, region, verification, feature) or ACCESS_DENIED (an escalation policy / webhook that is not yours)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/monitors/{id}":{"get":{"summary":"Get a monitor","description":"Every field of a monitor you own or that is shared with you. Credentials (basicAuthPassword, bearerToken, heartbeatToken, heartbeatUrl) are null unless you may edit it. Requires monitors:read.","tags":["API v1 - Monitors"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"description":"Monitor publicId (ULID). Internal numeric ids are refused."}],"responses":{"200":{"description":"The monitor","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Monitor"}}}}}},"400":{"description":"INVALID_MONITOR_ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"ACCESS_DENIED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"MONITOR_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"summary":"Update a monitor","description":"Partial update with the dashboard's rules. Needs edit access (owner or edit-level team share) and monitors:create. Plan gates judge only what changes, against the owner's plan.","tags":["API v1 - Monitors"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"description":"Monitor publicId (ULID). Internal numeric ids are refused."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorUpdate"}}}},"responses":{"200":{"description":"The updated monitor","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Monitor"}}}}}},"400":{"description":"VALIDATION_ERROR (the message names the field)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"ACCESS_DENIED or PLAN_LIMIT_REACHED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"MONITOR_NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"summary":"Delete a monitor","description":"Permanently delete a monitor and all its associated data. Needs edit access and monitors:delete.","tags":["API v1 - Monitors"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"description":"Monitor publicId (ULID). Internal numeric ids are refused."}],"responses":{"200":{"description":"Monitor deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Monitor deleted successfully"}}}}}},"403":{"description":"Not authorized to delete this monitor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Monitor not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/monitors/{id}/results":{"get":{"summary":"Get monitor check results","description":"\nRetrieve historical check results for a monitor.\n**Limited to 7 days of history for API tokens.**\n\nMultiple time range options:\n- **timeRange**: Quick presets (24h, 7d)\n- **startDate & endDate**: Specific date range (ISO 8601)\n- **since**: Results since a specific date\n- **days**: Number of days back from now\n\n**Examples:**\n- `?timeRange=24h` - Last 24 hours\n- `?startDate=2025-10-11T00:00:00Z&endDate=2025-10-18T00:00:00Z` - Specific week\n- `?days=5` - Last 5 days\n            ","tags":["API v1 - Monitors"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"description":"Monitor publicId (ULID). Internal numeric ids are refused."},{"in":"query","name":"timeRange","schema":{"type":"string","enum":["24h","7d"],"default":"24h"},"description":"Time range preset (maximum 7 days)"},{"in":"query","name":"startDate","schema":{"type":"string","format":"date-time"},"description":"Start date (ISO 8601). Max 7-day range."},{"in":"query","name":"endDate","schema":{"type":"string","format":"date-time"},"description":"End date (ISO 8601). Max 7-day range."},{"in":"query","name":"since","schema":{"type":"string","format":"date-time"},"description":"Get results since this date (max 7 days ago)"},{"in":"query","name":"days","schema":{"type":"integer","minimum":1,"maximum":7},"description":"Number of days back from now (maximum 7)"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":1000,"default":100},"description":"Maximum number of results"}],"responses":{"200":{"description":"Successfully retrieved results","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/MonitorResult"}},"meta":{"type":"object","properties":{"monitorId":{"type":"string","example":"01J9ZP4M3K8Q5R6S7T8V9W0X1Y"},"timeRange":{"type":"string","example":"7d"},"count":{"type":"integer","example":672},"limitation":{"type":"string","example":"API tokens are limited to 7 days of historical data"}}}}}}}},"403":{"description":"Time range exceeds 7 days","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"TIME_RANGE_EXCEEDED","message":"Time range exceeds maximum allowed","details":["Requested: 10 days","Maximum allowed: 7 days"]}}}}}}}},"/api/v1/monitors/{id}/stats":{"get":{"summary":"Get monitor statistics","description":"Get uptime and performance statistics for a monitor. Limited to 7 days of history.","tags":["API v1 - Monitors"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{26}$"},"description":"Monitor publicId (ULID). Internal numeric ids are refused."},{"in":"query","name":"timeRange","schema":{"type":"string","enum":["24h","7d"],"default":"7d"}}],"responses":{"200":{"description":"Successfully retrieved statistics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/MonitorStats"}}}}}}}}},"/api/v1/escalation-policies":{"get":{"summary":"List escalation policies","description":"Escalation policies you created: the ones escalationPolicyId accepts. Requires monitors:read.","tags":["API v1 - References"],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/EscalationPolicyRef"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions (monitors:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/webhooks":{"get":{"summary":"List webhooks","description":"Your webhook configs: the ones selectedWebhookIds accepts. Requires monitors:read.","tags":["API v1 - References"],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookRef"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions (monitors:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/regions":{"get":{"summary":"List monitoring regions","description":"Active region codes (for region and verificationRegions) and your plan's allowance. Requires monitors:read.","tags":["API v1 - References"],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Region"}},"plan":{"type":"object","description":"What your plan lets a monitor use (-1 = unlimited)","properties":{"regionSelection":{"type":"boolean"},"maxRegions":{"type":"integer"},"maxVerificationRegions":{"type":"integer"},"defaultConfirmingRegions":{"type":"integer"},"allowConsensusOverride":{"type":"boolean"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions (monitors:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/heartbeat/{token}/ping":{"post":{"summary":"Heartbeat success ping","description":"Your job ran. GET works too. {\"state\":\"failure\"} (or ?state=failure) records a failure instead.","tags":["Heartbeat"],"security":[],"parameters":[{"in":"path","name":"token","required":true,"schema":{"type":"string"},"description":"heartbeatToken of the monitor"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"state":{"type":"string","enum":["success","failure"],"description":"failure records a failure like /fail"},"message":{"type":"string","maxLength":500,"description":"Shown as the incident error message on failure"}}}}}},"responses":{"204":{"description":"Recorded"},"404":{"description":"unknown token (text/plain)"},"429":{"description":"rate limited (120/min per token and IP)"},"503":{"description":"temporarily unavailable; retry"}}}},"/api/heartbeat/{token}/fail":{"post":{"summary":"Heartbeat failure signal","description":"Your job ran and failed: the monitor goes down on the next evaluation (within 30 s) instead of after interval + grace. The next successful ping recovers it. GET works too.","tags":["Heartbeat"],"security":[],"parameters":[{"in":"path","name":"token","required":true,"schema":{"type":"string"},"description":"heartbeatToken of the monitor"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","maxLength":500,"description":"Shown as the incident error message on failure"}}}}}},"responses":{"204":{"description":"Recorded"},"404":{"description":"unknown token (text/plain)"},"429":{"description":"rate limited (120/min per token and IP)"},"503":{"description":"temporarily unavailable; retry"}}}},"/api/v1/incidents":{"get":{"summary":"List incidents","description":"Get incidents for monitors owned by API token user. Limited to 30 days of historical data.","tags":["API v1 - Incidents"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"query","name":"timeRange","schema":{"type":"string","enum":["24h","7d","30d"],"default":"7d"}},{"in":"query","name":"status","schema":{"type":"string","enum":["active","resolved","all"],"default":"all"}},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Successfully retrieved incidents","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Incident"}},"pagination":{"$ref":"#/components/schemas/Pagination"},"meta":{"type":"object","properties":{"limitation":{"type":"string","example":"API tokens are limited to 30 days of historical data"}}}}}}}}}}},"/api/v1/incidents/{id}":{"patch":{"summary":"Update incident","description":"Update incident status or add resolution message","tags":["API v1 - Incidents"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","resolved"]},"resolutionMessage":{"type":"string"}}}}}},"responses":{"200":{"description":"Incident updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Incident"}}}}}}}}},"/api/v1/incidents/{id}/comments":{"post":{"summary":"Add comment to incident","description":"Add a comment/update to an incident for tracking resolution progress","tags":["API v1 - Incidents"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","example":"Investigating the issue"}}}}}},"responses":{"201":{"description":"Comment added successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/IncidentComment"}}}}}}}}},"/api/v1/ssl/status":{"get":{"summary":"Get SSL status for all monitors","description":"Returns SSL certificate information for all user monitors","tags":["API v1 - SSL"],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Successfully retrieved SSL status","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/SSLCertificate"}}}}}}}}}},"/api/v1/ssl/monitors/{id}":{"get":{"summary":"Get SSL status for specific monitor","description":"Returns detailed SSL certificate information for a specific monitor","tags":["API v1 - SSL"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Successfully retrieved SSL status","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SSLCertificate"}}}}}}}}},"/api/v1/security/monitors/{id}/analysis":{"get":{"summary":"Get security analysis for monitor","description":"Returns security headers and vulnerability analysis for a monitor","tags":["API v1 - Security"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Successfully retrieved security analysis","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SecurityAnalysis"}}}}}}}}},"/api/v1/security/monitors/{id}/analyze":{"post":{"summary":"Run security analysis on monitor","description":"Performs fresh security analysis on the monitor endpoint","tags":["API v1 - Security"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Security analysis completed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SecurityAnalysis"},"message":{"type":"string","example":"Security analysis completed"}}}}}}}}},"/api/v1/security/analyze":{"post":{"summary":"Run security analysis on any website","description":"Performs security analysis on any provided URL (not limited to monitors)","tags":["API v1 - Security"],"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","example":"https://example.com"}}}}}},"responses":{"200":{"description":"Security analysis completed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SecurityAnalysis"},"message":{"type":"string","example":"Security analysis completed"}}}}}}}}},"/api/v1/health/monitors/{id}/predictions":{"get":{"summary":"Get AI health predictions for monitor","description":"Returns AI-powered health predictions and anomaly detection for a monitor","tags":["API v1 - Health Predictions"],"security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Successfully retrieved health predictions","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"anyOf":[{"$ref":"#/components/schemas/HealthPrediction"},{"type":"null"}]},"message":{"type":"string"},"details":{"type":"array","items":{"type":"string"}}}}}}}}}}}}