openapi: 3.0.3 info: title: 'statuswerk API Reference' description: 'REST API for status pages: incidents, maintenance, components, subscribers, metrics and more — for CI/CD pipelines, monitoring alerts and your own tools.' version: 1.0.0 servers: - url: 'https://statuswerk.eu' tags: - name: 'Audit log' description: "\nEvery change made in the workspace, by whom and from where — read-only, as in the dashboard. Subscribers are never named and secrets are redacted. Pro sees the last 30 days, Business the whole year kept (365 days); other plans get 403." - name: 'Component groups' description: "\nGroups that bundle components on the page. Creating needs a plan with component groups (403 otherwise); existing groups can be read, changed, reordered and deleted on every plan." - name: Components description: "\nThe parts of your service a status page shows — API, website, payments — each with its current status." - name: 'Custom domain' description: "\nServe a status page on your own domain. Needs a plan with custom domains (403 otherwise).\n\nManage the (single) custom domain of a statuspage.\n\nCustom domains are inherently asynchronous: after the domain is set, the\ncustomer points a CNAME at `cname_target` and adds the TXT record from\n`verification_record` (proof of ownership — without it the domain is not\nverified), a scheduled job verifies DNS, and Caddy provisions the certificate on\ndemand. A domain still unverified 30 days after it was set is released again. This controller is a thin state\nlayer over that existing machinery (StatuspageDomainSyncObserver +\nVerifyCustomDomain* jobs). Clients poll `show` until `status` is `active`." - name: Incidents description: "\nReport disruptions. Creating, updating and resolving an incident has the same consequences as in the dashboard: its components show the outage, the timeline records each step, subscribers and chat channels are notified. On a page with four-eyes approval a new incident is held until a second person approves it in the dashboard." - name: Integrations description: "\nPost incidents and maintenance into Slack, Microsoft Teams, Discord, Google Chat or any webhook. Needs a plan with webhook notifications: without it nothing is sent, creating returns `422` (`quota_exceeded`), changing and testing return `403`. Listing, switching off (`is_enabled: false`) and deleting always work." - name: 'Mail server' description: "\nThe workspace's own SMTP server, used for subscriber notifications instead of ours.\nBusiness only. Credentials are held once per workspace; the sender address can be\noverridden per status page through `mail_from_address` on the status page endpoint.\n\nWorkspace admins only: the token's owner needs the right to change workspace settings\nand must not be restricted to some status pages (`403` otherwise, also for reading)." - name: Maintenance description: "\nAnnounce planned work. Creating needs a plan with scheduled maintenance (403 otherwise); existing windows can be read, changed, started, completed and deleted on every plan, so a downgrade leaves none stuck." - name: Metrics description: "\nNumbers shown as charts on the page — response time, error rate, queue length — pushed by you.\n\nMetric definitions and the points pushed into them.\n\nMetrics are addressed by the `key` the customer chose, not by an opaque id — their\nmonitoring script can then be written once against a name they control rather than\nhaving to look up an identifier first." - name: Monitors description: "\nHTTP checks we run from several regions in Europe (Hetzner and UpCloud). A failure is\nconfirmed from a second region before the check counts as down; it is up again after\ntwo successes in a row. The number of checks and the shortest interval depend on the\nplan (403 / 422 otherwise)." - name: SMS description: "\nThe workspace's SMS this month: the plan's allowance, what is used, and what is left in bought packs. Subscriber SMS, confirmation codes and check alerts count, in SMS parts (160 characters, 70 with emoji or other characters outside the SMS character set). Read-only: packs are bought in the dashboard." - name: 'Status page' description: "\nSettings and status of the status page the request works on." - name: 'Status pages' description: "\nAll status pages of the workspace: list, create, delete.\n\nRESTful collection for a tenant's statuspages (create / list / show / delete).\n\nComplements the header-based singular endpoints (`/api/v1/statuspage`) with\nexplicit-ID resources needed for multi-page orgs and IaC tools (Terraform/CLI).\nUpdates continue to use `PATCH /api/v1/statuspage` (with X-Statuspage-Id) for now." - name: Subscribers description: "\nPeople and systems notified about incidents and maintenance: email, SMS, webhook." - name: Team description: "\nWho is in the workspace, and inviting more people. Removing members and changing roles stays in the dashboard: a token that can do that could rebuild the workspace's access around itself." - name: Templates description: "\nPrepared texts for recurring incidents and maintenance windows. Needs a plan with templates (403 otherwise)." components: securitySchemes: default: type: http scheme: bearer description: 'Create a token in the dashboard under Account → API Tokens and send it as `Authorization: Bearer YOUR_TOKEN`. A token belongs to one workspace — no workspace header needed — and is either read-only or read & write. Writing also needs a plan with API write access; on the Starter plan the API is read-only.' security: - default: [] paths: /api/v1/audit-log: get: summary: 'List audit entries' operationId: listAuditEntries description: "Newest first, for the whole workspace (each entry names its `statuspage_id`), within the plan's window — `since` does not reach past it. A change lists each field as `{from, to}` (entries before 12 November 2026 have `to` only); a secret or personal field is `{redacted: true}`, before and after." parameters: - in: query name: action description: 'Only this action, e.g. created, updated, deleted.' example: updated required: false schema: type: string description: 'Only this action, e.g. created, updated, deleted.' example: updated - in: query name: actor_type description: 'Only changes made by: user, api_token or system.' example: api_token required: false schema: type: string description: 'Only changes made by: user, api_token or system.' example: api_token - in: query name: since description: 'Only entries from this moment on (ISO 8601).' example: '2026-10-01T00:00:00Z' required: false schema: type: string description: 'Only entries from this moment on (ISO 8601).' example: '2026-10-01T00:00:00Z' - in: query name: until description: 'Only entries up to this moment (ISO 8601).' example: '2026-10-31T23:59:59Z' required: false schema: type: string description: 'Only entries up to this moment (ISO 8601).' example: '2026-10-31T23:59:59Z' - in: query name: statuspage_id description: 'Only entries about this status page.' example: 01a1c639-3aa8-70ef-8655-b6f3d56e786b required: false schema: type: string description: 'Only entries about this status page.' example: 01a1c639-3aa8-70ef-8655-b6f3d56e786b - in: query name: subject_type description: 'Only this kind of object, as `subject.type` names it (e.g. Incident, StatusComponent, ScheduledMaintenance, ApiToken).' example: Incident required: false schema: type: string description: 'Only this kind of object, as `subject.type` names it (e.g. Incident, StatusComponent, ScheduledMaintenance, ApiToken).' example: Incident - in: query name: per_page description: 'Page size, at most 100.' example: 50 required: false schema: type: integer description: 'Page size, at most 100.' example: 50 responses: { } tags: - 'Audit log' /api/v1/component-groups/reorder: post: summary: 'Reorder component groups' operationId: reorderComponentGroups description: 'Send `groups` as a list of `{id, position}`; lower positions come first. Ids of other pages are ignored.' parameters: [] responses: { } tags: - 'Component groups' requestBody: required: true content: application/json: schema: type: object properties: groups: type: array description: 'value darf nicht mehr als 500 Elemente haben.' example: - [] items: type: object properties: id: type: string description: 'value muss eine gültige UUID sein.' example: 6ff8f7f6-1eb3-3525-be4a-3932c805afed position: type: integer description: 'value muss mindestens 0 sein.' example: 84 required: - id - position required: - groups /api/v1/component-groups: get: summary: 'List component groups' operationId: listComponentGroups description: '' parameters: [] responses: { } tags: - 'Component groups' post: summary: 'Create a component group' operationId: createAComponentGroup description: '' parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01a1544c-7c05-70fc-9b8d-e46b1a39c2a3 name: Payments description: null position: 1 collapsed_by_default: null visible: null overall_status: operational components: [] created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' properties: data: type: object properties: id: type: string example: 01a1544c-7c05-70fc-9b8d-e46b1a39c2a3 name: type: string example: Payments description: type: string example: null nullable: true position: type: integer example: 1 collapsed_by_default: type: string example: null nullable: true visible: type: string example: null nullable: true overall_status: type: string example: operational components: type: array example: [] created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' tags: - 'Component groups' requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b description: type: string description: 'Shown under the name on the page. value darf nicht mehr als 500 Zeichen haben.' example: 'Et animi quos velit et fugiat.' nullable: true position: type: integer description: 'Order on the page; lower comes first. value muss mindestens 0 sein.' example: 42 nullable: true collapsed_by_default: type: boolean description: 'Show the group folded on the page.' example: false nullable: true visible: type: boolean description: 'false hides it from the page.' example: false nullable: true required: - name '/api/v1/component-groups/{id}': get: summary: 'Get a component group' operationId: getAComponentGroup description: '' parameters: [] responses: { } tags: - 'Component groups' put: summary: 'Update a component group' operationId: updateAComponentGroup description: '' parameters: [] responses: { } tags: - 'Component groups' requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b description: type: string description: 'Shown under the name on the page. value darf nicht mehr als 500 Zeichen haben.' example: 'Et animi quos velit et fugiat.' nullable: true position: type: integer description: 'Order on the page; lower comes first. value muss mindestens 0 sein.' example: 42 nullable: true collapsed_by_default: type: boolean description: 'Show the group folded on the page.' example: false nullable: true visible: type: boolean description: 'false hides it from the page.' example: true nullable: true delete: summary: 'Delete a component group' operationId: deleteAComponentGroup description: 'Its components stay, ungrouped.' parameters: [] responses: { } tags: - 'Component groups' parameters: - in: path name: id description: 'The ID of the component group.' example: 01a1f3c2-6a01-7b10-9c20-3d4e5f6a7b80 required: true schema: type: string /api/v1/components: get: summary: 'List components' operationId: listComponents description: 'All components of the status page, in their display order.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01a1bb24-fdc6-731a-9f22-b7e1198b2414 name: 'Checkout API' description: 'Payments and orders' status: operational status_label: Operational group_id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 group: id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 name: Payments position: 1 show_uptime: true uptime_start_date: null uptime_90d: 100 visible: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' properties: data: type: array example: - id: 01a1bb24-fdc6-731a-9f22-b7e1198b2414 name: 'Checkout API' description: 'Payments and orders' status: operational status_label: Operational group_id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 group: id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 name: Payments position: 1 show_uptime: true uptime_start_date: null uptime_90d: 100 visible: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' items: type: object properties: id: type: string example: 01a1bb24-fdc6-731a-9f22-b7e1198b2414 name: type: string example: 'Checkout API' description: type: string example: 'Payments and orders' status: type: string example: operational status_label: type: string example: Operational group_id: type: string example: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 group: type: object properties: id: type: string example: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 name: type: string example: Payments position: type: integer example: 1 show_uptime: type: boolean example: true uptime_start_date: type: string example: null nullable: true uptime_90d: type: integer example: 100 visible: type: boolean example: true created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' tags: - Components post: summary: 'Create a component' operationId: createAComponent description: "Over the plan's component limit: `422` with `error: quota_exceeded`." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01a1bb24-fdc6-731a-9f22-b7e1198b2414 name: 'Checkout API' description: 'Payments and orders' status: operational status_label: Operational group_id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 group: id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 name: Payments position: 1 show_uptime: null uptime_start_date: null uptime_90d: null visible: null created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' properties: data: type: object properties: id: type: string example: 01a1bb24-fdc6-731a-9f22-b7e1198b2414 name: type: string example: 'Checkout API' description: type: string example: 'Payments and orders' status: type: string example: operational status_label: type: string example: Operational group_id: type: string example: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 group: type: object properties: id: type: string example: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 name: type: string example: Payments position: type: integer example: 1 show_uptime: type: string example: null nullable: true uptime_start_date: type: string example: null nullable: true uptime_90d: type: string example: null nullable: true visible: type: string example: null nullable: true created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' tags: - Components requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b description: type: string description: 'Shown under the name on the page. value darf nicht mehr als 500 Zeichen haben.' example: 'Et animi quos velit et fugiat.' nullable: true group_id: type: string description: 'The component group it belongs to (a group of this page), or null. value muss eine gültige UUID sein.' example: 5707ca55-f609-3528-be8b-1baeaee1567e nullable: true status: type: string description: 'operational, degraded_performance, partial_outage, major_outage or maintenance.' example: degraded_performance enum: - operational - degraded_performance - partial_outage - major_outage - maintenance nullable: true position: type: integer description: 'Order on the page; lower comes first. value muss mindestens 0 sein.' example: 9 nullable: true show_uptime: type: boolean description: 'Show its uptime bars on the page.' example: true nullable: true uptime_start_date: type: string description: 'Count uptime from this date on (e.g. when the service went live). value muss ein gültiges Datum sein. value muss ein Datum vor oder gleich today sein.' example: '2022-12-07' nullable: true visible: type: boolean description: 'false hides it from the page.' example: true nullable: true required: - name '/api/v1/components/{id}': get: summary: 'Get a component' operationId: getAComponent description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01a1bb24-fdc6-731a-9f22-b7e1198b2414 name: 'Checkout API' description: 'Payments and orders' status: operational status_label: Operational group_id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 group: id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 name: Payments position: 1 show_uptime: true uptime_start_date: null uptime_90d: 100 visible: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' properties: data: type: object properties: id: type: string example: 01a1bb24-fdc6-731a-9f22-b7e1198b2414 name: type: string example: 'Checkout API' description: type: string example: 'Payments and orders' status: type: string example: operational status_label: type: string example: Operational group_id: type: string example: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 group: type: object properties: id: type: string example: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 name: type: string example: Payments position: type: integer example: 1 show_uptime: type: boolean example: true uptime_start_date: type: string example: null nullable: true uptime_90d: type: integer example: 100 visible: type: boolean example: true created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' tags: - Components put: summary: 'Update a component' operationId: updateAComponent description: '' parameters: [] responses: { } tags: - Components requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b description: type: string description: 'Shown under the name on the page. value darf nicht mehr als 500 Zeichen haben.' example: 'Et animi quos velit et fugiat.' nullable: true group_id: type: string description: 'The component group it belongs to (a group of this page), or null. value muss eine gültige UUID sein.' example: 5707ca55-f609-3528-be8b-1baeaee1567e nullable: true status: type: string description: 'operational, degraded_performance, partial_outage, major_outage or maintenance.' example: maintenance enum: - operational - degraded_performance - partial_outage - major_outage - maintenance position: type: integer description: 'Order on the page; lower comes first. value muss mindestens 0 sein.' example: 9 nullable: true show_uptime: type: boolean description: 'Show its uptime bars on the page.' example: false nullable: true uptime_start_date: type: string description: 'Count uptime from this date on (e.g. when the service went live). value muss ein gültiges Datum sein. value muss ein Datum vor oder gleich today sein.' example: '2022-12-07' nullable: true visible: type: boolean description: 'false hides it from the page.' example: true nullable: true delete: summary: 'Delete a component' operationId: deleteAComponent description: '' parameters: [] responses: { } tags: - Components parameters: - in: path name: id description: 'The ID of the component.' example: 01a1f3c2-6b11-7c20-8d41-6a2e9f0c3d11 required: true schema: type: string '/api/v1/components/{component}/status': post: summary: "Set a component's status" operationId: setAComponentsStatus description: "For monitoring alerts and pipelines: sets the status directly, without an incident, and records it in the component's history. To tell subscribers, open an incident instead." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01a1bb24-fdc6-731a-9f22-b7e1198b2414 name: 'Checkout API' description: 'Payments and orders' status: degraded_performance status_label: 'Degraded Performance' group_id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 group: id: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 name: Payments position: 1 show_uptime: true uptime_start_date: null uptime_90d: 100 visible: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' properties: data: type: object properties: id: type: string example: 01a1bb24-fdc6-731a-9f22-b7e1198b2414 name: type: string example: 'Checkout API' description: type: string example: 'Payments and orders' status: type: string example: degraded_performance status_label: type: string example: 'Degraded Performance' group_id: type: string example: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 group: type: object properties: id: type: string example: 01a1bb24-fdc3-7139-9cd9-6b02e7859302 name: type: string example: Payments position: type: integer example: 1 show_uptime: type: boolean example: true uptime_start_date: type: string example: null nullable: true uptime_90d: type: integer example: 100 visible: type: boolean example: true created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' tags: - Components requestBody: required: true content: application/json: schema: type: object properties: status: type: string description: 'operational, degraded_performance, partial_outage, major_outage or maintenance.' example: partial_outage enum: - operational - degraded_performance - partial_outage - major_outage - maintenance required: - status parameters: - in: path name: component description: 'The component.' example: 01a1f3c2-6b11-7c20-8d41-6a2e9f0c3d11 required: true schema: type: string /api/v1/components/reorder: post: summary: 'Reorder components' operationId: reorderComponents description: 'Send `components` as a list of `{id, position}`; lower positions come first. Ids of other pages are ignored.' parameters: [] responses: { } tags: - Components requestBody: required: true content: application/json: schema: type: object properties: components: type: array description: 'value darf nicht mehr als 500 Elemente haben.' example: - [] items: type: object properties: id: type: string description: 'value muss eine gültige UUID sein.' example: 6ff8f7f6-1eb3-3525-be4a-3932c805afed position: type: integer description: 'value muss mindestens 0 sein.' example: 84 required: - id - position required: - components '/api/v1/statuspages/{statuspage_id}/custom-domain': get: summary: 'Get the custom domain' operationId: getTheCustomDomain description: '`status` goes from `pending_dns` to `dns_verified` to `active` (or `dns_error`). `verification_record` is the TXT record that proves the domain is yours; it is required, alongside the CNAME to `cname_target`. Poll until `active`. `404` when none is set.' parameters: [] responses: { } tags: - 'Custom domain' put: summary: 'Set the custom domain' operationId: setTheCustomDomain description: 'Accepted with `202`: create the CNAME and the TXT record from `verification_record`, then the domain is verified on its own (or call `verify`). A domain unverified for 30 days is released. `422` with `error: domain_reserved` for our own domains, `domain_taken` when another page uses it.' parameters: [] responses: { } tags: - 'Custom domain' requestBody: required: true content: application/json: schema: type: object properties: domain: type: string description: 'value darf nicht mehr als 255 Zeichen haben.' example: b required: - domain delete: summary: 'Remove the custom domain' operationId: removeTheCustomDomain description: 'The page is served on its statuswerk.eu address again. Works on every plan, also after a downgrade.' parameters: [] responses: { } tags: - 'Custom domain' parameters: - in: path name: statuspage_id description: 'The ID of the statuspage.' example: 01a1f3c2-5c00-7a10-8b20-1c2d3e4f5a6b required: true schema: type: string - in: path name: statuspage description: 'The status page id.' example: 01a1f3c2-5c00-7a10-8b20-1c2d3e4f5a6b required: true schema: type: string '/api/v1/statuspages/{statuspage}/custom-domain/verify': post: summary: 'Check the DNS now' operationId: checkTheDNSNow description: 'Queues the next check due instead of waiting for the scheduled one: DNS until it is verified, then the SSL certificate. Limited to 10 per minute.' parameters: [] responses: { } tags: - 'Custom domain' parameters: - in: path name: statuspage description: 'The status page id.' example: 01a1f3c2-5c00-7a10-8b20-1c2d3e4f5a6b required: true schema: type: string /api/v1/incidents: get: summary: 'List incidents' operationId: listIncidents description: 'Newest first.' parameters: - in: query name: status description: 'Only incidents in this status: investigating, identified, monitoring, resolved.' example: investigating required: false schema: type: string description: 'Only incidents in this status: investigating, identified, monitoring, resolved.' example: investigating - in: query name: active description: 'Only open incidents.' example: true required: false schema: type: boolean description: 'Only open incidents.' example: true - in: query name: resolved description: 'Only resolved incidents.' example: false required: false schema: type: boolean description: 'Only resolved incidents.' example: false - in: query name: per_page description: 'Page size, at most 100.' example: 20 required: false schema: type: integer description: 'Page size, at most 100.' example: 20 responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 title: 'Checkout API unavailable' slug: checkout-api-unavailable public_url: 'https://acme.statuswerk.eu/incidents/checkout-api-unavailable' message: 'We are investigating failed payments.' status: identified status_label: Identified severity: major severity_label: Major impact: null visible: true is_published: true is_awaiting_approval: false approval_state: null approval_note: null is_unlisted: false excluded_from_uptime: false stickied: false notify_subscribers: true occurred_at: '2026-10-19T08:30:00+00:00' resolved_at: null duration_minutes: null is_resolved: false components: - id: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: 'Checkout API' status: null updates: - id: 01a1bb06-ac4b-714f-a2d1-f6630666fb42 incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: identified status_label: Identified message: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: true created_at: '2026-10-19T08:45:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' - id: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: investigating status_label: Investigating message: 'We are investigating failed payments.' notify_subscribers: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' links: first: 'https://statuswerk.eu/api/v1/incidents?page=1' last: 'https://statuswerk.eu/api/v1/incidents?page=1' prev: null next: null meta: current_page: 1 from: 1 last_page: 1 links: - url: null label: '« Previous' page: null active: false - url: 'https://statuswerk.eu/api/v1/incidents?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false path: 'https://statuswerk.eu/api/v1/incidents' per_page: 20 to: 1 total: 1 properties: data: type: array example: - id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 title: 'Checkout API unavailable' slug: checkout-api-unavailable public_url: 'https://acme.statuswerk.eu/incidents/checkout-api-unavailable' message: 'We are investigating failed payments.' status: identified status_label: Identified severity: major severity_label: Major impact: null visible: true is_published: true is_awaiting_approval: false approval_state: null approval_note: null is_unlisted: false excluded_from_uptime: false stickied: false notify_subscribers: true occurred_at: '2026-10-19T08:30:00+00:00' resolved_at: null duration_minutes: null is_resolved: false components: - id: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: 'Checkout API' status: null updates: - id: 01a1bb06-ac4b-714f-a2d1-f6630666fb42 incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: identified status_label: Identified message: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: true created_at: '2026-10-19T08:45:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' - id: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: investigating status_label: Investigating message: 'We are investigating failed payments.' notify_subscribers: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' items: type: object properties: id: type: string example: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 title: type: string example: 'Checkout API unavailable' slug: type: string example: checkout-api-unavailable public_url: type: string example: 'https://acme.statuswerk.eu/incidents/checkout-api-unavailable' message: type: string example: 'We are investigating failed payments.' status: type: string example: identified status_label: type: string example: Identified severity: type: string example: major severity_label: type: string example: Major impact: type: string example: null nullable: true visible: type: boolean example: true is_published: type: boolean example: true is_awaiting_approval: type: boolean example: false approval_state: type: string example: null nullable: true approval_note: type: string example: null nullable: true is_unlisted: type: boolean example: false excluded_from_uptime: type: boolean example: false stickied: type: boolean example: false notify_subscribers: type: boolean example: true occurred_at: type: string example: '2026-10-19T08:30:00+00:00' resolved_at: type: string example: null nullable: true duration_minutes: type: string example: null nullable: true is_resolved: type: boolean example: false components: type: array example: - id: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: 'Checkout API' status: null items: type: object properties: id: type: string example: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: type: string example: 'Checkout API' status: type: string example: null nullable: true updates: type: array example: - id: 01a1bb06-ac4b-714f-a2d1-f6630666fb42 incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: identified status_label: Identified message: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: true created_at: '2026-10-19T08:45:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' - id: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: investigating status_label: Investigating message: 'We are investigating failed payments.' notify_subscribers: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' items: type: object properties: id: type: string example: 01a1bb06-ac4b-714f-a2d1-f6630666fb42 incident_id: type: string example: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: type: string example: identified status_label: type: string example: Identified message: type: string example: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: type: boolean example: true created_at: type: string example: '2026-10-19T08:45:00+00:00' updated_at: type: string example: '2026-10-19T08:45:00+00:00' created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:45:00+00:00' links: type: object properties: first: type: string example: 'https://statuswerk.eu/api/v1/incidents?page=1' last: type: string example: 'https://statuswerk.eu/api/v1/incidents?page=1' prev: type: string example: null nullable: true next: type: string example: null nullable: true meta: type: object properties: current_page: type: integer example: 1 from: type: integer example: 1 last_page: type: integer example: 1 links: type: array example: - url: null label: '« Previous' page: null active: false - url: 'https://statuswerk.eu/api/v1/incidents?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false items: type: object properties: url: type: string example: null nullable: true label: type: string example: '« Previous' page: type: string example: null nullable: true active: type: boolean example: false path: type: string example: 'https://statuswerk.eu/api/v1/incidents' per_page: type: integer example: 20 to: type: integer example: 1 total: type: integer example: 1 tags: - Incidents post: summary: 'Open an incident' operationId: openAnIncident description: 'Without a `status` per component, each takes the status the severity implies (minor → partial outage, major and critical → major outage). Over the monthly incident limit: `422` with `error: quota_exceeded`. Held for four-eyes approval, the response says so in `message` and `is_awaiting_approval`; nothing is published or sent until it is approved.' parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 title: 'Checkout API unavailable' slug: checkout-api-unavailable public_url: 'https://acme.statuswerk.eu/incidents/checkout-api-unavailable' message: 'We are investigating failed payments.' status: investigating status_label: Investigating severity: major severity_label: Major impact: null visible: true is_published: true is_awaiting_approval: false approval_state: null approval_note: null is_unlisted: false excluded_from_uptime: false stickied: false notify_subscribers: true occurred_at: '2026-10-19T08:30:00+00:00' resolved_at: null duration_minutes: null is_resolved: false components: - id: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: 'Checkout API' status: null updates: - id: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: investigating status_label: Investigating message: 'We are investigating failed payments.' notify_subscribers: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' properties: data: type: object properties: id: type: string example: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 title: type: string example: 'Checkout API unavailable' slug: type: string example: checkout-api-unavailable public_url: type: string example: 'https://acme.statuswerk.eu/incidents/checkout-api-unavailable' message: type: string example: 'We are investigating failed payments.' status: type: string example: investigating status_label: type: string example: Investigating severity: type: string example: major severity_label: type: string example: Major impact: type: string example: null nullable: true visible: type: boolean example: true is_published: type: boolean example: true is_awaiting_approval: type: boolean example: false approval_state: type: string example: null nullable: true approval_note: type: string example: null nullable: true is_unlisted: type: boolean example: false excluded_from_uptime: type: boolean example: false stickied: type: boolean example: false notify_subscribers: type: boolean example: true occurred_at: type: string example: '2026-10-19T08:30:00+00:00' resolved_at: type: string example: null nullable: true duration_minutes: type: string example: null nullable: true is_resolved: type: boolean example: false components: type: array example: - id: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: 'Checkout API' status: null items: type: object properties: id: type: string example: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: type: string example: 'Checkout API' status: type: string example: null nullable: true updates: type: array example: - id: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: investigating status_label: Investigating message: 'We are investigating failed payments.' notify_subscribers: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' items: type: object properties: id: type: string example: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: type: string example: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: type: string example: investigating status_label: type: string example: Investigating message: type: string example: 'We are investigating failed payments.' notify_subscribers: type: boolean example: true created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' tags: - Incidents requestBody: required: true content: application/json: schema: type: object properties: title: type: string description: 'Shown on the page and in every notification. value darf nicht mehr als 255 Zeichen haben.' example: 'Checkout API unavailable' message: type: string description: 'The first update. HTML is sanitized on save: text formatting, lists, headings and links stay; scripts, event handlers, iframes, styles and javascript: links are removed. value darf nicht mehr als 10000 Zeichen haben.' example: 'We are investigating failed payments.' status: type: string description: 'investigating (default), identified, monitoring or resolved.' example: investigating enum: - investigating - identified - monitoring - resolved nullable: true severity: type: string description: "minor (default), major or critical. Decides the affected components' status unless you give one per component." example: major enum: - minor - major - critical nullable: true impact: type: string description: 'value darf nicht mehr als 255 Zeichen haben.' example: b nullable: true visible: type: boolean description: 'false prepares it: off the page, components untouched, nothing sent. Switching it on later (PATCH) publishes it then.' example: true nullable: true is_unlisted: type: boolean description: 'Not listed on the page, reachable by its link only.' example: false nullable: true excluded_from_uptime: type: boolean description: 'Leave it out of the uptime figures.' example: false nullable: true stickied: type: boolean description: 'Pin it to the top of the page.' example: false nullable: true notify_subscribers: type: boolean description: 'Tell subscribers (default true). Chat integrations are told either way.' example: true nullable: true occurred_at: type: string description: 'When it began, for an incident reported late. Default now. value muss ein gültiges Datum sein.' example: '2026-10-19T08:30:00+02:00' nullable: true resolved_at: type: string description: 'When it ended, for an incident filed after the fact (status `resolved` only). Default: now, when the status is `resolved`. value muss ein gültiges Datum sein. value muss ein Datum nach oder gleich occurred_at sein.' example: '2026-10-19T09:10:00+02:00' nullable: true components: type: array description: 'Affected components.' example: null items: type: object nullable: true properties: id: type: string description: 'A component id of this status page. value muss eine gültige UUID sein.' example: 01a1f3c2-6b11-7c20-8d41-6a2e9f0c3d11 status: type: string description: "This component's status during the incident: degraded_performance, partial_outage or major_outage. Without it the severity decides." example: major_outage enum: - operational - degraded_performance - partial_outage - major_outage - maintenance nullable: true required: - id required: - title - message '/api/v1/incidents/{id}': get: summary: 'Get an incident' operationId: getAnIncident description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 title: 'Checkout API unavailable' slug: checkout-api-unavailable public_url: 'https://acme.statuswerk.eu/incidents/checkout-api-unavailable' message: 'We are investigating failed payments.' status: identified status_label: Identified severity: major severity_label: Major impact: null visible: true is_published: true is_awaiting_approval: false approval_state: null approval_note: null is_unlisted: false excluded_from_uptime: false stickied: false notify_subscribers: true occurred_at: '2026-10-19T08:30:00+00:00' resolved_at: null duration_minutes: null is_resolved: false components: - id: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: 'Checkout API' status: null updates: - id: 01a1bb06-ac4b-714f-a2d1-f6630666fb42 incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: identified status_label: Identified message: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: true created_at: '2026-10-19T08:45:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' - id: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: investigating status_label: Investigating message: 'We are investigating failed payments.' notify_subscribers: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' properties: data: type: object properties: id: type: string example: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 title: type: string example: 'Checkout API unavailable' slug: type: string example: checkout-api-unavailable public_url: type: string example: 'https://acme.statuswerk.eu/incidents/checkout-api-unavailable' message: type: string example: 'We are investigating failed payments.' status: type: string example: identified status_label: type: string example: Identified severity: type: string example: major severity_label: type: string example: Major impact: type: string example: null nullable: true visible: type: boolean example: true is_published: type: boolean example: true is_awaiting_approval: type: boolean example: false approval_state: type: string example: null nullable: true approval_note: type: string example: null nullable: true is_unlisted: type: boolean example: false excluded_from_uptime: type: boolean example: false stickied: type: boolean example: false notify_subscribers: type: boolean example: true occurred_at: type: string example: '2026-10-19T08:30:00+00:00' resolved_at: type: string example: null nullable: true duration_minutes: type: string example: null nullable: true is_resolved: type: boolean example: false components: type: array example: - id: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: 'Checkout API' status: null items: type: object properties: id: type: string example: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: type: string example: 'Checkout API' status: type: string example: null nullable: true updates: type: array example: - id: 01a1bb06-ac4b-714f-a2d1-f6630666fb42 incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: identified status_label: Identified message: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: true created_at: '2026-10-19T08:45:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' - id: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: investigating status_label: Investigating message: 'We are investigating failed payments.' notify_subscribers: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' items: type: object properties: id: type: string example: 01a1bb06-ac4b-714f-a2d1-f6630666fb42 incident_id: type: string example: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: type: string example: identified status_label: type: string example: Identified message: type: string example: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: type: boolean example: true created_at: type: string example: '2026-10-19T08:45:00+00:00' updated_at: type: string example: '2026-10-19T08:45:00+00:00' created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:45:00+00:00' tags: - Incidents put: summary: 'Update an incident' operationId: updateAnIncident description: 'A changed status is recorded on the timeline, a changed severity moves the components, added and removed components follow. Setting `status` to `resolved` resolves it as `resolve` does.' parameters: [] responses: { } tags: - Incidents requestBody: required: false content: application/json: schema: type: object properties: title: type: string description: 'Shown on the page and in every notification. value darf nicht mehr als 255 Zeichen haben.' example: b message: type: string description: 'The text. HTML is sanitized on save: text formatting, lists, headings and links stay; scripts, event handlers, iframes, styles and javascript: links are removed. value darf nicht mehr als 10000 Zeichen haben.' example: 'n' status: type: string description: 'investigating, identified, monitoring or resolved.' example: monitoring enum: - investigating - identified - monitoring - resolved severity: type: string description: "minor, major or critical. Decides the affected components' status unless one is given per component." example: minor enum: - minor - major - critical nullable: true impact: type: string description: 'A short note on who or what is affected. value darf nicht mehr als 255 Zeichen haben.' example: g nullable: true visible: type: boolean description: 'false hides it from the page. Switching it on for an open incident publishes it now: components, subscribers, chat.' example: true nullable: true is_unlisted: type: boolean description: 'Not listed on the page; reachable by its link (`public_url`) only.' example: true nullable: true excluded_from_uptime: type: boolean description: 'Leave it out of the uptime figures.' example: false nullable: true stickied: type: boolean description: 'Pin it to the top of the page.' example: false nullable: true notify_subscribers: type: boolean description: 'Tell subscribers (default true). Chat integrations are told either way.' example: false nullable: true occurred_at: type: string description: 'value muss ein gültiges Datum sein.' example: '2026-11-12T21:59:18' resolved_at: type: string description: 'value muss ein gültiges Datum sein.' example: '2026-11-12T21:59:18' nullable: true components: type: array description: 'Affected components.' example: null items: type: object nullable: true properties: id: type: string description: 'A component id of this status page. value muss eine gültige UUID sein.' example: c90237e9-ced5-3af6-88ea-84aeaa148878 status: type: string description: "This component's status during the incident: degraded_performance, partial_outage or major_outage. Without it the severity decides." example: partial_outage enum: - operational - degraded_performance - partial_outage - major_outage - maintenance nullable: true required: - id delete: summary: 'Delete an incident' operationId: deleteAnIncident description: 'Its components return to operational unless another open incident still affects them.' parameters: [] responses: { } tags: - Incidents parameters: - in: path name: id description: 'The ID of the incident.' example: 01a1f3c2-7d0e-7a51-9c3b-2f6e8d4a1b90 required: true schema: type: string '/api/v1/incidents/{incident_id}/updates': get: summary: "List an incident's updates" operationId: listAnIncidentsUpdates description: '' parameters: [] responses: { } tags: - Incidents post: summary: 'Post an incident update' operationId: postAnIncidentUpdate description: 'Adds a step to the timeline and moves the incident to its `status`; subscribers are notified unless `notify_subscribers` is false. `resolved` resolves the incident and returns its components. On an incident still awaiting approval the update is kept but sent to nobody.' parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01a1544c-7c1d-7350-9874-aba971bbbc78 incident_id: 01a1544c-7c0f-7068-b8a5-30af62ccecd5 status: identified status_label: Identified message: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: true created_at: '2026-10-19T08:45:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' properties: data: type: object properties: id: type: string example: 01a1544c-7c1d-7350-9874-aba971bbbc78 incident_id: type: string example: 01a1544c-7c0f-7068-b8a5-30af62ccecd5 status: type: string example: identified status_label: type: string example: Identified message: type: string example: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: type: boolean example: true created_at: type: string example: '2026-10-19T08:45:00+00:00' updated_at: type: string example: '2026-10-19T08:45:00+00:00' tags: - Incidents requestBody: required: true content: application/json: schema: type: object properties: status: type: string description: "The incident's status from now on. resolved resolves it." example: identified enum: - investigating - identified - monitoring - resolved message: type: string description: 'What happened since the last update. HTML is sanitized on save: text formatting, lists, headings and links stay; scripts, event handlers, iframes, styles and javascript: links are removed. value darf nicht mehr als 10000 Zeichen haben.' example: 'A failing database migration; rolling back.' notify_subscribers: type: boolean description: 'Tell subscribers (default true).' example: true nullable: true created_at: type: string description: 'When it happened, for an update reported late. Default now. value muss ein gültiges Datum sein. value muss ein Datum vor oder gleich now sein.' example: '2022-12-07' nullable: true required: - status - message parameters: - in: path name: incident_id description: 'The ID of the incident.' example: 01a1f3c2-7d0e-7a51-9c3b-2f6e8d4a1b90 required: true schema: type: string '/api/v1/incidents/{incident_id}/updates/{id}': patch: summary: 'Correct an incident update' operationId: correctAnIncidentUpdate description: 'Fixes the text or the time of an update already posted. Nobody is notified again — a correction is not news.' parameters: [] responses: { } tags: - Incidents requestBody: required: false content: application/json: schema: type: object properties: message: type: string description: 'value darf nicht mehr als 10000 Zeichen haben.' example: b created_at: type: string description: 'value muss ein gültiges Datum sein. value muss ein Datum vor oder gleich now sein.' example: '2022-12-07' delete: summary: 'Delete an incident update' operationId: deleteAnIncidentUpdate description: 'Removes the step from the timeline. The incident keeps its current status.' parameters: [] responses: { } tags: - Incidents parameters: - in: path name: incident_id description: 'The ID of the incident.' example: 01a1f3c2-7d0e-7a51-9c3b-2f6e8d4a1b90 required: true schema: type: string - in: path name: id description: 'The ID of the update.' example: 01a1f3c2-7d10-7f02-a9b4-0c1d2e3f4a5b required: true schema: type: string - in: path name: update description: "The update's id." example: 01a1f3c2-7d10-7f02-a9b4-0c1d2e3f4a5b required: true schema: type: string '/api/v1/incidents/{incident}/resolve': patch: summary: 'Resolve an incident' operationId: resolveAnIncident description: 'Components return to operational unless another open incident still affects them; subscribers get the resolution, with `message` if you send one.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 title: 'Checkout API unavailable' slug: checkout-api-unavailable public_url: 'https://acme.statuswerk.eu/incidents/checkout-api-unavailable' message: 'We are investigating failed payments.' status: resolved status_label: Resolved severity: major severity_label: Major impact: null visible: true is_published: true is_awaiting_approval: false approval_state: null approval_note: null is_unlisted: false excluded_from_uptime: false stickied: false notify_subscribers: true occurred_at: '2026-10-19T08:30:00+00:00' resolved_at: '2026-10-19T09:10:00+00:00' duration_minutes: 40 is_resolved: true components: - id: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: 'Checkout API' status: null updates: - id: 01a1bb06-ac51-71da-a566-49dd7cc5c4cf incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: resolved status_label: Resolved message: 'Payments work again.' notify_subscribers: true created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' - id: 01a1bb06-ac4b-714f-a2d1-f6630666fb42 incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: identified status_label: Identified message: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: true created_at: '2026-10-19T08:45:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' - id: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: investigating status_label: Investigating message: 'We are investigating failed payments.' notify_subscribers: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' properties: data: type: object properties: id: type: string example: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 title: type: string example: 'Checkout API unavailable' slug: type: string example: checkout-api-unavailable public_url: type: string example: 'https://acme.statuswerk.eu/incidents/checkout-api-unavailable' message: type: string example: 'We are investigating failed payments.' status: type: string example: resolved status_label: type: string example: Resolved severity: type: string example: major severity_label: type: string example: Major impact: type: string example: null nullable: true visible: type: boolean example: true is_published: type: boolean example: true is_awaiting_approval: type: boolean example: false approval_state: type: string example: null nullable: true approval_note: type: string example: null nullable: true is_unlisted: type: boolean example: false excluded_from_uptime: type: boolean example: false stickied: type: boolean example: false notify_subscribers: type: boolean example: true occurred_at: type: string example: '2026-10-19T08:30:00+00:00' resolved_at: type: string example: '2026-10-19T09:10:00+00:00' duration_minutes: type: integer example: 40 is_resolved: type: boolean example: true components: type: array example: - id: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: 'Checkout API' status: null items: type: object properties: id: type: string example: 01a1bb06-ac3a-73d9-bdeb-b86ecd87c763 name: type: string example: 'Checkout API' status: type: string example: null nullable: true updates: type: array example: - id: 01a1bb06-ac51-71da-a566-49dd7cc5c4cf incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: resolved status_label: Resolved message: 'Payments work again.' notify_subscribers: true created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' - id: 01a1bb06-ac4b-714f-a2d1-f6630666fb42 incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: identified status_label: Identified message: 'A certificate expired at our payment provider. We are rolling out a new one.' notify_subscribers: true created_at: '2026-10-19T08:45:00+00:00' updated_at: '2026-10-19T08:45:00+00:00' - id: 01a1bb06-ac46-7344-8e3c-1f5dabca8d6b incident_id: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: investigating status_label: Investigating message: 'We are investigating failed payments.' notify_subscribers: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' items: type: object properties: id: type: string example: 01a1bb06-ac51-71da-a566-49dd7cc5c4cf incident_id: type: string example: 01a1bb06-ac42-72a7-af4d-7bf1db7bb967 status: type: string example: resolved status_label: type: string example: Resolved message: type: string example: 'Payments work again.' notify_subscribers: type: boolean example: true created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' tags: - Incidents requestBody: required: false content: application/json: schema: type: object properties: message: type: string description: 'value darf nicht mehr als 10000 Zeichen haben.' example: b nullable: true notify_subscribers: type: boolean description: '' example: true nullable: true parameters: - in: path name: incident description: 'The incident.' example: 01a1f3c2-7d0e-7a51-9c3b-2f6e8d4a1b90 required: true schema: type: string /api/v1/integrations: get: summary: 'List integrations' operationId: listIntegrations description: 'A read-only token sees only the host of each webhook URL — the full URL is a credential.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 1 type: slack name: 'Ops channel' url: 'https://hooks.slack.com/services/T000/B000/XXXXXXXX' is_enabled: true events: - incident.created - incident.updated - incident.resolved - maintenance.scheduled - maintenance.started - maintenance.completed last_triggered_at: null last_status_code: null created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' properties: data: type: array example: - id: 1 type: slack name: 'Ops channel' url: 'https://hooks.slack.com/services/T000/B000/XXXXXXXX' is_enabled: true events: - incident.created - incident.updated - incident.resolved - maintenance.scheduled - maintenance.started - maintenance.completed last_triggered_at: null last_status_code: null created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' items: type: object properties: id: type: integer example: 1 type: type: string example: slack name: type: string example: 'Ops channel' url: type: string example: 'https://hooks.slack.com/services/T000/B000/XXXXXXXX' is_enabled: type: boolean example: true events: type: array example: - incident.created - incident.updated - incident.resolved - maintenance.scheduled - maintenance.started - maintenance.completed items: type: string last_triggered_at: type: string example: null nullable: true last_status_code: type: string example: null nullable: true created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' tags: - Integrations post: summary: 'Create an integration' operationId: createAnIntegration description: "Over the plan's integration limit: `422` with `error: quota_exceeded`. The URL must be public HTTPS." parameters: [] responses: { } tags: - Integrations requestBody: required: true content: application/json: schema: type: object properties: type: type: string description: 'slack, microsoft_teams, discord, google_chat or generic.' example: generic enum: - generic - slack - microsoft_teams - discord - google_chat name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b url: type: string description: 'The webhook URL; public HTTPS only. It is a credential: read-only tokens see its host only. Must be a valid URL. value darf nicht mehr als 2000 Zeichen haben.' example: 'http://bailey.com/' is_enabled: type: boolean description: 'false keeps it but sends nothing.' example: false nullable: true events: type: array description: '' example: - incident.created items: type: string enum: - incident.created - incident.updated - incident.resolved - maintenance.scheduled - maintenance.started - maintenance.completed required: - type - name - url '/api/v1/integrations/{id}': get: summary: 'Get an integration' operationId: getAnIntegration description: '' parameters: [] responses: { } tags: - Integrations put: summary: 'Update an integration' operationId: updateAnIntegration description: 'Without a plan with webhook notifications only switching it off is allowed (`403` otherwise).' parameters: [] responses: { } tags: - Integrations requestBody: required: false content: application/json: schema: type: object properties: type: type: string description: 'slack, microsoft_teams, discord, google_chat or generic.' example: generic enum: - generic - slack - microsoft_teams - discord - google_chat name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b url: type: string description: 'The webhook URL; public HTTPS only. It is a credential: read-only tokens see its host only. Must be a valid URL. value darf nicht mehr als 2000 Zeichen haben.' example: 'http://bailey.com/' is_enabled: type: boolean description: 'false keeps it but sends nothing.' example: true events: type: array description: '' example: - maintenance.scheduled items: type: string enum: - incident.created - incident.updated - incident.resolved - maintenance.scheduled - maintenance.started - maintenance.completed delete: summary: 'Delete an integration' operationId: deleteAnIntegration description: '' parameters: [] responses: { } tags: - Integrations parameters: - in: path name: id description: 'The ID of the integration.' example: 12 required: true schema: type: integer '/api/v1/integrations/{integration}/test': post: summary: 'Send a test message' operationId: sendATestMessage description: 'Posts a test message to the integration. `422` when the URL could not be reached. Limited to 10 per minute.' parameters: [] responses: { } tags: - Integrations parameters: - in: path name: integration description: 'The integration.' example: 12 required: true schema: type: integer /api/v1/mail-settings: get: summary: 'Get the mail server settings' operationId: getTheMailServerSettings description: '`404` when none are set. The password is never returned, only `has_password`.' parameters: [] responses: { } tags: - 'Mail server' patch: summary: 'Set the mail server' operationId: setTheMailServer description: "The host must be reachable from the public internet.\n\nOmit `password` to keep the stored one — only while host, port, username and\nencryption stay the same; changing any of them without sending the password again\nanswers 422. `is_active` false keeps the configuration but sends through our own\nservers again." parameters: [] responses: { } tags: - 'Mail server' requestBody: required: false content: application/json: schema: type: object properties: host: type: string description: 'value darf nicht mehr als 255 Zeichen haben.' example: b port: type: integer description: 'value muss mindestens 1 sein. value darf nicht größer als 65535 sein.' example: 22 encryption: type: string description: "As the dashboard: always encrypted. Without it the password could cross the\nnetwork in plain text (opportunistic STARTTLS can be stripped)." example: tls enum: - tls - ssl username: type: string description: 'value darf nicht mehr als 255 Zeichen haben.' example: g nullable: true password: type: string description: 'value darf nicht mehr als 255 Zeichen haben.' example: '{+-0pBNvYgx' nullable: true from_address: type: string description: 'value muss eine gültige E-Mail-Adresse sein. value darf nicht mehr als 255 Zeichen haben.' example: w is_active: type: boolean description: '' example: true delete: summary: 'Remove the mail server' operationId: removeTheMailServer description: "Subscriber mail goes through our servers again.\n\nNotifications go back through our own servers immediately." parameters: [] responses: { } tags: - 'Mail server' /api/v1/mail-settings/test: post: summary: 'Test the mail server' operationId: testTheMailServer description: "Connects and signs in without sending mail; the result says whether the login was checked. With `send_test_mail: true` a real test message goes through the server to the token owner's address. Limited to 10 per minute.\n\nOpens a connection, performs the handshake, signs in and hangs up. Nothing is sent.\n\nAlways answers 200 when the test could be carried out — the outcome is in `ok`,\nbecause a server refusing the login is a result, not a failed request. The stored\nconfiguration is the only thing it will test; it does not accept a host to connect\nto, which would make this an authenticated port scanner." parameters: [] responses: { } tags: - 'Mail server' /api/v1/maintenances: get: summary: 'List maintenance windows' operationId: listMaintenanceWindows description: 'In order of their start.' parameters: - in: query name: status description: 'Only windows in this status: scheduled, in_progress, completed.' example: scheduled required: false schema: type: string description: 'Only windows in this status: scheduled, in_progress, completed.' example: scheduled - in: query name: upcoming description: 'Only scheduled windows still ahead.' example: true required: false schema: type: boolean description: 'Only scheduled windows still ahead.' example: true - in: query name: active description: 'Only windows in progress.' example: false required: false schema: type: boolean description: 'Only windows in progress.' example: false - in: query name: per_page description: 'Page size, at most 100.' example: 20 required: false schema: type: integer description: 'Page size, at most 100.' example: 20 responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01a1bb06-ac56-730b-ba95-295abe87a0b3 title: 'Database upgrade' public_url: 'https://acme.statuswerk.eu/maintenance/01a1bb06-ac56-730b-ba95-295abe87a0b3' message: 'The dashboard is read-only for up to 30 minutes.' status: scheduled status_label: Scheduled scheduled_start_at: '2026-10-24T22:00:00+00:00' scheduled_end_at: '2026-10-24T23:00:00+00:00' actual_start_at: null actual_end_at: null scheduled_duration_minutes: 60 actual_duration_minutes: null auto_start: false auto_complete: false notify_subscribers: true is_published: true is_awaiting_approval: false approval_state: null approval_note: null is_unlisted: false notify_at_scheduled: true send_reminder_1h: true notify_at_start: true notify_at_end: true update_component_status: false is_scheduled: true is_in_progress: false is_completed: false components: [] created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' links: first: 'https://statuswerk.eu/api/v1/maintenances?page=1' last: 'https://statuswerk.eu/api/v1/maintenances?page=1' prev: null next: null meta: current_page: 1 from: 1 last_page: 1 links: - url: null label: '« Previous' page: null active: false - url: 'https://statuswerk.eu/api/v1/maintenances?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false path: 'https://statuswerk.eu/api/v1/maintenances' per_page: 20 to: 1 total: 1 properties: data: type: array example: - id: 01a1bb06-ac56-730b-ba95-295abe87a0b3 title: 'Database upgrade' public_url: 'https://acme.statuswerk.eu/maintenance/01a1bb06-ac56-730b-ba95-295abe87a0b3' message: 'The dashboard is read-only for up to 30 minutes.' status: scheduled status_label: Scheduled scheduled_start_at: '2026-10-24T22:00:00+00:00' scheduled_end_at: '2026-10-24T23:00:00+00:00' actual_start_at: null actual_end_at: null scheduled_duration_minutes: 60 actual_duration_minutes: null auto_start: false auto_complete: false notify_subscribers: true is_published: true is_awaiting_approval: false approval_state: null approval_note: null is_unlisted: false notify_at_scheduled: true send_reminder_1h: true notify_at_start: true notify_at_end: true update_component_status: false is_scheduled: true is_in_progress: false is_completed: false components: [] created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' items: type: object properties: id: type: string example: 01a1bb06-ac56-730b-ba95-295abe87a0b3 title: type: string example: 'Database upgrade' public_url: type: string example: 'https://acme.statuswerk.eu/maintenance/01a1bb06-ac56-730b-ba95-295abe87a0b3' message: type: string example: 'The dashboard is read-only for up to 30 minutes.' status: type: string example: scheduled status_label: type: string example: Scheduled scheduled_start_at: type: string example: '2026-10-24T22:00:00+00:00' scheduled_end_at: type: string example: '2026-10-24T23:00:00+00:00' actual_start_at: type: string example: null nullable: true actual_end_at: type: string example: null nullable: true scheduled_duration_minutes: type: integer example: 60 actual_duration_minutes: type: string example: null nullable: true auto_start: type: boolean example: false auto_complete: type: boolean example: false notify_subscribers: type: boolean example: true is_published: type: boolean example: true is_awaiting_approval: type: boolean example: false approval_state: type: string example: null nullable: true approval_note: type: string example: null nullable: true is_unlisted: type: boolean example: false notify_at_scheduled: type: boolean example: true send_reminder_1h: type: boolean example: true notify_at_start: type: boolean example: true notify_at_end: type: boolean example: true update_component_status: type: boolean example: false is_scheduled: type: boolean example: true is_in_progress: type: boolean example: false is_completed: type: boolean example: false components: type: array example: [] created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' links: type: object properties: first: type: string example: 'https://statuswerk.eu/api/v1/maintenances?page=1' last: type: string example: 'https://statuswerk.eu/api/v1/maintenances?page=1' prev: type: string example: null nullable: true next: type: string example: null nullable: true meta: type: object properties: current_page: type: integer example: 1 from: type: integer example: 1 last_page: type: integer example: 1 links: type: array example: - url: null label: '« Previous' page: null active: false - url: 'https://statuswerk.eu/api/v1/maintenances?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false items: type: object properties: url: type: string example: null nullable: true label: type: string example: '« Previous' page: type: string example: null nullable: true active: type: boolean example: false path: type: string example: 'https://statuswerk.eu/api/v1/maintenances' per_page: type: integer example: 20 to: type: integer example: 1 total: type: integer example: 1 tags: - Maintenance post: summary: 'Schedule maintenance' operationId: scheduleMaintenance description: 'Subscribers are told when it is scheduled, an hour before, when it starts and when it ends — each switchable with `notify_at_scheduled`, `send_reminder_1h`, `notify_at_start`, `notify_at_end`. Held for four-eyes approval, it is announced once approved.' parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01a1bb06-ac56-730b-ba95-295abe87a0b3 title: 'Database upgrade' public_url: 'https://acme.statuswerk.eu/maintenance/01a1bb06-ac56-730b-ba95-295abe87a0b3' message: 'The dashboard is read-only for up to 30 minutes.' status: scheduled status_label: Scheduled scheduled_start_at: '2026-10-24T22:00:00+00:00' scheduled_end_at: '2026-10-24T23:00:00+00:00' actual_start_at: null actual_end_at: null scheduled_duration_minutes: 60 actual_duration_minutes: null auto_start: false auto_complete: false notify_subscribers: true is_published: true is_awaiting_approval: false approval_state: null approval_note: null is_unlisted: false notify_at_scheduled: null send_reminder_1h: null notify_at_start: null notify_at_end: null update_component_status: null is_scheduled: true is_in_progress: false is_completed: false components: [] created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' properties: data: type: object properties: id: type: string example: 01a1bb06-ac56-730b-ba95-295abe87a0b3 title: type: string example: 'Database upgrade' public_url: type: string example: 'https://acme.statuswerk.eu/maintenance/01a1bb06-ac56-730b-ba95-295abe87a0b3' message: type: string example: 'The dashboard is read-only for up to 30 minutes.' status: type: string example: scheduled status_label: type: string example: Scheduled scheduled_start_at: type: string example: '2026-10-24T22:00:00+00:00' scheduled_end_at: type: string example: '2026-10-24T23:00:00+00:00' actual_start_at: type: string example: null nullable: true actual_end_at: type: string example: null nullable: true scheduled_duration_minutes: type: integer example: 60 actual_duration_minutes: type: string example: null nullable: true auto_start: type: boolean example: false auto_complete: type: boolean example: false notify_subscribers: type: boolean example: true is_published: type: boolean example: true is_awaiting_approval: type: boolean example: false approval_state: type: string example: null nullable: true approval_note: type: string example: null nullable: true is_unlisted: type: boolean example: false notify_at_scheduled: type: string example: null nullable: true send_reminder_1h: type: string example: null nullable: true notify_at_start: type: string example: null nullable: true notify_at_end: type: string example: null nullable: true update_component_status: type: string example: null nullable: true is_scheduled: type: boolean example: true is_in_progress: type: boolean example: false is_completed: type: boolean example: false components: type: array example: [] created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' tags: - Maintenance requestBody: required: true content: application/json: schema: type: object properties: title: type: string description: 'Shown on the page and in every notification. value darf nicht mehr als 255 Zeichen haben.' example: b message: type: string description: 'The text. HTML is sanitized on save: text formatting, lists, headings and links stay; scripts, event handlers, iframes, styles and javascript: links are removed. value darf nicht mehr als 10000 Zeichen haben.' example: 'n' scheduled_start_at: type: string description: 'When it begins (ISO 8601). value muss ein gültiges Datum sein. value muss ein Datum nach now sein.' example: '2052-12-06' scheduled_end_at: type: string description: 'When it ends; after the start. value muss ein gültiges Datum sein. value muss ein Datum nach scheduled_start_at sein.' example: '2052-12-05' auto_start: type: boolean description: 'Start it by itself at `scheduled_start_at`.' example: false nullable: true auto_complete: type: boolean description: 'Complete it by itself at `scheduled_end_at`.' example: false nullable: true notify_subscribers: type: boolean description: 'Tell subscribers (default true). Chat integrations are told either way.' example: true nullable: true is_unlisted: type: boolean description: 'Not listed on the page; reachable by its link (`public_url`) only.' example: false nullable: true notify_at_scheduled: type: boolean description: 'Tell subscribers when it is scheduled.' example: false nullable: true send_reminder_1h: type: boolean description: 'Remind subscribers an hour before.' example: false nullable: true notify_at_start: type: boolean description: 'Tell subscribers when it starts.' example: true nullable: true notify_at_end: type: boolean description: 'Tell subscribers when it ends.' example: true nullable: true update_component_status: type: boolean description: 'Show the components as under maintenance while it runs.' example: true nullable: true component_ids: type: array description: 'value muss eine gültige UUID sein.' example: - a4855dc5-0acb-33c3-b921-f4291f719ca0 items: type: string required: - title - message - scheduled_start_at - scheduled_end_at '/api/v1/maintenances/{id}': get: summary: 'Get a maintenance window' operationId: getAMaintenanceWindow description: '' parameters: [] responses: { } tags: - Maintenance put: summary: 'Update a maintenance window' operationId: updateAMaintenanceWindow description: '' parameters: [] responses: { } tags: - Maintenance requestBody: required: false content: application/json: schema: type: object properties: title: type: string description: 'Shown on the page and in every notification. value darf nicht mehr als 255 Zeichen haben.' example: b message: type: string description: 'The text. HTML is sanitized on save: text formatting, lists, headings and links stay; scripts, event handlers, iframes, styles and javascript: links are removed. value darf nicht mehr als 10000 Zeichen haben.' example: 'n' scheduled_start_at: type: string description: 'When it begins (ISO 8601). value muss ein gültiges Datum sein.' example: '2026-11-12T21:59:18' scheduled_end_at: type: string description: 'When it ends; after the start. value muss ein gültiges Datum sein. value muss ein Datum nach scheduled_start_at sein.' example: '2052-12-05' auto_start: type: boolean description: 'Start it by itself at `scheduled_start_at`.' example: true nullable: true auto_complete: type: boolean description: 'Complete it by itself at `scheduled_end_at`.' example: false nullable: true notify_subscribers: type: boolean description: 'Tell subscribers (default true). Chat integrations are told either way.' example: true nullable: true is_unlisted: type: boolean description: 'Not listed on the page; reachable by its link (`public_url`) only.' example: false nullable: true notify_at_scheduled: type: boolean description: 'Tell subscribers when it is scheduled.' example: true nullable: true send_reminder_1h: type: boolean description: 'Remind subscribers an hour before.' example: true nullable: true notify_at_start: type: boolean description: 'Tell subscribers when it starts.' example: true nullable: true notify_at_end: type: boolean description: 'Tell subscribers when it ends.' example: true nullable: true update_component_status: type: boolean description: 'Show the components as under maintenance while it runs.' example: true nullable: true status: type: string description: 'scheduled, in_progress or completed. Moving it on has the same consequences as start/complete.' example: scheduled enum: - scheduled - in_progress - completed actual_start_at: type: string description: 'When it really began, to correct the record. value muss ein gültiges Datum sein.' example: '2026-11-12T21:59:18' nullable: true actual_end_at: type: string description: 'When it really ended; not before `actual_start_at`. value muss ein gültiges Datum sein. value muss ein Datum nach oder gleich actual_start_at sein.' example: '2052-12-05' nullable: true component_ids: type: array description: 'value muss eine gültige UUID sein.' example: - a4855dc5-0acb-33c3-b921-f4291f719ca0 items: type: string delete: summary: 'Delete a maintenance window' operationId: deleteAMaintenanceWindow description: '' parameters: [] responses: { } tags: - Maintenance parameters: - in: path name: id description: 'The ID of the maintenance.' example: 01a1f3c2-8f40-7d51-a263-7d8e9f0a1b2c required: true schema: type: string '/api/v1/maintenances/{maintenance}/start': post: summary: 'Start maintenance now' operationId: startMaintenanceNow description: '`422` unless it is scheduled.' parameters: [] responses: { } tags: - Maintenance parameters: - in: path name: maintenance description: 'The maintenance.' example: 01a1f3c2-8f40-7d51-a263-7d8e9f0a1b2c required: true schema: type: string '/api/v1/maintenances/{maintenance}/complete': post: summary: 'Complete maintenance now' operationId: completeMaintenanceNow description: '`422` unless it is in progress.' parameters: [] responses: { } tags: - Maintenance parameters: - in: path name: maintenance description: 'The maintenance.' example: 01a1f3c2-8f40-7d51-a263-7d8e9f0a1b2c required: true schema: type: string /api/v1/metrics: get: summary: 'List metrics' operationId: listMetrics description: '' parameters: [] responses: { } tags: - Metrics post: summary: 'Create a metric' operationId: createAMetric description: "`403` when the plan's metric limit is reached or the plan has no metrics." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01a1544c-7cb2-72ab-8a4d-ad75c201d2c1 key: api.response_time name: 'API response time' source: push accepts_points: true suffix: ms decimals: 0 aggregation: avg description: null visible: true position: 0 y_axis_min: null y_axis_max: null last_point_at: null is_stale: true created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' properties: data: type: object properties: id: type: string example: 01a1544c-7cb2-72ab-8a4d-ad75c201d2c1 key: type: string example: api.response_time name: type: string example: 'API response time' source: type: string example: push accepts_points: type: boolean example: true suffix: type: string example: ms decimals: type: integer example: 0 aggregation: type: string example: avg description: type: string example: null nullable: true visible: type: boolean example: true position: type: integer example: 0 y_axis_min: type: string example: null nullable: true y_axis_max: type: string example: null nullable: true last_point_at: type: string example: null nullable: true is_stale: type: boolean example: true created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' tags: - Metrics requestBody: required: true content: application/json: schema: type: object properties: key: type: string description: 'Stable identifier used in URLs, e.g. response-time: lowercase letters, digits, dot, underscore and dash, up to 64. Must match the regex /^[a-z0-9][a-z0-9_.-]*$/. value darf nicht mehr als 64 Zeichen haben.' example: b name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: 'n' suffix: type: string description: 'Unit shown after values, e.g. ms or %. value darf nicht mehr als 16 Zeichen haben.' example: gzmiyvdljnikhway nullable: true decimals: type: integer description: 'Decimal places shown (0–6). value muss mindestens 0 sein. value darf nicht größer als 6 sein.' example: 1 nullable: true aggregation: type: string description: 'How points within an interval are combined: avg, min, max, sum or last.' example: last enum: - avg - sum - min - max - last nullable: true description: type: string description: 'Shown under the name on the page. value darf nicht mehr als 2000 Zeichen haben.' example: 'Omnis nostrum aut adipisci quidem nostrum qui commodi.' nullable: true visible: type: boolean description: 'false hides it from the page.' example: false nullable: true position: type: integer description: 'Order on the page; lower comes first. value muss mindestens 0 sein.' example: 3 nullable: true y_axis_min: type: number description: "Lower end of the chart's axis." example: 4326.41688 nullable: true y_axis_max: type: number description: 'Upper end; above `y_axis_min`.' example: 4326.41688 nullable: true required: - key - name '/api/v1/metrics/{metricKey}': get: summary: 'Get a metric' operationId: getAMetric description: '' parameters: [] responses: { } tags: - Metrics put: summary: 'Update a metric' operationId: updateAMetric description: '' parameters: [] responses: { } tags: - Metrics requestBody: required: false content: application/json: schema: type: object properties: key: type: string description: 'Stable identifier used in URLs, e.g. response-time: lowercase letters, digits, dot, underscore and dash, up to 64. Must match the regex /^[a-z0-9][a-z0-9_.-]*$/. value darf nicht mehr als 64 Zeichen haben.' example: b name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: 'n' suffix: type: string description: 'Unit shown after values, e.g. ms or %. value darf nicht mehr als 16 Zeichen haben.' example: gzmiyvdljnikhway nullable: true decimals: type: integer description: 'Decimal places shown (0–6). value muss mindestens 0 sein. value darf nicht größer als 6 sein.' example: 1 nullable: true aggregation: type: string description: 'How points within an interval are combined: avg, min, max, sum or last.' example: max enum: - avg - sum - min - max - last nullable: true description: type: string description: 'Shown under the name on the page. value darf nicht mehr als 2000 Zeichen haben.' example: 'Omnis nostrum aut adipisci quidem nostrum qui commodi.' nullable: true visible: type: boolean description: 'false hides it from the page.' example: true nullable: true position: type: integer description: 'Order on the page; lower comes first. value muss mindestens 0 sein.' example: 3 nullable: true y_axis_min: type: number description: "Lower end of the chart's axis." example: 4326.41688 nullable: true y_axis_max: type: number description: 'Upper end; above `y_axis_min`.' example: 4326.41688 nullable: true delete: summary: 'Delete a metric' operationId: deleteAMetric description: 'Removes its points too.' parameters: [] responses: { } tags: - Metrics parameters: - in: path name: metricKey description: "The metric's key." example: api.response_time required: true schema: type: string '/api/v1/metrics/{metricKey}/points': post: summary: 'Push points' operationId: pushPoints description: "One point or a batch; accepted with `202`. `409` for a metric fed by another source. `403` on a plan without metrics (after a downgrade the metrics stay, but take no new points — as the dashboard hides them).\n\nIdempotent: points are bucketed on write, so a client retrying a failed request\noverwrites rather than duplicates." parameters: [] responses: 202: description: '' content: application/json: schema: type: object example: accepted: 2 bucket_seconds: 60 metric: id: 01a1544c-7cb2-72ab-8a4d-ad75c201d2c1 key: api.response_time name: 'API response time' source: push accepts_points: true suffix: ms decimals: 0 aggregation: avg description: null visible: true position: 0 y_axis_min: null y_axis_max: null last_point_at: '2026-10-19T09:05:00+00:00' is_stale: false created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' properties: accepted: type: integer example: 2 bucket_seconds: type: integer example: 60 metric: type: object properties: id: type: string example: 01a1544c-7cb2-72ab-8a4d-ad75c201d2c1 key: type: string example: api.response_time name: type: string example: 'API response time' source: type: string example: push accepts_points: type: boolean example: true suffix: type: string example: ms decimals: type: integer example: 0 aggregation: type: string example: avg description: type: string example: null nullable: true visible: type: boolean example: true position: type: integer example: 0 y_axis_min: type: string example: null nullable: true y_axis_max: type: string example: null nullable: true last_point_at: type: string example: '2026-10-19T09:05:00+00:00' is_stale: type: boolean example: false created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' tags: - Metrics requestBody: required: true content: application/json: schema: type: object properties: points: type: array description: 'One or more points. value muss mindestens 1 Elemente haben. value darf nicht mehr als 5000 Elemente haben.' example: - [] items: type: object properties: value: type: number description: 'The measured value.' example: 4326.41688 timestamp: type: string description: 'When it was measured (ISO 8601); default now. value muss ein gültiges Datum sein.' example: '2026-11-12T21:59:18' nullable: true required: - value required: - points get: summary: 'Read points' operationId: readPoints description: 'Without `from` and `to`, the last 24 hours.' parameters: - in: query name: from description: 'Start (ISO 8601).' example: '2026-10-18T09:00:00Z' required: false schema: type: string description: 'Start (ISO 8601).' example: '2026-10-18T09:00:00Z' nullable: true - in: query name: to description: 'End (ISO 8601), default now.' example: '2026-10-19T09:00:00Z' required: false schema: type: string description: 'End (ISO 8601), default now.' example: '2026-10-19T09:00:00Z' nullable: true - in: query name: resolution description: 'Bucket size in seconds, one of the stored resolutions.' example: 60 required: false schema: type: integer description: 'Bucket size in seconds, one of the stored resolutions.' example: 60 nullable: true responses: { } tags: - Metrics parameters: - in: path name: metricKey description: "The metric's key." example: api.response_time required: true schema: type: string /api/v1/monitors: get: summary: 'List monitors' operationId: listMonitors description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01a1bb34-522b-7341-9533-fe0f0f1b9d46 name: 'Checkout API' url: 'https://api.example.com/health' method: GET interval_seconds: 300 timeout_seconds: 10 expected_status_from: 200 expected_status_to: 399 keyword: null regions: - fsn - nbg - hel - es-mad1 - pl-waw1 - nl-ams1 all_regions: true auth: type: basic username: monitor component_id: 01a1bb34-5188-7276-954d-338721448041 on_down: switch_component down_component_status: major_outage is_public: true is_paused: false paused_by_plan: false state: up in_maintenance: false state_changed_at: '2026-10-19T08:20:00+00:00' last_checked_at: '2026-10-19T08:29:41+00:00' last_region: nbg last_status_code: 200 last_response_ms: 184 last_error: null certificate_expires_at: '2027-01-12T23:59:59+00:00' metric_key: null recipients: members: [] emails: - oncall@example.com phones: [] integrations: [] created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' properties: data: type: array example: - id: 01a1bb34-522b-7341-9533-fe0f0f1b9d46 name: 'Checkout API' url: 'https://api.example.com/health' method: GET interval_seconds: 300 timeout_seconds: 10 expected_status_from: 200 expected_status_to: 399 keyword: null regions: - fsn - nbg - hel - es-mad1 - pl-waw1 - nl-ams1 all_regions: true auth: type: basic username: monitor component_id: 01a1bb34-5188-7276-954d-338721448041 on_down: switch_component down_component_status: major_outage is_public: true is_paused: false paused_by_plan: false state: up in_maintenance: false state_changed_at: '2026-10-19T08:20:00+00:00' last_checked_at: '2026-10-19T08:29:41+00:00' last_region: nbg last_status_code: 200 last_response_ms: 184 last_error: null certificate_expires_at: '2027-01-12T23:59:59+00:00' metric_key: null recipients: members: [] emails: - oncall@example.com phones: [] integrations: [] created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' items: type: object properties: id: type: string example: 01a1bb34-522b-7341-9533-fe0f0f1b9d46 name: type: string example: 'Checkout API' url: type: string example: 'https://api.example.com/health' method: type: string example: GET interval_seconds: type: integer example: 300 timeout_seconds: type: integer example: 10 expected_status_from: type: integer example: 200 expected_status_to: type: integer example: 399 keyword: type: string example: null nullable: true regions: type: array example: - fsn - nbg - hel - es-mad1 - pl-waw1 - nl-ams1 items: type: string all_regions: type: boolean example: true auth: type: object properties: type: type: string example: basic username: type: string example: monitor component_id: type: string example: 01a1bb34-5188-7276-954d-338721448041 on_down: type: string example: switch_component down_component_status: type: string example: major_outage is_public: type: boolean example: true is_paused: type: boolean example: false paused_by_plan: type: boolean example: false state: type: string example: up in_maintenance: type: boolean example: false state_changed_at: type: string example: '2026-10-19T08:20:00+00:00' last_checked_at: type: string example: '2026-10-19T08:29:41+00:00' last_region: type: string example: nbg last_status_code: type: integer example: 200 last_response_ms: type: integer example: 184 last_error: type: string example: null nullable: true certificate_expires_at: type: string example: '2027-01-12T23:59:59+00:00' metric_key: type: string example: null nullable: true recipients: type: object properties: members: type: array example: [] emails: type: array example: - oncall@example.com items: type: string phones: type: array example: [] integrations: type: array example: [] created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' tags: - Monitors post: summary: 'Create a monitor' operationId: createAMonitor description: "Runs for the first time within seconds. `403` when the plan has no monitors left or\nSMS recipients are given on a plan without SMS." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01a1bb34-522b-7341-9533-fe0f0f1b9d46 name: 'Checkout API' url: 'https://api.example.com/health' method: GET interval_seconds: 300 timeout_seconds: 10 expected_status_from: 200 expected_status_to: 399 keyword: null regions: - fsn - nbg - hel - es-mad1 - pl-waw1 - nl-ams1 all_regions: true auth: type: basic username: monitor component_id: 01a1bb34-5188-7276-954d-338721448041 on_down: switch_component down_component_status: major_outage is_public: true is_paused: false paused_by_plan: false state: pending in_maintenance: false state_changed_at: null last_checked_at: null last_region: null last_status_code: null last_response_ms: null last_error: null certificate_expires_at: null metric_key: null recipients: members: [] emails: - oncall@example.com phones: [] integrations: [] created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' properties: data: type: object properties: id: type: string example: 01a1bb34-522b-7341-9533-fe0f0f1b9d46 name: type: string example: 'Checkout API' url: type: string example: 'https://api.example.com/health' method: type: string example: GET interval_seconds: type: integer example: 300 timeout_seconds: type: integer example: 10 expected_status_from: type: integer example: 200 expected_status_to: type: integer example: 399 keyword: type: string example: null nullable: true regions: type: array example: - fsn - nbg - hel - es-mad1 - pl-waw1 - nl-ams1 items: type: string all_regions: type: boolean example: true auth: type: object properties: type: type: string example: basic username: type: string example: monitor component_id: type: string example: 01a1bb34-5188-7276-954d-338721448041 on_down: type: string example: switch_component down_component_status: type: string example: major_outage is_public: type: boolean example: true is_paused: type: boolean example: false paused_by_plan: type: boolean example: false state: type: string example: pending in_maintenance: type: boolean example: false state_changed_at: type: string example: null nullable: true last_checked_at: type: string example: null nullable: true last_region: type: string example: null nullable: true last_status_code: type: string example: null nullable: true last_response_ms: type: string example: null nullable: true last_error: type: string example: null nullable: true certificate_expires_at: type: string example: null nullable: true metric_key: type: string example: null nullable: true recipients: type: object properties: members: type: array example: [] emails: type: array example: - oncall@example.com items: type: string phones: type: array example: [] integrations: type: array example: [] created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' tags: - Monitors requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Shown in alerts and, if public, on the status page. value darf nicht mehr als 255 Zeichen haben.' example: Website url: type: string description: 'Public http(s) URL on port 80, 443, 8080 or 8443. Internal and reserved addresses are refused. value darf nicht mehr als 2048 Zeichen haben.' example: 'https://example.com/health' method: type: string description: 'GET (default) or HEAD.' example: GET enum: - GET - HEAD interval_seconds: type: integer description: "How often to check: 30, 60, 120, 180, 300, 600, 900, 1800 or 3600, at least the plan's minimum (30 s on Business). Default 300. value muss mindestens 300 sein. value darf nicht größer als 3600 sein." example: 60 enum: - 30 - 60 - 120 - 180 - 300 - 600 - 900 - 1800 - 3600 timeout_seconds: type: integer description: '1–30, default 10. value muss mindestens 1 sein. value darf nicht größer als 30 sein.' example: 10 expected_status_from: type: integer description: 'Lowest status code that counts as up. Default 200. value muss mindestens 100 sein. value darf nicht größer als 599 sein.' example: 200 expected_status_to: type: integer description: 'Highest status code that counts as up. Default 399. value muss mindestens 100 sein. value darf nicht größer als 599 sein.' example: 399 keyword: type: string description: 'Optional text that must appear in the first 1 MB of the body. GET only: with HEAD it is refused. value darf nicht mehr als 255 Zeichen haben.' example: null nullable: true regions: type: array description: '' example: - architecto items: type: string auth_type: type: string description: 'Credentials sent with every check: none (default), basic (HTTP Basic auth, e.g. .htaccess) or bearer. Needs an https:// URL.' example: basic enum: - none - basic - bearer nullable: true auth_username: type: string description: 'Basic auth username. Must not contain a colon. value darf nicht mehr als 255 Zeichen haben.' example: monitor nullable: true auth_password: type: string description: 'Basic auth password. Write-only: never returned. Omitted on update: unchanged. value darf nicht mehr als 255 Zeichen haben.' example: correct-horse-battery nullable: true auth_token: type: string description: 'Bearer token, sent as "Authorization: Bearer ". Write-only: never returned. Omitted on update: unchanged. Must match the regex /^[\x21-\x7E]+$/. value darf nicht mehr als 4096 Zeichen haben.' example: null nullable: true component_id: type: string description: 'Optional component of this status page the check belongs to. value muss eine gültige UUID sein. Must match an existing stored value.' example: null nullable: true on_down: type: string description: 'notify (default) or switch_component — also set the component to down_component_status while down.' example: notify enum: - notify - switch_component down_component_status: type: string description: 'degraded_performance, partial_outage or major_outage (default).' example: major_outage enum: - degraded_performance - partial_outage - major_outage is_public: type: boolean description: 'Show uptime and response time on the status page. Default false.' example: false is_paused: type: boolean description: 'Keep the check but stop running it.' example: false recipients: type: object description: 'Who is alerted. Omitted on create: every workspace member. Omitted on update: unchanged.' example: null properties: members: type: array description: '' example: - 16 items: type: integer emails: type: array description: 'value muss eine gültige E-Mail-Adresse sein. value darf nicht mehr als 255 Zeichen haben.' example: - 'n' items: type: string phones: type: array description: 'Must match the regex /^\+[1-9]\d{6,14}$/.' example: - '+3642559314' items: type: string integrations: type: array description: '' example: - 16 items: type: integer required: - name - url '/api/v1/monitors/{id}': get: summary: 'Get a monitor' operationId: getAMonitor description: '' parameters: [] responses: { } tags: - Monitors put: summary: 'Update a monitor' operationId: updateAMonitor description: "Changing the URL, method, expected status or keyword starts the check afresh: an\nopen outage is closed and a component the check switched goes back to operational.\nPausing does the same. If the check was down, its recipients are told the outage\nended (mail and integrations with the event `monitor.closed`, no SMS). Resuming\nbeyond the plan's limit: `403`." parameters: [] responses: { } tags: - Monitors requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Shown in alerts and, if public, on the status page. value darf nicht mehr als 255 Zeichen haben.' example: Website url: type: string description: 'Public http(s) URL on port 80, 443, 8080 or 8443. Internal and reserved addresses are refused. value darf nicht mehr als 2048 Zeichen haben.' example: 'https://example.com/health' method: type: string description: 'GET (default) or HEAD.' example: GET enum: - GET - HEAD interval_seconds: type: integer description: "How often to check: 30, 60, 120, 180, 300, 600, 900, 1800 or 3600, at least the plan's minimum (30 s on Business). Default 300. value muss mindestens 300 sein. value darf nicht größer als 3600 sein." example: 60 enum: - 30 - 60 - 120 - 180 - 300 - 600 - 900 - 1800 - 3600 timeout_seconds: type: integer description: '1–30, default 10. value muss mindestens 1 sein. value darf nicht größer als 30 sein.' example: 10 expected_status_from: type: integer description: 'Lowest status code that counts as up. Default 200. value muss mindestens 100 sein. value darf nicht größer als 599 sein.' example: 200 expected_status_to: type: integer description: 'Highest status code that counts as up. Default 399. value muss mindestens 100 sein. value darf nicht größer als 599 sein.' example: 399 keyword: type: string description: 'Optional text that must appear in the first 1 MB of the body. GET only: with HEAD it is refused. value darf nicht mehr als 255 Zeichen haben.' example: null nullable: true regions: type: array description: '' example: - architecto items: type: string auth_type: type: string description: 'Credentials sent with every check: none (default), basic (HTTP Basic auth, e.g. .htaccess) or bearer. Needs an https:// URL.' example: basic enum: - none - basic - bearer nullable: true auth_username: type: string description: 'Basic auth username. Must not contain a colon. value darf nicht mehr als 255 Zeichen haben.' example: monitor nullable: true auth_password: type: string description: 'Basic auth password. Write-only: never returned. Omitted on update: unchanged. value darf nicht mehr als 255 Zeichen haben.' example: correct-horse-battery nullable: true auth_token: type: string description: 'Bearer token, sent as "Authorization: Bearer ". Write-only: never returned. Omitted on update: unchanged. Must match the regex /^[\x21-\x7E]+$/. value darf nicht mehr als 4096 Zeichen haben.' example: null nullable: true component_id: type: string description: 'Optional component of this status page the check belongs to. value muss eine gültige UUID sein. Must match an existing stored value.' example: null nullable: true on_down: type: string description: 'notify (default) or switch_component — also set the component to down_component_status while down.' example: notify enum: - notify - switch_component down_component_status: type: string description: 'degraded_performance, partial_outage or major_outage (default).' example: major_outage enum: - degraded_performance - partial_outage - major_outage is_public: type: boolean description: 'Show uptime and response time on the status page. Default false.' example: false is_paused: type: boolean description: 'Keep the check but stop running it.' example: false recipients: type: object description: 'Who is alerted. Omitted on create: every workspace member. Omitted on update: unchanged.' example: null properties: members: type: array description: '' example: - 16 items: type: integer emails: type: array description: 'value muss eine gültige E-Mail-Adresse sein. value darf nicht mehr als 255 Zeichen haben.' example: - 'n' items: type: string phones: type: array description: 'Must match the regex /^\+[1-9]\d{6,14}$/.' example: - '+3642559314' items: type: string integrations: type: array description: '' example: - 16 items: type: integer delete: summary: 'Delete a monitor' operationId: deleteAMonitor description: "Removes its outages and response times. A component the check had switched to an\noutage goes back to operational. If the check was down, its recipients are told the\noutage ended (mail and integrations with the event `monitor.closed`, no SMS)." parameters: [] responses: { } tags: - Monitors parameters: - in: path name: id description: 'The ID of the monitor.' example: architecto required: true schema: type: string '/api/v1/monitors/{monitor}/outages': get: summary: 'List outages' operationId: listOutages description: "Confirmed outages of one monitor, newest first. A single failed run that a second\nregion did not confirm is not an outage and does not appear here." parameters: - in: query name: per_page description: 'Up to 100.' example: 25 required: false schema: type: integer description: 'Up to 100.' example: 25 responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 1 started_at: '2026-10-19T08:02:10+00:00' ended_at: '2026-10-19T08:20:00+00:00' duration_seconds: 1070 regions: - fsn - hel status_code: 503 error: 'HTTP 503' links: first: 'https://statuswerk.eu/api/v1/monitors/01a1a79f-8af8-70ee-9168-1ab293fc293d/outages?page=1' last: 'https://statuswerk.eu/api/v1/monitors/01a1a79f-8af8-70ee-9168-1ab293fc293d/outages?page=1' prev: null next: null meta: current_page: 1 from: 1 last_page: 1 links: - url: null label: '« Previous' page: null active: false - url: 'https://statuswerk.eu/api/v1/monitors/01a1a79f-8af8-70ee-9168-1ab293fc293d/outages?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false path: 'https://statuswerk.eu/api/v1/monitors/01a1a79f-8af8-70ee-9168-1ab293fc293d/outages' per_page: 25 to: 1 total: 1 properties: data: type: array example: - id: 1 started_at: '2026-10-19T08:02:10+00:00' ended_at: '2026-10-19T08:20:00+00:00' duration_seconds: 1070 regions: - fsn - hel status_code: 503 error: 'HTTP 503' items: type: object properties: id: type: integer example: 1 started_at: type: string example: '2026-10-19T08:02:10+00:00' ended_at: type: string example: '2026-10-19T08:20:00+00:00' duration_seconds: type: integer example: 1070 regions: type: array example: - fsn - hel items: type: string status_code: type: integer example: 503 error: type: string example: 'HTTP 503' links: type: object properties: first: type: string example: 'https://statuswerk.eu/api/v1/monitors/01a1a79f-8af8-70ee-9168-1ab293fc293d/outages?page=1' last: type: string example: 'https://statuswerk.eu/api/v1/monitors/01a1a79f-8af8-70ee-9168-1ab293fc293d/outages?page=1' prev: type: string example: null nullable: true next: type: string example: null nullable: true meta: type: object properties: current_page: type: integer example: 1 from: type: integer example: 1 last_page: type: integer example: 1 links: type: array example: - url: null label: '« Previous' page: null active: false - url: 'https://statuswerk.eu/api/v1/monitors/01a1a79f-8af8-70ee-9168-1ab293fc293d/outages?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false items: type: object properties: url: type: string example: null nullable: true label: type: string example: '« Previous' page: type: string example: null nullable: true active: type: boolean example: false path: type: string example: 'https://statuswerk.eu/api/v1/monitors/01a1a79f-8af8-70ee-9168-1ab293fc293d/outages' per_page: type: integer example: 25 to: type: integer example: 1 total: type: integer example: 1 tags: - Monitors parameters: - in: path name: monitor description: 'The monitor.' example: BcECdBDA-CdED-bFEA-CbCE-BcCdeBfbbebc required: true schema: type: string /api/v1/sms-usage: get: summary: 'Get SMS usage' operationId: getSMSUsage description: '`allowance` is `null` on plans without a monthly number. `paused` is true while the allowance and every pack are used up: SMS are not sent until the next month or a new pack; email, webhooks and chat carry on.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: period: 2026-11 allowance: 250 used: 212 from_packs: 0 pack_remaining: 250 paused: false properties: data: type: object properties: period: type: string example: 2026-11 allowance: type: integer example: 250 used: type: integer example: 212 from_packs: type: integer example: 0 pack_remaining: type: integer example: 250 paused: type: boolean example: false tags: - SMS /api/v1/statuspage: get: summary: 'Get the status page' operationId: getTheStatusPage description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01a1cca7-529c-73dc-99c0-06ad67b5f04c name: Acme slug: acme subdomain: acme custom_domain: null public_url: 'https://acme.statuswerk.eu' timezone: UTC language: en is_public: true is_password_protected: false access_ip_allowlist: [] overall_status: major_outage settings: allow_subscriptions: true show_uptime: true uptime_days_to_show: 90 allow_email_subscribers: true allow_sms_subscribers: false allow_webhook_subscribers: true allow_rss_subscribers: true allow_public_api: true show_overall_uptime: true uptime_threshold_degraded: 99.5 approval_required_for_incidents: false approval_required_for_maintenances: false reply_to_email: null mail_from_address: null branding: primary_color: '#3B82F6' operational_color: null section_titles: [] theme: light logo_path: null logo_dark_path: null favicon_path: null logo_url: null logo_dark_url: null favicon_url: null header_html: null footer_html: null custom_css: null analytics_provider: null analytics_site: null analytics_host: null seo: meta_title: null meta_description: null is_noindex: false component_groups: - id: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 name: Payments description: null position: 1 collapsed_by_default: false visible: true overall_status: major_outage components: - id: 01a1cca7-52c1-7051-9d9d-9e3639607967 name: 'Checkout API' description: 'Payments and orders' status: major_outage status_label: 'Major Outage' group_id: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 position: 1 show_uptime: true uptime_start_date: null uptime_90d: 100 visible: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' components: - id: 01a1cca7-52c1-7051-9d9d-9e3639607967 name: 'Checkout API' description: 'Payments and orders' status: major_outage status_label: 'Major Outage' group_id: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 position: 1 show_uptime: true uptime_start_date: null uptime_90d: 100 visible: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' active_incidents_count: 1 created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' properties: data: type: object properties: id: type: string example: 01a1cca7-529c-73dc-99c0-06ad67b5f04c name: type: string example: Acme slug: type: string example: acme subdomain: type: string example: acme custom_domain: type: string example: null nullable: true public_url: type: string example: 'https://acme.statuswerk.eu' timezone: type: string example: UTC language: type: string example: en is_public: type: boolean example: true is_password_protected: type: boolean example: false access_ip_allowlist: type: array example: [] overall_status: type: string example: major_outage settings: type: object properties: allow_subscriptions: type: boolean example: true show_uptime: type: boolean example: true uptime_days_to_show: type: integer example: 90 allow_email_subscribers: type: boolean example: true allow_sms_subscribers: type: boolean example: false allow_webhook_subscribers: type: boolean example: true allow_rss_subscribers: type: boolean example: true allow_public_api: type: boolean example: true show_overall_uptime: type: boolean example: true uptime_threshold_degraded: type: number example: 99.5 approval_required_for_incidents: type: boolean example: false approval_required_for_maintenances: type: boolean example: false reply_to_email: type: string example: null nullable: true mail_from_address: type: string example: null nullable: true branding: type: object properties: primary_color: type: string example: '#3B82F6' operational_color: type: string example: null nullable: true section_titles: type: array example: [] theme: type: string example: light logo_path: type: string example: null nullable: true logo_dark_path: type: string example: null nullable: true favicon_path: type: string example: null nullable: true logo_url: type: string example: null nullable: true logo_dark_url: type: string example: null nullable: true favicon_url: type: string example: null nullable: true header_html: type: string example: null nullable: true footer_html: type: string example: null nullable: true custom_css: type: string example: null nullable: true analytics_provider: type: string example: null nullable: true analytics_site: type: string example: null nullable: true analytics_host: type: string example: null nullable: true seo: type: object properties: meta_title: type: string example: null nullable: true meta_description: type: string example: null nullable: true is_noindex: type: boolean example: false component_groups: type: array example: - id: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 name: Payments description: null position: 1 collapsed_by_default: false visible: true overall_status: major_outage components: - id: 01a1cca7-52c1-7051-9d9d-9e3639607967 name: 'Checkout API' description: 'Payments and orders' status: major_outage status_label: 'Major Outage' group_id: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 position: 1 show_uptime: true uptime_start_date: null uptime_90d: 100 visible: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' items: type: object properties: id: type: string example: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 name: type: string example: Payments description: type: string example: null nullable: true position: type: integer example: 1 collapsed_by_default: type: boolean example: false visible: type: boolean example: true overall_status: type: string example: major_outage components: type: array example: - id: 01a1cca7-52c1-7051-9d9d-9e3639607967 name: 'Checkout API' description: 'Payments and orders' status: major_outage status_label: 'Major Outage' group_id: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 position: 1 show_uptime: true uptime_start_date: null uptime_90d: 100 visible: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' items: type: object properties: id: type: string example: 01a1cca7-52c1-7051-9d9d-9e3639607967 name: type: string example: 'Checkout API' description: type: string example: 'Payments and orders' status: type: string example: major_outage status_label: type: string example: 'Major Outage' group_id: type: string example: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 position: type: integer example: 1 show_uptime: type: boolean example: true uptime_start_date: type: string example: null nullable: true uptime_90d: type: integer example: 100 visible: type: boolean example: true created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' components: type: array example: - id: 01a1cca7-52c1-7051-9d9d-9e3639607967 name: 'Checkout API' description: 'Payments and orders' status: major_outage status_label: 'Major Outage' group_id: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 position: 1 show_uptime: true uptime_start_date: null uptime_90d: 100 visible: true created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' items: type: object properties: id: type: string example: 01a1cca7-52c1-7051-9d9d-9e3639607967 name: type: string example: 'Checkout API' description: type: string example: 'Payments and orders' status: type: string example: major_outage status_label: type: string example: 'Major Outage' group_id: type: string example: 01a1cca7-52be-71d3-90fc-fdaee25a62c1 position: type: integer example: 1 show_uptime: type: boolean example: true uptime_start_date: type: string example: null nullable: true uptime_90d: type: integer example: 100 visible: type: boolean example: true created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' active_incidents_count: type: integer example: 1 created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' tags: - 'Status page' patch: summary: 'Update the status page' operationId: updateTheStatusPage description: "`language` (`de` or `en`) switches the public page, its feeds and badge, and every notification its subscribers receive. Switching on SMS or webhook subscribers needs the plan (`403`), as do a password, an IP allowlist, hiding from search engines (`is_noindex`), and custom HTML/CSS (cleaned of scripts on save); switching any of them off works on every plan. The four-eyes switches are read-only here (`403`): a token bound by the rule must not be able to lift it. Logo and favicon have their own endpoints.\n\nEvery field is optional; only those you send change." parameters: [] responses: { } tags: - 'Status page' requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Shown at the top of the page.' example: Acme timezone: type: string description: 'Times on the page are shown in it.' example: Europe/Berlin language: type: string description: '`de` or `en`.' example: de is_public: type: boolean description: '`false` takes the page offline: its address shows "not available", and only members of the workspace see it, in the dashboard''s preview.' example: true access_password: type: string description: 'Protects the page with a password (min. 8 characters); `null` removes it.' example: null nullable: true access_ip_allowlist: type: array description: 'Only these addresses or CIDR ranges may open the page; `[]` lifts the restriction.' example: - 203.0.113.0/24 items: type: string allow_subscriptions: type: boolean description: 'Visitors may subscribe at all.' example: true show_uptime: type: boolean description: 'Show the uptime bars.' example: true uptime_days_to_show: type: integer description: 'Days in the uptime bars, 7 to 365.' example: 90 allow_email_subscribers: type: boolean description: '' example: true allow_sms_subscribers: type: boolean description: 'Needs a plan with SMS. Stored also while the platform has SMS switched off, but inert until it is on again.' example: false allow_webhook_subscribers: type: boolean description: 'Needs a plan with webhooks.' example: false allow_rss_subscribers: type: boolean description: 'Offer the RSS and Atom feeds.' example: true allow_public_api: type: boolean description: "Offer the tokenless status at `/summary.json` on the page's address." example: true reply_to_email: type: string description: "Where subscribers' replies go; `null` clears it." example: support@acme.example nullable: true mail_from_address: type: string description: 'Sender address; only used with your own mail server.' example: status@acme.example nullable: true meta_title: type: string description: 'Title for search engines, at most 70 characters.' example: 'Acme status' nullable: true meta_description: type: string description: 'Description for search engines, at most 160 characters.' example: "Current availability of Acme's services." nullable: true primary_color: type: string description: 'Hex colour.' example: '#16A34A' operational_color: type: string description: 'Hex colour for "operational": uptime bars, badges and the status banner; `null` returns to the default green.' example: '#16A34A' nullable: true section_titles: type: object description: 'Your own wording for the page''s headings, at most 80 characters each. Keys: `active_incidents`, `scheduled_maintenance`, `component_uptime`, `timeline`, `metrics`, `incident_history`, `past_maintenance`. Only the keys you send change; `null` or `""` for a key returns it to the default in the page''s language, `null` for the whole object resets all.' example: component_uptime: 'Our services' properties: { } nullable: true theme: type: string description: '`light`, `dark` or `system`.' example: system show_overall_uptime: type: boolean description: 'Show the overall uptime chart.' example: true uptime_threshold_degraded: type: number description: 'Below this uptime percentage a day counts as degraded.' example: 99.5 is_noindex: type: boolean description: 'Hide the page from search engines (plan feature).' example: false header_html: type: string description: "HTML added to the page's `` (plan feature): only `` and `` are kept, everything else is removed on save." example: null nullable: true footer_html: type: string description: 'Custom HTML below the page (plan feature, scripts removed).' example: null nullable: true custom_css: type: string description: 'Custom CSS (plan feature).' example: null nullable: true analytics_provider: type: string description: '`plausible`, `umami`, `matomo` or null to switch off (plan feature, Pro and up).' example: null analytics_site: type: string description: 'Plausible: the site domain; Umami: the website ID; Matomo: the site ID.' example: null analytics_host: type: string description: 'Matomo only: your Matomo Cloud address (https://name.matomo.cloud). Plausible and Umami use their cloud services; self-hosted servers are not accepted.' example: null /api/v1/statuspage/status: get: summary: 'Get the overall status' operationId: getTheOverallStatus description: "The one call a pipeline or health check needs: the page's worst current status and how many incidents are open. `uptime` is the page's uptime in percent over `uptime_days` — the number the page shows (average of its visible components with uptime shown), by default over the page's own period." parameters: - in: query name: days description: 'Period for `uptime`, 1 to 365 days. Defaults to the period the page shows.' example: 30 required: false schema: type: integer description: 'Period for `uptime`, 1 to 365 days. Defaults to the period the page shows.' example: 30 responses: 200: description: '' content: application/json: schema: type: object example: status: major_outage active_incidents: 1 url: 'https://acme.statuswerk.eu' uptime: 100 uptime_days: 90 properties: status: type: string example: major_outage active_incidents: type: integer example: 1 url: type: string example: 'https://acme.statuswerk.eu' uptime: type: integer example: 100 uptime_days: type: integer example: 90 tags: - 'Status page' '/api/v1/statuspage/{asset}': post: summary: 'Upload the logo, dark-theme logo or favicon' operationId: uploadTheLogoDarkThemeLogoOrFavicon description: 'Send the image as multipart form data in `file`. Logo and dark-theme logo: SVG, PNG, JPEG, WebP or GIF up to 2 MB; favicon: SVG, PNG, ICO, WebP or GIF up to 512 KB. An SVG is stored sanitized (scripts, event handlers and external references removed); one that is no usable SVG afterwards is refused. Replaces the previous one.' parameters: [] responses: { } tags: - 'Status page' requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary description: 'The image.' required: - file delete: summary: 'Remove the logo, dark-theme logo or favicon' operationId: removeTheLogoDarkThemeLogoOrFavicon description: '' parameters: [] responses: { } tags: - 'Status page' parameters: - in: path name: asset description: '`logo`, `logo-dark` or `favicon`.' example: logo required: true schema: type: string /api/v1/statuspages: get: summary: 'List status pages' operationId: listStatusPages description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01a1cca7-529c-73dc-99c0-06ad67b5f04c name: Acme slug: acme subdomain: acme custom_domain: null public_url: 'https://acme.statuswerk.eu' timezone: UTC language: en is_public: true is_password_protected: false access_ip_allowlist: [] overall_status: operational settings: allow_subscriptions: true show_uptime: true uptime_days_to_show: 90 allow_email_subscribers: true allow_sms_subscribers: false allow_webhook_subscribers: true allow_rss_subscribers: true allow_public_api: true show_overall_uptime: true uptime_threshold_degraded: 99.5 approval_required_for_incidents: false approval_required_for_maintenances: false reply_to_email: null mail_from_address: null branding: primary_color: '#3B82F6' operational_color: null section_titles: [] theme: light logo_path: null logo_dark_path: null favicon_path: null logo_url: null logo_dark_url: null favicon_url: null header_html: null footer_html: null custom_css: null analytics_provider: null analytics_site: null analytics_host: null seo: meta_title: null meta_description: null is_noindex: false created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' properties: data: type: array example: - id: 01a1cca7-529c-73dc-99c0-06ad67b5f04c name: Acme slug: acme subdomain: acme custom_domain: null public_url: 'https://acme.statuswerk.eu' timezone: UTC language: en is_public: true is_password_protected: false access_ip_allowlist: [] overall_status: operational settings: allow_subscriptions: true show_uptime: true uptime_days_to_show: 90 allow_email_subscribers: true allow_sms_subscribers: false allow_webhook_subscribers: true allow_rss_subscribers: true allow_public_api: true show_overall_uptime: true uptime_threshold_degraded: 99.5 approval_required_for_incidents: false approval_required_for_maintenances: false reply_to_email: null mail_from_address: null branding: primary_color: '#3B82F6' operational_color: null section_titles: [] theme: light logo_path: null logo_dark_path: null favicon_path: null logo_url: null logo_dark_url: null favicon_url: null header_html: null footer_html: null custom_css: null analytics_provider: null analytics_site: null analytics_host: null seo: meta_title: null meta_description: null is_noindex: false created_at: '2026-10-19T08:30:00+00:00' updated_at: '2026-10-19T08:30:00+00:00' items: type: object properties: id: type: string example: 01a1cca7-529c-73dc-99c0-06ad67b5f04c name: type: string example: Acme slug: type: string example: acme subdomain: type: string example: acme custom_domain: type: string example: null nullable: true public_url: type: string example: 'https://acme.statuswerk.eu' timezone: type: string example: UTC language: type: string example: en is_public: type: boolean example: true is_password_protected: type: boolean example: false access_ip_allowlist: type: array example: [] overall_status: type: string example: operational settings: type: object properties: allow_subscriptions: type: boolean example: true show_uptime: type: boolean example: true uptime_days_to_show: type: integer example: 90 allow_email_subscribers: type: boolean example: true allow_sms_subscribers: type: boolean example: false allow_webhook_subscribers: type: boolean example: true allow_rss_subscribers: type: boolean example: true allow_public_api: type: boolean example: true show_overall_uptime: type: boolean example: true uptime_threshold_degraded: type: number example: 99.5 approval_required_for_incidents: type: boolean example: false approval_required_for_maintenances: type: boolean example: false reply_to_email: type: string example: null nullable: true mail_from_address: type: string example: null nullable: true branding: type: object properties: primary_color: type: string example: '#3B82F6' operational_color: type: string example: null nullable: true section_titles: type: array example: [] theme: type: string example: light logo_path: type: string example: null nullable: true logo_dark_path: type: string example: null nullable: true favicon_path: type: string example: null nullable: true logo_url: type: string example: null nullable: true logo_dark_url: type: string example: null nullable: true favicon_url: type: string example: null nullable: true header_html: type: string example: null nullable: true footer_html: type: string example: null nullable: true custom_css: type: string example: null nullable: true analytics_provider: type: string example: null nullable: true analytics_site: type: string example: null nullable: true analytics_host: type: string example: null nullable: true seo: type: object properties: meta_title: type: string example: null nullable: true meta_description: type: string example: null nullable: true is_noindex: type: boolean example: false created_at: type: string example: '2026-10-19T08:30:00+00:00' updated_at: type: string example: '2026-10-19T08:30:00+00:00' tags: - 'Status pages' post: summary: 'Create a status page' operationId: createAStatusPage description: "`language` (`de` or `en`, default `en`) is the language of the public page, its feeds and badge, and of every notification its subscribers receive. Over the plan's page limit: `422` with `error: quota_exceeded`; a subdomain in use: `422` with `error: subdomain_taken`; one of ours (www, api, app, mail, login, billing …): `error: subdomain_reserved`." parameters: [] responses: { } tags: - 'Status pages' requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Shown at the top of the page.' example: Acme subdomain: type: string description: 'The address under statuswerk.eu; derived from the name if left out.' example: acme nullable: true timezone: type: string description: 'Times on the page are shown in it.' example: Europe/Berlin language: type: string description: '`de` or `en`.' example: de reply_to_email: type: string description: "Where subscribers' replies go." example: support@acme.example nullable: true required: - name '/api/v1/statuspages/{id}': get: summary: 'Get a status page' operationId: getAStatusPage description: '' parameters: [] responses: { } tags: - 'Status pages' delete: summary: 'Delete a status page' operationId: deleteAStatusPage description: 'With its components, incidents, maintenance windows and subscribers — for good.' parameters: [] responses: { } tags: - 'Status pages' parameters: - in: path name: id description: 'The ID of the statuspage.' example: 01a1f3c2-5c00-7a10-8b20-1c2d3e4f5a6b required: true schema: type: string - in: path name: statuspage description: 'The status page id.' example: 01a1f3c2-5c00-7a10-8b20-1c2d3e4f5a6b required: true schema: type: string /api/v1/subscribers/import: post: summary: 'Import subscribers from CSV' operationId: importSubscribersFromCSV description: "The dashboard's import: a CSV file (`file`, up to 1 MB) with one email address per row or a column named `email`. The addresses are added as confirmed email subscribers — import only people who agreed elsewhere, and confirm it with `consent: true`, as the dashboard asks (`422` otherwise). Duplicates and invalid addresses are skipped, and so is everything over the plan's subscriber limit; the response counts each. While the first invoice of an annual plan on invoice is unpaid: `403` with `error: awaiting_payment`." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: imported: 120 skipped_duplicates: 3 skipped_invalid: 1 skipped_quota: 0 properties: data: type: object properties: imported: type: integer example: 120 skipped_duplicates: type: integer example: 3 skipped_invalid: type: integer example: 1 skipped_quota: type: integer example: 0 tags: - Subscribers requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary description: 'The CSV file.' consent: type: boolean description: "You have every listed person's consent to these notifications (GDPR)." example: true required: - file - consent /api/v1/subscribers: get: summary: 'List subscribers' operationId: listSubscribers description: 'A read-only token sees email addresses and phone numbers masked (`j••••@example.com`, `••••••••••567`) and only the host of a webhook URL.' parameters: - in: query name: verified description: 'Only confirmed (true) or only unconfirmed (false) subscribers.' example: true required: false schema: type: boolean description: 'Only confirmed (true) or only unconfirmed (false) subscribers.' example: true - in: query name: channel description: 'Only subscribers on this channel: email, sms, webhook.' example: email required: false schema: type: string description: 'Only subscribers on this channel: email, sms, webhook.' example: email - in: query name: undeliverable description: 'Only subscribers taken out of delivery (true) or only reachable ones (false).' example: true required: false schema: type: boolean description: 'Only subscribers taken out of delivery (true) or only reachable ones (false).' example: true - in: query name: per_page description: 'Page size, at most 100.' example: 50 required: false schema: type: integer description: 'Page size, at most 100.' example: 50 responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01a1bb39-facc-703f-b5da-dc8141951647 email: jane@example.com phone: null webhook_url: null webhook_type: null channels: - email component_ids: null locale: en is_verified: true verified_at: '2026-10-19T09:10:00+00:00' undeliverable_at: null undeliverable_reason: null created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' links: first: 'https://statuswerk.eu/api/v1/subscribers?page=1' last: 'https://statuswerk.eu/api/v1/subscribers?page=1' prev: null next: null meta: current_page: 1 from: 1 last_page: 1 links: - url: null label: '« Previous' page: null active: false - url: 'https://statuswerk.eu/api/v1/subscribers?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false path: 'https://statuswerk.eu/api/v1/subscribers' per_page: 50 to: 1 total: 1 properties: data: type: array example: - id: 01a1bb39-facc-703f-b5da-dc8141951647 email: jane@example.com phone: null webhook_url: null webhook_type: null channels: - email component_ids: null locale: en is_verified: true verified_at: '2026-10-19T09:10:00+00:00' undeliverable_at: null undeliverable_reason: null created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' items: type: object properties: id: type: string example: 01a1bb39-facc-703f-b5da-dc8141951647 email: type: string example: jane@example.com phone: type: string example: null nullable: true webhook_url: type: string example: null nullable: true webhook_type: type: string example: null nullable: true channels: type: array example: - email items: type: string component_ids: type: string example: null nullable: true locale: type: string example: en is_verified: type: boolean example: true verified_at: type: string example: '2026-10-19T09:10:00+00:00' undeliverable_at: type: string example: null nullable: true undeliverable_reason: type: string example: null nullable: true created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' links: type: object properties: first: type: string example: 'https://statuswerk.eu/api/v1/subscribers?page=1' last: type: string example: 'https://statuswerk.eu/api/v1/subscribers?page=1' prev: type: string example: null nullable: true next: type: string example: null nullable: true meta: type: object properties: current_page: type: integer example: 1 from: type: integer example: 1 last_page: type: integer example: 1 links: type: array example: - url: null label: '« Previous' page: null active: false - url: 'https://statuswerk.eu/api/v1/subscribers?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false items: type: object properties: url: type: string example: null nullable: true label: type: string example: '« Previous' page: type: string example: null nullable: true active: type: boolean example: false path: type: string example: 'https://statuswerk.eu/api/v1/subscribers' per_page: type: integer example: 50 to: type: integer example: 1 total: type: integer example: 1 tags: - Subscribers post: summary: 'Create a new subscriber.' operationId: createANewSubscriber description: "The subscriber receives a confirmation email (or SMS code) and is notified once they confirm.\nWith `skip_verification` the subscriber is confirmed at once — use it only for\npeople who already agreed elsewhere. A workspace whose first invoice for an annual\nplan on invoice is still unpaid gets `403` with `error: awaiting_payment` for\n`skip_verification` until the payment has arrived; without it the call works as\nusual.\n\nEvery mail, SMS and webhook text a subscriber gets is in the status page's\n`language`. `locale` is stored as given but does not change that.\n\n`phone` is in international format (`+491701234567`). SMS and webhook subscribers\nneed the channel switched on for the page and included in the plan, subscribing to\nsingle `component_ids` needs the plan too — otherwise `403` with\n`error: channel_unavailable` / `feature_unavailable`. An SMS subscriber always\nconfirms the number with the code we send: `skip_verification` with a `phone`\ngets `422` with `error: sms_requires_verification`. Over the subscriber limit:\n`422` with `error: quota_exceeded`.\n\nA webhook-only subscriber is confirmed by its endpoint, as on the public page: we\nsend one signed test POST right away and a `2xx` answer confirms it. Anything else\ncreates nothing and returns `422` with `error: webhook_unreachable`. The same\naddress (email, number or webhook URL) twice returns the existing subscriber." parameters: [] responses: { } tags: - Subscribers requestBody: required: false content: application/json: schema: type: object properties: email: type: string description: 'Gets a confirmation mail unless skip_verification. This field is required when none of phone and webhook_url are present. value muss eine gültige E-Mail-Adresse sein. value darf nicht mehr als 255 Zeichen haben.' example: ops@example.com nullable: true phone: type: string description: 'International format, e.g. +491701234567. Gets a confirmation code by SMS. This field is required when none of email and webhook_url are present. Must match the regex /^\+[1-9][0-9]{6,14}$/.' example: '+3642559314' nullable: true webhook_url: type: string description: 'Public HTTPS URL that receives the notifications as JSON. This field is required when none of email and phone are present. Must be a valid URL. value darf nicht mehr als 2000 Zeichen haben.' example: 'http://www.considine.com/provident-perspiciatis-quo-omnis-nostrum-aut-adipisci-quidem' nullable: true webhook_type: type: string description: 'generic, slack, microsoft_teams, discord or google_chat. This field is required when webhook_url is present.' example: google_chat enum: - generic - slack - microsoft_teams - discord - google_chat nullable: true webhook_secret: type: string description: 'Your own signing secret, 32 to 64 characters; one is generated otherwise and returned once. value muss mindestens 32 Zeichen haben. value darf nicht mehr als 64 Zeichen haben.' example: w nullable: true channels: type: array description: '' example: - webhook items: type: string enum: - email - sms - webhook component_ids: type: array description: 'value muss eine gültige UUID sein.' example: - 445bd3f6-8f2c-38cb-aa04-2f4e1edb32bb items: type: string locale: type: string description: 'value darf nicht mehr als 10 Zeichen haben.' example: sw_TZ nullable: true skip_verification: type: boolean description: 'Confirmed at once — only for people who agreed elsewhere. Not for phone numbers.' example: false nullable: true '/api/v1/subscribers/{id}': get: summary: 'Get a subscriber' operationId: getASubscriber description: '' parameters: [] responses: { } tags: - Subscribers delete: summary: 'Delete a subscriber' operationId: deleteASubscriber description: '' parameters: [] responses: { } tags: - Subscribers parameters: - in: path name: id description: 'The ID of the subscriber.' example: 01a1f3c2-a060-7f71-8485-9f0a1b2c3d4e required: true schema: type: string '/api/v1/subscribers/{subscriber}/resend-verification': post: summary: 'Resend the confirmation mail' operationId: resendTheConfirmationMail description: '`422` when the subscriber is confirmed already or has no email address; `429` with `error: too_many_confirmations` after three confirmation mails to one address within an hour. Limited to 10 per minute.' parameters: [] responses: { } tags: - Subscribers parameters: - in: path name: subscriber description: 'The subscriber.' example: 01a1f3c2-a060-7f71-8485-9f0a1b2c3d4e required: true schema: type: string /api/v1/team/members: get: summary: 'List members' operationId: listMembers description: "Names, email addresses, roles and status page access (`statuspage_access`: `null` for every page, otherwise page id => `edit`, `read` or `none`, where a page not listed is `none` and `{}` means no page at all; set in the dashboard). The token's owner needs the right to manage the team, as for the team page in the dashboard (`403` otherwise)." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 2 name: 'Jane Doe' email: jane.doe@acme.example roles: [] statuspage_access: null properties: data: type: array example: - id: 2 name: 'Jane Doe' email: jane.doe@acme.example roles: [] statuspage_access: null items: type: object properties: id: type: integer example: 2 name: type: string example: 'Jane Doe' email: type: string example: jane.doe@acme.example roles: type: array example: [] statuspage_access: type: string example: null nullable: true tags: - Team /api/v1/team/invitations: get: summary: 'List open invitations' operationId: listOpenInvitations description: "The token's owner needs the right to invite members, as in the dashboard (`403` otherwise)." parameters: [] responses: { } tags: - Team post: summary: 'Invite someone' operationId: inviteSomeone description: "Sends the invitation mail, as the dashboard does; it is valid for 7 days. Invitations through the API are always for the member role. The token's owner needs the right to invite members (`403` otherwise). `422` when the address is already in the team or invited, and with `error: quota_exceeded` when the plan has no seat left." parameters: [] responses: { } tags: - Team requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'Who to invite.' example: colleague@example.com role: type: string description: 'Always the member role (`user`); higher roles are given in the dashboard.' example: user required: - email '/api/v1/team/invitations/{id}': delete: summary: 'Withdraw an invitation' operationId: withdrawAnInvitation description: '' parameters: [] responses: { } tags: - Team parameters: - in: path name: id description: 'The ID of the invitation.' example: 01a1f3c2-a170-7081-9596-0a1b2c3d4e5f required: true schema: type: string - in: path name: invitation description: "The invitation's id." example: 01a1f3c2-a170-7081-9596-0a1b2c3d4e5f required: true schema: type: string /api/v1/incident-templates: get: summary: 'List incident templates' operationId: listIncidentTemplates description: '' parameters: [] responses: { } tags: - Templates post: summary: 'Create an incident template' operationId: createAnIncidentTemplate description: 'Use `{key}` placeholders in title and message; `apply` fills them from `variables`.' parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01a1544c-7c2f-70af-a6e8-1a99bc95fd92 name: 'Payment provider down' title_template: '{provider} unavailable' message_template: 'Payments through {provider} are failing. We are in contact with them.' default_status: null default_severity: null default_component_ids: [] visible: null stickied: null notify_subscribers: null created_at: '2026-10-19T09:10:00+00:00' updated_at: '2026-10-19T09:10:00+00:00' properties: data: type: object properties: id: type: string example: 01a1544c-7c2f-70af-a6e8-1a99bc95fd92 name: type: string example: 'Payment provider down' title_template: type: string example: '{provider} unavailable' message_template: type: string example: 'Payments through {provider} are failing. We are in contact with them.' default_status: type: string example: null nullable: true default_severity: type: string example: null nullable: true default_component_ids: type: array example: [] visible: type: string example: null nullable: true stickied: type: string example: null nullable: true notify_subscribers: type: string example: null nullable: true created_at: type: string example: '2026-10-19T09:10:00+00:00' updated_at: type: string example: '2026-10-19T09:10:00+00:00' tags: - Templates requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b title_template: type: string description: 'The title; `{key}` placeholders are filled from `variables` when applied. value darf nicht mehr als 255 Zeichen haben.' example: 'n' message_template: type: string description: 'The message; `{key}` placeholders are filled from `variables` when applied. value darf nicht mehr als 10000 Zeichen haben.' example: g default_status: type: string description: 'The status a new incident starts with.' example: investigating enum: - investigating - identified - monitoring - resolved nullable: true default_severity: type: string description: 'The severity a new incident starts with.' example: critical enum: - minor - major - critical nullable: true visible: type: boolean description: 'false hides it from the page.' example: false nullable: true stickied: type: boolean description: 'Pin it to the top of the page.' example: true nullable: true notify_subscribers: type: boolean description: 'Tell subscribers (default true). Chat integrations are told either way.' example: false nullable: true default_component_ids: type: array description: 'value muss eine gültige UUID sein.' example: - c90237e9-ced5-3af6-88ea-84aeaa148878 items: type: string required: - name - title_template - message_template '/api/v1/incident-templates/{id}': get: summary: 'Get an incident template' operationId: getAnIncidentTemplate description: '' parameters: [] responses: { } tags: - Templates put: summary: 'Update an incident template' operationId: updateAnIncidentTemplate description: '' parameters: [] responses: { } tags: - Templates requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b title_template: type: string description: 'The title; `{key}` placeholders are filled from `variables` when applied. value darf nicht mehr als 255 Zeichen haben.' example: 'n' message_template: type: string description: 'The message; `{key}` placeholders are filled from `variables` when applied. value darf nicht mehr als 10000 Zeichen haben.' example: g default_status: type: string description: 'The status a new incident starts with.' example: monitoring enum: - investigating - identified - monitoring - resolved nullable: true default_severity: type: string description: 'The severity a new incident starts with.' example: critical enum: - minor - major - critical nullable: true visible: type: boolean description: 'false hides it from the page.' example: false nullable: true stickied: type: boolean description: 'Pin it to the top of the page.' example: false nullable: true notify_subscribers: type: boolean description: 'Tell subscribers (default true). Chat integrations are told either way.' example: false nullable: true default_component_ids: type: array description: 'value muss eine gültige UUID sein.' example: - c90237e9-ced5-3af6-88ea-84aeaa148878 items: type: string delete: summary: 'Delete an incident template' operationId: deleteAnIncidentTemplate description: '' parameters: [] responses: { } tags: - Templates parameters: - in: path name: id description: 'The ID of the incident template.' example: 01a1f3c2-9a30-7c41-8b52-6c7d8e9f0a1b required: true schema: type: string '/api/v1/incident-templates/{incident_template}/apply': post: summary: 'Open an incident from a template' operationId: openAnIncidentFromATemplate description: "Fills the placeholders from `variables` and opens the incident as `POST /incidents` would. Over the monthly incident limit: `422` with `error: quota_exceeded`.\n\nThe endpoint CI/CD and alerting hooks use: name the template, optionally pass\nvariables for the placeholders, and every other field comes from the template." parameters: [] responses: { } tags: - Templates requestBody: required: false content: application/json: schema: type: object properties: occurred_at: type: string description: 'value muss ein gültiges Datum sein.' example: '2026-11-12T21:59:18' nullable: true variables: type: array description: 'value darf nicht mehr als 255 Zeichen haben.' example: - b items: type: string nullable: true parameters: - in: path name: incident_template description: "The incident template's id." example: 01a1f3c2-9a30-7c41-8b52-6c7d8e9f0a1b required: true schema: type: string '/api/v1/incident-templates/{incident_template}/duplicate': post: summary: 'Duplicate an incident template' operationId: duplicateAnIncidentTemplate description: 'A copy named "… (copy)", to start a variant from.' parameters: [] responses: { } tags: - Templates parameters: - in: path name: incident_template description: "The incident template's id." example: 01a1f3c2-9a30-7c41-8b52-6c7d8e9f0a1b required: true schema: type: string '/api/v1/incidents/{incident}/save-as-template': post: summary: 'Save an incident as a template' operationId: saveAnIncidentAsATemplate description: "Title, message, status, severity, components and switches of the incident become a template's defaults." parameters: [] responses: { } tags: - Templates requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: "The template's name." example: 'Ingest degradation' required: - name parameters: - in: path name: incident description: 'The incident.' example: 01a1f3c2-7d0e-7a51-9c3b-2f6e8d4a1b90 required: true schema: type: string /api/v1/maintenance-templates: get: summary: 'List maintenance templates' operationId: listMaintenanceTemplates description: '' parameters: [] responses: { } tags: - Templates post: summary: 'Create a maintenance template' operationId: createAMaintenanceTemplate description: '' parameters: [] responses: { } tags: - Templates requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b title_template: type: string description: 'The title; `{key}` placeholders are filled from `variables` when applied. value darf nicht mehr als 255 Zeichen haben.' example: 'n' message_template: type: string description: 'The message; `{key}` placeholders are filled from `variables` when applied. value darf nicht mehr als 10000 Zeichen haben.' example: g default_duration_minutes: type: integer description: 'Length of a window scheduled from it, in minutes. value muss mindestens 1 sein. value darf nicht größer als 43200 sein.' example: 16 nullable: true notify_subscribers: type: boolean description: 'Tell subscribers (default true). Chat integrations are told either way.' example: false nullable: true send_reminder_1h: type: boolean description: 'Remind subscribers an hour before.' example: false nullable: true auto_start: type: boolean description: 'Start it by itself at `scheduled_start_at`.' example: false nullable: true notify_at_start: type: boolean description: 'Tell subscribers when it starts.' example: true nullable: true auto_complete: type: boolean description: 'Complete it by itself at `scheduled_end_at`.' example: false nullable: true notify_at_end: type: boolean description: 'Tell subscribers when it ends.' example: true nullable: true update_component_status: type: boolean description: 'Show the components as under maintenance while it runs.' example: true nullable: true default_component_ids: type: array description: 'value muss eine gültige UUID sein.' example: - 977e5426-8d13-3824-86aa-b092f8ae52c5 items: type: string required: - name - title_template - message_template '/api/v1/maintenance-templates/{id}': get: summary: 'Get a maintenance template' operationId: getAMaintenanceTemplate description: '' parameters: [] responses: { } tags: - Templates put: summary: 'Update a maintenance template' operationId: updateAMaintenanceTemplate description: '' parameters: [] responses: { } tags: - Templates requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Its name, shown on the page (templates: in the dashboard only). value darf nicht mehr als 255 Zeichen haben.' example: b title_template: type: string description: 'The title; `{key}` placeholders are filled from `variables` when applied. value darf nicht mehr als 255 Zeichen haben.' example: 'n' message_template: type: string description: 'The message; `{key}` placeholders are filled from `variables` when applied. value darf nicht mehr als 10000 Zeichen haben.' example: g default_duration_minutes: type: integer description: 'Length of a window scheduled from it, in minutes. value muss mindestens 1 sein. value darf nicht größer als 43200 sein.' example: 16 nullable: true notify_subscribers: type: boolean description: 'Tell subscribers (default true). Chat integrations are told either way.' example: true nullable: true send_reminder_1h: type: boolean description: 'Remind subscribers an hour before.' example: true nullable: true auto_start: type: boolean description: 'Start it by itself at `scheduled_start_at`.' example: true nullable: true notify_at_start: type: boolean description: 'Tell subscribers when it starts.' example: false nullable: true auto_complete: type: boolean description: 'Complete it by itself at `scheduled_end_at`.' example: false nullable: true notify_at_end: type: boolean description: 'Tell subscribers when it ends.' example: false nullable: true update_component_status: type: boolean description: 'Show the components as under maintenance while it runs.' example: false nullable: true default_component_ids: type: array description: 'value muss eine gültige UUID sein.' example: - 977e5426-8d13-3824-86aa-b092f8ae52c5 items: type: string delete: summary: 'Delete a maintenance template' operationId: deleteAMaintenanceTemplate description: '' parameters: [] responses: { } tags: - Templates parameters: - in: path name: id description: 'The ID of the maintenance template.' example: 01a1f3c2-9b50-7e61-b374-8e9f0a1b2c3d required: true schema: type: string '/api/v1/maintenance-templates/{maintenance_template}/apply': post: summary: 'Schedule maintenance from a template' operationId: scheduleMaintenanceFromATemplate description: "`403` without scheduled maintenance in the plan, `422` when the times are invalid.\n\nThis is the endpoint CI/CD and schedulers use: pick the template, give it a start\ntime, and every other field comes from the template." parameters: [] responses: { } tags: - Templates requestBody: required: true content: application/json: schema: type: object properties: scheduled_start_at: type: string description: "Unlike POST /maintenances, also now or just past: a pipeline announces the\nwindow it is about to open. value muss ein gültiges Datum sein." example: '2026-11-12T21:59:18' scheduled_end_at: type: string description: 'value muss ein gültiges Datum sein. value muss ein Datum nach scheduled_start_at sein.' example: '2052-12-05' nullable: true variables: type: array description: 'value darf nicht mehr als 255 Zeichen haben.' example: - 'n' items: type: string nullable: true required: - scheduled_start_at parameters: - in: path name: maintenance_template description: "The maintenance template's id." example: 01a1f3c2-9b50-7e61-b374-8e9f0a1b2c3d required: true schema: type: string '/api/v1/maintenance-templates/{maintenance_template}/duplicate': post: summary: 'Duplicate a maintenance template' operationId: duplicateAMaintenanceTemplate description: 'A copy named "… (copy)", to start a variant from.' parameters: [] responses: { } tags: - Templates parameters: - in: path name: maintenance_template description: "The maintenance template's id." example: 01a1f3c2-9b50-7e61-b374-8e9f0a1b2c3d required: true schema: type: string '/api/v1/maintenances/{maintenance}/save-as-template': post: summary: 'Save a maintenance window as a template' operationId: saveAMaintenanceWindowAsATemplate description: "Title, message, components, switches and the scheduled length (as default duration) become a template's defaults." parameters: [] responses: { } tags: - Templates requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: "The template's name." example: 'Monthly database patch' required: - name parameters: - in: path name: maintenance description: 'The maintenance.' example: 01a1f3c2-8f40-7d51-a263-7d8e9f0a1b2c required: true schema: type: string