API
API-Schlüssel mit Geltungsbereichen, gebunden an Ihre Organisation. Bei jedem Build aus dem OpenAPI-Vertrag des Produkts neu erzeugt, damit diese Seite nicht vom Code abweichen kann.
API-Schlüssel sind da. Sie legen sie in der App unter Integrationen, API-Schlüssel an (nur Owner und Admin) und schicken sie als Bearer-Token:
Authorization: Bearer pst_...
Ein Schlüssel gehört zu genau einer Organisation. Er trägt Geltungsbereiche, nämlich
monitors, incidents, status-pages und webhooks, jeweils als :read oder :write,
dazu org:read; ein Schreibrecht schließt das Leserecht derselben Ressource ein. Sie
können einen Schlüssel weiter verengen, auf ausgewählte Projekte oder auf einzelne
Monitore. Widerruf und Ablauf greifen bei der nächsten Anfrage, nicht erst am Ende irgendeines
Zwischenspeichers.
Schlüssel können keine Schlüssel verwalten. Die Verwaltungsendpunkte verlangen konstruktionsbedingt eine Browser-Sitzung. Ein abhandengekommener Schlüssel liest also, was seine Geltungsbereiche erlauben, und kann sich niemals selbst einen Nachfolger ausstellen.
Was heute einen Schlüssel annimmt
Die Schlüssel-Authentifizierung ist auf sieben lesenden Endpunkten aktiv:
| Endpunkt | was er liefert |
|---|---|
| Monitore eines Projekts | die Liste mit Zustand, Typ, Intervall, Regionen |
| ein einzelner Monitor | die Detailansicht, wie das Cockpit sie zeigt |
| Checks eines Monitors | die rohen Checkergebnisse dahinter |
| Zeitreihe eines Monitors | Antwortzeiten über einen Zeitraum |
| Incidents eines Monitors | die Incidents an diesem Monitor |
| Incidents einer Organisation | die Liste |
| ein einzelner Incident | die Detailansicht mit Zeitachse |
Jeder andere Endpunkt unten verlangt weiterhin eine Sitzung, und Schreibrechte sind zwar wählbar, werden aber noch nirgends ausgewertet. Die kuratierte öffentliche Referenz in der Version 1.0.0-beta.1 folgt mit dem nächsten Release; bis dahin zeigt diese Seite den vollständigen Umfang, mit dem die Apps sprechen, damit Sie die Form dessen sehen, was kommt.
Funktionsbereiche, die nicht veröffentlicht sind, etwa mehrstufige Checks, bleiben ausgeschlossen, bis sie ausgeliefert werden.
Auth and session
- POST
/auth/login - POST
/auth/logoutBeendet die aktuelle Sitzung serverseitig. Sitzungen sind einzeln und gesamthaft widerrufbar.
- POST
/auth/magicMagic-Link-Anmeldung: Der Endpunkt nimmt eine E-Mail-Adresse entgegen und verschickt einen einmaligen Anmeldelink. Antwortet bewusst neutral, unabhängig davon, ob die Adresse existiert.
- POST
/auth/magic/verify - POST
/auth/registerOnboarding: legt User + Organization + Owner-Membership an und loggt direkt ein (Bearer-Token). 201 bei Erfolg, 409 wenn E-Mail/Org-Slug schon existiert.
- GET
/me - GET
/me/activityAktivitätslog ÜBER ALLE Orgs des Users (Scope „Alle Organisationen").
- GET
/me/cockpit-bootstrap - GET
/me/cockpit-stats - GET
/me/devicesVerbundene Push-Geräte des eingeloggten Users (ohne Roh-Token).
- POST
/me/devicesRegistriert ein Push-Device-Token für den angemeldeten User (Upsert). Grundlage für die spätere Push-Auslieferung bei Incidents.
- DELETE
/me/devices/{id}Entfernt ein verbundenes Gerät des Users.
- GET
/me/downtimes - GET
/me/invitations - POST
/me/invitations/{inv_id}/accept - POST
/me/locale - GET
/me/loginsLetzte Anmeldungen (Sessions) des eingeloggten Users — neueste zuerst.
- POST
/me/logins/revoke-othersMeldet alle anderen Sessions des Users ab („überall abmelden") — die aktuelle Session bleibt aktiv.
- DELETE
/me/logins/{id}Meldet eine bestimmte Session des Users ab (widerruft sie).
- GET
/me/notification-preferences - PUT
/me/notification-preferences - GET
/me/notificationsBenachrichtigungen des eingeloggten Users (neueste zuerst, max. 30).
- POST
/me/notifications/readMarkiert alle Benachrichtigungen des Users als gelesen.
- GET
/me/notifications/unreadAnzahl ungelesener Benachrichtigungen (Glocken-Badge, billig pollbar).
- GET
/me/open-incidentsOffene Incidents ÜBER ALLE Orgs des Users — für die globale Incident-Leiste (Scope „Alle Organisationen"). Älteste zuerst.
- GET
/me/org-summaries - GET
/me/organizations - GET
/me/phone - PUT
/me/phone - POST
/me/phone/verifyBestätigt die Nummer mit dem SMS-Code. `204` bei Erfolg, sonst `400` (kein Oracle: falsch/abgelaufen/zu viele Versuche → einheitlich 400).
- POST
/me/phone/verify/requestFordert einen 6-stelligen SMS-Code zur Verifizierung der EIGENEN Nummer an. Braucht eine gesetzte Nummer + konfiguriertes Twilio (`503` sonst). `429` bei aktivem Cooldown. Schon verifiziert → `200 {sent:false}`.
- GET
/me/raw-down-days - GET
/me/region-capabilitiesRegionen-Katalog: IPv6-Fähigkeit (für die Regionen-Filterung im Monitor- Formular) plus Geo-Anreicherung aus der kanonischen Registry (ADR-0010) — Kontinent als Anzeige-Rollup und, wo betrieben, die PoP-Stadt/-Land für die nutzersichtbare Transparenz.
- GET
/me/region-summaries - GET
/me/resolve-hostPrüft, ob ein Host nach IPv4/IPv6 auflöst (bzw. eine IP-Literal ist). Das Formular nutzt das, um IPv6 nur anzubieten, wenn ein AAAA/IPv6 existiert. Reine DNS-Auflösung (keine Verbindung).
- GET
/me/timelineKonsolidierte Statuswechsel-Zeitleiste ÜBER ALLE Orgs des Users (Scope „Alle Organisationen").
- GET
/organizations/{org_id}/members - PATCH
/organizations/{org_id}/members/{user_id} - DELETE
/organizations/{org_id}/members/{user_id}
Organizations and members
- POST
/invitations/accept - POST
/invitations/inspectLiest die Eckdaten einer offenen Einladung per Token — OHNE sie zu verbrauchen. Damit kann das Frontend vor der Annahme ein Bestätigungs-Modal (Org + Rolle) zeigen.
- POST
/organizations - PATCH
/organizations/{org_id} - DELETE
/organizations/{org_id} - GET
/organizations/{org_id}/activityAktivitätslog der Org: Konfig-Änderungen durch User/API (wer, wann, was).
- POST
/organizations/{org_id}/convertKonversion Trial→zahlend: setzt den lokalen Plan-Spiegel (Gating sofort) und synchronisiert best-effort mit dem ERP (Kunde + Firmendaten + Tarif). Nur Owner/BillingAdmin. Ohne ERP-Config bleibt die Konversion rein lokal (lazy ERP).
- GET
/organizations/{org_id}/downtimes - GET
/organizations/{org_id}/entitlements - GET
/organizations/{org_id}/invitations - POST
/organizations/{org_id}/invitations - DELETE
/organizations/{org_id}/invitations/{inv_id} - GET
/organizations/{org_id}/project-summaries - GET
/organizations/{org_id}/raw-down-days - GET
/organizations/{org_id}/timelineKonsolidierte Statuswechsel-Zeitleiste der Org (was passierte wann).
Projects
- GET
/organizations/{org_id}/projects - POST
/organizations/{org_id}/projects - POST
/organizations/{org_id}/projects/reorder - PATCH
/projects/{project_id} - DELETE
/projects/{project_id} - GET
/projects/{project_id}/activityAktivitätslog EINES Projekts: Änderungen am Projekt, seinen Monitoren und Journeys.
- GET
/projects/{project_id}/downtimes - GET
/projects/{project_id}/monitors - POST
/projects/{project_id}/monitors - POST
/projects/{project_id}/monitors/reorder - POST
/projects/{project_id}/moveVerschiebt ein Projekt in eine andere Organisation (mit Org-Cascade auf alle Dienste). Erfordert Manage-Rolle in Quell- UND Ziel-Org.
- GET
/projects/{project_id}/raw-down-days - GET
/projects/{project_id}/timelineStatuswechsel-Zeitleiste EINES Projekts (gefiltert über die Monitore des Projekts).
Monitors and checks
- PATCH
/alert-profiles/{id} - DELETE
/alert-profiles/{id} - GET
/monitors/{monitor_id} - PATCH
/monitors/{monitor_id}Aktualisiert einen Monitor (partiell). Auch fuer das Aktiv/Inaktiv-Schalten (`{ "enabled": false }`) genutzt — wie bei Journeys.
- DELETE
/monitors/{monitor_id} - GET
/monitors/{monitor_id}/alarm-state - GET
/monitors/{monitor_id}/checks - POST
/monitors/{monitor_id}/clone - GET
/monitors/{monitor_id}/incidents - POST
/monitors/{monitor_id}/moveVerschiebt einen Monitor in ein anderes Projekt (ggf. andere Org). Erfordert Manage-Rolle in Quell- UND Ziel-Org.
- POST
/monitors/{monitor_id}/runFuehrt einen Monitor JETZT aus (interim In-API-Executor, vgl. run_journey).
- GET
/monitors/{monitor_id}/series - GET
/organizations/{org_id}/alert-profiles - POST
/organizations/{org_id}/alert-profiles - POST
/organizations/{org_id}/monitors/{monitor_id}/discard-dayIncident-losen roten Tag als Fehlalarm verwerfen: Tages-Exclusion-Fenster. Nur Owner/Admin, auditiert, per Restore umkehrbar.
Incidents and post-mortems
- GET
/organizations/{org_id}/incidents - POST
/organizations/{org_id}/incidents - GET
/organizations/{org_id}/incidents/feedOrg-weite Incident-Liste für die Incidents-Seite: offene zuerst, dann die jüngsten gelösten (gedeckelt auf 200). Ergänzt `GET .../incidents` (nur offene, schlanke DTOs für Down-Markierungen), ersetzt es nicht.
- GET
/organizations/{org_id}/incidents/{incident_id} - POST
/organizations/{org_id}/incidents/{incident_id}/ack - GET
/organizations/{org_id}/incidents/{incident_id}/action-items - POST
/organizations/{org_id}/incidents/{incident_id}/action-items - PUT
/organizations/{org_id}/incidents/{incident_id}/action-items/{item_id} - DELETE
/organizations/{org_id}/incidents/{incident_id}/action-items/{item_id} - POST
/organizations/{org_id}/incidents/{incident_id}/assign - POST
/organizations/{org_id}/incidents/{incident_id}/deleteIncident-Meldung entfernen (Soft-Delete): verschwindet aus der öffentlichen Incident-Historie; Uptime/Balken bleiben unverändert. Nur Owner/Admin, nur RESOLVED, auditiert, per Restore umkehrbar.
- POST
/organizations/{org_id}/incidents/{incident_id}/discard-downtimeDowntime als Fehlalarm verwerfen: das Fenster fällt aus Uptime %, Tages- balken und Badge heraus (statusseiten-wirksam); optional verschwindet auch die Incident-Meldung. Nur Owner/Admin, nur beendete Ausfälle, auditiert.
- GET
/organizations/{org_id}/incidents/{incident_id}/discard-previewVorschau: wie ändert sich die Uptime (7/30/90 Tage), wenn dieses Fenster verworfen wird? Speist den Bestätigungs-Dialog VOR der Aktion.
- GET
/organizations/{org_id}/incidents/{incident_id}/events - POST
/organizations/{org_id}/incidents/{incident_id}/note - GET
/organizations/{org_id}/incidents/{incident_id}/on-call - POST
/organizations/{org_id}/incidents/{incident_id}/on-call/ack - GET
/organizations/{org_id}/incidents/{incident_id}/pages - POST
/organizations/{org_id}/incidents/{incident_id}/pages - DELETE
/organizations/{org_id}/incidents/{incident_id}/pages/{page_id} - GET
/organizations/{org_id}/incidents/{incident_id}/postmortem - PUT
/organizations/{org_id}/incidents/{incident_id}/postmortem - POST
/organizations/{org_id}/incidents/{incident_id}/postmortem/publish - POST
/organizations/{org_id}/incidents/{incident_id}/resolve - POST
/organizations/{org_id}/incidents/{incident_id}/restoreGelöschte Incident-Meldung wiederherstellen.
- POST
/organizations/{org_id}/incidents/{incident_id}/restore-downtimeVerworfene Downtime wiederherstellen — alle Aggregate heilen zurück.
- POST
/organizations/{org_id}/incidents/{incident_id}/severity - POST
/organizations/{org_id}/incidents/{incident_id}/snoozeSchlummert einen Incident für den AUFRUFER (nur ihn) für `SNOOZE_MINUTES` (15). Der Broadcast-/Owner-Push unterdrückt diese Person bis zum Ablauf; andere Mitarbeiter werden weiter normal alarmiert. KEIN Ack (übernimmt den Fall nicht).
- POST
/organizations/{org_id}/incidents/{incident_id}/summary
On-call and paging
- GET
/organizations/{org_id}/on-call/duty - GET
/organizations/{org_id}/on-call/members - PUT
/organizations/{org_id}/on-call/members - GET
/organizations/{org_id}/on-call/settings - PUT
/organizations/{org_id}/on-call/settings - GET
/organizations/{org_id}/paging-usage
Status pages
- GET
/badge.svgÖFFENTLICH: Badge unter der EIGENEN Custom-Domain — `https://<domain>/badge.svg`. Der Edge reicht den `Host`-Header an die API durch; wir lösen die Domain via [`StatusPageRepository::find_public_by_domain`] auf die Seite auf. So kann der Badge-Embed dieselbe (kurze) Domain wie der Link nutzen, statt der API-URL. (Auf der Wildcard-Subdomain existiert keine Domain-Row → 404; dort nutzt das Frontend weiter die `/public/status-pages/{slug}/badge.svg`-URL.)
- GET
/organizations/{org_id}/status-pages - POST
/organizations/{org_id}/status-pages - GET
/organizations/{org_id}/status-pages/archived - GET
/public/status-pages/resolvePublic: löst eine Custom-Domain (Host-Header oder `?host=`) auf den Slug der zugehörigen, publizierten Status-Seite auf. Kein Auth.
- GET
/public/status-pages/{slug}ÖFFENTLICH (kein Auth). Liefert eine publizierte Status-Seite anhand ihres Slugs: Komponenten = die handverlesenen Monitore (NUR über den Page-Join, nie eine Monitor-ID vom Aufrufer) mit aktuellem Status + Uptime%. Keine internen/Tenant-IDs in der Antwort.
- GET
/public/status-pages/{slug}/badge.svgÖFFENTLICH: einbettbares SVG-Status/Uptime-Badge einer Status-Seite. `?metric=uptime` zeigt die aggregierte Uptime% statt des Gesamtstatus.
- GET
/public/status-pages/{slug}/feed.rssÖFFENTLICH: RSS-2.0-Feed der Incidents + geplanten Wartungen einer Status-Seite. Reuse der bereits öffentlichen Daten hinter demselben Sichtbarkeits-Gate.
- POST
/public/status-pages/{slug}/loginÖFFENTLICH (rate-limited): Login eines Viewers einer privaten Status-Seite. Erfolg → langlebiges Viewer-Token. Bei jedem Fehlschlag einheitlich `401` (keine Unterscheidung „User unbekannt" vs. „Passwort falsch" → kein Enum-Oracle).
- GET
/public/status-pages/{slug}/logoÖFFENTLICH: Logo einer publizierten Status-Seite (per Slug).
- GET
/public/status-pages/{slug}/logo/darkÖFFENTLICH: Dark-Mode-Logo einer publizierten Status-Seite (per Slug).
- POST
/public/status-pages/{slug}/subscribeÖFFENTLICH (rate-limited): Abo-Anfrage für Statusseiten-Updates (Double-Opt-in). Antwortet immer `202` (außer ungültige Adresse → `400` / unbekannte Seite → `404`) — verrät nie, ob die Adresse neu oder schon bestätigt ist. Eine Bestätigungsmail geht NUR bei neuem oder noch unbestätigtem Abo raus.
- POST
/public/status-pages/{slug}/unlockÖFFENTLICH (rate-limited): EIN geteiltes Kennwort schaltet die ganze Seite frei. Erfolg → langlebiges Shared-Token im HttpOnly-Cookie `sp_unlock_<slug>` (kein Token im Body — Cookie-only, damit kein geteilter Link den Zugang leckt). Bei jedem Fehlschlag einheitlich `401` (kein Oracle); Seite ohne Shared-Modus → `404`.
- GET
/status-pages/{id} - PATCH
/status-pages/{id} - DELETE
/status-pages/{id} - GET
/status-pages/{id}/domains - POST
/status-pages/{id}/domains - POST
/status-pages/{id}/domains/reorderReihenfolge der Custom-Domains setzen (Drag&Drop). Die ERSTE Domain ist der Default-Host, der überall verlinkt wird (Badge + obere URL der Editor-Kachel).
- DELETE
/status-pages/{id}/domains/{domain_id} - POST
/status-pages/{id}/domains/{domain_id}/verifySynchroner Verify-Klick: DNS prüfen (CNAME); bei Erfolg verifizieren + (falls Edge konfiguriert) als VHost pushen. Liefert den aktuellen Stand.
- DELETE
/status-pages/{id}/logo - DELETE
/status-pages/{id}/logo/dark - POST
/status-pages/{id}/monitors - PUT
/status-pages/{id}/shared-passwordOperator: geteiltes Kennwort setzen/rotieren. Das Setzen ist der EINZIGE Pfad, der `shared_password_hash` befüllt (nie die Settings-PUT). Rotation invalidiert alle bestehenden Shared-Cookies (delete_shared_sessions). Min. 12 Zeichen.
- DELETE
/status-pages/{id}/shared-passwordOperator: geteiltes Kennwort entfernen (Modus aus, Hash leeren, Sessions weg).
- GET
/status-pages/{id}/subscribersOperator: bestätigte Abonnenten einer Status-Seite auflisten. Nur Operator (`can_manage_projects`) — die E-Mails sind PII. BEWUSST nicht cap-gegated, damit eine herabgestufte Org ihren Bestand noch einsehen/aufräumen kann.
- DELETE
/status-pages/{id}/subscribers/{subscriber_id}Operator: einen Abonnenten entfernen (per interner id, gescopt auf die Seite).
- POST
/status-pages/{id}/unarchive - GET
/status-pages/{id}/versions - POST
/status-pages/{id}/versions - POST
/status-pages/{id}/versions/{version_id}/restore - GET
/status-pages/{id}/viewersOperator: Viewer einer (privaten) Status-Seite auflisten.
- POST
/status-pages/{id}/viewersOperator: Viewer anlegen. Passwort wird generiert + EINMALIG zurückgegeben.
- DELETE
/status-pages/{id}/viewers/{viewer_id}Operator: Viewer entfernen (seine Sessions kaskadieren mit).
Maintenance and curation
- POST
/organizations/{org_id}/exclusions/{exclusion_id}/restoreManuelles Tages-Fenster zurücknehmen — der Tag zählt wieder wie gemessen.
- GET
/organizations/{org_id}/maintenance-windows - POST
/organizations/{org_id}/maintenance-windows - PATCH
/organizations/{org_id}/maintenance-windows/{id} - DELETE
/organizations/{org_id}/maintenance-windows/{id} - POST
/organizations/{org_id}/maintenance-windows/{id}/cancel
Host agents
- POST
/organizations/{org_id}/agent-enroll-tokens`POST /organizations/{org_id}/agent-enroll-tokens`: erzeugt ein Enrollment- Token (UI). Erfordert Projektverwaltungs-Rechte.
- GET
/organizations/{org_id}/agents`GET /organizations/{org_id}/agents`: aktive Agents der Org (Listenanzeige).
- PATCH
/organizations/{org_id}/agents/{agent_id}`PATCH /organizations/{org_id}/agents/{agent_id}`: erweiterte Konfiguration eines Agents (v1: nur das Inventar-Opt-in). Erfordert Projektverwaltungs- Rechte. Der Agent übernimmt das Flag beim nächsten Config-Poll (~5 min).
- DELETE
/organizations/{org_id}/agents/{agent_id}`DELETE /organizations/{org_id}/agents/{agent_id}`: entfernt einen Agent (soft-delete) — das Per-Agent-Token wird sofort ungültig und der Agent verschwindet aus der Liste. Erfordert Projektverwaltungs-Rechte. Die rückstandslose Entfernung VOM HOST erfolgt separat (uninstall.sh).
Webhooks
- GET
/organizations/{org_id}/webhooks - POST
/organizations/{org_id}/webhooks - PATCH
/organizations/{org_id}/webhooks/{target_id} - DELETE
/organizations/{org_id}/webhooks/{target_id} - POST
/organizations/{org_id}/webhooks/{target_id}/rotate-secretNeues Signatur-Secret setzen (nur kind=webhook). Antwort trägt das volle Secret genau EINMAL; alte Signaturen sind ab sofort ungültig.
- POST
/organizations/{org_id}/webhooks/{target_id}/testTest-Zustellung (synchron, Timeout 10s): sendet ein `incident.test`-Ereignis an GENAU dieses Ziel und hält das Ergebnis als letzten Versuch fest.