{"openapi":"3.0.3","info":{"title":"UptimeX API","version":"1.1.0","description":"The UptimeX REST API. Authenticate with a project API key (`upk_...`, created in the dashboard) sent as `Authorization: Bearer <key>`. A key is scoped to one project and acts with the role of whoever created it; it reaches that project's monitors, events, incidents, channels, maintenance windows, status page and escalation policy. The Projects, Tokens, Team and Connectors groups, and custom status-page domains, are dashboard-only: they take a session and answer `403 session_required` to a key.\n\nRequests made with a key are rate limited per account (requests per minute: free 30, pro 120, team 300); over the limit the API answers 429 with `Retry-After`. Every error is JSON with an `error` code; see the `Error` schema for the extra keys some codes carry. Timestamps are epoch milliseconds. Lists are not paginated."},"servers":[{"url":"https://api.uptimex.co","description":"Production"},{"url":"https://api-staging.uptimex.co","description":"Staging"}],"tags":[{"name":"Monitors","description":"Create, read, update, pause and delete monitors; test a configuration; heartbeat check-ins."},{"name":"Events","description":"Status changes and user actions, per monitor or across the project."},{"name":"Incidents","description":"Outages the checks opened and incidents declared by hand, with their update timeline, acknowledgement and the per-project policy. Paid plans."},{"name":"Channels","description":"Where alerts go (Slack, Discord, Telegram, webhooks, email) and which transitions the project alerts on."},{"name":"Maintenance","description":"Scheduled windows during which covered monitors are not checked."},{"name":"Status pages","description":"The project's public status page, its monitor selection and custom domain. Paid plans."},{"name":"Escalation","description":"On-call escalation steps for unacknowledged incidents. Team plan."},{"name":"Projects","description":"Dashboard-only: project lifecycle. An API key is refused with `403 session_required`."},{"name":"Tokens","description":"Dashboard-only: create, list and revoke API keys. An API key is refused with `403 session_required`."},{"name":"Team","description":"Dashboard-only: members and invites. An API key is refused with `403 session_required`."},{"name":"Connectors","description":"Dashboard-only: import Vercel and Supabase projects as monitors. An API key is refused with `403 session_required`."}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"A project API key (`upk_...`), created in the dashboard under the project's Access tokens. It reaches that one project's monitors, events, incidents, channels, maintenance windows, status page and escalation policy, with the role of the person who created it."},"session":{"type":"http","scheme":"bearer","description":"A dashboard session token, issued to the UptimeX app and web dashboard by the sign-in flow. Not obtainable through this API. Routes that list only this scheme are dashboard-only: an API key gets `403 session_required`."}},"schemas":{"ContentRule":{"type":"object","properties":{"type":{"type":"string","enum":["text_contains","text_absent","json_field"],"description":"Rule kind."},"value":{"type":"string","maxLength":256,"description":"text_contains / text_absent: the literal to look for."},"path":{"type":"string","maxLength":128,"description":"json_field: dot path into the JSON body, e.g. `data.status`."},"equals":{"type":"string","maxLength":256,"description":"json_field: expected value. Omit to require only that the field exists."}},"required":["type"]},"HeaderOut":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["bearer","apikey","custom"]}},"required":["name"],"description":"Header name (+ type hint) only. Values are write-only and never returned."},"Monitor":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["http","keyword","api","heartbeat","scheduler","dns","port"]},"url":{"type":"string","description":"Empty for heartbeat, port and dns monitors."},"method":{"type":"string"},"interval_sec":{"type":"integer"},"slow_ms":{"type":"integer"},"timeout_ms":{"type":"integer"},"expect_status":{"type":"integer","nullable":true},"follow_redirects":{"type":"boolean"},"check_ssl":{"type":"boolean"},"check_domain":{"type":"boolean"},"domain_expires_at":{"type":"integer","nullable":true,"description":"Domain registration expiry from RDAP; null until looked up. Read-only. Epoch milliseconds."},"cert_expires_at":{"type":"integer","nullable":true,"description":"TLS certificate expiry; null until probed. Read-only. Epoch milliseconds."},"host":{"type":"string","nullable":true,"description":"port / dns: the target host. null for other types."},"port":{"type":"integer","nullable":true,"description":"port monitors only; null otherwise."},"dns_record_type":{"type":"string","nullable":true,"enum":["A","AAAA","CNAME","MX","TXT","NS"],"description":"dns monitors only; null otherwise."},"dns_expected_value":{"type":"string","nullable":true,"description":"dns: the required answer substring, or null."},"content_rules":{"type":"array","items":{"$ref":"#/components/schemas/ContentRule"}},"request_headers":{"type":"array","items":{"$ref":"#/components/schemas/HeaderOut"}},"request_body":{"type":"string","nullable":true},"fail_threshold":{"type":"integer"},"recover_threshold":{"type":"integer"},"grace_sec":{"type":"integer","description":"heartbeat: grace seconds after `interval_sec`."},"last_ping_at":{"type":"integer","nullable":true,"description":"heartbeat: the last ping; null until the first. Epoch milliseconds."},"last_http_status":{"type":"integer","nullable":true,"description":"Response code of the newest check; null when there was no response or the type has none."},"last_dns_answers":{"type":"array","nullable":true,"items":{"type":"string"},"description":"dns: the records the last resolve returned; null for other types or before the first resolve."},"last_dns_answers_at":{"type":"integer","nullable":true,"description":"dns: when the answer set last changed (not when it was last checked). Epoch milliseconds."},"muted_until":{"type":"integer","nullable":true,"description":"Down detection and alerts are suppressed until this time; null when not muted. Epoch milliseconds."},"enabled":{"type":"boolean"},"paused_reason":{"type":"string","nullable":true,"description":"Set when the system paused the monitor, separately from `enabled`. `plan`: the account holds more monitors than its plan allows after a downgrade and this one is over the line. null otherwise."},"project_id":{"type":"string","nullable":true,"description":"Owning project, or null when ungrouped."},"status":{"type":"string","nullable":true,"enum":["up","slow","down"],"description":"null until the first check completes."},"status_since":{"type":"integer","nullable":true,"description":"When the current status began; null if never set. Epoch milliseconds."},"last_latency_ms":{"type":"number","nullable":true},"last_connect_ms":{"type":"number","nullable":true},"last_ttfb_ms":{"type":"number","nullable":true},"uptime_24h":{"type":"number","nullable":true,"description":"Percent of checks in the last 24h that were not down."},"avg_latency_24h":{"type":"number","nullable":true},"last_checked_at":{"type":"integer","nullable":true,"description":"Newest check. Epoch milliseconds."}},"required":["id","name","type","url","method","interval_sec","slow_ms","timeout_ms","expect_status","follow_redirects","check_ssl","check_domain","domain_expires_at","cert_expires_at","host","port","dns_record_type","dns_expected_value","content_rules","request_headers","request_body","fail_threshold","recover_threshold","grace_sec","last_ping_at","last_http_status","last_dns_answers","last_dns_answers_at","muted_until","enabled","paused_reason","project_id","status","status_since","last_latency_ms","last_connect_ms","last_ttfb_ms","uptime_24h","avg_latency_24h","last_checked_at"]},"MonitorWithHistory":{"allOf":[{"$ref":"#/components/schemas/Monitor"},{"type":"object","properties":{"history":{"type":"array","items":{"type":"string","nullable":true,"enum":["up","slow","down"]},"description":"The last 30 check results, oldest first, padded with null on the left while fewer than 30 have run."}},"required":["history"]}]},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Machine-readable code. The docs list every code at /docs/api/errors.","example":"not_found"},"limit":{"type":"number","description":"With a plan-limit code (`monitor_limit`, `project_limit`, `domain_limit`, `rate_limited`, `plan_required` for maintenance): the cap that was hit."},"feature":{"type":"string","description":"With `plan_required`: the plan feature the request needs (`monitor_type`, `advanced_monitoring`, `email_alerts`, `maintenance`, `escalation`, `audit_log`). Absent when a free project asked for incidents or a status page."},"field":{"type":"string","description":"With `invalid`: the request field that is out of range."},"reason":{"type":"string","description":"With `invalid_target`: why the URL or host cannot be monitored (`invalid_url`, `scheme_not_allowed`, `internal_host`, `private_ip`, `ip_not_allowed`, `ipv6_literal_blocked`, `non_public_host`)."},"request_id":{"type":"string","nullable":true,"description":"With `internal_error` (500): the request id to quote when reporting it."}},"required":["error"]},"HeaderInput":{"type":"object","properties":{"name":{"type":"string","example":"Authorization"},"value":{"type":"string","description":"Plaintext value, encrypted at rest. On PATCH, omit it to keep the stored value for this name."},"type":{"type":"string","enum":["bearer","apikey","custom"],"description":"Dashboard hint only."}},"required":["name"]},"MonitorInput":{"type":"object","properties":{"type":{"type":"string","enum":["http","keyword","api","heartbeat","scheduler","dns","port"],"default":"http","description":"What the monitor checks. `http` polls a URL; `keyword` is http plus at least one content rule; `api` is http with JSON-field rules (paid); `heartbeat` waits for your job to ping it; `scheduler` calls your URL on a schedule and treats 2xx as success (paid); `port` opens a TCP connection to host:port; `dns` resolves a record (paid). Cannot be changed after creation."},"name":{"type":"string","default":"Untitled"},"url":{"type":"string","format":"uri","description":"http / keyword / api / scheduler: the URL to call. Required for those types. Public hosts only (`invalid_target` otherwise).","example":"https://example.com/health"},"method":{"type":"string","enum":["HEAD","GET","POST","PUT","PATCH","DELETE","OPTIONS"],"default":"HEAD","description":"http / keyword / api: HEAD is switched to GET when content rules are set. scheduler: one of GET, POST, PUT, PATCH, DELETE (a trigger must act), default POST."},"interval_sec":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Seconds between checks, raised to the project owner's plan minimum (free 300s, pro 60s, team 60s). heartbeat: the longest allowed gap between pings."},"grace_sec":{"type":"integer","minimum":0,"default":60,"description":"heartbeat only: extra seconds after `interval_sec` before the monitor goes down."},"slow_ms":{"type":"integer","default":1500,"description":"http / keyword / api: latency at or above this is `slow`."},"timeout_ms":{"type":"integer","minimum":1000,"maximum":60000,"default":10000,"description":"Request timeout, clamped to 1000 to 60000. Not used by heartbeat."},"expect_status":{"type":"integer","nullable":true,"description":"http / keyword / api: exact status code required. null or 0 accepts any 2xx or 3xx."},"follow_redirects":{"type":"boolean","description":"http / keyword / api: follow 3xx and judge the final response. Off by default (a 3xx counts as reachable)."},"check_ssl":{"type":"boolean","description":"https only, paid (`plan_required` with `feature: advanced_monitoring` otherwise): report a certificate or TLS failure as a distinct SSL problem and track the certificate expiry."},"check_domain":{"type":"boolean","description":"Paid (`feature: advanced_monitoring`): look up the domain's registration expiry over RDAP and warn before it lapses."},"content_rules":{"type":"array","items":{"$ref":"#/components/schemas/ContentRule"},"maxItems":4,"description":"http / keyword / api: up to 4 rules the response must satisfy. keyword needs at least one (`keyword_needs_rule`). json_field rules are paid (`feature: advanced_monitoring`)."},"request_headers":{"type":"array","items":{"$ref":"#/components/schemas/HeaderInput"},"maxItems":4,"description":"http / keyword / api / scheduler: up to 4 headers sent with every check. Values are encrypted and never returned."},"request_body":{"type":"string","maxLength":8192,"description":"http / keyword / api / scheduler: body for POST, PUT, PATCH or DELETE (`invalid_body` with GET or HEAD, or over 8 KB). Sent with every check, so point writes at test data. `application/json` unless a Content-Type header is set."},"host":{"type":"string","description":"port / dns: bare hostname, no scheme, path or port. Required for those types. port accepts a public IP literal; dns does not.","example":"db.example.com"},"port":{"type":"integer","minimum":1,"maximum":65535,"description":"port only: TCP port to connect to. Required."},"dns_record_type":{"type":"string","enum":["A","AAAA","CNAME","MX","TXT","NS"],"default":"A","description":"dns only: record type to resolve."},"dns_expected_value":{"type":"string","maxLength":256,"description":"dns only: a string one of the answers must contain. Omit to accept any answer."},"fail_threshold":{"type":"integer","minimum":1,"default":3,"description":"Consecutive failed checks before `down`. Not used by heartbeat or scheduler."},"recover_threshold":{"type":"integer","minimum":1,"default":1,"description":"Consecutive good checks before `up` again."},"project_id":{"type":"string","description":"Project to create the monitor in. An API key always creates in its own project, whatever is sent here."}},"description":"Create body. Pick a `type`, then send the fields that type reads; the rest are ignored. `url` is required for http, keyword, api and scheduler; `host` for port and dns; `port` for port."},"CheckResult":{"type":"object","properties":{"status":{"type":"string","enum":["up","slow","down"]},"latency_ms":{"type":"number","nullable":true,"description":"Total; null on failure."},"connect_ms":{"type":"number","nullable":true,"description":"DNS + TCP + TLS; null when not measured."},"ttfb_ms":{"type":"number","nullable":true,"description":"Request to first byte; null when not measured."},"detail":{"type":"string","nullable":true,"description":"null when up; the failure reason otherwise."},"http_status":{"type":"number","nullable":true,"description":"Response code; null when there was no response."},"body":{"type":"string","description":"The first 4,096 characters of the response body. Test endpoint only; never stored."},"dns_answers":{"type":"array","items":{"type":"string"},"description":"dns only: the records the resolve returned, sorted."}},"required":["status","latency_ms","connect_ms","ttfb_ms","detail","http_status"]},"MonitorPatch":{"type":"object","properties":{"name":{"type":"string","default":"Untitled"},"url":{"type":"string","format":"uri","description":"http / keyword / api / scheduler: the URL to call. Required for those types. Public hosts only (`invalid_target` otherwise).","example":"https://example.com/health"},"method":{"type":"string","enum":["HEAD","GET","POST","PUT","PATCH","DELETE","OPTIONS"],"default":"HEAD","description":"http / keyword / api: HEAD is switched to GET when content rules are set. scheduler: one of GET, POST, PUT, PATCH, DELETE (a trigger must act), default POST."},"interval_sec":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Seconds between checks, raised to the project owner's plan minimum (free 300s, pro 60s, team 60s). heartbeat: the longest allowed gap between pings."},"grace_sec":{"type":"integer","minimum":0,"default":60,"description":"heartbeat only: extra seconds after `interval_sec` before the monitor goes down."},"slow_ms":{"type":"integer","default":1500,"description":"http / keyword / api: latency at or above this is `slow`."},"timeout_ms":{"type":"integer","minimum":1000,"maximum":60000,"default":10000,"description":"Request timeout, clamped to 1000 to 60000. Not used by heartbeat."},"expect_status":{"type":"integer","nullable":true,"description":"http / keyword / api: exact status code required. null or 0 accepts any 2xx or 3xx."},"follow_redirects":{"type":"boolean","description":"http / keyword / api: follow 3xx and judge the final response. Off by default (a 3xx counts as reachable)."},"check_ssl":{"type":"boolean","description":"https only, paid (`plan_required` with `feature: advanced_monitoring` otherwise): report a certificate or TLS failure as a distinct SSL problem and track the certificate expiry."},"check_domain":{"type":"boolean","description":"Paid (`feature: advanced_monitoring`): look up the domain's registration expiry over RDAP and warn before it lapses."},"content_rules":{"type":"array","items":{"$ref":"#/components/schemas/ContentRule"},"maxItems":4,"description":"http / keyword / api: up to 4 rules the response must satisfy. keyword needs at least one (`keyword_needs_rule`). json_field rules are paid (`feature: advanced_monitoring`)."},"request_headers":{"type":"array","items":{"$ref":"#/components/schemas/HeaderInput"},"maxItems":4,"description":"http / keyword / api / scheduler: up to 4 headers sent with every check. Values are encrypted and never returned."},"request_body":{"type":"string","maxLength":8192,"description":"http / keyword / api / scheduler: body for POST, PUT, PATCH or DELETE (`invalid_body` with GET or HEAD, or over 8 KB). Sent with every check, so point writes at test data. `application/json` unless a Content-Type header is set."},"host":{"type":"string","description":"port / dns: bare hostname, no scheme, path or port. Required for those types. port accepts a public IP literal; dns does not.","example":"db.example.com"},"port":{"type":"integer","minimum":1,"maximum":65535,"description":"port only: TCP port to connect to. Required."},"dns_record_type":{"type":"string","enum":["A","AAAA","CNAME","MX","TXT","NS"],"default":"A","description":"dns only: record type to resolve."},"dns_expected_value":{"type":"string","nullable":true,"maxLength":256,"description":"dns only. null clears the answer check."},"fail_threshold":{"type":"integer","minimum":1,"default":3,"description":"Consecutive failed checks before `down`. Not used by heartbeat or scheduler."},"recover_threshold":{"type":"integer","minimum":1,"default":1,"description":"Consecutive good checks before `up` again."},"enabled":{"type":"boolean","description":"false pauses the monitor, true resumes it."},"project_id":{"type":"string","nullable":true,"description":"Move the monitor to another project; null makes it ungrouped. An API key cannot move a monitor out of its project."}},"description":"Partial update: only the fields sent are changed. `request_headers` replaces the stored list (an entry with a `name` and no `value` keeps that header's stored value). A scheduler cannot be given HEAD or OPTIONS (`invalid_method`). The type cannot be changed."},"Ok":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]},"MuteInput":{"type":"object","properties":{"minutes":{"type":"number","nullable":true}},"required":["minutes"]},"Pinged":{"type":"object","properties":{"ok":{"type":"boolean"},"deduped":{"type":"boolean"}},"required":["ok"]},"History":{"type":"object","properties":{"latency":{"type":"array","items":{"type":"number"},"description":"Hourly average latency, oldest first, only for hours with a reachable check."},"peak":{"type":"array","items":{"type":"number"},"description":"Hourly peak latency, aligned with `latency`."},"recent":{"type":"array","items":{"type":"number"},"description":"Latency of the last 30 reachable checks, oldest first."},"status":{"type":"array","items":{"type":"string","nullable":true,"enum":["up","slow","down"]},"description":"The last 30 check results, oldest first, null-padded on the left."},"upHourly":{"type":"array","items":{"type":"integer"},"description":"Per hour in the window: checks that were up or slow."},"totalHourly":{"type":"array","items":{"type":"integer"},"description":"Per hour in the window: checks attempted. Divide `upHourly` by this for uptime."},"points":{"type":"array","items":{"type":"number","nullable":true},"description":"Per-check latency over the whole window, oldest first, null for a down or skipped check. At most 2880 entries."},"hourly":{"type":"array","items":{"type":"object","properties":{"t":{"type":"integer","description":"Hour bucket start. Epoch milliseconds."},"avg":{"type":"number","nullable":true,"description":"Average latency of reachable checks that hour; null with none."},"peak":{"type":"number","nullable":true,"description":"Slowest reachable check that hour; null with none."}},"required":["t","avg","peak"]},"description":"One entry per hour across the whole window, time-aligned."},"percentiles":{"type":"object","nullable":true,"properties":{"p50":{"type":"number"},"p95":{"type":"number"},"p99":{"type":"number"}},"required":["p50","p95","p99"],"description":"Latency percentiles over every reachable check in the window; null with none."}},"required":["latency","peak","recent","status","upHourly","totalHourly","points","hourly","percentiles"]},"Event":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["status_change","user_action"],"description":"Which fields are present: a status change carries `from`/`to`/`detail`/`latency_ms`/`http_status`; a user action carries `action`/`summary`."},"at":{"type":"integer","description":"When it happened. Epoch milliseconds."},"from":{"type":"string","nullable":true,"enum":["up","slow","down"],"description":"status_change: previous status (null when it was unknown)."},"to":{"type":"string","nullable":true,"enum":["up","slow","down"],"description":"status_change: new status."},"detail":{"type":"string","nullable":true,"description":"status_change: failure reason, or null."},"latency_ms":{"type":"number","nullable":true},"http_status":{"type":"number","nullable":true},"action":{"type":"string","description":"user_action: `paused`, `resumed`, `edited`, `muted`, `unmuted`."},"summary":{"type":"string","nullable":true,"description":"user_action: human summary of the change."},"monitor_id":{"type":"string","description":"GET /v1/events only: the monitor this event belongs to."},"monitor_name":{"type":"string","description":"GET /v1/events only."}},"required":["id","kind","at"]},"IncidentUpdate":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["detected","investigating","identified","monitoring","resolved"]},"severity":{"type":"string","nullable":true,"enum":["degraded_performance","partial_outage","major_outage"],"description":"Severity set by this update, or null when it left it alone."},"body":{"type":"string","nullable":true},"author_id":{"type":"string","nullable":true,"description":"Who posted it. Present on GET /v1/incidents/{id} only."},"created_at":{"type":"integer","description":"When it was posted. Epoch milliseconds."}},"required":["id","status","severity","body","created_at"]},"Incident":{"type":"object","properties":{"id":{"type":"string"},"monitor_id":{"type":"string","description":"The triggering (or first affected) monitor."},"monitor_name":{"type":"string","description":"Present on the feeds and the detail; absent on GET /v1/monitors/{id}/incidents."},"started_at":{"type":"integer","description":"When the monitor first went down. Epoch milliseconds."},"opened_at":{"type":"integer","description":"When it crossed the project's incident policy threshold (the public 'since'). Epoch milliseconds."},"resolved_at":{"type":"integer","nullable":true,"description":"null while ongoing. Epoch milliseconds."},"ongoing":{"type":"boolean"},"duration_ms":{"type":"number","nullable":true,"description":"resolved_at minus started_at; null while ongoing."},"cause":{"type":"string","nullable":true,"description":"Failure reason from the check; null for manual incidents."},"http_status":{"type":"number","nullable":true},"severity":{"type":"string","enum":["degraded_performance","partial_outage","major_outage"]},"public_status":{"type":"string","enum":["detected","investigating","identified","monitoring","resolved"]},"flap_count":{"type":"integer","description":"Re-downs coalesced into this incident during the close grace window."},"source":{"type":"string","enum":["auto","manual"]},"title":{"type":"string","nullable":true,"description":"Manual incidents carry a title; auto incidents null."},"acked_at":{"type":"integer","nullable":true,"description":"When an on-call acknowledgement halted escalation; null if unacked. Epoch milliseconds."},"acked_by":{"type":"string","nullable":true,"description":"User id that acknowledged it."},"postmortem":{"type":"string","nullable":true,"description":"The write-up, or null. Filled on the detail fetch; always null on the feeds."},"affected":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"description":"Every monitor the incident spans."},"updates":{"type":"array","items":{"$ref":"#/components/schemas/IncidentUpdate"},"description":"The human update timeline, oldest first."}},"required":["id","monitor_id","started_at","opened_at","resolved_at","ongoing","duration_ms","cause","http_status","severity","public_status","flap_count","source","title","acked_at","acked_by","postmortem","affected","updates"]},"Coverage":{"type":"object","properties":{"under_maintenance":{"type":"boolean","description":"An active maintenance window is pausing this monitor right now."},"incident":{"type":"object","nullable":true,"properties":{"severity":{"type":"string","enum":["degraded_performance","partial_outage","major_outage"]}},"required":["severity"],"description":"The worst ongoing incident affecting it, or null."}},"required":["under_maintenance","incident"]},"IncidentInput":{"type":"object","properties":{"title":{"type":"string","maxLength":120},"severity":{"type":"string","enum":["degraded_performance","partial_outage","major_outage"]},"monitor_ids":{"type":"array","items":{"type":"string"},"minItems":1,"description":"Monitors in this project. Ids from other projects are dropped; `invalid_monitors` if none remain."},"body":{"type":"string","maxLength":2000,"description":"Text of the opening update."}},"required":["title","severity","monitor_ids"]},"PostmortemInput":{"type":"object","properties":{"postmortem":{"type":"string","maxLength":10000}},"required":["postmortem"]},"IncidentUpdateInput":{"type":"object","properties":{"status":{"type":"string","enum":["detected","investigating","identified","monitoring","resolved"]},"severity":{"type":"string","enum":["degraded_performance","partial_outage","major_outage"]},"body":{"type":"string","maxLength":2000}}},"IncidentPolicy":{"type":"object","properties":{"open_after_min":{"type":"integer","minimum":0,"maximum":1440,"description":"Minutes a monitor must stay down before an incident opens (and the public status flips, and alerts fire)."},"close_grace_min":{"type":"integer","minimum":0,"maximum":1440,"description":"Minutes recovery must hold before the incident closes."},"trigger":{"type":"string","enum":["down","down_slow"],"description":"Whether `slow` also counts toward opening an incident."}},"required":["open_after_min","close_grace_min","trigger"]},"IncidentPolicyPatch":{"type":"object","properties":{"open_after_min":{"type":"integer","minimum":0,"maximum":1440,"description":"Minutes a monitor must stay down before an incident opens (and the public status flips, and alerts fire)."},"close_grace_min":{"type":"integer","minimum":0,"maximum":1440,"description":"Minutes recovery must hold before the incident closes."},"trigger":{"type":"string","enum":["down","down_slow"],"description":"Whether `slow` also counts toward opening an incident."}}},"EventMask":{"type":"object","properties":{"down":{"type":"boolean"},"slow":{"type":"boolean"},"recovery":{"type":"boolean"}},"required":["down","slow","recovery"],"description":"Which transitions the channel receives (down, slow, recovery)."},"Channel":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string","enum":["slack","discord","telegram","webhook","email"]},"name":{"type":"string"},"enabled":{"type":"boolean"},"created_at":{"type":"integer","description":"Created. Epoch milliseconds."},"url_hint":{"type":"string","description":"The destination's host (or mailbox domain) as a recognizability hint. The full destination is a secret and never returned."},"events":{"$ref":"#/components/schemas/EventMask"},"monitor_ids":{"type":"array","nullable":true,"items":{"type":"string"},"description":"null: every monitor in the project. An array: exactly these (an empty array means none)."}},"required":["id","provider","name","enabled","created_at","url_hint","events","monitor_ids"]},"ChannelInput":{"type":"object","properties":{"provider":{"type":"string","enum":["slack","discord","telegram","webhook","email"]},"name":{"type":"string","maxLength":40},"url":{"type":"string","description":"The destination: an https webhook URL, or the mailbox for `email`."}},"required":["provider","name","url"]},"ChannelPatch":{"type":"object","properties":{"name":{"type":"string","maxLength":40},"enabled":{"type":"boolean"},"url":{"type":"string","description":"Replacement destination; must match the channel's provider."},"events":{"allOf":[{"$ref":"#/components/schemas/EventMask"},{"description":"Only the booleans sent are changed."}]},"monitor_ids":{"type":"array","nullable":true,"items":{"type":"string"},"description":"null: the whole project. An array: exactly these monitors (an empty array covers none)."}}},"Recurrence":{"type":"object","nullable":true,"properties":{"freq":{"type":"string","enum":["daily","weekly"]},"weekdays":{"type":"array","items":{"type":"integer","minimum":0,"maximum":6},"description":"weekly only, required then: 0 (Sunday) to 6 (Saturday)."},"until":{"type":"integer","description":"Last occurrence, epoch milliseconds. Absent repeats indefinitely."}},"required":["freq"]},"Maintenance":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string","maxLength":60},"description":{"type":"string","nullable":true,"maxLength":280},"start_at":{"type":"integer","description":"Start; for a recurring window, the template occurrence's start. Epoch milliseconds."},"end_at":{"type":"integer","description":"End; for a recurring window, the template occurrence's end. Epoch milliseconds."},"created_at":{"type":"integer","description":"Created. Epoch milliseconds."},"recurrence":{"$ref":"#/components/schemas/Recurrence"},"monitor_ids":{"type":"array","items":{"type":"string"},"description":"Monitors the window covers. Empty: every monitor in the project."}},"required":["id","title","description","start_at","end_at","created_at","recurrence","monitor_ids"]},"MaintenanceInput":{"type":"object","properties":{"title":{"type":"string","maxLength":60},"description":{"type":"string","maxLength":280},"start_at":{"type":"integer","description":"Start. Epoch milliseconds."},"end_at":{"type":"integer","description":"End. Must be after `start_at` (`invalid_window`). Epoch milliseconds."},"recurrence":{"allOf":[{"$ref":"#/components/schemas/Recurrence"},{"description":"Omit or null for a one-off window. `until` must be after `start_at`."}]},"monitor_ids":{"type":"array","items":{"type":"string"},"description":"Monitors to cover. Omit or send [] to cover the whole project."}},"required":["title","start_at","end_at"]},"MaintenancePatch":{"type":"object","properties":{"title":{"type":"string","maxLength":60},"description":{"type":"string","nullable":true,"maxLength":280,"description":"Present replaces (null clears); absent leaves it alone."},"start_at":{"type":"integer"},"end_at":{"type":"integer"},"recurrence":{"allOf":[{"$ref":"#/components/schemas/Recurrence"},{"description":"Present replaces (null makes it one-off); absent leaves it alone."}]},"monitor_ids":{"type":"array","items":{"type":"string"},"description":"Present replaces; absent leaves it alone."}}},"StatusPage":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The page id, also its public slug."},"name":{"type":"string","maxLength":40},"description":{"type":"string","nullable":true,"maxLength":280},"is_public":{"type":"boolean"},"custom_domain":{"type":"string","nullable":true,"description":"Connected custom domain, or null."},"domain_status":{"type":"string","nullable":true,"enum":["pending","active","error"],"description":"Custom domain issuance state; null with no domain."},"created_at":{"type":"integer","description":"Created. Epoch milliseconds."},"logo_url":{"type":"string","nullable":true},"brand_color":{"type":"string","nullable":true},"uptime_days":{"type":"integer","description":"Uptime window shown on the page."},"show_uptime":{"type":"boolean"},"subdomain":{"type":"string","nullable":true,"description":"Vanity handle: the page is served at `<subdomain>.uptimex.co`."},"monitors":{"type":"array","items":{"type":"object","properties":{"monitor_id":{"type":"string"},"label":{"type":"string","nullable":true,"description":"Display name on the page; null shows the monitor's name."},"position":{"type":"integer","description":"Display order."}},"required":["monitor_id","label","position"]},"description":"Explicit selection in display order. Empty: every enabled monitor in the project."}},"required":["id","name","description","is_public","custom_domain","domain_status","created_at","logo_url","brand_color","uptime_days","show_uptime","subdomain","monitors"]},"StatusPageInput":{"type":"object","properties":{"name":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":280}},"required":["name"]},"StatusPagePatch":{"type":"object","properties":{"name":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":280},"is_public":{"type":"boolean"},"logo_url":{"type":"string","nullable":true,"maxLength":500,"description":"null or empty clears it."},"brand_color":{"type":"string","nullable":true,"maxLength":32,"description":"null or empty clears it."},"uptime_days":{"type":"integer"},"show_uptime":{"type":"boolean"},"subdomain":{"type":"string","description":"New vanity handle (`invalid_subdomain` if malformed or reserved, `subdomain_taken` if in use)."}}},"StatusPageMonitorsInput":{"type":"object","properties":{"monitors":{"type":"array","items":{"type":"object","properties":{"monitor_id":{"type":"string"},"label":{"type":"string","nullable":true}},"required":["monitor_id"]}}},"required":["monitors"]},"DomainStatus":{"type":"object","properties":{"custom_domain":{"type":"string","nullable":true},"domain_status":{"type":"string","nullable":true,"enum":["pending","active","error"]},"cname_target":{"type":"string","description":"The hostname to CNAME the custom domain to."}},"required":["custom_domain","domain_status","cname_target"]},"DomainInput":{"type":"object","properties":{"domain":{"type":"string"}},"required":["domain"]},"ProjectAlertPrefs":{"type":"object","properties":{"down":{"type":"boolean","nullable":true,"description":"true/false pins the event for this project; null follows the account default."},"slow":{"type":"boolean","nullable":true,"description":"true/false pins the event for this project; null follows the account default."},"recovery":{"type":"boolean","nullable":true,"description":"true/false pins the event for this project; null follows the account default."}},"required":["down","slow","recovery"]},"AccountAlertPrefs":{"type":"object","properties":{"down":{"type":"boolean"},"slow":{"type":"boolean"},"recovery":{"type":"boolean"}},"required":["down","slow","recovery"],"description":"The project owner's account defaults, which a null override falls back to."},"ProjectAlertPrefsPatch":{"type":"object","properties":{"down":{"type":"boolean","nullable":true,"description":"true/false pins the event for this project; null follows the account default."},"slow":{"type":"boolean","nullable":true,"description":"true/false pins the event for this project; null follows the account default."},"recovery":{"type":"boolean","nullable":true,"description":"true/false pins the event for this project; null follows the account default."}}},"EscalationPolicy":{"type":"object","properties":{"enabled":{"type":"boolean"},"repeat_min":{"type":"integer","description":"Minutes between repeats of the last step while unacknowledged; 0 for no repeat."},"steps":{"type":"array","items":{"type":"object","properties":{"step_order":{"type":"integer"},"target_type":{"type":"string","enum":["member","channel"]},"target_id":{"type":"string","description":"A member's user id or a channel id in this project."},"delay_min":{"type":"integer","minimum":0,"description":"Minutes after the incident opens (or the previous step) before this step pages."}},"required":["step_order","target_type","target_id","delay_min"]},"maxItems":10}},"required":["enabled","repeat_min","steps"]},"EscalationPolicyInput":{"type":"object","properties":{"enabled":{"type":"boolean"},"repeat_min":{"type":"integer","minimum":0},"steps":{"type":"array","items":{"type":"object","properties":{"target_type":{"type":"string","enum":["member","channel"]},"target_id":{"type":"string","description":"A member's user id or a channel id in this project."},"delay_min":{"type":"integer","minimum":0,"description":"Minutes after the incident opens (or the previous step) before this step pages."}},"required":["target_type","target_id","delay_min"]},"maxItems":10,"description":"In order, at most 10. Enabling with no steps is `invalid` (`field: enabled`)."}},"required":["enabled","repeat_min","steps"]},"Project":{"type":"object","properties":{"id":{"type":"string","description":"The project ref used in `/v1/projects/{ref}/...` paths."},"name":{"type":"string"},"created_at":{"type":"integer","description":"Created. Epoch milliseconds."},"role":{"type":"string","enum":["owner","admin","member","viewer"],"description":"The caller's role on this project."},"plan":{"type":"string","description":"The plan that governs the project: always the owner's, never the caller's."},"monitors":{"type":"integer","description":"Monitor count. List only."},"up":{"type":"integer","description":"List only."},"slow":{"type":"integer","description":"List only."},"down":{"type":"integer","description":"List only."},"unknown":{"type":"integer","description":"Monitors with no result yet. List only."}},"required":["id","name","created_at","role","plan"]},"ProjectInput":{"type":"object","properties":{"name":{"type":"string","maxLength":18}},"required":["name"]},"Token":{"type":"object","properties":{"id":{"type":"string"},"project_id":{"type":"string","description":"The one project this key is scoped to."},"name":{"type":"string","nullable":true},"created_at":{"type":"integer","description":"Created. Epoch milliseconds."},"last_used_at":{"type":"integer","nullable":true,"description":"Last request made with it. Epoch milliseconds."},"expires_at":{"type":"integer","nullable":true,"description":"null never expires. Epoch milliseconds."}},"required":["id","project_id","name","created_at","last_used_at","expires_at"]},"TokenCreated":{"allOf":[{"$ref":"#/components/schemas/Token"},{"type":"object","properties":{"token":{"type":"string","description":"The plaintext `upk_...` key. Returned once, never again.","example":"upk_ab12…"}},"required":["token"]}]},"TokenInput":{"type":"object","properties":{"project_id":{"type":"string","description":"The one project the key will be scoped to."},"name":{"type":"string","maxLength":64,"description":"Label shown in the key list."},"ttl_seconds":{"type":"integer","description":"Lifetime, clamped to 60 to 7,776,000 (90 days). Omit for a key that never expires."}},"required":["project_id","name"]},"Member":{"type":"object","properties":{"user_id":{"type":"string"},"email":{"type":"string","nullable":true},"role":{"type":"string","enum":["owner","admin","member","viewer"]},"is_owner":{"type":"boolean"},"created_at":{"type":"integer","nullable":true,"description":"When they joined; null for the owner. Epoch milliseconds."}},"required":["user_id","email","role","is_owner","created_at"]},"RoleInput":{"type":"object","properties":{"role":{"type":"string","enum":["admin","member","viewer"]}},"required":["role"]},"Invite":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string"},"expires_at":{"type":"integer","description":"Invites expire after 7 days. Epoch milliseconds."},"created_at":{"type":"integer","description":"Sent. Epoch milliseconds."}},"required":["id","email","role","expires_at","created_at"]},"InviteInput":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["admin","member","viewer"]},"origin":{"type":"string","description":"Dashboard origin to build the accept link from."}},"required":["email","role"]},"InviteAcceptInput":{"type":"object","properties":{"token":{"type":"string","description":"The token from the invite link."}},"required":["token"]},"Connector":{"type":"object","properties":{"provider":{"type":"string"},"created_at":{"type":"integer","description":"Connected. Epoch milliseconds."},"meta":{"type":"string","nullable":true}},"required":["provider","created_at","meta"]},"ImportableProject":{"type":"object","properties":{"external_ref":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"already_imported":{"type":"boolean"}},"required":["external_ref","name","url","already_imported"]},"ImportResult":{"type":"object","properties":{"created":{"type":"array","items":{"$ref":"#/components/schemas/Monitor"}},"skipped":{"type":"array","items":{"type":"string"},"description":"external_refs already imported."},"failed":{"type":"array","items":{"type":"object","properties":{"external_ref":{"type":"string"},"error":{"type":"string"}},"required":["external_ref","error"]}}},"required":["created","skipped","failed"]},"ImportInput":{"type":"object","properties":{"external_refs":{"type":"array","items":{"type":"string"},"minItems":1},"project_id":{"type":"string","description":"Project to import the monitors into."}},"required":["external_refs"]}},"parameters":{}},"paths":{"/v1/monitors":{"get":{"operationId":"listMonitors","tags":["Monitors"],"security":[{"apiKey":[]},{"session":[]}],"summary":"List monitors","description":"Every monitor the credential can see (an API key: its project's), oldest first, with current status, 24h aggregates and the last 30 check results. Not paginated.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MonitorWithHistory"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createMonitor","tags":["Monitors"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Create a monitor","description":"Creates the monitor and, for every type but heartbeat and scheduler, runs its first check in the background. `status` is null until that completes. An API key creates in its own project.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Monitor"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`monitor_limit`: the owner's plan cap is reached (`limit`; free 5, pro 30, team 50). `plan_required`: `feature: monitor_type` for api, scheduler or dns on a free plan; `feature: advanced_monitoring` for check_ssl, check_domain or a json_field rule on a free plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: `project_id` is not a project the caller can create in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_target`, `invalid_headers`, `invalid_body`, `invalid_content_rules`, `keyword_needs_rule`, `invalid_method`; `invalid` (`field`) for a value of the wrong type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/monitors/test":{"post":{"operationId":"testMonitor","tags":["Monitors"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Run one check without saving","description":"Takes the same body as an http, keyword or api create and runs a single check. Nothing is stored. Every header must carry a value (nothing stored to keep).","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorInput"}}}},"responses":{"200":{"description":"Check result, with a response body snippet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckResult"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_target`, `invalid_headers`, `invalid_body`, `invalid_content_rules`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/monitors/{id}":{"get":{"operationId":"getMonitor","tags":["Monitors"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Get a monitor","description":"The full editable configuration plus current status. Header values are never returned.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Monitor id.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Monitor"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateMonitor","tags":["Monitors"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Update a monitor","description":"Partial update; returns the updated monitor. Send `{\"enabled\": false}` to pause and `true` to resume.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Monitor id.","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorPatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Monitor"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required` (`feature: advanced_monitoring`): check_ssl, check_domain or a json_field rule on a free-plan project.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_target`, `invalid_headers`, `invalid_body`, `invalid_content_rules`, `keyword_needs_rule`, `invalid_method`; `invalid` (`field`) for a value of the wrong type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteMonitor","tags":["Monitors"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Delete a monitor","description":"Deletes the monitor with its history, events and incidents.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Monitor id.","name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/monitors/{id}/mute":{"post":{"operationId":"muteMonitor","tags":["Monitors"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Mute a monitor","description":"Suppresses down detection and alerts for `minutes` (capped at 7 days). 0 clears the mute. Returns the updated monitor.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Monitor id.","name":"id","in":"path"}],"requestBody":{"description":"`minutes`: how long to mute; 0 clears.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MuteInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Monitor"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed. The `error` code names the field or rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/heartbeats/{id}/ping":{"post":{"operationId":"heartbeatPing","tags":["Monitors"],"security":[],"summary":"Heartbeat check-in","description":"Call this from your job. No auth: the monitor id is the secret. GET and POST both work, so a bare `curl` does. A ping that lands well before the next one is due is deduplicated.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Heartbeat monitor id.","name":"id","in":"path"}],"responses":{"200":{"description":"Ping recorded (`deduped: true` when it was ignored as a duplicate)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pinged"}}}},"404":{"description":"`not_found`: not a heartbeat monitor, or it is paused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"heartbeatPingGet","tags":["Monitors"],"security":[],"summary":"Heartbeat check-in","description":"Call this from your job. No auth: the monitor id is the secret. GET and POST both work, so a bare `curl` does. A ping that lands well before the next one is due is deduplicated.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Heartbeat monitor id.","name":"id","in":"path"}],"responses":{"200":{"description":"Ping recorded (`deduped: true` when it was ignored as a duplicate)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pinged"}}}},"404":{"description":"`not_found`: not a heartbeat monitor, or it is paused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/monitors/{id}/history":{"get":{"operationId":"getMonitorHistory","tags":["Monitors"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Chart data","description":"Latency and uptime series over the last `range` hours, derived from hourly rollups. The window is clamped to the owner's plan retention (free 7d, pro 30d, team 90d).","parameters":[{"schema":{"type":"string"},"required":true,"description":"Monitor id.","name":"id","in":"path"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"default":48},"required":false,"description":"Hours to cover. Default 48; clamped to the plan's retention.","name":"range","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/History"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/monitors/{id}/events":{"get":{"operationId":"listMonitorEvents","tags":["Events"],"security":[{"apiKey":[]},{"session":[]}],"summary":"A monitor's activity","description":"Status changes and user actions, newest first, within the owner's plan retention.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Monitor id.","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"description":"Rows to return (1 to 200). Default 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Event"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/events":{"get":{"operationId":"listEvents","tags":["Events"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Activity across monitors","description":"Status changes (only) across every monitor the credential can see, newest first, each tagged with `monitor_id` and `monitor_name`.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":100},"required":false,"description":"Rows to return (1 to 200). Default 100.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Event"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/incidents":{"get":{"operationId":"listIncidents","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Incident feed","description":"Incidents across every monitor the credential can see, ongoing first then newest. `project` narrows it to one project.","parameters":[{"schema":{"type":"string"},"required":false,"description":"Project ref to narrow the feed to.","name":"project","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":100},"required":false,"description":"Rows to return (1 to 200). Default 100.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Incident"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required`: incidents are a paid feature and the project owner is on the free plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/monitors/{id}/incidents":{"get":{"operationId":"listMonitorIncidents","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"A monitor's incidents","description":"Ongoing first, then newest.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Monitor id.","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"description":"Rows to return (1 to 200). Default 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Incident"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/monitors/{id}/coverage":{"get":{"operationId":"getMonitorCoverage","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Is the monitor under maintenance or in an incident","parameters":[{"schema":{"type":"string"},"required":true,"description":"Monitor id.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Coverage"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/incidents":{"post":{"operationId":"createIncident","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Declare a manual incident","description":"Opens an incident the checks did not catch, spanning one or more of the project's monitors. Owner or admin. Manual incidents are closed by a `resolved` update, never automatically.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required`: the project owner is on the free plan. `forbidden`: the caller is not an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid`: missing title, severity or monitors. `invalid_monitors`: none of the ids belong to the project.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/incidents/{id}":{"get":{"operationId":"getIncident","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Get an incident","description":"One incident with its full update timeline (including `author_id`) and postmortem.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Incident id.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Incident"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"setIncidentPostmortem","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Set the postmortem","description":"Owner or admin of the incident's project. An empty string clears it.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Incident id.","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostmortemInput"}}}},"responses":{"200":{"description":"Saved","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"postmortem":{"type":"string","nullable":true}},"required":["ok","postmortem"]}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`forbidden`: not an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid`: `postmortem` is not a string.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteIncident","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Delete an incident","description":"Owner or admin. Removes the incident with its updates.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Incident id.","name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`forbidden`: not an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/incidents/{id}/updates":{"post":{"operationId":"postIncidentUpdate","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Post an update","description":"Adds to the timeline and applies the new `status` and/or `severity` to the incident. A `resolved` status closes it. Owner or admin. At least one field is required.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Incident id.","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentUpdateInput"}}}},"responses":{"201":{"description":"Posted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`forbidden`: not an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`incident_resolved`: the incident is closed and takes no more updates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid`: no status, severity or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/incidents/{id}/ack":{"post":{"operationId":"ackIncident","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Acknowledge an incident","description":"Halts escalation; the incident stays open until it recovers or is resolved. Anyone who can see the monitor. Idempotent: the first ack wins.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Incident id.","name":"id","in":"path"}],"responses":{"200":{"description":"Acknowledged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/incident-policy":{"get":{"operationId":"getIncidentPolicy","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Get the incident policy","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentPolicy"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateIncidentPolicy","tags":["Incidents"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Update the incident policy","description":"Owner or admin. Only the fields sent are changed; values outside 0 to 1440 are ignored.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentPolicyPatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`forbidden`: not an owner or admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid`: nothing valid to change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/channels":{"get":{"operationId":"listChannels","tags":["Channels"],"security":[{"apiKey":[]},{"session":[]}],"summary":"List a project's channels","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Channel"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createChannel","tags":["Channels"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Add a channel","description":"One channel per provider per project. Owner or admin. Email channels are paid; the webhook family (slack, discord, telegram, webhook) is free.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required` (`feature: email_alerts`): an email channel on a free-plan project.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`channel_exists`: the project already has a channel for this provider.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_provider`, `invalid_name`, `invalid_url`, `invalid_email`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/channels/{id}":{"patch":{"operationId":"updateChannel","tags":["Channels"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Update a channel","description":"Owner or admin. Only the fields sent are changed.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Channel id.","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelPatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_url`, `invalid_email`, `invalid_monitor_ids`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteChannel","tags":["Channels"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Delete a channel","parameters":[{"schema":{"type":"string"},"required":true,"description":"Channel id.","name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/channels/{id}/test":{"post":{"operationId":"testChannel","tags":["Channels"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Send a test alert","description":"Delivers a sample message to the destination. Owner or admin.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Channel id.","name":"id","in":"path"}],"responses":{"200":{"description":"Delivery attempted: `ok` says whether the destination accepted it, `status` is its HTTP response code when there was one","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"status":{"type":"integer"}},"required":["ok"]}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required` (`feature: email_alerts`): an email channel on a free-plan project.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/maintenance":{"get":{"operationId":"listMaintenance","tags":["Maintenance"],"security":[{"apiKey":[]},{"session":[]}],"summary":"List maintenance windows","description":"Newest window first. While a window is active the covered monitors are not checked and raise no alerts or incidents.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Maintenance"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createMaintenance","tags":["Maintenance"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Schedule a window","description":"Owner or admin. Active or scheduled windows per project are capped by the owner's plan (free 1, pro 10, team unlimited).","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Maintenance"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required` (`feature: maintenance`, `limit`): the plan's active-window cap is reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_name`, `invalid_window`, `invalid_recurrence`, `invalid_monitor_ids`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/maintenance/{id}":{"patch":{"operationId":"updateMaintenance","tags":["Maintenance"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Update a window","description":"Owner or admin. `description`, `recurrence` and `monitor_ids` replace when present; omit a field to leave it alone.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Maintenance window id.","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenancePatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_window`, `invalid_recurrence`, `invalid_monitor_ids`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteMaintenance","tags":["Maintenance"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Delete a window","parameters":[{"schema":{"type":"string"},"required":true,"description":"Maintenance window id.","name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/status-page":{"get":{"operationId":"getStatusPage","tags":["Status pages"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Get the project's status page","description":"The page's configuration, or null when the project has none.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPage"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required`: status pages are a paid feature and the project owner is on the free plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createStatusPage","tags":["Status pages"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Create the status page","description":"One per project. Owner or admin. The page starts public with a vanity subdomain derived from its name.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPageInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPage"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required`: status pages are a paid feature and the project owner is on the free plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`status_page_exists`: the project already has one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_name`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/status-pages/{id}":{"patch":{"operationId":"updateStatusPage","tags":["Status pages"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Update a status page","description":"Owner or admin. Only the fields sent are changed.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Status page id.","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPagePatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`subdomain_taken`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_subdomain`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteStatusPage","tags":["Status pages"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Delete a status page","parameters":[{"schema":{"type":"string"},"required":true,"description":"Status page id.","name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/status-pages/{id}/monitors":{"put":{"operationId":"setStatusPageMonitors","tags":["Status pages"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Choose the monitors shown","description":"Replaces the selection; array order is display order. Monitors outside the page's project are dropped. An empty list shows every enabled monitor in the project.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Status page id.","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPageMonitorsInput"}}}},"responses":{"200":{"description":"Saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/status-pages/{id}/domain":{"post":{"operationId":"connectStatusPageDomain","tags":["Status pages"],"security":[{"session":[]}],"summary":"Connect a custom domain","description":"Dashboard-only: an API key is refused with `403 session_required`. Registers the domain for the page and returns the CNAME target to point it at. Custom domains per account are capped by plan (free 0, pro 1, team 3).","parameters":[{"schema":{"type":"string"},"required":true,"description":"Status page id.","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainInput"}}}},"responses":{"200":{"description":"Registered; issuance is `pending` until the CNAME resolves","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainStatus"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: called with an API key. `plan_required`: the plan allows no custom domain. `domain_limit`: the plan's cap is reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_domain`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"`cf_unreachable`, `cf_error`: the certificate provider did not answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"`domain_unconfigured`: custom domains are not set up on this deployment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"refreshStatusPageDomain","tags":["Status pages"],"security":[{"session":[]}],"summary":"Re-check the custom domain","description":"Dashboard-only: an API key is refused with `403 session_required`. Polls issuance and returns the current state.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Status page id.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainStatus"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"`cf_unreachable`, `cf_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"`domain_unconfigured`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"disconnectStatusPageDomain","tags":["Status pages"],"security":[{"session":[]}],"summary":"Disconnect the custom domain","description":"Dashboard-only: an API key is refused with `403 session_required`.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Status page id.","name":"id","in":"path"}],"responses":{"200":{"description":"Disconnected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/alert-prefs":{"get":{"operationId":"getProjectAlertPrefs","tags":["Channels"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Get the project's alert overrides","description":"Which transitions alert for this project (`prefs`) and the owner's account defaults they fall back to (`account`).","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"prefs":{"$ref":"#/components/schemas/ProjectAlertPrefs"},"account":{"$ref":"#/components/schemas/AccountAlertPrefs"}},"required":["prefs","account"]}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateProjectAlertPrefs","tags":["Channels"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Set the project's alert overrides","description":"Owner or admin. true/false pins an event for the project, null clears the override so it follows the account again. An event not sent is left alone.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectAlertPrefsPatch"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such project, not an owner or admin, or nothing to change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/escalation":{"get":{"operationId":"getEscalationPolicy","tags":["Escalation"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Get the on-call escalation policy","description":"Team plan. Any project member may read it.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationPolicy"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required` (`feature: escalation`): the project owner is not on the Team plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"putEscalationPolicy","tags":["Escalation"],"security":[{"apiKey":[]},{"session":[]}],"summary":"Replace the escalation policy","description":"Team plan. Owner or admin. The whole policy is replaced; every target must belong to the project.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationPolicyInput"}}}},"responses":{"200":{"description":"Saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationPolicy"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`plan_required` (`feature: escalation`): the project owner is not on the Team plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid` with `field`: `steps` (too many), `enabled` (enabled with no steps), `target_type`, `target_id` (not in this project), `delay_min`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects":{"get":{"operationId":"listProjects","tags":["Projects"],"security":[{"session":[]}],"summary":"List projects","description":"Dashboard-only: an API key is refused with `403 session_required`. Every project the account owns or is a member of, with status counts.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Project"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createProject","tags":["Projects"],"security":[{"session":[]}],"summary":"Create a project","description":"Dashboard-only: an API key is refused with `403 session_required`. Projects per account are capped by plan (free 1, pro 3, team 5).","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectInput"}}}},"responses":{"201":{"description":"Created (without the count fields)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: called with an API key. `project_limit` (`limit`): the plan's cap is reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_name`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}":{"patch":{"operationId":"renameProject","tags":["Projects"],"security":[{"session":[]}],"summary":"Rename a project","description":"Dashboard-only: an API key is refused with `403 session_required`. Owner only.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectInput"}}}},"responses":{"200":{"description":"Renamed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_name`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteProject","tags":["Projects"],"security":[{"session":[]}],"summary":"Delete a project","description":"Dashboard-only: an API key is refused with `403 session_required`. Owner only. Deletes the project and everything in it, its monitors included, with their history and incidents.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tokens":{"get":{"operationId":"listTokens","tags":["Tokens"],"security":[{"session":[]}],"summary":"List API keys","description":"Dashboard-only: an API key is refused with `403 session_required`. The caller's own keys, metadata only.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Token"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createToken","tags":["Tokens"],"security":[{"session":[]}],"summary":"Create an API key","description":"Dashboard-only: an API key is refused with `403 session_required`. Keys are minted from the dashboard so a leaked key can never mint more. The caller must be an owner, admin or member of the project; viewers cannot mint.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenInput"}}}},"responses":{"201":{"description":"Created; the plaintext key is returned once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenCreated"}}}},"400":{"description":"`project_required`: no `project_id`, or no write role on it. `name_required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tokens/{id}":{"delete":{"operationId":"revokeToken","tags":["Tokens"],"security":[{"session":[]}],"summary":"Revoke an API key","description":"Dashboard-only: an API key is refused with `403 session_required`.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Token id.","name":"id","in":"path"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/members":{"get":{"operationId":"listMembers","tags":["Team"],"security":[{"session":[]}],"summary":"List members","description":"Dashboard-only: an API key is refused with `403 session_required`. Owner first. Any member may read the roster.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Member"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/members/{userId}":{"patch":{"operationId":"updateMemberRole","tags":["Team"],"security":[{"session":[]}],"summary":"Change a member's role","description":"Dashboard-only: an API key is refused with `403 session_required`. Owner or admin.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref.","name":"ref","in":"path"},{"schema":{"type":"string"},"required":true,"description":"The member's user id.","name":"userId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_role`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"removeMember","tags":["Team"],"security":[{"session":[]}],"summary":"Remove a member","description":"Dashboard-only: an API key is refused with `403 session_required`. Owner or admin; a member may remove themselves.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref.","name":"ref","in":"path"},{"schema":{"type":"string"},"required":true,"description":"The member's user id.","name":"userId","in":"path"}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/projects/{ref}/invites":{"get":{"operationId":"listInvites","tags":["Team"],"security":[{"session":[]}],"summary":"List pending invites","description":"Dashboard-only: an API key is refused with `403 session_required`. Owner or admin.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Invite"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createInvite","tags":["Team"],"security":[{"session":[]}],"summary":"Invite by email","description":"Dashboard-only: an API key is refused with `403 session_required`. Owner or admin. Sends the invite email; the recipient's account email must match to accept.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Project ref (the `id` from GET /v1/projects).","name":"ref","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteInput"}}}},"responses":{"201":{"description":"Sent","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"email":{"type":"string"},"role":{"type":"string","enum":["admin","member","viewer"]}},"required":["ok","email","role"]}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: called with an API key. `plan_required`: the project owner's plan has no team seats.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`already_member`, `seat_limit`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_email`, `invalid_role`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/invites/{id}":{"delete":{"operationId":"revokeInvite","tags":["Team"],"security":[{"session":[]}],"summary":"Revoke an invite","description":"Dashboard-only: an API key is refused with `403 session_required`. Owner or admin.","parameters":[{"schema":{"type":"string"},"required":true,"description":"Invite id.","name":"id","in":"path"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: no such object, or the key's project cannot see it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/invites/accept":{"post":{"operationId":"acceptInvite","tags":["Team"],"security":[{"session":[]}],"summary":"Accept an invite","description":"Dashboard-only: an API key is refused with `403 session_required`. The signed-in account's email must match the invited address.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteAcceptInput"}}}},"responses":{"200":{"description":"Joined","content":{"application/json":{"schema":{"type":"object","properties":{"project_id":{"type":"string"},"role":{"type":"string"}},"required":["project_id","role"]}}}},"400":{"description":"`invalid_invite`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: called with an API key. `email_mismatch`: the account's email is not the invited one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`already_member`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"`invite_expired`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/connectors":{"get":{"operationId":"listConnectors","tags":["Connectors"],"security":[{"session":[]}],"summary":"List connected providers","description":"Dashboard-only: an API key is refused with `403 session_required`. Paid feature.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Connector"}}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: called with an API key. `plan_required`: the account is on the free plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/connectors/{provider}/oauth/start":{"post":{"operationId":"startConnectorOauth","tags":["Connectors"],"security":[{"session":[]}],"summary":"Begin the OAuth connect flow","description":"Dashboard-only: an API key is refused with `403 session_required`.","parameters":[{"schema":{"type":"string","enum":["vercel","supabase"]},"required":true,"name":"provider","in":"path"}],"responses":{"200":{"description":"Open this URL to authorize","content":{"application/json":{"schema":{"type":"object","properties":{"authorize_url":{"type":"string"}},"required":["authorize_url"]}}}},"400":{"description":"`unknown_provider`, or an OAuth error code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"`provider_unconfigured`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/connectors/{provider}/projects":{"get":{"operationId":"listConnectorProjects","tags":["Connectors"],"security":[{"session":[]}],"summary":"List a provider's projects","description":"Dashboard-only: an API key is refused with `403 session_required`. Live from the provider, flagging the ones already imported.","parameters":[{"schema":{"type":"string","enum":["vercel","supabase"]},"required":true,"name":"provider","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"projects":{"type":"array","items":{"$ref":"#/components/schemas/ImportableProject"}}},"required":["projects"]}}}},"400":{"description":"`unknown_provider`. `invalid_token`: the provider rejected the stored token; reconnect.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"`connector_unavailable`: the provider did not answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/connectors/{provider}/import":{"post":{"operationId":"importConnectorProjects","tags":["Connectors"],"security":[{"session":[]}],"summary":"Import projects as monitors","description":"Dashboard-only: an API key is refused with `403 session_required`. Already-imported refs are skipped; per-project failures (such as the monitor cap) are listed in `failed` rather than failing the batch.","parameters":[{"schema":{"type":"string","enum":["vercel","supabase"]},"required":true,"name":"provider","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportInput"}}}},"responses":{"200":{"description":"Import result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}},"400":{"description":"`unknown_provider`, `invalid_token`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`no_projects`: `external_refs` is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"`connector_unavailable`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/connectors/{provider}":{"delete":{"operationId":"disconnectConnector","tags":["Connectors"],"security":[{"session":[]}],"summary":"Disconnect a provider","description":"Dashboard-only: an API key is refused with `403 session_required`.","parameters":[{"schema":{"type":"string","enum":["vercel","supabase"]},"required":true,"name":"provider","in":"path"}],"responses":{"200":{"description":"Disconnected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"description":"`unauthorized`: the `Authorization` header is missing, or the token is invalid, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"`session_required`: this route is dashboard-only and was called with an API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"`not_found`: not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited`: API-key requests are pooled per account across all its projects and keys, per minute (free 30, pro 120, team 300). Dashboard sessions are not limited. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds until the window resets. Always 60: the window is a fixed minute.","schema":{"type":"string","example":"60"}},"RateLimit-Limit":{"description":"Requests allowed per minute for the project owner's plan.","schema":{"type":"string","example":"30"}},"RateLimit-Remaining":{"description":"Requests left in the window. Always 0 on a 429.","schema":{"type":"string","example":"0"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}