{"openapi":"3.1.0","info":{"title":"Uptrack Public API","description":"","license":{"name":"Apache-2.0","identifier":"Apache-2.0"},"version":"2.0.0"},"paths":{"/api/alert-channels":{"get":{"tags":["alert-channels"],"summary":"`GET /api/alert-channels` — the authenticated org's alert channels. Secret\nconfig values are masked (`••••` + last 4) and each channel carries a\n`config_fingerprint` of the real config.","operationId":"get_api_alert_channels","responses":{"200":{"description":"Org alert channels (no config secrets)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertChannelListResponse"}}}},"401":{"description":""}}},"post":{"tags":["alert-channels"],"summary":"`POST /api/alert-channels` — create a channel.","operationId":"create_api_alert_channel","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlertChannel"}}},"required":true},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertChannelOut"}}}},"401":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/alert-channels/allowed-types":{"get":{"tags":["alert-channels"],"summary":"`GET /api/alert-channels/allowed-types` — the alert-channel types the\nauthenticated org may use, plus its plan name. Port of\n`AlertChannelController.allowed_types`.","operationId":"get_api_alert_channels_allowed_types","responses":{"200":{"description":"Allowed channel types + plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllowedTypesResponse"}}}},"401":{"description":""}}}},"/api/alert-channels/usage":{"get":{"tags":["alert-channels"],"summary":"`GET /api/alert-channels/usage` — SMS and call counts this month vs the plan\nlimits, for the dashboard (\"12 of 20 SMS used\"). Counters that cannot be read\n(table or column not migrated yet) show 0, matching the fail-open send path.","operationId":"get_api_alert_channels_usage","responses":{"200":{"description":"SMS and call usage this month","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsVoiceUsageResponse"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/alert-channels/{id}":{"delete":{"tags":["alert-channels"],"summary":"`DELETE /api/alert-channels/{id}`.","operationId":"delete_api_alert_channel","parameters":[{"name":"id","in":"path","description":"Alert channel id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"patch":{"tags":["alert-channels"],"summary":"`PATCH /api/alert-channels/{id}` — partial update.","operationId":"update_api_alert_channel","parameters":[{"name":"id","in":"path","description":"Alert channel id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlertChannel"}}},"required":true},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertChannelOut"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/alert-channels/{id}/test":{"post":{"tags":["alert-channels"],"summary":"`POST /api/alert-channels/{id}/test` — send a test notification through\nthe channel. Ports Phoenix `AlertChannelController.test` +\n`Alerting.send_test_alert/1`, reusing the same `uptrack-notifications`\ndelivery path real alerts use. Org-scoped (404 if not owned). A delivery\nfailure returns `{ok:false, error}` with HTTP 200 — never a 5xx — per the\n\"never raise on delivery failure\" contract.","operationId":"test_api_alert_channel","parameters":[{"name":"id","in":"path","description":"Alert channel id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Test delivery result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertChannelTestResult"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/analytics/dashboard":{"get":{"tags":["analytics"],"summary":"`GET /api/analytics/dashboard?days` — overview stats + org uptime trend.","operationId":"get_api_analytics_dashboard","parameters":[{"name":"days","in":"query","description":"Window in days (1..=365, default 30)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Dashboard analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardAnalyticsOut"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/analytics/monitors/{monitor_id}":{"get":{"tags":["analytics"],"summary":"`GET /api/analytics/monitors/{monitor_id}?days` — per-monitor analytics\n(uptime chart + response-time series + percentiles + incident stats).","operationId":"get_api_analytics_monitors_id","parameters":[{"name":"monitor_id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"days","in":"query","description":"Window in days (default 30, clamped to the plan's retention)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Monitor analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorAnalyticsOut"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/analytics/monitors/{monitor_id}/locations":{"get":{"tags":["analytics"],"summary":"`GET /api/analytics/monitors/{monitor_id}/locations?days` — history per selected location.","operationId":"get_api_analytics_monitors_monitor_id_locations","parameters":[{"name":"monitor_id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"days","in":"query","description":"Window in days (default 30, clamped to the plan's retention)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"History per location","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationHistoryOut"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/analytics/organization/trends":{"get":{"tags":["analytics"],"summary":"`GET /api/analytics/organization/trends?days` — org-wide trends.","operationId":"get_api_analytics_organization_trends","parameters":[{"name":"days","in":"query","description":"Window in days (1..=365, default 30)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Organization trends","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgTrendsOut"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/api-keys":{"get":{"tags":["api-keys"],"summary":"`GET /api/api-keys` — the authenticated org's API keys (metadata only).","operationId":"get_api_api_keys","responses":{"200":{"description":"Org API keys (metadata only, no secret)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyListResponse"}}}},"401":{"description":""},"403":{"description":""}},"security":[{"session":[]}]},"post":{"tags":["api-keys"],"summary":"`POST /api/api-keys` — create a key; returns the raw token ONCE.","operationId":"create_api_api_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKey"}}},"required":true},"responses":{"201":{"description":"Created (raw_key shown once)"},"401":{"description":""},"403":{"description":""},"422":{"description":""}},"security":[{"session":[]}]}},"/api/api-keys/{id}":{"delete":{"tags":["api-keys"],"summary":"`DELETE /api/api-keys/{id}`.","operationId":"delete_api_api_key","parameters":[{"name":"id","in":"path","description":"API key id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted"},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"session":[]}]}},"/api/api-keys/{id}/revoke":{"post":{"tags":["api-keys"],"summary":"`POST /api/api-keys/{id}/revoke` — deactivate (does not delete).","operationId":"revoke_api_api_key","parameters":[{"name":"id","in":"path","description":"API key id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Revoked"},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"session":[]}]}},"/api/audit-logs":{"get":{"tags":["audit-logs"],"summary":"`GET /api/audit-logs` — the authenticated admin's org audit log, newest\nfirst. Filters: `?action=`, `?user_id=`, `?since=` (RFC3339), `?limit=`\n(default 50, max 200), `?offset=`.","operationId":"get_api_audit_logs","parameters":[{"name":"limit","in":"query","description":"Page size (default 50, max 200)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"offset","in":"query","description":"Offset (default 0)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"action","in":"query","description":"Filter by action","required":false,"schema":{"type":"string"}},{"name":"user_id","in":"query","description":"Filter by acting user","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"since","in":"query","description":"RFC3339 lower bound on created_at","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Org audit log (paginated)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogListResponse"}}}},"401":{"description":""},"403":{"description":""}}}},"/api/auth/2fa/status":{"get":{"tags":["auth"],"summary":"`GET /api/auth/2fa/status` — whether 2FA (TOTP) is enabled for the current\nuser. Port of `TwoFactorController.status`.","operationId":"get_api_auth_2fa_status","responses":{"200":{"description":"2FA status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorStatus"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/auth/connected-apps":{"get":{"tags":["auth"],"summary":"`GET /api/auth/connected-apps` — the apps the signed-in user has connected (live grants).","operationId":"get_api_auth_connected_apps","responses":{"200":{"description":"Connected apps","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectedAppsOut"}}}},"401":{"description":""},"403":{"description":""}},"security":[{"session":[]}]}},"/api/auth/connected-apps/{client_id}":{"delete":{"tags":["auth"],"summary":"`DELETE /api/auth/connected-apps/{client_id}` — disconnect an app: revoke its grant.\nAnswers 204 whether or not the user had a grant, so it can be repeated.","operationId":"delete_api_auth_connected_apps_client_id","parameters":[{"name":"client_id","in":"path","description":"OAuth client id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Disconnected"},"401":{"description":""},"403":{"description":""}},"security":[{"session":[]}]}},"/api/auth/device-tokens":{"get":{"tags":["auth"],"summary":"`GET /api/auth/device-tokens` — the caller's live (unrevoked) tokens.","operationId":"get_api_auth_device_tokens","responses":{"200":{"description":"Caller device tokens (metadata only)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceTokenListResponse"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"post":{"tags":["auth"],"summary":"`POST /api/auth/device-tokens` — issue a device token for the session\nuser. Session-cookie auth ONLY (an API key must not mint device tokens);\nreturns the raw token once alongside the new row's id/label.","operationId":"create_api_auth_device_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceToken"}}},"required":true},"responses":{"201":{"description":"Issued (raw token shown once)"},"401":{"description":""},"403":{"description":""}},"security":[{"session":[]}]}},"/api/auth/device-tokens/{id}":{"delete":{"tags":["auth"],"summary":"`DELETE /api/auth/device-tokens/{id}` — owner-only soft-revoke\n(`revoked_at`); unknown/already-revoked/foreign ids → 404 (no oracle).","operationId":"delete_api_auth_device_token","parameters":[{"name":"id","in":"path","description":"Device token id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Revoked"},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/auth/logout":{"post":{"tags":["auth"],"summary":"`POST /api/auth/logout` — clear the Phoenix session cookie. Port of `logout`.","operationId":"post_api_auth_logout","responses":{"200":{"description":"Logged out"}}}},"/api/auth/me":{"get":{"tags":["auth"],"summary":"`GET /api/auth/me` — current user + organization. Port of `AuthController.me`.\nOn an impersonation session the `user`/`organization` are the *target's*, plus\n`impersonating_admin` + `impersonation_expires_at` so the dashboard can render\nthe \"Impersonating …\" banner and the \"Exit\" control.","operationId":"get_api_auth_me","responses":{"200":{"description":"Current user + org"},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/auth/providers":{"get":{"tags":["auth"],"summary":"`GET /api/auth/providers` — which login providers are configured (email is\nalways on; github/google gated by env client-id). Port of `providers`.","operationId":"get_api_auth_providers","responses":{"200":{"description":"Configured providers"}}}},"/api/auth/sso/config":{"get":{"tags":["auth"],"summary":"`GET /api/auth/sso/config` — {data: SsoConfig | null}. Port of SamlController.show.","operationId":"get_api_auth_sso_config","responses":{"200":{"description":"SSO config (or null)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoConfigResponse"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/billing/add-ons":{"get":{"tags":["billing"],"summary":"`GET /api/billing/add-ons` — current add-ons + monthly cost + catalog.","operationId":"get_api_billing_add_ons","responses":{"200":{"description":"Add-ons + monthly cost + catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddOnsResponse"}}}},"401":{"description":""},"402":{"description":"Add-ons require a paid plan"}},"security":[{"api_key":[]},{"session":[]}]}},"/api/billing/apple/transactions":{"post":{"tags":["billing"],"summary":"`POST /api/billing/apple/transactions` — record a StoreKit 2 purchase or\nrestore for the caller's organization. Owner only (D8); one live\nsubscription per organization (D7); idempotent on `originalTransactionId`.","operationId":"post_api_billing_apple_transactions","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppleTransactionRequest"}}},"required":true},"responses":{"200":{"description":"Subscription stored; same body as GET /api/billing/subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionResponse"}}}},"401":{"description":""},"403":{"description":"`{\"error_code\": \"not_owner\"}`"},"404":{"description":"APPLE_IAP_ENABLED is off"},"409":{"description":"`{\"error_code\": \"subscription_exists\", \"provider\": \"paddle\"}` (D7)"},"422":{"description":"`{\"error_code\": \"invalid_transaction\"}`, or `{\"error_code\": \"sandbox_not_allowed\"}` for a Sandbox purchase by an organization not on APPLE_IAP_SANDBOX_ORGS"}},"security":[{"api_key":[]},{"session":[]}]}},"/api/billing/downgrade-preview":{"get":{"tags":["billing"],"summary":"`GET /api/billing/downgrade-preview` — what a downgrade to free would pause.\n`select_excess_monitors`: active monitors past the free limit, oldest kept\n(ORDER BY inserted_at ASC OFFSET limit). Port of\n`BillingController.downgrade_preview` + `Monitoring.select_excess_monitors`.","operationId":"get_api_billing_downgrade_preview","responses":{"200":{"description":"Downgrade preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DowngradePreviewOut"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/billing/popular-plan":{"get":{"tags":["billing"],"summary":"`GET /api/billing/popular-plan` — the most common plan across orgs (pricing\npage social proof). Public. Port of `BillingController.popular_plan`.","operationId":"get_api_billing_popular_plan","responses":{"200":{"description":"Most popular plan"}}}},"/api/billing/subscription":{"get":{"tags":["billing"],"summary":"`GET /api/billing/subscription` — the org's active subscription (or null) +\nthe org's current plan. Port of `BillingController.subscription`.","operationId":"get_api_billing_subscription","responses":{"200":{"description":"Active subscription + plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionResponse"}}}},"401":{"description":""}}}},"/api/custom-sender":{"get":{"tags":["auth"],"summary":"`GET /api/custom-sender` — the org's sender (or null). Port of\nCustomSenderController.show.","operationId":"get_api_custom_sender","responses":{"200":{"description":"Custom sender (or null)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomSenderResponse"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/custom-sender/verify/{token}":{"get":{"tags":["auth"],"summary":"`GET /api/custom-sender/verify/{token}` — public; the token IS the\ncredential. Ports `CustomSenderController.verify` + `CustomSenders.verify_token`:\nmarks the sender verified and clears the token (single-use). 404 if the\ntoken is unknown or already used.","operationId":"verify_api_custom_sender","parameters":[{"name":"token","in":"path","description":"Verification token","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Verified"},"404":{"description":"Invalid or used token"}}}},"/api/dashboard/stats":{"get":{"tags":["misc"],"summary":"`GET /api/dashboard/stats` — org dashboard counts. Port of\n`DashboardController.stats` + `Monitoring.get_dashboard_stats`.","operationId":"get_api_dashboard_stats","responses":{"200":{"description":"Org dashboard stats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardStatsResponse"}}}},"401":{"description":""}}}},"/api/escalation-policies":{"get":{"tags":["escalation-policies"],"summary":"`GET /api/escalation-policies` — the authenticated org's escalation policies,\neach with its steps (ordered by `step_order`).","operationId":"get_api_escalation_policies","responses":{"200":{"description":"Org escalation policies + steps","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationPolicyListResponse"}}}},"401":{"description":""}}},"post":{"tags":["escalation-policies"],"summary":"`POST /api/escalation-policies`.","operationId":"create_api_escalation_policy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePolicy"}}},"required":true},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationPolicyResponse"}}}},"401":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/escalation-policies/{id}":{"get":{"tags":["escalation-policies"],"summary":"`GET /api/escalation-policies/{id}` — one escalation policy + its steps,\nscoped to the authenticated org (404 if missing or another org's).","operationId":"get_api_escalation_policies_id","parameters":[{"name":"id","in":"path","description":"Escalation policy id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Escalation policy + steps","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationPolicyResponse"}}}},"401":{"description":""},"404":{"description":""}}},"delete":{"tags":["escalation-policies"],"summary":"`DELETE /api/escalation-policies/{id}` (cascades steps).","operationId":"delete_api_escalation_policy","parameters":[{"name":"id","in":"path","description":"Escalation policy id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"patch":{"tags":["escalation-policies"],"summary":"`PATCH /api/escalation-policies/{id}`.","operationId":"update_api_escalation_policy","parameters":[{"name":"id","in":"path","description":"Escalation policy id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePolicy"}}},"required":true},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationPolicyResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/incidents":{"get":{"tags":["incidents"],"summary":"`GET /api/incidents` — the authenticated org's incidents, newest first.\n`?status=ongoing` restricts to open incidents (mirrors the Phoenix branch).","operationId":"get_api_incidents","parameters":[{"name":"status","in":"query","description":"'ongoing' = open incidents only","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Org incidents (newest first)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentListResponse"}}}},"401":{"description":""}}},"post":{"tags":["incidents"],"summary":"`POST /api/incidents` — open a manual incident for an org-owned monitor.","operationId":"create_api_incident","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIncident"}}},"required":true},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentDetailResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/incidents/{id}":{"get":{"tags":["incidents"],"summary":"`GET /api/incidents/{id}` — one incident + its posted updates, scoped to the\nauthenticated org (404 if missing or another org's). Port of\n`IncidentController.show` + `Monitoring.get_incident_with_updates!`.","operationId":"get_api_incidents_id","parameters":[{"name":"id","in":"path","description":"Incident id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Incident detail + updates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentDetailResponse"}}}},"401":{"description":""},"404":{"description":""}}},"patch":{"tags":["incidents"],"summary":"`PATCH /api/incidents/{id}` — update cause/status; status=resolved resolves it.","operationId":"update_api_incident","parameters":[{"name":"id","in":"path","description":"Incident id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIncident"}}},"required":true},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentDetailResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/incidents/{id}/acknowledge":{"post":{"tags":["incidents"],"summary":"`POST /api/incidents/{id}/acknowledge` — pause escalation + auto-post an update.","operationId":"acknowledge_api_incident","parameters":[{"name":"id","in":"path","description":"Incident id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Acknowledged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentDetailResponse"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/incidents/{id}/escalate":{"post":{"tags":["incidents"],"summary":"`POST /api/incidents/{id}/escalate` — device-token Bearer auth ONLY.\nFires every not-yet-fired step of the monitor's escalation policy\nimmediately (claim + NATS publish per target channel); schedule timers\nare ignored. 404 for a foreign/unknown incident, 422 when the monitor\nhas no escalation policy (or the policy has no steps), 503 when NATS is\nunavailable for dispatch.","operationId":"post_api_incidents_id_escalate","parameters":[{"name":"id","in":"path","description":"Incident id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Escalated (or idempotent no-op)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalateResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""},"422":{"description":""},"503":{"description":""}},"security":[{"device_token":[]}]}},"/api/incidents/{id}/explain":{"post":{"tags":["incidents"],"summary":"`POST /api/incidents/{id}/explain` — AI root-cause summary, generated once\nand cached on the incident. Paid-only; inert (422) without ANTHROPIC_API_KEY.","operationId":"explain_api_incident","parameters":[{"name":"id","in":"path","description":"Incident id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExplainResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/incidents/{id}/updates":{"post":{"tags":["incidents"],"summary":"`POST /api/incidents/{id}/updates` — post an incident update (auto-resolves\nthe incident if status=resolved and it isn't already).","operationId":"create_api_incident_update","parameters":[{"name":"id","in":"path","description":"Incident id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIncidentUpdate"}}},"required":true},"responses":{"200":{"description":"Update posted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentDetailResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/invitations":{"get":{"tags":["invitations"],"summary":"`GET /api/invitations` — the org's pending (non-expired) invitations, newest\nfirst. The invite `token` is never exposed.","operationId":"get_api_invitations","responses":{"200":{"description":"Pending invitations (no token)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationListResponse"}}}},"401":{"description":""},"403":{"description":""}}}},"/api/invitations/{token}":{"get":{"tags":["invitations"],"summary":"`GET /api/invitations/{token}` — public invite-details lookup (no auth; the\ntoken IS the secret). Port of `InvitationController.show` + `Teams.get_invitation_by_token`.\nReturns 404 if unknown, 410-style 401 if expired. The token is never echoed back.","operationId":"show_api_invitation_by_token","parameters":[{"name":"token","in":"path","description":"Invitation token (secret)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Invitation details (no token)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicInvitationResponse"}}}},"401":{"description":"Invitation expired"},"404":{"description":"Invitation not found"}}}},"/api/maintenance-windows":{"get":{"tags":["maintenance-windows"],"summary":"`GET /api/maintenance-windows` — the authenticated org's maintenance windows,\nnewest first. Optional `?status=` and `?monitor_id=` filters (mirrors Phoenix).","operationId":"get_api_maintenance_windows","parameters":[{"name":"status","in":"query","description":"Filter by status","required":false,"schema":{"type":"string"}},{"name":"monitor_id","in":"query","description":"Filter to a monitor's windows","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Org maintenance windows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceWindowListResponse"}}}},"401":{"description":""}}},"post":{"tags":["maintenance-windows"],"summary":"`POST /api/maintenance-windows`.","operationId":"create_api_maintenance_window","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMaintenanceWindow"}}},"required":true},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceWindowResponse"}}}},"401":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/maintenance-windows/{id}":{"get":{"tags":["maintenance-windows"],"summary":"`GET /api/maintenance-windows/{id}` — one maintenance window, scoped to the\nauthenticated org (404 if missing or another org's).","operationId":"get_api_maintenance_windows_id","parameters":[{"name":"id","in":"path","description":"Maintenance window id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Maintenance window","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceWindowResponse"}}}},"401":{"description":""},"404":{"description":""}}},"delete":{"tags":["maintenance-windows"],"summary":"`DELETE /api/maintenance-windows/{id}`.","operationId":"delete_api_maintenance_window","parameters":[{"name":"id","in":"path","description":"Maintenance window id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"patch":{"tags":["maintenance-windows"],"summary":"`PATCH /api/maintenance-windows/{id}`.","operationId":"update_api_maintenance_window","parameters":[{"name":"id","in":"path","description":"Maintenance window id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMaintenanceWindow"}}},"required":true},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceWindowResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/members":{"get":{"tags":["members"],"summary":"`GET /api/members` — the authenticated org's (non-deleted) members, ordered\nby role then name. Metadata only — no credentials/2FA material.","operationId":"get_api_members","responses":{"200":{"description":"Org members","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberListResponse"}}}},"401":{"description":""}}}},"/api/monitors":{"get":{"tags":["monitors"],"summary":"`GET /api/monitors` — list the authenticated org's monitors.","operationId":"get_api_monitors","parameters":[{"name":"page","in":"query","description":"1-based page (default 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Page size (default 20, max 100)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"search","in":"query","description":"Filter by name/url (ILIKE)","required":false,"schema":{"type":"string"}},{"name":"category","in":"query","description":"`browser` (browser checks), `third_party` (third party monitors) or `uptime` (everything except browser checks, third party monitors included). Absent = all.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Org monitors (paginated)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndexResponse"}}}},"401":{"description":""}}},"post":{"tags":["monitors"],"summary":"`POST /api/monitors` — create a monitor from minimal input + smart defaults.","description":"`monitor_type: \"third_party\"` (OpenSpec 128) watches a vendor's public status\npage instead of a URL of yours: send `third_party: { service_slug,\ncomponent_ids? }` (services from `GET /api/third-party/services`); `url` is\nnot needed and no interval applies. Third party monitors have their own\nplan allowance: at the limit the answer is 402 with `code:\n\"third_party_limit_reached\"`; a free plan gets the same 402 as for a browser\ncheck. While `THIRD_PARTY_ENABLED` is off the type answers 422 as an unknown\ntype.","operationId":"create_api_monitor","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMonitor"}}},"required":true},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShowResponse"}}}},"401":{"description":""},"402":{"description":"Plan limit reached, or the monitor type is not on this plan. A third party monitor at its allowance answers `{ error, code: \"third_party_limit_reached\" }`."},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/monitors/bulk":{"post":{"tags":["monitors"],"summary":"`POST /api/monitors/bulk` — pause/resume/delete/update_interval over a set of\norg-owned monitors.","operationId":"bulk_api_monitors","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkAction"}}},"required":true},"responses":{"200":{"description":"Action applied"},"401":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/monitors/regions":{"get":{"tags":["monitors"],"summary":"`GET /api/monitors/regions?ids=a,b` — what `/api/monitors/{id}/regions` returns, for a whole page\nof monitors in one request. A monitor that this organization does not own is left out.","operationId":"get_api_monitors_regions","parameters":[{"name":"ids","in":"query","description":"Monitor ids, comma separated, at most 100","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Per-region consensus of each monitor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorConsensusListResponse"}}}},"400":{"description":""},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/monitors/{id}":{"get":{"tags":["monitors"],"summary":"`GET /api/monitors/{id}` — a single monitor, scoped to the authenticated\norg (404 if it doesn't exist or belongs to another org). Port of\n`MonitorController.show` + `MonitorJSON.show`.","operationId":"get_api_monitors_id","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Monitor detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShowResponse"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"delete":{"tags":["monitors"],"summary":"`DELETE /api/monitors/{id}`.","operationId":"delete_api_monitor","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"patch":{"tags":["monitors"],"summary":"`PATCH /api/monitors/{id}` — partial update. On a `third_party` monitor,\n`third_party: { component_ids }` replaces the watched components (`[]` = the\nwhole service); the service, URL, interval and type cannot change.","operationId":"update_api_monitor","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMonitor"}}},"required":true},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShowResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/monitors/{id}/browser-runs":{"get":{"tags":["browser_runs"],"operationId":"list","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","description":"1-based page (default 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Page size (default 20, max 100)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Browser runs, newest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrowserRunListResponse"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/monitors/{id}/browser-runs/run-now":{"post":{"tags":["browser_runs"],"operationId":"run_now","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"202":{"description":"Browser check queued"},"401":{"description":""},"404":{"description":""},"422":{"description":"Not a browser monitor"},"503":{"description":"Dispatch unavailable"}},"security":[{"api_key":[]},{"session":[]}]}},"/api/monitors/{id}/browser-runs/vitals":{"get":{"tags":["browser_runs"],"summary":"`GET /api/monitors/{id}/browser-runs/vitals?days=N` — LCP/CLS trend for the\nrun-detail / monitor page. Org-scoped; runtime query (manual-apply table).\nTolerant: a missing table OR missing vitals columns (pre-migration browser\nbuilds) returns an empty series rather than erroring, so the FE renders a\n\"no data yet\" state. `days` clamped to 1..=90 (default 30).","operationId":"vitals","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"days","in":"query","description":"Trailing window in days (1-90, default 30)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Web Vitals trend, oldest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VitalsSeriesResponse"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/monitors/{id}/browser-runs/{run_id}":{"get":{"tags":["browser_runs"],"operationId":"show","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"run_id","in":"path","description":"Browser run (check_run_id)","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Run detail + signed artifact URLs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrowserRunDetailResponse"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/monitors/{id}/checks":{"get":{"tags":["monitors"],"summary":"`GET /api/monitors/{id}/checks?limit=N` — the last N (default 20, max 200)\ncheck points for one of the org's monitors, newest first (VM-derived).","operationId":"get_api_monitors_id_checks","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","description":"Number of recent checks (default 20, max 200)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Recent check points","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckListResponse"}}}},"401":{"description":""},"404":{"description":""}}}},"/api/monitors/{id}/incidents":{"get":{"tags":["incidents"],"summary":"`GET /api/monitors/{id}/incidents` — the latest 20 incidents for one of the\norg's monitors, newest first. Org-scoped (a foreign `monitor_id` simply\nreturns no rows). Port of `IncidentController.monitor_incidents` +\n`Monitoring.list_monitor_incidents/2`.","operationId":"get_api_monitors_id_incidents","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Monitor incidents (latest 20)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentListResponse"}}}},"401":{"description":""}}}},"/api/monitors/{id}/regions":{"get":{"tags":["monitors"],"summary":"`GET /api/monitors/{id}/regions` — per-region latest verdict + consensus\ndecision, scoped to the authenticated org (404 if not owned).","operationId":"get_api_monitors_id_regions","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Per-region consensus","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorConsensusResponse"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/monitors/{id}/snooze":{"post":{"tags":["monitors"],"summary":"`POST /api/monitors/{id}/snooze` — device-token Bearer auth ONLY.\nSuppresses `mobile_push` delivery for the calling user + this monitor for\none hour (re-snoozing pushes the window out). 404 for a foreign/unknown\nmonitor. Other channels, other users, and other monitors are unaffected.","operationId":"post_api_monitors_id_snooze","parameters":[{"name":"id","in":"path","description":"Monitor id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Snoozed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnoozeResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"device_token":[]}]}},"/api/nonprofit/applications":{"post":{"tags":["nonprofit"],"summary":"`POST /api/nonprofit/applications` — a manual application for a domain that is not\non the whitelist. It waits for an admin; nothing goes to a third party.","operationId":"post_api_nonprofit_applications","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationInput"}}},"required":true},"responses":{"201":{"description":"Application stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Application"}}}},"403":{"description":"owner_required"},"404":{"description":"nonprofit_program_disabled"},"409":{"description":"application_pending, too_many_applications, already_granted or domain_not_allowed"},"422":{"description":"invalid_application"}}}},"/api/nonprofit/claim":{"post":{"tags":["nonprofit"],"summary":"`POST /api/nonprofit/claim` `{domain}` — the automatic grant for an eligible domain.","operationId":"post_api_nonprofit_claim","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimInput"}}},"required":true},"responses":{"200":{"description":"Grant created; `paid_subscription` true asks the owner to cancel the paid plan"},"403":{"description":"owner_required"},"404":{"description":"nonprofit_program_disabled"},"409":{"description":"already_granted, not_eligible or domain_taken"}}}},"/api/nonprofit/status":{"get":{"tags":["nonprofit"],"summary":"`GET /api/nonprofit/status` — the program state for the caller's organization.","operationId":"get_api_nonprofit_status","responses":{"200":{"description":"Nonprofit program state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}},"401":{"description":""}}}},"/api/notification-deliveries":{"get":{"tags":["notification-deliveries"],"summary":"`GET /api/notification-deliveries` — the authenticated org's delivery records,\nnewest first. Filters: `?status=`, `?incident_id=`, `?limit=` (default 50,\nmax 200).","operationId":"get_api_notification_deliveries","parameters":[{"name":"limit","in":"query","description":"Page size (default 50, max 200)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"status","in":"query","description":"Filter by delivery status","required":false,"schema":{"type":"string"}},{"name":"incident_id","in":"query","description":"Filter to an incident","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Org notification deliveries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryListResponse"}}}},"401":{"description":""}}}},"/api/notification-deliveries/stats":{"get":{"tags":["notification-deliveries"],"summary":"`GET /api/notification-deliveries/stats?days=N` — delivery counts grouped by\nstatus over the last N days (default 7, range 1–90), org-scoped. Port of\n`NotificationDeliveryController.stats` + `DeliveryTracker.get_delivery_stats`.","operationId":"get_api_notification_deliveries_stats","parameters":[{"name":"days","in":"query","description":"Window in days (default 7, 1–90)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Delivery counts by status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryStatsResponse"}}}},"401":{"description":""}}}},"/api/oauth-clients":{"get":{"tags":["auth"],"summary":"`GET /api/oauth-clients` — the org's OAuth clients (no secrets). Port of\n`OAuthClientController.index` + `OAuth.list_clients/1`.","operationId":"get_api_oauth_clients","responses":{"200":{"description":"OAuth clients","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthClientsResponse"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"post":{"tags":["auth"],"summary":"`POST /api/oauth-clients` — create a Boruta OAuth client for the org. Port of\n`OAuthClientController.create` + `OAuth.create_client/1`. Returns the\nplaintext `client_secret` ONCE.","operationId":"post_api_oauth_clients","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOAuthClient"}}},"required":true},"responses":{"201":{"description":"Created client (secret shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOAuthClientOut"}}}},"401":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/oauth-clients/{id}":{"delete":{"tags":["auth"],"summary":"`DELETE /api/oauth-clients/{id}` — delete the org's client. Port of\n`OAuthClientController.delete` + `OAuth.delete_client/1`. Org-scoped via metadata.","operationId":"delete_api_oauth_clients_id","parameters":[{"name":"id","in":"path","description":"OAuth client id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteOAuthClientOut"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/on-call-schedules":{"get":{"tags":["on-call"],"summary":"`GET /api/on-call-schedules` — the org's on-call schedules.","operationId":"get_api_on_call_schedules","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleListResponse"}}}},"401":{"description":""}}},"post":{"tags":["on-call"],"summary":"`POST /api/on-call-schedules`.","operationId":"create_api_on_call_schedule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSchedule"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleResponse"}}}},"401":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/on-call-schedules/{id}":{"get":{"tags":["on-call"],"summary":"`GET /api/on-call-schedules/{id}`.","operationId":"get_api_on_call_schedule","parameters":[{"name":"id","in":"path","description":"Schedule id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleResponse"}}}},"401":{"description":""},"404":{"description":""}}},"delete":{"tags":["on-call"],"summary":"`DELETE /api/on-call-schedules/{id}` (cascades overrides).","operationId":"delete_api_on_call_schedule","parameters":[{"name":"id","in":"path","description":"Schedule id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":""},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"patch":{"tags":["on-call"],"summary":"`PATCH /api/on-call-schedules/{id}`.","operationId":"update_api_on_call_schedule","parameters":[{"name":"id","in":"path","description":"Schedule id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSchedule"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/on-call-schedules/{id}/current":{"get":{"tags":["on-call"],"summary":"`GET /api/on-call-schedules/{id}/current` — who is on call now + when it ends.","operationId":"get_api_on_call_current","parameters":[{"name":"id","in":"path","description":"Schedule id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolvedResponse"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/on-call-schedules/{id}/next":{"get":{"tags":["on-call"],"summary":"`GET /api/on-call-schedules/{id}/next` — who is on call after the next handoff.","operationId":"get_api_on_call_next","parameters":[{"name":"id","in":"path","description":"Schedule id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolvedResponse"}}}},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/on-call-schedules/{id}/overrides":{"post":{"tags":["on-call"],"summary":"`POST /api/on-call-schedules/{id}/overrides`.","operationId":"create_api_on_call_override","parameters":[{"name":"id","in":"path","description":"Schedule id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOverride"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverrideResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/on-call-schedules/{id}/overrides/{override_id}":{"delete":{"tags":["on-call"],"summary":"`DELETE /api/on-call-schedules/{id}/overrides/{override_id}`.","operationId":"delete_api_on_call_override","parameters":[{"name":"id","in":"path","description":"Schedule id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"override_id","in":"path","description":"Override id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":""},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/organizations/{org_id}/invitations":{"post":{"tags":["invitations"],"summary":"`POST /api/organizations/{org_id}/invitations` — invite a member (email\ndeferred). `org_id` path segment is accepted but the authed org is authoritative.","operationId":"create_api_invitation","parameters":[{"name":"org_id","in":"path","description":"Organization id (authed org is authoritative)","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvitation"}}},"required":true},"responses":{"201":{"description":"Invitation created (email deferred)"},"401":{"description":""},"403":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/organizations/{org_id}/invitations/{id}":{"delete":{"tags":["invitations"],"summary":"`DELETE /api/organizations/{org_id}/invitations/{id}` — cancel a pending invite.","operationId":"delete_api_invitation","parameters":[{"name":"org_id","in":"path","description":"Organization id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","description":"Invitation id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Cancelled"},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/organizations/{org_id}/members/transfer-ownership":{"post":{"tags":["members"],"summary":"`POST /api/organizations/{org_id}/members/transfer-ownership` — owner → another member.","operationId":"transfer_api_ownership","parameters":[{"name":"org_id","in":"path","description":"Org id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOwnership"}}},"required":true},"responses":{"200":{"description":"Transferred","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberOut"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/organizations/{org_id}/members/{id}":{"delete":{"tags":["members"],"summary":"`DELETE /api/organizations/{org_id}/members/{id}` — remove a member.","operationId":"remove_api_member","parameters":[{"name":"org_id","in":"path","description":"Org id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","description":"Member user id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Removed"},"401":{"description":""},"403":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"patch":{"tags":["members"],"summary":"`PATCH /api/organizations/{org_id}/members/{id}` — change a member's role.","operationId":"update_api_member_role","parameters":[{"name":"org_id","in":"path","description":"Org id","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","description":"Member user id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRole"}}},"required":true},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberOut"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/push/devices":{"post":{"tags":["push"],"summary":"`POST /api/push/devices` — device-token Bearer auth ONLY (per-device\nlifecycle; org API keys and browser sessions must not register devices).","operationId":"post_api_push_devices","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterPushDevice"}}},"required":true},"responses":{"200":{"description":"Registered (idempotent upsert)"},"401":{"description":""},"403":{"description":""},"422":{"description":""}},"security":[{"device_token":[]}]},"delete":{"tags":["push"],"summary":"`DELETE /api/push/devices` — owner-scoped soft-unregister\n(`invalidated_at`); unknown/already-invalidated/foreign tokens → 404\n(no oracle). Called on logout; provider-reported deaths use the\nsender-side invalidate path instead.","operationId":"delete_api_push_devices","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnregisterPushDevice"}}},"required":true},"responses":{"200":{"description":"Unregistered"},"401":{"description":""},"403":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"device_token":[]}]}},"/api/push/live-activities":{"post":{"tags":["push"],"summary":"`POST /api/push/live-activities` — device-token Bearer auth ONLY\n(per-device lifecycle, like `POST /api/push/devices`).","description":"* push-to-start: upsert one row for the caller's device (no incident\n  checks — an old-app `incident_id` is ignored).\n* update: reject incidents outside the caller's live org and unknown ones\n  (both 404, nothing written) and already-resolved ones (422), then\n  prune stale rows and upsert the token with its device + environment.\n\nBoth kinds follow the latest-device-session rule: presenting a token from\na `udt_` device session takes it over (see\n[`release_push_to_start_token_sql`]).","operationId":"post_api_push_live_activities","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterLiveActivity"}}},"required":true},"responses":{"200":{"description":"Registered (idempotent upsert)"},"401":{"description":""},"403":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"device_token":[]}]},"delete":{"tags":["push"],"summary":"`DELETE /api/push/live-activities` — removal of an update or\npush-to-start token the caller registered from THIS device session; unknown / already-removed / foreign tokens → 404\n(no oracle). Called when the activity ends on-device; provider-side\npruning covers the rest.","operationId":"delete_api_push_live_activities","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveLiveActivity"}}},"required":true},"responses":{"200":{"description":"Removed"},"401":{"description":""},"403":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"device_token":[]}]}},"/api/regions":{"get":{"tags":["misc"],"summary":"`GET /api/regions` — active check regions (Cloudflare cities excluded).\nPort of `MonitorController.regions`.","operationId":"get_api_regions","responses":{"200":{"description":"Active regions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveRegionsResponse"}}}},"401":{"description":""}}}},"/api/status-pages":{"get":{"tags":["status-pages"],"summary":"`GET /api/status-pages` — the authenticated org's status pages, by name.","operationId":"get_api_status_pages","responses":{"200":{"description":"Org status pages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPageListResponse"}}}},"401":{"description":""}}},"post":{"tags":["status-pages"],"summary":"`POST /api/status-pages`.","operationId":"create_api_status_page","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateStatusPage"}}},"required":true},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPageDetailResponse"}}}},"401":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/status-pages/{id}":{"get":{"tags":["status-pages"],"summary":"`GET /api/status-pages/{id}` — one status page + its monitor assignments,\nscoped to the authenticated org (404 if missing or another org's). Port of\n`StatusPageController.show` + `StatusPageJSON.show`.","operationId":"get_api_status_pages_id","parameters":[{"name":"id","in":"path","description":"Status page id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Status page + assignments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPageDetailResponse"}}}},"401":{"description":""},"404":{"description":""}}},"delete":{"tags":["status-pages"],"summary":"`DELETE /api/status-pages/{id}` (cascades status_page_monitors).","operationId":"delete_api_status_page","parameters":[{"name":"id","in":"path","description":"Status page id","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":""},"404":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"patch":{"tags":["status-pages"],"summary":"`PATCH /api/status-pages/{id}`.","operationId":"update_api_status_page","parameters":[{"name":"id","in":"path","description":"Status page id","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStatusPage"}}},"required":true},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPageDetailResponse"}}}},"401":{"description":""},"404":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/status/{slug}":{"get":{"tags":["status"],"operationId":"get_api_status_slug","parameters":[{"name":"slug","in":"path","description":"Status page slug","required":true,"schema":{"type":"string"}},{"name":"password","in":"query","description":"Page password when password-protected","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Public status page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShowPublicEnvelope"}}}},"404":{"description":""}}}},"/api/status/{slug}/history":{"get":{"tags":["status"],"summary":"`GET /api/status/:slug/history?days=N` — per-monitor daily uptime % over\nthe last N days (default 90, max 365), VM-derived. Public + read-only.","operationId":"get_api_status_slug_history","parameters":[{"name":"slug","in":"path","description":"Status page slug","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","description":"Window in days (default 90, max 365)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"password","in":"query","description":"Page password when password-protected","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Per-monitor daily uptime %","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryResponse"}}}},"404":{"description":""}}}},"/api/status/{slug}/incidents":{"get":{"tags":["status"],"summary":"`GET /api/status/:slug/incidents` — recent incident history for a public\nstatus page's monitors (newest first, capped). Public + read-only.","operationId":"get_api_status_slug_incidents","parameters":[{"name":"slug","in":"path","description":"Status page slug","required":true,"schema":{"type":"string"}},{"name":"password","in":"query","description":"Page password when password-protected","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Recent incidents","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentHistory"}}}},"404":{"description":""}}}},"/api/status/{slug}/maintenance":{"get":{"tags":["status"],"summary":"`GET /api/status/:slug/maintenance` — active + upcoming (next 7d)\nmaintenance windows relevant to a public status page (org-wide windows\nor ones scoped to a monitor on the page). Public + read-only.","operationId":"get_api_status_slug_maintenance","parameters":[{"name":"slug","in":"path","description":"Status page slug","required":true,"schema":{"type":"string"}},{"name":"password","in":"query","description":"Page password when password-protected","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Active + upcoming maintenance windows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceResponse"}}}},"404":{"description":""}}}},"/api/status/{slug}/regions":{"get":{"tags":["status"],"summary":"`GET /api/status/:slug/regions` — per-monitor, per-region latest status +\nresponse time (VM-derived). Public + read-only.","operationId":"get_api_status_slug_regions","parameters":[{"name":"slug","in":"path","description":"Status page slug","required":true,"schema":{"type":"string"}},{"name":"password","in":"query","description":"Page password when password-protected","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Per-monitor per-region latest status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegionsResponse"}}}},"404":{"description":""}}}},"/api/status/{slug}/uptime":{"get":{"tags":["status"],"summary":"`GET /api/status/:slug/uptime` — per-monitor uptime % over the last 90d,\nVM-derived (mean of daily uptime points), consistent with the page summary.\nPublic + read-only.","operationId":"get_api_status_slug_uptime","parameters":[{"name":"slug","in":"path","description":"Status page slug","required":true,"schema":{"type":"string"}},{"name":"password","in":"query","description":"Page password when password-protected","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Per-monitor uptime %","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UptimeResponse"}}}},"404":{"description":""}}}},"/api/third-party/popularity":{"get":{"tags":["third-party"],"summary":"`GET /api/third-party/popularity`: which services customers watch most, from\nUptrack's own data. Public and cached; names and counts only. While the\nthresholds are not met it answers `{\"data\":{\"visible\":false}}`.","operationId":"get_api_third_party_popularity","responses":{"200":{"description":"The block, or `visible: false` below the thresholds (14 days since launch, 30 monitors, 10 organizations). Cached 60 s","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PopularityResponse"}}}},"404":{"description":"Third party monitoring is switched off"},"429":{"description":"Rate limited"},"503":{"description":"Unavailable"}}}},"/api/third-party/services":{"get":{"tags":["third-party"],"summary":"`GET /api/third-party/services`: the services a customer can watch, grouped\nfor the picker. Public; names and statuses only.","operationId":"get_api_third_party_services","responses":{"200":{"description":"Enabled services grouped by category (cached 60 s)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogResponse"}}}},"404":{"description":"Third party monitoring is switched off"},"429":{"description":"Rate limited"},"503":{"description":"Catalog unavailable"}}}},"/api/third-party/services/{slug}":{"get":{"tags":["third-party"],"summary":"`GET /api/third-party/services/{slug}`: one service with its components,\nrecent vendor incidents and the caller's allowance.","operationId":"get_api_third_party_service","parameters":[{"name":"slug","in":"path","description":"Service slug, for example `cloudflare`","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Service detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceDetailResponse"}}}},"401":{"description":""},"404":{"description":"Unknown or disabled service, or third party monitoring is switched off"}},"security":[{"api_key":[]},{"session":[]}]}},"/api/tools/browser-preview":{"post":{"tags":["tools"],"operationId":"post_api_tools_browser_preview","requestBody":{"content":{"application/json":{"schema":{}}},"required":true},"responses":{"200":{"description":"Preview result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewResponse"}}}},"422":{"description":"Invalid/blocked URL"},"429":{"description":"Rate limited"},"503":{"description":"No probe available / dispatch unavailable"}}}},"/api/tools/check-website":{"post":{"tags":["tools"],"summary":"`POST /api/tools/check-website` — public, no auth. Body `{ url }` plus the\noptional create-form echo `{ method, headers, expected_status_codes,\nverify_ssl }`.","operationId":"post_api_tools_check_website","requestBody":{"content":{"application/json":{"schema":{}}},"required":true},"responses":{"200":{"description":"Per-region website check results + summary"},"400":{"description":"URL is required"},"429":{"description":"Rate limited"},"503":{"description":"Busy / dispatch unavailable"}}}},"/api/tools/cluster-health":{"get":{"tags":["tools"],"summary":"`GET /api/tools/cluster-health` — public, no auth. A node-local,\npublic-safe health summary. Port of `ToolsController.cluster_health` minus\nthe BEAM `:erpc` worker fan-out (the worker mesh is being retired); returns\nthis node's status. Exposes no addresses, credentials, or peer internals.","operationId":"get_api_tools_cluster_health","responses":{"200":{"description":"Node-local cluster health summary"}}}},"/api/tools/dns-lookup":{"post":{"tags":["tools"],"summary":"`POST /api/tools/dns-lookup` — public, no auth. Body `{ name, record_type?, resolvers? }`.","operationId":"post_api_tools_dns_lookup","requestBody":{"content":{"application/json":{"schema":{}}},"required":true},"responses":{"200":{"description":"Per-resolver answers and whether they agree"},"400":{"description":"Bad name, record type or resolver"},"429":{"description":"Rate limited"},"503":{"description":"Busy"}}}},"/api/tools/domain-lookup":{"post":{"tags":["tools"],"summary":"`POST /api/tools/domain-lookup` — public, no auth. Body `{ domain }`.","operationId":"post_api_tools_domain_lookup","requestBody":{"content":{"application/json":{"schema":{}}},"required":true},"responses":{"200":{"description":"RDAP registration details"},"400":{"description":"Not a domain name"},"429":{"description":"Rate limited"},"503":{"description":"Busy"}}}},"/api/tools/ssl-check":{"post":{"tags":["tools"],"summary":"`POST /api/tools/ssl-check` — public, no auth. Body `{ host, port? }`.","operationId":"post_api_tools_ssl_check","requestBody":{"content":{"application/json":{"schema":{}}},"required":true},"responses":{"200":{"description":"Certificate details, trust verdict and chain"},"400":{"description":"Bad host or port, or the host resolves to an internal address"},"429":{"description":"Rate limited"},"503":{"description":"Busy"}}}},"/api/usage/browser-runs":{"get":{"tags":["browser_runs"],"operationId":"usage","responses":{"200":{"description":"Browser-run usage this month + plan ceiling","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrowserUsageResponse"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/users/me/notification-preferences":{"get":{"tags":["users"],"summary":"`GET /api/users/me/notification-preferences` — the caller's prefs, or\nthe defaults when they never saved any (no row is created on read).","operationId":"get_api_users_me_notification_preferences","responses":{"200":{"description":"Notification preferences (defaults when unset)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferences"}}}},"401":{"description":""}},"security":[{"api_key":[]},{"session":[]}]},"patch":{"tags":["users"],"summary":"`PATCH /api/users/me/notification-preferences` — merge the given fields\nover the current (or default) prefs and upsert.","operationId":"patch_api_users_me_notification_preferences","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchNotificationPreferences"}}},"required":true},"responses":{"200":{"description":"Updated notification preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferences"}}}},"401":{"description":""},"422":{"description":""}},"security":[{"api_key":[]},{"session":[]}]}},"/api/widget/{slug}/data":{"get":{"tags":["status"],"summary":"`GET /api/widget/:slug/data` — compact public status payload for the\nembeddable widget (overall status + 30d uptime, VM-derived). Public,\nCDN-cached. Port of `StatusWidgetController.data`.","operationId":"get_api_widget_slug_data","parameters":[{"name":"slug","in":"path","description":"Status page slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Widget status payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetData"}}}},"404":{"description":""}}}},"/api/widget/{slug}/script.js":{"get":{"tags":["status-pages"],"summary":"`GET /api/widget/{slug}/script.js` — public embeddable widget JS. Port of\n`StatusWidgetController.script`: serves a `console.error` 404 (still as JS)\nwhen the slug isn't a public page, else a self-contained script that\nfetches `/api/widget/{slug}/data` and renders a status pill. Served as\n`application/javascript` with a short CDN cache.","operationId":"get_api_widget_script","parameters":[{"name":"slug","in":"path","description":"Status page slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Embeddable widget JS"},"404":{"description":"Unknown slug (JS console.error)"}}}}},"components":{"schemas":{"ActiveRegionsResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RegionOut"}}}},"AddOnCatalogItem":{"type":"object","description":"A catalog entry: an available add-on type + its per-unit price.","required":["type","unit_price_cents"],"properties":{"type":{"type":"string"},"unit_price_cents":{"type":"integer","format":"int64"}}},"AddOnItem":{"type":"object","description":"A configured add-on: type + quantity + per-unit price (cents/month).","required":["type","quantity","unit_price_cents"],"properties":{"quantity":{"type":"integer","format":"int32"},"type":{"type":"string"},"unit_price_cents":{"type":"integer","format":"int64"}}},"AddOnsResponse":{"type":"object","description":"`GET /api/billing/add-ons` response — current add-ons + monthly cost + catalog.","required":["data","monthly_cost_cents","available_types"],"properties":{"available_types":{"type":"array","items":{"$ref":"#/components/schemas/AddOnCatalogItem"}},"data":{"type":"array","items":{"$ref":"#/components/schemas/AddOnItem"}},"monthly_cost_cents":{"type":"integer","format":"int64"}}},"AlertChannelListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AlertChannelOut"}}}},"AlertChannelOut":{"type":"object","required":["id","config","type","is_active","inserted_at","updated_at","config_fingerprint"],"properties":{"config":{"type":"object"},"config_fingerprint":{"type":"string","description":"`sha256:<hex>` of the stored config (keys sorted). Changes whenever any\nvalue changes, including a masked secret, so a client (e.g. `uptrack\ndiff`) can compare configs without seeing the secrets."},"id":{"type":"string","format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"is_active":{"type":"boolean"},"name":{"type":["string","null"]},"type":{"type":"string","description":"Channel kind (slack/discord/telegram/email/webhook/…). Serialized as `type`."},"updated_at":{"type":"string","format":"date-time"}}},"AlertChannelTestResult":{"type":"object","description":"Result of `POST /api/alert-channels/{id}/test`.","required":["ok"],"properties":{"error":{"type":["string","null"]},"ok":{"type":"boolean"}}},"Allowance":{"type":"object","required":["used"],"properties":{"limit":{"type":["integer","null"],"format":"int64","description":"Null = unlimited."},"used":{"type":"integer","format":"int64"}}},"AllowedTypesResponse":{"type":"object","required":["allowed"],"properties":{"allowed":{"type":"array","items":{"type":"string"}},"plan":{"type":["string","null"]}}},"AnalyticsDashboardStats":{"type":"object","description":"Org-scoped dashboard counts (same shape as `misc::DashboardStats`, kept\ndistinct so utoipa doesn't collide on the short name).","required":["total_monitors","active_monitors","ongoing_incidents","recent_incidents"],"properties":{"active_monitors":{"type":"integer","format":"int64"},"ongoing_incidents":{"type":"integer","format":"int64"},"recent_incidents":{"type":"integer","format":"int64"},"total_monitors":{"type":"integer","format":"int64"}}},"ApiKeyListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyOut"}}}},"ApiKeyOut":{"type":"object","required":["id","name","scopes","is_active","created_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"id":{"type":"string","format":"uuid"},"is_active":{"type":"boolean"},"key_prefix":{"type":["string","null"],"description":"The visible key prefix (e.g. `utk_…`) — NOT the secret."},"last_used_at":{"type":["string","null"],"format":"date-time"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}}},"AppleTransactionRequest":{"type":"object","description":"`POST /api/billing/apple/transactions` body.","required":["signed_transaction"],"properties":{"signed_transaction":{"type":"string","description":"StoreKit 2 `Transaction.jwsRepresentation`."}}},"Application":{"type":"object","required":["id","domain","country_code","legal_name","registry_name","registry_id","status","inserted_at"],"properties":{"country_code":{"type":"string"},"decided_at":{"type":["string","null"],"format":"date-time"},"decision_note":{"type":["string","null"]},"domain":{"type":"string"},"id":{"type":"string","format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"legal_name":{"type":"string"},"register_url":{"type":["string","null"]},"registry_id":{"type":"string"},"registry_name":{"type":"string"},"status":{"type":"string"}}},"ApplicationInput":{"type":"object","required":["domain","country_code","legal_name","registry_name","registry_id"],"properties":{"country_code":{"type":"string"},"domain":{"type":"string"},"legal_name":{"type":"string"},"register_url":{"type":["string","null"]},"registry_id":{"type":"string"},"registry_name":{"type":"string"}}},"AuditLogListResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AuditLogOut"}},"meta":{"$ref":"#/components/schemas/AuditMeta"}}},"AuditLogOut":{"type":"object","required":["id","metadata"],"properties":{"action":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time"},"id":{"type":"string","format":"uuid"},"ip_address":{"type":["string","null"]},"metadata":{},"resource_id":{"type":["string","null"],"format":"uuid"},"resource_type":{"type":["string","null"]},"user":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AuditUser","description":"`null` for system actions with no acting user."}]}}},"AuditMeta":{"type":"object","required":["total"],"properties":{"total":{"type":"integer","format":"int64"}}},"AuditUser":{"type":"object","required":["id"],"properties":{"email":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}},"BrowserRunDetailOut":{"type":"object","required":["check_run_id","region","status","step_count","duration_ms","inserted_at"],"properties":{"baseline_seeded":{"type":["boolean","null"]},"baseline_url":{"type":["string","null"]},"baseline_version":{"type":["integer","null"],"format":"int64"},"check_run_id":{"type":"string","format":"uuid"},"cls":{"type":["number","null"],"format":"double"},"console":{"type":"array","items":{"$ref":"#/components/schemas/ConsoleEntry"},"description":"Captured console messages (capped); empty pre-diagnostics."},"diff_url":{"type":["string","null"],"description":"Diff-overlay (visual regression). Deterministic key; only present when a\nregression run stored an overlay."},"duration_ms":{"type":"integer","format":"int64"},"error":{"type":["string","null"]},"failed_step_index":{"type":["integer","null"],"format":"int32"},"fcp_ms":{"type":["number","null"],"format":"double"},"inp_ms":{"type":["number","null"],"format":"double"},"inserted_at":{"type":"string"},"lcp_ms":{"type":["number","null"],"format":"double"},"network":{"type":"array","items":{"$ref":"#/components/schemas/NetworkEntry"},"description":"Captured network requests (capped); empty pre-diagnostics."},"region":{"type":"string"},"screenshot_url":{"type":["string","null"],"description":"Presigned URLs (15-min), null when R2 is unconfigured / the key is absent."},"ssim":{"type":["number","null"],"format":"double"},"status":{"type":"string"},"step_count":{"type":"integer","format":"int32"},"steps":{"type":["object","null"],"description":"Per-step timeline [{index,name,ok,duration_ms,error}] for the replay UI."},"tarball_url":{"type":["string","null"]},"trace_url":{"type":["string","null"],"description":"Presigned trace.zip (every run when captured) + failure-only video.webm\n(15-min); null when absent. Console/network/DOM remain in `tarball_url`."},"ttfb_ms":{"type":["number","null"],"format":"double"},"video_url":{"type":["string","null"]},"visual_passed":{"type":["boolean","null"]}}},"BrowserRunDetailResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/BrowserRunDetailOut"}}},"BrowserRunListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BrowserRunOut"}}}},"BrowserRunOut":{"type":"object","required":["check_run_id","status","step_count","duration_ms","inserted_at"],"properties":{"baseline_seeded":{"type":["boolean","null"]},"check_run_id":{"type":"string","format":"uuid"},"duration_ms":{"type":"integer","format":"int64"},"failed_step_index":{"type":["integer","null"],"format":"int32"},"inserted_at":{"type":"string"},"screenshot_url":{"type":["string","null"],"description":"Presigned thumbnail URL (15-min); null when R2 is unconfigured or the run\nhas no standalone screenshot."},"ssim":{"type":["number","null"],"format":"double"},"status":{"type":"string","description":"\"up\" | \"down\"."},"step_count":{"type":"integer","format":"int32"},"visual_passed":{"type":["boolean","null"]}}},"BrowserUsageOut":{"type":"object","description":"Browser-run usage for the current calendar month (UTC), with the plan's\nderived ceiling. `estimate` is `null` for unlimited/fair-use (Business).","required":["plan","month_runs"],"properties":{"estimate":{"type":["integer","null"],"format":"int64"},"month_runs":{"type":"integer","format":"int64"},"plan":{"type":"string"}}},"BrowserUsageResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/BrowserUsageOut"}}},"BulkAction":{"type":"object","description":"Request body for `POST /api/monitors/bulk`.","required":["action","monitor_ids"],"properties":{"action":{"type":"string"},"interval":{"type":["integer","null"],"format":"int64"},"monitor_ids":{"type":"array","items":{"type":"string","format":"uuid"}}}},"Catalog":{"type":"object","required":["service_count","categories"],"properties":{"categories":{"type":"array","items":{"$ref":"#/components/schemas/CatalogCategory"},"description":"Only categories that hold at least one enabled service."},"service_count":{"type":"integer","format":"int64","description":"Enabled services. The marketing page takes its \"N services\" from here."}}},"CatalogCategory":{"type":"object","required":["category","label","services"],"properties":{"category":{"type":"string"},"label":{"type":"string"},"services":{"type":"array","items":{"$ref":"#/components/schemas/CatalogService"}}}},"CatalogResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Catalog"}}},"CatalogService":{"type":"object","description":"One service of the public catalog.","required":["slug","name","category","status","component_count"],"properties":{"category":{"type":"string"},"component_count":{"type":"integer","format":"int64","description":"Components a whole-service monitor watches."},"name":{"type":"string"},"slug":{"type":"string"},"status":{"type":"string","description":"Worst status among the components a whole-service monitor watches:\n`operational`, `maintenance`, `degraded`, `partial_outage`,\n`major_outage`, or `unknown` (not read recently)."}}},"CheckListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CheckOut"}}}},"CheckOut":{"type":"object","required":["status","response_time","status_code","checked_at","response_headers"],"properties":{"checked_at":{"type":"string"},"error_message":{"type":["string","null"],"description":"DOWN checks only: the failure's error message (nearest failure row)."},"response_body":{"type":["string","null"],"description":"DOWN checks only: the captured response body (nearest failure row)."},"response_headers":{"type":["object","null"],"description":"DOWN checks only: the captured response headers (incl. SSL cert metadata),\nfrom the nearest `monitor_check_failures` row. `null` for UP checks —\nmatches Phoenix (`MonitorJSON` only attaches failure details on down)."},"response_time":{"type":"integer","format":"int64"},"status":{"type":"string","description":"\"up\" | \"down\" (VM status threshold)."},"status_code":{"type":"integer","format":"int64"}}},"ClaimInput":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string"}}},"ConnectedApp":{"type":"object","description":"One app a user has connected.","required":["client_id","name","connected_at","last_used_at"],"properties":{"client_id":{"type":"string","format":"uuid"},"connected_at":{"type":"string","format":"date-time"},"last_used_at":{"type":"string","format":"date-time"},"name":{"type":"string"},"scope":{"type":["string","null"]}}},"ConnectedAppsOut":{"type":"object","required":["apps"],"properties":{"apps":{"type":"array","items":{"$ref":"#/components/schemas/ConnectedApp"}}}},"ConsoleEntry":{"type":"object","description":"One console message from a run's pages.","required":["level","text"],"properties":{"level":{"type":"string"},"text":{"type":"string"},"ts":{"type":["string","null"]}}},"CreateAlertChannel":{"type":"object","description":"Request body for `POST /api/alert-channels`.","properties":{"config":{"type":["object","null"]},"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"]},"type":{"type":["string","null"]}}},"CreateApiKey":{"type":"object","properties":{"expires_at":{"type":["string","null"],"format":"date-time"},"name":{"type":["string","null"]},"scopes":{"type":["array","null"],"items":{"type":"string"}}}},"CreateDeviceToken":{"type":"object","description":"`POST /api/auth/device-tokens` body — an optional human label\n(\"Pixel 9\", \"Work iPhone\") shown on the device-management screen.","properties":{"label":{"type":["string","null"]}}},"CreateIncident":{"type":"object","properties":{"cause":{"type":["string","null"]},"monitor_id":{"type":["string","null"],"format":"uuid"}}},"CreateIncidentUpdate":{"type":"object","properties":{"description":{"type":["string","null"]},"status":{"type":["string","null"]},"title":{"type":["string","null"]}}},"CreateInvitation":{"type":"object","properties":{"email":{"type":["string","null"]},"role":{"type":["string","null"]}}},"CreateMaintenanceWindow":{"type":"object","properties":{"description":{"type":["string","null"]},"end_time":{"type":["string","null"],"format":"date-time"},"monitor_id":{"type":["string","null"],"format":"uuid"},"recurrence":{"type":["string","null"]},"start_time":{"type":["string","null"],"format":"date-time"},"title":{"type":["string","null"]}}},"CreateMonitor":{"type":"object","description":"Request body for `POST /api/monitors`. Most fields optional — smart defaults\nfill them from the URL (the minimal-input Phoenix create).","properties":{"confirmation_threshold":{"type":["integer","null"],"format":"int64"},"confirmation_window":{"type":["string","null"]},"description":{"type":["string","null"]},"escalation_policy_id":{"type":["string","null"],"format":"uuid"},"interval":{"type":["integer","null"],"format":"int64"},"monitor_type":{"type":["string","null"]},"name":{"type":["string","null"]},"region_ids":{"type":["array","null"],"items":{"type":"integer","format":"int64"}},"regions_required":{"type":["string","null"]},"reminder_interval_minutes":{"type":["integer","null"],"format":"int64"},"settings":{"type":["object","null"]},"third_party":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ThirdPartyInput","description":"Required when `monitor_type` is `third_party`, ignored otherwise. The\nmonitor's `url` is then the service's status page and need not be sent."}]},"timeout":{"type":["integer","null"],"format":"int64"},"url":{"type":["string","null"]}}},"CreateOAuthClient":{"type":"object","description":"`POST /api/oauth-clients` request body.","properties":{"name":{"type":["string","null"]},"redirect_uris":{"type":["array","null"],"items":{"type":"string"}}}},"CreateOAuthClientOut":{"type":"object","description":"`POST /api/oauth-clients` response — includes the plaintext secret (shown once).","required":["id","name","client_id","client_secret","redirect_uris"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}}}},"CreateOverride":{"type":"object","required":["participant","starts_at","ends_at"],"properties":{"ends_at":{"type":"string","format":"date-time"},"participant":{"$ref":"#/components/schemas/ParticipantDto"},"starts_at":{"type":"string","format":"date-time"}}},"CreatePolicy":{"type":"object","properties":{"description":{"type":["string","null"]},"name":{"type":["string","null"]},"steps":{"type":["array","null"],"items":{"$ref":"#/components/schemas/StepInput"}}}},"CreateSchedule":{"type":"object","properties":{"anchor_at":{"type":["string","null"],"format":"date-time"},"name":{"type":["string","null"]},"participants":{"type":"array","items":{"$ref":"#/components/schemas/ParticipantDto"}},"rotation_length_secs":{"type":["integer","null"],"format":"int64","description":"Required only for rotation_type=custom (daily/weekly derive their length)."},"rotation_type":{"type":["string","null"]},"timezone":{"type":["string","null"]}}},"CreateStatusPage":{"type":"object","properties":{"allow_subscriptions":{"type":["boolean","null"]},"custom_domain":{"type":["string","null"]},"default_language":{"type":["string","null"]},"description":{"type":["string","null"]},"is_public":{"type":["boolean","null"]},"logo_url":{"type":["string","null"]},"monitor_ids":{"type":["array","null"],"items":{"type":"string","format":"uuid"}},"name":{"type":["string","null"]},"noindex":{"type":["boolean","null"]},"password":{"type":["string","null"]},"password_protected":{"type":["boolean","null"]},"slug":{"type":["string","null"]},"theme_config":{"type":["object","null"]},"whitelabel":{"type":["boolean","null"]}}},"CustomSenderData":{"type":"object","description":"The org's custom email sender — name, address, and whether it's verified.","required":["sender_name","sender_email","verified"],"properties":{"sender_email":{"type":"string"},"sender_name":{"type":"string"},"verified":{"type":"boolean"}}},"CustomSenderResponse":{"type":"object","description":"`{ data: CustomSenderData | null }` — the custom-sender response envelope.","properties":{"data":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CustomSenderData"}]}}},"DashboardAnalyticsOut":{"type":"object","description":"`GET /api/analytics/dashboard` — overview counts + org overall uptime + trend.","required":["stats","overall_uptime","uptime_trend","period_days"],"properties":{"overall_uptime":{"type":"number","format":"double"},"period_days":{"type":"integer","format":"int64"},"stats":{"$ref":"#/components/schemas/AnalyticsDashboardStats"},"uptime_trend":{"type":"array","items":{"$ref":"#/components/schemas/UptimeTrendPoint"}}}},"DashboardStats":{"type":"object","required":["total_monitors","active_monitors","ongoing_incidents","recent_incidents"],"properties":{"active_monitors":{"type":"integer","format":"int64"},"ongoing_incidents":{"type":"integer","format":"int64"},"recent_incidents":{"type":"integer","format":"int64"},"total_monitors":{"type":"integer","format":"int64"}}},"DashboardStatsResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/DashboardStats"}}},"DayUptime":{"type":"object","required":["date","uptime_percent"],"properties":{"date":{"type":"string"},"uptime_percent":{"type":"number","format":"double"}}},"DeleteOAuthClientOut":{"type":"object","description":"`{ deleted: bool }` — the delete response shape the FE expects.","required":["deleted"],"properties":{"deleted":{"type":"boolean"}}},"DeliveryListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeliveryOut"}}}},"DeliveryOut":{"type":"object","required":["id","channel_type","event_type","status","inserted_at"],"properties":{"alert_channel_id":{"type":["string","null"],"format":"uuid"},"channel_type":{"type":"string"},"error_message":{"type":["string","null"]},"event_type":{"type":"string"},"id":{"type":"string","format":"uuid"},"incident_id":{"type":["string","null"],"format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"monitor_id":{"type":["string","null"],"format":"uuid"},"status":{"type":"string"}}},"DeliveryStatsResponse":{"type":"object","required":["stats","period_days"],"properties":{"period_days":{"type":"integer","format":"int64"},"stats":{"type":"object","description":"`status` → count over the period.","additionalProperties":{"type":"integer","format":"int64"},"propertyNames":{"type":"string"}}}},"DetailComponent":{"type":"object","required":["id","name","status","status_since","in_scope"],"properties":{"group":{"type":["string","null"],"description":"The vendor's group for this component, if any."},"id":{"type":"string","format":"uuid"},"in_scope":{"type":"boolean","description":"True when a whole-service monitor counts this component (the service has\nno scope group, or this component is in it)."},"name":{"type":"string"},"status":{"type":"string","description":"`operational`, `maintenance`, `degraded`, `partial_outage`,\n`major_outage`, or `unknown` while the service is not read recently."},"status_since":{"type":"string"}}},"DetailIncident":{"type":"object","required":["id","title","impact","started_at"],"properties":{"id":{"type":"string"},"impact":{"type":"string","description":"`none`, `minor`, `major` or `critical`."},"resolved_at":{"type":["string","null"]},"started_at":{"type":"string"},"title":{"type":"string"},"url":{"type":["string","null"],"description":"An `https` link on the service's own host, or null."}}},"DeviceTokenListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeviceTokenOut"}}}},"DeviceTokenOut":{"type":"object","description":"Device-token metadata — the stored secret (`token_hash`) is NEVER exposed.","required":["id","created_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"string","format":"uuid"},"label":{"type":["string","null"]},"last_used_at":{"type":["string","null"],"format":"date-time"}}},"DomainVerdict":{"type":"object","required":["domain","verdict"],"properties":{"domain":{"type":"string"},"source":{"type":["string","null"],"description":"Where the eligibility comes from: `tld`, `curated`, `manual`,\n`uk_charity_commission` or `acnc`. Null unless eligible."},"verdict":{"$ref":"#/components/schemas/Verdict"}}},"DowngradePreviewOut":{"type":"object","description":"`GET /api/billing/downgrade-preview` response — current monitor count, the\nfree-plan limit, and the monitors that would be paused.","required":["current_count","limit","monitors_to_pause"],"properties":{"current_count":{"type":"integer","format":"int64"},"limit":{"type":"integer","format":"int64"},"monitors_to_pause":{"type":"array","items":{"$ref":"#/components/schemas/MonitorToPause"}}}},"EscalateResponse":{"type":"object","description":"`POST /api/incidents/{id}/escalate` response.","required":["ok","escalated","steps_fired"],"properties":{"escalated":{"type":"boolean","description":"False when the call was a no-op (already acknowledged/resolved, or\nevery step had fired already)."},"ok":{"type":"boolean"},"steps_fired":{"type":"integer","format":"int32","description":"Escalation events published by this call."}}},"EscalationPolicyListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EscalationPolicyOut"}}}},"EscalationPolicyOut":{"type":"object","required":["id","organization_id","name","steps","inserted_at","updated_at"],"properties":{"description":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"name":{"type":"string"},"organization_id":{"type":"string","format":"uuid"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/EscalationStepOut"}},"updated_at":{"type":"string","format":"date-time"}}},"EscalationPolicyResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/EscalationPolicyOut"}}},"EscalationStepOut":{"type":"object","required":["id"],"properties":{"alert_channel_id":{"type":["string","null"],"format":"uuid"},"delay_minutes":{"type":["integer","null"],"format":"int32"},"id":{"type":"string","format":"uuid"},"on_call_schedule_id":{"type":["string","null"],"format":"uuid"},"step_order":{"type":["integer","null"],"format":"int32"}}},"ExplainResponse":{"type":"object","required":["summary","cached"],"properties":{"cached":{"type":"boolean"},"classification":{"type":["string","null"],"description":"\"true_failure\" | \"misconfiguration\" | \"insufficient_data\", or null for\nsummaries generated before classification existed (legacy cache)."},"summary":{"type":"string"}}},"FreqPoint":{"type":"object","description":"One daily incident-frequency point — `{ date, count }`.","required":["date","count"],"properties":{"count":{"type":"integer","format":"int64"},"date":{"type":"string"}}},"Grant":{"type":"object","required":["id","source","domain","status","starts_at","ends_at"],"properties":{"domain":{"type":"string"},"ends_at":{"type":"string","format":"date-time"},"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"starts_at":{"type":"string","format":"date-time"},"status":{"type":"string"}}},"GrantOut":{"type":"object","description":"A live nonprofit grant (OpenSpec 136), shown next to the subscription.","required":["ends_at","source","domain"],"properties":{"domain":{"type":"string"},"ends_at":{"type":"string","format":"date-time"},"source":{"type":"string","description":"`tld`, `curated`, `uk_charity_commission`, `acnc`, `manual` or `admin`."}}},"HistoryResponse":{"type":"object","required":["slug","days","monitors","updated_at"],"properties":{"days":{"type":"integer","format":"int64"},"monitors":{"type":"array","items":{"$ref":"#/components/schemas/MonitorHistory"}},"slug":{"type":"string"},"updated_at":{"type":"string"}}},"IncidentDetail":{"type":"object","required":["incident","updates"],"properties":{"incident":{"$ref":"#/components/schemas/IncidentOut"},"updates":{"type":"array","items":{"$ref":"#/components/schemas/IncidentUpdateOut"}}}},"IncidentDetailResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/IncidentDetail"}}},"IncidentEntry":{"type":"object","required":["monitor","status"],"properties":{"cause":{"type":["string","null"]},"monitor":{"type":"string"},"resolved_at":{"type":["string","null"]},"started_at":{"type":["string","null"]},"status":{"type":"string","description":"\"ongoing\" | \"resolved\"."}}},"IncidentHistory":{"type":"object","required":["slug","incidents","updated_at"],"properties":{"incidents":{"type":"array","items":{"$ref":"#/components/schemas/IncidentEntry"}},"slug":{"type":"string"},"updated_at":{"type":"string"}}},"IncidentListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/IncidentOut"}}}},"IncidentOut":{"type":"object","required":["id","monitor_id","status","inserted_at"],"properties":{"acknowledged_at":{"type":["string","null"],"format":"date-time"},"acknowledged_by_id":{"type":["string","null"],"format":"uuid"},"alert_level":{"type":["string","null"]},"cause":{"type":["string","null"]},"duration":{"type":["integer","null"],"format":"int32"},"id":{"type":"string","format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"monitor_id":{"type":"string","format":"uuid"},"monitor_name":{"type":["string","null"],"description":"`null` if the monitor was deleted (incidents outlive monitors)."},"resolved_at":{"type":["string","null"],"format":"date-time"},"started_at":{"type":["string","null"],"format":"date-time"},"status":{"type":"string"},"vl_trace_id":{"type":["string","null"],"format":"uuid"}}},"IncidentStats":{"type":"object","required":["total_incidents","ongoing_incidents","resolved_incidents","mttr_minutes"],"properties":{"mttr_minutes":{"type":"number","format":"double"},"ongoing_incidents":{"type":"integer","format":"int64"},"resolved_incidents":{"type":"integer","format":"int64"},"total_incidents":{"type":"integer","format":"int64"}}},"IncidentUpdateOut":{"type":"object","required":["id","status"],"properties":{"description":{"type":["string","null"]},"id":{"type":"integer","format":"int64","description":"`incident_updates.id` is a bigint sequence (NOT a uuid)."},"posted_at":{"type":["string","null"],"format":"date-time"},"status":{"type":"string"},"title":{"type":["string","null"]},"user_id":{"type":["string","null"],"format":"uuid"}}},"IndexResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MonitorOut"}},"meta":{"$ref":"#/components/schemas/Meta"}}},"InvitationListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InvitationOut"}}}},"InvitationOut":{"type":"object","required":["id","email","role","inserted_at"],"properties":{"email":{"type":"string"},"expires_at":{"type":["string","null"],"format":"date-time"},"id":{"type":"string","format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"invited_by":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Inviter","description":"The member who sent the invite (`null` if that user was removed)."}]},"role":{"type":"string"}}},"Inviter":{"type":"object","required":["id"],"properties":{"email":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}},"LastCheck":{"type":"object","description":"Latest VM-derived check for a monitor (list/detail enrichment). Mirrors the\nPhoenix `last_check` object on the monitor JSON.","required":["status","response_time","checked_at"],"properties":{"checked_at":{"type":"string"},"response_time":{"type":"integer","format":"int64"},"status":{"type":"string"}}},"LocationHistory":{"type":"object","description":"One location's history.","required":["region","step_seconds","points"],"properties":{"first_at":{"type":["integer","null"],"format":"int64","description":"The first sample in the period, in unix seconds. A young location starts after the period."},"points":{"type":"array","items":{"$ref":"#/components/schemas/LocationPoint"}},"region":{"type":"string"},"step_seconds":{"type":"integer","format":"int32","description":"Seconds between the points of this location. Young data has short steps.","minimum":0},"uptime":{"type":["number","null"],"format":"double","description":"Uptime % over the part of the period that has data."}}},"LocationHistoryOut":{"type":"object","description":"The chart data of `GET /api/analytics/monitors/{monitor_id}/locations`.","required":["monitor_id","period_days","step_seconds","locations"],"properties":{"locations":{"type":"array","items":{"$ref":"#/components/schemas/LocationHistory"}},"monitor_id":{"type":"string","format":"uuid"},"period_days":{"type":"integer","format":"int64"},"step_seconds":{"type":"integer","format":"int32","minimum":0}}},"LocationPoint":{"type":"object","description":"One point of a location's history. A field is `None` when the window has no such sample: a\nwindow of only failed city checks has an uptime and no response time.","required":["timestamp"],"properties":{"response_time":{"type":["number","null"],"format":"double"},"timestamp":{"type":"integer","format":"int64"},"uptime":{"type":["number","null"],"format":"double"}}},"MaintenanceEntry":{"type":"object","required":["status"],"properties":{"end_time":{"type":["string","null"]},"monitor":{"type":["string","null"],"description":"`None` → applies to all monitors on the page (org-wide window)."},"start_time":{"type":["string","null"]},"status":{"type":"string","description":"\"active\" | \"scheduled\"."},"title":{"type":["string","null"]}}},"MaintenanceResponse":{"type":"object","required":["slug","windows","updated_at"],"properties":{"slug":{"type":"string"},"updated_at":{"type":"string"},"windows":{"type":"array","items":{"$ref":"#/components/schemas/MaintenanceEntry"}}}},"MaintenanceWindowListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MaintenanceWindowOut"}}}},"MaintenanceWindowOut":{"type":"object","required":["id","recurrence","status","organization_id","inserted_at","updated_at"],"properties":{"description":{"type":["string","null"]},"end_time":{"type":["string","null"],"format":"date-time"},"id":{"type":"string","format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"monitor_id":{"type":["string","null"],"format":"uuid","description":"`null` ⇒ org-wide window (applies to every monitor)."},"organization_id":{"type":"string","format":"uuid"},"recurrence":{"type":"string"},"start_time":{"type":["string","null"],"format":"date-time"},"status":{"type":"string"},"title":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"}}},"MaintenanceWindowResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/MaintenanceWindowOut"}}},"MemberListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MemberOut"}}}},"MemberOut":{"type":"object","required":["id","email","role","is_admin","is_owner","can_manage_team","inserted_at"],"properties":{"can_manage_team":{"type":"boolean","description":"`role IN ('owner','admin')` — Phoenix `User.can_manage_team?/1`. The team\nUI gates edit/remove on this."},"confirmed_at":{"type":["string","null"],"format":"date-time"},"email":{"type":"string"},"id":{"type":"string","format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"is_admin":{"type":"boolean"},"is_owner":{"type":"boolean","description":"`role == 'owner'` — Phoenix `User.is_owner?/1`."},"last_signed_in_at":{"type":["string","null"],"format":"date-time"},"name":{"type":["string","null"]},"role":{"type":"string"}}},"Meta":{"type":"object","required":["total","page","per_page"],"properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"total":{"type":"integer","format":"int64"}}},"MonitorAnalyticsOut":{"type":"object","required":["monitor_id","period_days","uptime_chart","response_times","percentiles","incident_stats"],"properties":{"data_since":{"type":["integer","null"],"format":"int64","description":"The first sample in the period, in unix seconds. A young monitor starts after the period."},"incident_stats":{"$ref":"#/components/schemas/IncidentStats"},"monitor_id":{"type":"string","format":"uuid"},"percentiles":{"$ref":"#/components/schemas/Percentiles"},"period_days":{"type":"integer","format":"int64"},"response_times":{"type":"array","items":{"$ref":"#/components/schemas/ResponseTimePoint"}},"uptime_chart":{"type":"array","items":{"$ref":"#/components/schemas/UptimePoint"}}}},"MonitorAssignment":{"type":"object","required":["id","monitor_id"],"properties":{"display_name":{"type":["string","null"]},"id":{"type":"integer","format":"int64","description":"`status_page_monitors.id` is a bigint sequence (NOT a uuid). Mistyping\nthis as Uuid made the row decode fail → `unwrap_or_default()` silently\nreturned an empty monitor list (latent read-API bug, fixed here)."},"monitor_id":{"type":"string","format":"uuid"},"monitor_name":{"type":["string","null"]},"sort_order":{"type":["integer","null"],"format":"int32"}}},"MonitorConsensus":{"type":"object","required":["monitor_id","rule","regions","down_count","total","holds","cities"],"properties":{"cities":{"type":"array","items":{"$ref":"#/components/schemas/RegionVerdict"},"description":"The latest answer of each Cloudflare city that checks this monitor. They are not part of\n`down_count` and `total`, which count core probes."},"down_count":{"type":"integer","minimum":0},"holds":{"type":"array","items":{"$ref":"#/components/schemas/RegionHold"},"description":"Edge cities held off for this monitor right now (empty when none)."},"monitor_id":{"type":"string","format":"uuid"},"regions":{"type":"array","items":{"$ref":"#/components/schemas/RegionVerdict"}},"rule":{"type":"string","description":"The active rule, verbatim from `regions_required` (\"majority\"|\"all\"|\"any\"|\"<n>\")."},"total":{"type":"integer","minimum":0},"verdict":{"type":["string","null"],"description":"\"up\" | \"down\", or null when no region has reported yet."}}},"MonitorConsensusListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MonitorConsensus"}}}},"MonitorConsensusResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/MonitorConsensus"}}},"MonitorHistory":{"type":"object","required":["name","history"],"properties":{"history":{"type":"array","items":{"$ref":"#/components/schemas/DayUptime"}},"name":{"type":"string"}}},"MonitorOut":{"type":"object","required":["id","name","url","monitor_type","status","interval","timeout","settings","confirmation_window","regions_required","alert_contacts","created_at","updated_at"],"properties":{"alert_contacts":{"type":"array","items":{"type":"string"}},"confirmation_threshold":{"type":["integer","null"],"format":"int32"},"confirmation_window":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"degraded_since":{"type":["string","null"],"description":"Set while the monitor is in the early-warning degraded state\n(grow-browser-testing-ux). Populated best-effort post-fetch; null when\nthe feature is off / the column is pre-migration. Drives the amber badge."},"description":{"type":["string","null"]},"escalation_policy_id":{"type":["string","null"],"format":"uuid"},"heartbeat_ping_url":{"type":["string","null"],"description":"Heartbeat monitors only: the ping URL the customer's job POSTs to. Phoenix\nparity (`Heartbeat.heartbeat_url`). `None` for non-heartbeat monitors."},"id":{"type":"string","format":"uuid"},"interval":{"type":"integer","format":"int32"},"last_check":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/LastCheck"}]},"monitor_type":{"type":"string"},"name":{"type":"string"},"regions_required":{"type":"string"},"reminder_interval_minutes":{"type":["integer","null"],"format":"int32"},"settings":{},"status":{"type":"string"},"third_party":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ThirdPartySummary","description":"`third_party` monitors only: the service, what it watches and the worst\nstatus right now. Absent for every other type."}]},"timeout":{"type":"integer","format":"int32"},"updated_at":{"type":"string","format":"date-time"},"uptime_percentage":{"type":["number","null"],"format":"double"},"url":{"type":"string"}}},"MonitorRegions":{"type":"object","required":["monitor_id","name","regions"],"properties":{"monitor_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"regions":{"type":"object","description":"region → latest `{status, response_time}` (VM-derived).","additionalProperties":{"$ref":"#/components/schemas/RegionEntry"},"propertyNames":{"type":"string"}}}},"MonitorToPause":{"type":"object","description":"A monitor that WOULD be paused on a downgrade to free.","required":["id","name","url"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"url":{"type":"string"}}},"MonitorUptime":{"type":"object","required":["name","uptime_available"],"properties":{"name":{"type":"string"},"uptime_available":{"type":"boolean","description":"False when VictoriaMetrics failed or has no point for this monitor."},"uptime_percent":{"type":["number","null"],"format":"double","description":"`null` when not known and `STATUS_UPTIME_NULL_WHEN_UNKNOWN` is on."}}},"NetworkEntry":{"type":"object","description":"One network request from a run.","required":["url"],"properties":{"duration_ms":{"type":"integer","format":"int64"},"size":{"type":"integer","format":"int64"},"status":{"type":"integer","format":"int64"},"type":{"type":"string"},"url":{"type":"string"}}},"NotificationPreferences":{"type":"object","description":"Row in `app.notification_preferences`. `quiet_hours_*` serialize as\n`\"HH:MM:SS\"` strings (or null); `severity_overrides` is a JSON object\nlike `{\"p1\": \"time-sensitive\"}`. `timezone` is an IANA name\n(`America/New_York`) or null (= UTC); it is validated by\n[`validate_timezone`] and used by the fan-out (T038) to evaluate the\nquiet-hours window in local wall-clock time.","required":["user_id","severity_overrides","mobile_push_enabled","digest_p3"],"properties":{"digest_p3":{"type":"boolean"},"mobile_push_enabled":{"type":"boolean"},"quiet_hours_end":{"type":["string","null"]},"quiet_hours_start":{"type":["string","null"]},"severity_overrides":{},"timezone":{"type":["string","null"]},"user_id":{"type":"string","format":"uuid"}}},"OAuthClientOut":{"type":"object","description":"One OAuth client in the management list (no secret). Mirrors `OAuth.list_clients`.","required":["id","name","redirect_uris","inserted_at"],"properties":{"id":{"type":"string"},"inserted_at":{"type":"string","format":"date-time"},"name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}}}},"OAuthClientsResponse":{"type":"object","description":"`{ clients: [...] }` — the OAuth-clients list response.","required":["clients"],"properties":{"clients":{"type":"array","items":{"$ref":"#/components/schemas/OAuthClientOut"}}}},"Offender":{"type":"object","description":"A worst-offender monitor over the window — incident count + total downtime.","required":["monitor_id","monitor_name","incident_count","total_downtime_seconds"],"properties":{"incident_count":{"type":"integer","format":"int64"},"monitor_id":{"type":"string","format":"uuid"},"monitor_name":{"type":"string"},"total_downtime_seconds":{"type":"integer","format":"int64"}}},"OrgTrendsOut":{"type":"object","description":"`GET /api/analytics/organization/trends` — org overall uptime + uptime trend\n+ incident frequency + top offenders.","required":["period_days","overall_uptime","uptime_trends","incident_frequency","top_offenders"],"properties":{"incident_frequency":{"type":"array","items":{"$ref":"#/components/schemas/FreqPoint"}},"overall_uptime":{"type":"number","format":"double"},"period_days":{"type":"integer","format":"int64"},"top_offenders":{"type":"array","items":{"$ref":"#/components/schemas/Offender"}},"uptime_trends":{"type":"array","items":{"$ref":"#/components/schemas/UptimeTrendPoint"}}}},"OverrideOut":{"type":"object","required":["id","participant","starts_at","ends_at"],"properties":{"ends_at":{"type":"string","format":"date-time"},"id":{"type":"string","format":"uuid"},"participant":{"$ref":"#/components/schemas/ParticipantDto"},"starts_at":{"type":"string","format":"date-time"}}},"OverrideResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/OverrideOut"}}},"ParticipantDto":{"type":"object","description":"A rotation participant: who, and the channels to page them on.","required":["id"],"properties":{"channel_ids":{"type":"array","items":{"type":"string"}},"id":{"type":"string"}}},"PatchNotificationPreferences":{"type":"object","description":"`PATCH /api/users/me/notification-preferences` body. Every field is\noptional (absent = no change); the quiet-hours fields are tri-state\n(absent = no change, null = clear the window, `\"HH:MM\"` = set it).","properties":{"digest_p3":{"type":["boolean","null"]},"mobile_push_enabled":{"type":["boolean","null"]},"quiet_hours_end":{"type":["string","null"]},"quiet_hours_start":{"type":["string","null"]},"severity_overrides":{},"timezone":{"type":["string","null"],"description":"Tri-state like the quiet-hours fields (absent = no change,\nnull = clear to UTC, `\"Area/City\"` = set after IANA validation)."}}},"Percentiles":{"type":"object","required":["p50","p95","p99"],"properties":{"p50":{"type":"number","format":"double"},"p95":{"type":"number","format":"double"},"p99":{"type":"number","format":"double"}}},"Popularity":{"type":"object","description":"The popularity block. Below the thresholds only `visible: false` is sent:\nno count leaks while the data is too thin to show.","required":["visible"],"properties":{"launched_at":{"type":["string","null"],"description":"When the feature went live for customers. The text's launch month comes\nfrom this value, never from a typed constant."},"services":{"type":"array","items":{"$ref":"#/components/schemas/PopularityService"},"description":"The most watched services, most first (at most 5). Only real counts."},"total_monitors":{"type":["integer","null"],"format":"int64"},"total_organizations":{"type":["integer","null"],"format":"int64","description":"Organizations with at least one third party monitor."},"visible":{"type":"boolean"}}},"PopularityResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Popularity"}}},"PopularityService":{"type":"object","required":["slug","name","organizations","share_percent"],"properties":{"name":{"type":"string"},"organizations":{"type":"integer","format":"int64","description":"Organizations that watch this service with at least one monitor."},"share_percent":{"type":"integer","format":"int64","description":"`organizations` as a whole percent of `total_organizations`."},"slug":{"type":"string"}}},"PreviewResponse":{"type":"object","required":["status","duration_ms"],"properties":{"duration_ms":{"type":"integer","format":"int64","minimum":0},"error":{"type":["string","null"],"description":"Why the preview is `down` (one short line from the browser, for example\n`page.goto: net::ERR_CONNECTION_RESET`). Absent when it is up, or when the probe cannot say why."},"screenshot_url":{"type":["string","null"],"description":"Presigned screenshot URL (15-min); null if R2 unconfigured / no shot."},"status":{"type":"string","description":"\"up\" | \"down\"."},"web_vitals":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PreviewVitals"}]}}},"PreviewVitals":{"type":"object","properties":{"cls":{"type":["number","null"],"format":"double"},"fcp_ms":{"type":["number","null"],"format":"double"},"inp_ms":{"type":["number","null"],"format":"double"},"lcp_ms":{"type":["number","null"],"format":"double"},"ttfb_ms":{"type":["number","null"],"format":"double"}}},"PublicInvitationOrg":{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}},"PublicInvitationOut":{"type":"object","required":["id","email","role","invited_at","organization"],"properties":{"email":{"type":"string"},"expires_at":{"type":["string","null"],"format":"date-time"},"id":{"type":"string","format":"uuid"},"invited_at":{"type":"string","format":"date-time","description":"`inserted_at` exposed as `invited_at` to match the legacy client shape."},"invited_by":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Inviter","description":"The member who sent the invite (`null` if that user was removed)."}]},"organization":{"$ref":"#/components/schemas/PublicInvitationOrg"},"role":{"type":"string"}}},"PublicInvitationResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/PublicInvitationOut"}}},"RegionEntry":{"type":"object","required":["status","response_time"],"properties":{"label":{"type":["string","null"],"description":"Display name when the API knows one (\"Nuremberg (free)\" for the free\nregion, a city for the others). The map key stays the region code."},"response_time":{"type":"integer","format":"int64"},"status":{"type":"string"}}},"RegionHold":{"type":"object","description":"A Cloudflare city a site blocks or throttles for this monitor, held off\nfor a while (OpenSpec 121, rule P19). The city is not checking, so it is\nnot in `regions` and does not count in the verdict.","required":["region","reason","vendor","since","until"],"properties":{"label":{"type":["string","null"],"description":"Display name when the API knows one (\"Jakarta, ID\")."},"reason":{"type":"string","description":"\"bot_wall\" | \"refused_core_up\" | \"throttled\" | \"blocked\"."},"region":{"type":"string","description":"City code, as in `regions` (`cgk`)."},"since":{"type":"string","format":"date-time"},"status_code":{"type":["integer","null"],"format":"int32","description":"The last blocked answer's HTTP status (\"blocked from Jakarta (HTTP 403)\").","minimum":0},"until":{"type":"string","format":"date-time","description":"When the city checks again (a new hold may follow)."},"vendor":{"type":"string","description":"Bot-wall product, or \"none\"."}}},"RegionOut":{"type":"object","required":["id","code","name"],"properties":{"code":{"type":"string"},"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}},"RegionVerdict":{"type":"object","required":["region","status","response_time"],"properties":{"checked_at":{"type":["string","null"],"description":"When this location last checked. Absent only when the server has no time for it."},"label":{"type":["string","null"],"description":"Display name when the API knows one (\"Nuremberg (free)\" for the free\nregion); the dashboard falls back to its own city map when absent."},"region":{"type":"string"},"response_time":{"type":"integer","format":"int64"},"stale":{"type":"boolean","description":"No check in the last 2 intervals plus 5 minutes. Not in `down_count`, `total` or `verdict`."},"status":{"type":"string","description":"\"up\" | \"down\" (VM last-status; binary, matches the alert pipeline)."}}},"RegionsResponse":{"type":"object","required":["slug","monitors","updated_at"],"properties":{"monitors":{"type":"array","items":{"$ref":"#/components/schemas/MonitorRegions"}},"slug":{"type":"string"},"updated_at":{"type":"string"}}},"RegisterLiveActivity":{"type":"object","description":"`POST /api/push/live-activities` body.\n\n* `kind = \"push_to_start\"`: `{token, kind, environment?}` — stored per\n  device. `incident_id` (sent by app 1.0.0) is accepted and ignored.\n* `kind = \"update\"`: `{incident_id, token, kind, expires_in_seconds?,\n  environment?}` — the per-activity update token (app 1.1 sends a 12 h\n  TTL).\n\n`environment` is `sandbox` | `production`; absent or blank = not\nreported. The device is always the caller's bearer; any device or user\nid in the body is ignored.","required":["token","kind"],"properties":{"environment":{"type":["string","null"]},"expires_in_seconds":{"type":["integer","null"],"format":"int64"},"incident_id":{"type":["string","null"],"format":"uuid"},"kind":{"type":"string"},"token":{"type":"string"}}},"RegisterPushDevice":{"type":"object","description":"`POST /api/push/devices` body — the Flutter app registers its provider\ntoken after login (and re-registers on token refresh). Idempotent: the\n`(platform, token)` upsert refreshes ownership/metadata and clears a\nprevious invalidation instead of duplicating the row.","required":["platform","token"],"properties":{"app_version":{"type":["string","null"]},"environment":{"type":["string","null"]},"platform":{"type":"string"},"token":{"type":"string"}}},"RemoveLiveActivity":{"type":"object","description":"`DELETE /api/push/live-activities` body — the activity is identified by\nits push token (globally unique per activity).","required":["token"],"properties":{"token":{"type":"string"}}},"ResolvedResponse":{"type":"object","properties":{"at":{"type":["string","null"],"format":"date-time","description":"When this shift ends / the next handoff occurs (UTC)."},"participant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ParticipantDto","description":"Who is on call (null if nobody — empty rotation, no override)."}]}}},"ResponseTimePoint":{"type":"object","description":"One response-time sample — `{ timestamp: unix-secs, response_time: ms }`.","required":["timestamp","response_time"],"properties":{"response_time":{"type":"number","format":"double"},"timestamp":{"type":"integer","format":"int64"}}},"ScheduleListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleOut"}}}},"ScheduleOut":{"type":"object","required":["id","organization_id","name","timezone","rotation_type","rotation_length_secs","anchor_at","participants","inserted_at","updated_at"],"properties":{"anchor_at":{"type":"string","format":"date-time"},"id":{"type":"string","format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"name":{"type":"string"},"organization_id":{"type":"string","format":"uuid"},"participants":{"type":"array","items":{"$ref":"#/components/schemas/ParticipantDto"}},"rotation_length_secs":{"type":"integer","format":"int64"},"rotation_type":{"type":"string"},"timezone":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"ScheduleResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ScheduleOut"}}},"ServiceDetail":{"type":"object","required":["slug","name","category","status","status_page_url","allowance","components","incidents"],"properties":{"allowance":{"$ref":"#/components/schemas/Allowance"},"category":{"type":"string"},"components":{"type":"array","items":{"$ref":"#/components/schemas/DetailComponent"}},"incidents":{"type":"array","items":{"$ref":"#/components/schemas/DetailIncident"}},"last_ok_at":{"type":["string","null"]},"name":{"type":"string"},"scope_group":{"type":["string","null"],"description":"When set, a whole-service monitor counts only this vendor group."},"slug":{"type":"string"},"status":{"type":"string"},"status_page_url":{"type":"string"}}},"ServiceDetailResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ServiceDetail"}}},"ShowIncident":{"type":"object","required":["id","status"],"properties":{"cause":{"type":["string","null"]},"duration":{"type":["integer","null"],"format":"int32"},"id":{"type":"string","format":"uuid"},"monitor_name":{"type":["string","null"]},"resolved_at":{"type":["string","null"]},"started_at":{"type":["string","null"]},"status":{"type":"string"}}},"ShowMaintenance":{"type":"object","required":["status"],"properties":{"end_time":{"type":["string","null"]},"start_time":{"type":["string","null"]},"status":{"type":"string"},"title":{"type":["string","null"]}}},"ShowMonitor":{"type":"object","required":["name","status"],"properties":{"last_checked_at":{"type":["string","null"]},"name":{"type":"string"},"response_time":{"type":["integer","null"],"format":"int64"},"status":{"type":"string","description":"\"up\" | \"down\" | \"unknown\" (VM latest check; \"unknown\" when no sample), or\n\"paused\" when the monitor is paused."}}},"ShowPublicData":{"type":"object","required":["name","slug","allow_subscriptions","whitelabel","noindex","theme","overall_status","uptime_available","monitors","recent_incidents","maintenance_windows"],"properties":{"allow_subscriptions":{"type":"boolean"},"description":{"type":["string","null"]},"logo_url":{"type":["string","null"]},"maintenance_windows":{"type":"array","items":{"$ref":"#/components/schemas/ShowMaintenance"}},"monitors":{"type":"array","items":{"$ref":"#/components/schemas/ShowMonitor"}},"name":{"type":"string"},"noindex":{"type":"boolean"},"overall_status":{"type":"string","description":"\"operational\" | \"degraded\" | \"partial_outage\" | \"major_outage\"."},"recent_incidents":{"type":"array","items":{"$ref":"#/components/schemas/ShowIncident"}},"slug":{"type":"string"},"theme":{"description":"`status_pages.theme_config` (jsonb), defaults to `{}`."},"uptime_available":{"type":"boolean","description":"False when VictoriaMetrics failed or had no data: `uptime_percentage` is not a measurement."},"uptime_percentage":{"type":["number","null"],"format":"double","description":"Page-level mean daily uptime % over the last 30d (VM-derived). `null` when not known and\n`STATUS_UPTIME_NULL_WHEN_UNKNOWN` is on; see `uptime_available`."},"whitelabel":{"type":"boolean"}}},"ShowPublicEnvelope":{"type":"object","description":"`GET /api/status/:slug` — public JSON status page.\n\nDROP-IN replacement for the Phoenix `show_public` view: same `data`-enveloped\nshape and the same data sources — monitor `status` / `response_time` /\n`last_checked_at` and the page `uptime_percentage` come from VictoriaMetrics\n(via [`crate::vm`]), NOT from Postgres incidents. Public + read-only.","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ShowPublicData"}}},"ShowResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/MonitorOut"}}},"SmsVoiceUsage":{"type":"object","description":"SMS and phone-call usage for the current month (UTC) against the plan limits.","required":["plan","month","sms_used","sms_limit","calls_used","calls_limit","intl_sms_used","intl_sms_limit","intl_calls_used","intl_calls_limit","countries","sms_denied_calling_codes","voice_denied_calling_codes"],"properties":{"calls_limit":{"type":"integer","format":"int32"},"calls_used":{"type":"integer","format":"int32"},"countries":{"type":"string","description":"Where the plan can send: `none` (free), `launch` (pro: US, Canada, Lithuania, UAE, Vietnam) or `all`."},"intl_calls_limit":{"type":"integer","format":"int32"},"intl_calls_used":{"type":"integer","format":"int32","description":"Calls to numbers outside US/Canada (also counted in `calls_used`)."},"intl_sms_limit":{"type":"integer","format":"int32"},"intl_sms_used":{"type":"integer","format":"int32","description":"SMS to numbers outside US/Canada (also counted in `sms_used`)."},"month":{"type":"string","description":"`YYYY-MM` (UTC)."},"plan":{"type":"string"},"plan_calling_codes":{"type":["array","null"],"items":{"type":"string"},"description":"Codes the plan is limited to (`null` = every supported code). The server is the authority."},"sms_calling_codes":{"type":["array","null"],"items":{"type":"string"},"description":"When set, SMS goes only to these calling codes besides US/Canada. `null` (default):\nevery country except `sms_denied_calling_codes`."},"sms_denied_calling_codes":{"type":"array","items":{"type":"string"},"description":"Calling codes we never send an SMS to."},"sms_limit":{"type":"integer","format":"int32"},"sms_used":{"type":"integer","format":"int32"},"voice_calling_codes":{"type":["array","null"],"items":{"type":"string"},"description":"When set, calls go only to these calling codes besides US/Canada. `null` (default):\nevery country except `sms_denied_calling_codes` and `voice_denied_calling_codes`."},"voice_denied_calling_codes":{"type":"array","items":{"type":"string"},"description":"Calling codes we also never call (on top of the SMS list). Every `+1` number outside\nUS and Canada is not called either."}}},"SmsVoiceUsageResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/SmsVoiceUsage"}}},"SnoozeResponse":{"type":"object","description":"`POST /api/monitors/{id}/snooze` response.","required":["ok","snoozed_until"],"properties":{"ok":{"type":"boolean"},"snoozed_until":{"type":"string","format":"date-time","description":"`mobile_push` for this user + monitor resumes after this instant."}}},"SsoConfig":{"type":"object","description":"SSO/SAML provider config for the org (certificate omitted — only its presence\nis exposed via `has_certificate`). Port of the SamlController `show` shape.","required":["entity_id","sso_url","enforce","is_active","has_certificate"],"properties":{"enforce":{"type":"boolean"},"entity_id":{"type":"string"},"has_certificate":{"type":"boolean"},"is_active":{"type":"boolean"},"name_id_format":{"type":["string","null"]},"slo_url":{"type":["string","null"]},"sso_url":{"type":"string"}}},"SsoConfigResponse":{"type":"object","description":"`{ data: SsoConfig | null }` — the SSO config response envelope.","properties":{"data":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SsoConfig"}]}}},"StatusPageDetail":{"type":"object","required":["page","monitors"],"properties":{"monitors":{"type":"array","items":{"$ref":"#/components/schemas/MonitorAssignment"}},"page":{"$ref":"#/components/schemas/StatusPageOut"}}},"StatusPageDetailResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/StatusPageDetail"}}},"StatusPageListResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StatusPageOut"}}}},"StatusPageOut":{"type":"object","required":["id","name","slug","is_public","theme_config","allow_subscriptions","whitelabel","noindex","default_language","inserted_at","updated_at"],"properties":{"allow_subscriptions":{"type":"boolean"},"custom_domain":{"type":["string","null"]},"default_language":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"inserted_at":{"type":"string","format":"date-time"},"is_public":{"type":"boolean"},"logo_url":{"type":["string","null"]},"name":{"type":"string"},"noindex":{"type":"boolean"},"slug":{"type":"string"},"theme_config":{"description":"`theme_config` jsonb, defaults to `{}`."},"updated_at":{"type":"string","format":"date-time"},"whitelabel":{"type":"boolean"}}},"StatusResponse":{"type":"object","description":"`GET /api/nonprofit/status` body.","required":["enabled","can_manage","paid_subscription","domains"],"properties":{"application":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Application","description":"The newest application, if any."}]},"can_manage":{"type":"boolean","description":"The caller may claim or apply (owner or admin role)."},"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainVerdict"}},"enabled":{"type":"boolean"},"grant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Grant"}]},"paid_subscription":{"type":"boolean","description":"The organization pays for a plan now (Paddle or App Store)."}}},"StepInput":{"type":"object","properties":{"alert_channel_id":{"type":["string","null"],"format":"uuid","description":"Exactly one of `alert_channel_id` or `on_call_schedule_id` must be set."},"delay_minutes":{"type":["integer","null"],"format":"int32"},"on_call_schedule_id":{"type":["string","null"],"format":"uuid"},"step_order":{"type":["integer","null"],"format":"int32"}}},"SubscriptionOut":{"type":"object","required":["id","plan","status","provider"],"properties":{"apple_product_id":{"type":["string","null"],"description":"App Store product id (for example `app.uptrack.mobile.pro.monthly`);\nnull for Paddle."},"cancelled_at":{"type":["string","null"],"format":"date-time"},"current_period_end":{"type":["string","null"],"format":"date-time"},"current_period_start":{"type":["string","null"],"format":"date-time"},"id":{"type":"string","format":"uuid"},"past_due_since":{"type":["string","null"],"format":"date-time","description":"When a Paddle subscription first became `past_due` (OpenSpec 138); null for any\nother status and for App Store rows. The web banner shows \"Payment failed on {date}\"."},"plan":{"type":"string"},"provider":{"type":"string","description":"`paddle` or `apple`: who bills this subscription (D7). The app and the\nweb show the matching text and buttons.","example":"paddle"},"scheduled_cancel_at":{"type":["string","null"],"format":"date-time","description":"Set when a cancel is scheduled at period end (access ends then): Paddle's\nscheduled change, or App Store auto-renew turned off."},"status":{"type":"string"}}},"SubscriptionResponse":{"type":"object","description":"`{ data: subscription|null, plan, grant }` — the billing-subscription response envelope.","required":["plan"],"properties":{"data":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SubscriptionOut"}]},"grant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GrantOut","description":"The live nonprofit grant, or null. `data` keeps its meaning: the paid subscription."}]},"plan":{"type":"string"}}},"ThirdPartyComponentRef":{"type":"object","required":["id","name","status","removed"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"removed":{"type":"boolean","description":"True when the vendor no longer lists the component."},"status":{"type":"string","description":"The component's status, or `unknown` while the service is not read\nrecently or the vendor removed the component."}}},"ThirdPartyInput":{"type":"object","description":"The service and components of a new third party monitor.","required":["service_slug"],"properties":{"component_ids":{"type":["array","null"],"items":{"type":"string","format":"uuid"},"description":"Components of that service to watch. Empty or absent = the whole service."},"service_slug":{"type":"string","description":"Slug of an enabled catalog service, for example `cloudflare`\n(`GET /api/third-party/services`)."}}},"ThirdPartyServiceRef":{"type":"object","required":["slug","name","status_page_url"],"properties":{"name":{"type":"string"},"slug":{"type":"string"},"status_page_url":{"type":"string"}}},"ThirdPartySummary":{"type":"object","description":"What a monitor response carries for a `third_party` monitor.","required":["service","whole_service","status","watched_count","components"],"properties":{"components":{"type":"array","items":{"$ref":"#/components/schemas/ThirdPartyComponentRef"},"description":"The picked components. Empty for a whole-service monitor."},"service":{"$ref":"#/components/schemas/ThirdPartyServiceRef"},"status":{"type":"string","description":"Worst status among what the monitor watches: `operational`,\n`maintenance`, `degraded`, `partial_outage`, `major_outage` or `unknown`."},"watched_count":{"type":"integer","format":"int64","description":"How many components the monitor watches (picked, or in scope for a\nwhole-service monitor)."},"whole_service":{"type":"boolean","description":"True when the monitor watches the whole service (no components picked)."}}},"ThirdPartyUpdate":{"type":"object","description":"What an update may change on a third party monitor.","properties":{"component_ids":{"type":["array","null"],"items":{"type":"string","format":"uuid"},"description":"Absent = keep the current set. A list replaces it; `[]` = the whole service."},"service_slug":{"type":["string","null"],"description":"Optional; when sent it must be the monitor's own service (a monitor\ncannot move to another service: create a new one)."}}},"TransferOwnership":{"type":"object","properties":{"to_user_id":{"type":["string","null"],"format":"uuid"}}},"TwoFactorStatus":{"type":"object","description":"`GET /api/auth/2fa/status` — whether the user has TOTP enabled. Port of\n`TwoFactorController.status`.\n`{ enabled }` — whether the current user has a confirmed TOTP credential.","required":["enabled"],"properties":{"enabled":{"type":"boolean"}}},"UnregisterPushDevice":{"type":"object","description":"`DELETE /api/push/devices` body — the device is identified by its\nprovider token (globally unique per platform); `platform` optionally\nnarrows the match.","required":["token"],"properties":{"platform":{"type":["string","null"]},"token":{"type":"string"}}},"UpdateAlertChannel":{"type":"object","description":"Request body for `PATCH /api/alert-channels/{id}` (all optional).","properties":{"config":{"type":["object","null"]},"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"]},"type":{"type":["string","null"]}}},"UpdateIncident":{"type":"object","properties":{"cause":{"type":["string","null"]},"status":{"type":["string","null"]}}},"UpdateMaintenanceWindow":{"type":"object","properties":{"description":{"type":["string","null"]},"end_time":{"type":["string","null"],"format":"date-time"},"recurrence":{"type":["string","null"]},"start_time":{"type":["string","null"],"format":"date-time"},"status":{"type":["string","null"]},"title":{"type":["string","null"]}}},"UpdateMonitor":{"type":"object","description":"Request body for `PATCH /api/monitors/{id}`. All optional (partial update);\nsemantic validation runs in the handler against the current row.","properties":{"alert_contacts":{"type":["array","null"],"items":{"type":"string"},"description":"Per-monitor alert-channel selection (channel ids). `app.monitors.alert_contacts`\nis `varchar[]`; empty/absent = all channels (Phoenix semantics)."},"confirmation_threshold":{"type":["integer","null"],"format":"int64"},"confirmation_window":{"type":["string","null"]},"description":{"type":["string","null"]},"escalation_policy_id":{"type":["string","null"],"format":"uuid"},"interval":{"type":["integer","null"],"format":"int64"},"monitor_type":{"type":["string","null"]},"name":{"type":["string","null"]},"region_ids":{"type":["array","null"],"items":{"type":"integer","format":"int64"}},"regions_required":{"type":["string","null"]},"reminder_interval_minutes":{"type":["integer","null"],"format":"int64"},"settings":{"type":["object","null"]},"status":{"type":["string","null"]},"third_party":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ThirdPartyUpdate","description":"Third party monitors only: change the watched components."}]},"timeout":{"type":["integer","null"],"format":"int64"},"url":{"type":["string","null"]}}},"UpdatePolicy":{"type":"object","properties":{"description":{"type":["string","null"]},"name":{"type":["string","null"]},"steps":{"type":["array","null"],"items":{"$ref":"#/components/schemas/StepInput"}}}},"UpdateRole":{"type":"object","properties":{"role":{"type":["string","null"]}}},"UpdateSchedule":{"type":"object","properties":{"anchor_at":{"type":["string","null"],"format":"date-time"},"name":{"type":["string","null"]},"participants":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ParticipantDto"}},"rotation_length_secs":{"type":["integer","null"],"format":"int64"},"rotation_type":{"type":["string","null"]},"timezone":{"type":["string","null"]}}},"UpdateStatusPage":{"type":"object","properties":{"allow_subscriptions":{"type":["boolean","null"]},"custom_domain":{"type":["string","null"]},"default_language":{"type":["string","null"]},"description":{"type":["string","null"]},"is_public":{"type":["boolean","null"]},"logo_url":{"type":["string","null"]},"monitor_ids":{"type":["array","null"],"items":{"type":"string","format":"uuid"}},"name":{"type":["string","null"]},"noindex":{"type":["boolean","null"]},"password":{"type":["string","null"]},"password_protected":{"type":["boolean","null"]},"slug":{"type":["string","null"]},"theme_config":{"type":["object","null"]},"whitelabel":{"type":["boolean","null"]}}},"UptimePoint":{"type":"object","description":"One daily uptime point — `{ date: \"YYYY-MM-DD\", uptime: % }`. Date-based so it\nmatches the React UptimeChart/UptimeBar (`{ date, uptime }`).","required":["date","uptime"],"properties":{"date":{"type":"string"},"uptime":{"type":"number","format":"double"}}},"UptimeResponse":{"type":"object","required":["slug","window_days","monitors","updated_at"],"properties":{"monitors":{"type":"array","items":{"$ref":"#/components/schemas/MonitorUptime"}},"slug":{"type":"string"},"updated_at":{"type":"string"},"window_days":{"type":"integer","format":"int64"}}},"UptimeTrendPoint":{"type":"object","description":"One daily org uptime-trend point — `{ date, uptime: %, total_checks }`.","required":["date","uptime","total_checks"],"properties":{"date":{"type":"string"},"total_checks":{"type":"integer","format":"int64"},"uptime":{"type":"number","format":"double"}}},"Verdict":{"type":"string","description":"Why a domain can or cannot get the automatic grant.","enum":["eligible","blocked","government","taken","not_listed"]},"VitalsPoint":{"type":"object","description":"One point on the Web Vitals trend (per browser run). `cls` is unitless;\nthe `_ms` metrics are milliseconds. Any may be null (unmeasured / capture\noff / pre-migration build).","required":["inserted_at"],"properties":{"cls":{"type":["number","null"],"format":"double"},"fcp_ms":{"type":["number","null"],"format":"double"},"inp_ms":{"type":["number","null"],"format":"double"},"inserted_at":{"type":"string"},"lcp_ms":{"type":["number","null"],"format":"double"},"ttfb_ms":{"type":["number","null"],"format":"double"}}},"VitalsSeriesResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/VitalsPoint"}}}},"WidgetData":{"type":"object","required":["slug","name","status","status_text","status_color","uptime_text","uptime_available","updated_at"],"properties":{"name":{"type":"string"},"slug":{"type":"string"},"status":{"type":"string"},"status_color":{"type":"string"},"status_text":{"type":"string"},"updated_at":{"type":"string"},"uptime":{"type":["number","null"],"format":"double","description":"30 day uptime %. `null` when not known and `STATUS_UPTIME_NULL_WHEN_UNKNOWN` is on."},"uptime_available":{"type":"boolean","description":"False when VictoriaMetrics failed or had no data: `uptime` is not a measurement."},"uptime_text":{"type":"string","description":"`\"99.95%\"`, or `\"\"` when `uptime` is `null`."}}}},"securitySchemes":{"api_key":{"type":"http","scheme":"bearer"},"session":{"type":"apiKey","in":"cookie","name":"_uptrack_key"}}},"tags":[{"name":"status","description":"Public status-page read API"},{"name":"third-party","description":"Third party monitoring: the catalog of vendor status pages (404 while THIRD_PARTY_ENABLED is off)"},{"name":"nonprofit","description":"Free Pro for nonprofits (OpenSpec 136; claim and applications answer 404 while NONPROFIT_PROGRAM_ENABLED is off)"}]}