Service Status
Service-Status
Öffentlicher, unauthentifizierter Endpunkt mit Uptimeifys eigener Plattform-Verfügbarkeit — Check- und Alert-Delivery-Quoten, Komponenten-Status und die hash-verketteten eingefrorenen Monatswerte.
GET /api/service-status
Keine Authentifizierung nötig. Liefert keine Kundendaten — nur die eigenen Delivery-Kennzahlen der Plattform, den Status der veröffentlichten Komponenten und die eingefrorenen Monatswerte dahinter.
Beispiel (cURL)
curl -X GET "https://uptimeify.io/api/service-status" \
-H "Accept: application/json"Antwort (Response)
{
"checkDelivery": {
"pct": 99.97,
"coveragePct": 99.94,
"insufficientData": false,
"windowDays": 90
},
"alertDelivery": {
"pct": 97.31,
"sampleSize": 2454,
"endpointFailures": 140,
"latencyP90Ms": 1727,
"latencySampleSize": 812,
"insufficientData": false,
"latencyInsufficientData": false
},
"components": [
{ "key": "de-fra", "displayName": "Frankfurt (DE)", "state": "operational", "coveragePct": 99.94 },
{ "key": "alerting", "displayName": "Alert Delivery", "state": "operational", "coveragePct": 100 }
],
"frozenMonths": [
{
"month": "2026-06-01",
"sliKind": "check_delivery",
"scopeKey": "mesh",
"numerator": 4318204,
"denominator": 4319850,
"unknownUnits": 612,
"rowHash": "9f2c1a7e4b8d0f3a6c5e2b1d8a7f4e9c0b3d6a1f8e5c2b9d7a4f1e8c5b2d9a6f"
},
{
"month": "2026-06-01",
"sliKind": "measurement_coverage",
"scopeKey": "mesh",
"numerator": 43176,
"denominator": 43200,
"unknownUnits": 24,
"rowHash": "4d1b8e0cc0a2f7593e6b4c1d8a05f2e7b9c3d6a1f8e5c2b9d7a4f1e8c5b2d9a6"
}
]
}Hinweise:
checkDelivery.pctundalertDelivery.pctsind rollierendewindowDays-Werte (aktuell 90 Tage), auf zwei Nachkommastellen gekappt — nie aufgerundet.unknownUnitssteckt in KEINEM Nenner auf diesem Endpunkt. Jede Quote wird über das gemessen, was die Plattform tatsächlich belegen kann:denominatorist die Erwartung über die erfassten Einheiten,unknownUnitsdie Erwartung über die nie erfassten — eine Lücke im minütlichen Recorder, ein hängengebliebener Rollup. Beides sind getrennte Achsen, weil „wir waren nicht verfügbar" und „wir konnten nicht messen" zwei verschiedene Tatsachen sind: Die zweite in die erste einzurechnen, veröffentlicht einen Ausfall, den es nicht gegeben hat, und macht die Zahl zum Maß für die Zuverlässigkeit des Recorders statt für die des Dienstes.coveragePctist die zweite Hälfte jeder Aussage und wird nie weggelassen. Es ist der Anteil des Fensters, den die Plattform belegen kann,0-100, auf zwei Nachkommastellen gekappt —nullnur dann, wenn im Fenster noch gar nichts geschuldet war.checkDelivery.coveragePctgilt für das gesamte Prüfnetz,components[].coveragePctje Komponente; für eine nie gemessene Komponente ist esnull. Die konservative Lesart — der Anteil des Fensters, der positiv als ausgeliefert bestätigt ist — ist das Produkt beider Werte:pct x coveragePct / 100.- Aus jeder
frozenMonths-Zeile lässt sich die Abdeckung selbst nachrechnen:denominator / (denominator + unknownUnits). Zeilen mit"sliKind": "measurement_coverage"geben sie direkt in Minuten an:numeratorsind die erfassten,denominatordie geschuldeten Minuten. Diese Art existiert, weil an einem Tag, an dem der Recorder gar nicht lief,check_deliverybei0/0steht — es gibt keine beobachtete Rate, mit der sich eine fehlende Check-Minute bewerten ließe — und nur eine minutenbasierte Zeile so einen Tag sichtbar hält. - Alarm-Zustellung sind zwei Zahlen — und keine davon ist eine 60-Sekunden-Schwelle.
alertDelivery.pctist der Anteil der versuchten Zustellungen, die am Ende angekommen sind;alertDelivery.latencyP90Msist die p90-Zeit von der Eröffnung des Incidents bis zur ersten Benachrichtigung, die unsere Systeme tatsächlich verlassen hat, in Millisekunden. Die erste Zahl beantwortet „ist sie angekommen", die zweite „wie schnell" — eine einzelne Zahl kann beides nicht leisten. Der zuvor veröffentlichte Wert (Anteil der Zustellungen innerhalb von 60 Sekunden) leistete keines von beidem: Bei einem Median unter einer Sekunde konnte er eine schnelle Zustellung nicht von einer unterscheiden, die fast eine Minute brauchte — und er bewertete eine Zustellung, die nie ankam, genauso wie eine langsame. alertDelivery.pctzählt jede Zustellung einmal, nicht jeden Versuch. Die Einheit ist ein Paar aus(Incident, Benachrichtigungskanal); das Paar gilt als zugestellt, wenn irgendein Versuch dafür erfolgreich war. Eine Benachrichtigung, die zweimal scheitert und im dritten Anlauf durchgeht, ist damit ein Erfolg — würden wir Versuche zählen, fiele die Zahl umso schlechter aus, je härter unsere Wiederholungslogik arbeitet.alertDelivery.sampleSizeist die Anzahl dieser Paare. Trägt eine Zustellung keine Kanal-ID (E-Mail an die hinterlegte Adresse, die Incident-Management-Brücke), tritt der Transportweg an ihre Stelle.alertDelivery.pctzählt die Fehler, die wir zu verantworten haben —endpointFailureszählt die anderen. Eine Zustellung, die nie ankam, weil das Ziel nicht mehr existierte (404,410), weil die uns anvertrauten Zugangsdaten zurückgezogen wurden (401,403), weil dein Dienst uns gedrosselt hat (429), weil er mit5xxantwortete oder weil sein Host überhaupt nicht erreichbar war (DNS-Fehler, abgewiesene Verbindung, TLS-Fehler, Zeitüberschreitung), ist ein Fehler dieses Ziels und keiner unserer Alarmierung. Solche Zustellungen verlassenpct— sie stehen weder im Zähler noch insampleSize— und werden stattdessen inalertDelivery.endpointFailuresgezählt. Fehler auf unserer Seite bleiben drin und gehen zulasten der Quote: eine von einem Chat-Dienst als fehlerhaft abgewiesene Nachricht, ein Kanaltyp, für den unser Versand keine Behandlung hatte, ein von unserem eigenen Relay oder unserer Sendebremse übersprungener Versand — und jeder Fehler, den wir der Gegenseite nicht zweifelsfrei zuordnen können. Im Zweifel entscheiden wir gegen uns: Was sich nicht zuordnen lässt, zählt als unser Fehler. Die umgekehrte Regel würde die Zahl jedes Mal verbessern, wenn wir auf eine neue Art scheitern.endpointFailureswird nie unterdrückt und nie weggelassen. Es ist eine Anzahl, also bei jeder Stichprobengröße exakt richtig, und hat deshalb keine Veröffentlichungsschwelle: Der Wert steht auch dann da, wennpctnullist. Zusammen mit den Fehlern innerhalb vonpctergibt er alle Alarme, die im Zeitfenster nicht angekommen sind — aus welchem Grund auch immer. Der Ausschluss oben ändert, in welcher Zahl ein Fehler auftaucht, nie ob er auftaucht.- Was die beiden Alarm-Zahlen ausschließen — und was nicht. Außen vor bleiben Incidents, für die nie eine Benachrichtigung geschuldet war: eine durch ein Wartungsfenster unterdrückte Alarmierung, ein Monitor ohne konfigurierten Benachrichtigungskanal, ein durch die Flapping-Dämpfung zurückgehaltener Incident oder einer, der sich erledigt hat, bevor eine Benachrichtigung fällig wurde. Eine Zustellung, bei der jeder Versuch auf unserer Seite fehlgeschlagen ist, steht in
alertDelivery.pctund geht zulasten der Quote — ein fehlgeschlagener Versand ist ein Zustellfehler, kein Ausschlussgrund. Eine, die an deinem Ziel gescheitert ist, steht nach der Regel oben stattdessen inendpointFailures. Im p90 fehlt sie, denn ein Alarm, der nie hinausging, hat keine Versandzeit; ihm eine zuzuschreiben, würde einen Zustellfehler in einer Laufzeit verstecken.alertDelivery.latencySampleSizeist deshalb die Anzahl der erfolgreich benachrichtigten Incidents und stets kleiner alssampleSize. - Keine Alarm-Zahl reicht hinter den Beginn der Messung zurück.
alertDelivery.pct,endpointFailuresundlatencyP90Mssind nach unten auf den Moment begrenzt, in dem unser Recorder den ersten Messwert geschrieben hat — genau den Zeitpunkt, den die öffentliche Statusseite als „Messung seit" ausweist. Unser Benachrichtigungsprotokoll enthält echte Historie von lange davor; sie zählt nicht mit, denn eine Zahl, die hinter das daneben gedruckte Startdatum zurückreicht, wäre eine andere Aussage als die, die dieses Datum trägt. Die Datensätze bleiben in der Datenbank — sie liegen nur außerhalb des Fensters. - Versuche zählen bis 24 Stunden nach dem Tag des Incidents. Eine Zustellung, die einen vollen Tag nach Eröffnung des Incidents noch nicht durch ist, ist eine fehlgeschlagene Zustellung — unabhängig davon, was danach passiert. Über echte 90 Tage gemessen verschiebt diese Grenze 2 von 2590 Zustell-Paaren, und zwar zu unseren Lasten.
- Eine Laufzeit ist ein Perzentil und wird deshalb weder summiert noch eingefroren. Der veröffentlichte p90 wird über die Verteilung des Fensters selbst berechnet, nicht aus den Tageswerten dahinter abgeleitet: Die Summe täglicher Perzentile ist kein Perzentil, ihr gewichteter Mittelwert ebenso wenig. Aus demselben Grund taucht in
frozenMonthskeine Zeilealert_dispatch_latency_p90auf — ein Monatswert, der sich nicht durch Summieren von Tagen bilden lässt, fehlt besser, als dass er erfunden wird. Die Tageswerte stehen in unserer Belegtabelle, jeder mit seiner eigenen Stichprobengröße. - Eine Quote erscheint nie ohne ihre Stichprobengröße — und gar nicht, wenn diese zu klein ist.
alertDelivery.pctundalertDelivery.latencyP90Mssindnull, und das jeweilige FlaginsufficientDatabzw.latencyInsufficientDatasteht auftrue, solange weniger als 20 Ereignisse dahinterstehen.checkDelivery.pctistnullmitcheckDelivery.insufficientDataauftrue, bis unsere Messreihe 24 Stunden abdeckt: Was eine Minute schuldet, ist eine Rate pro Minute, was sie liefert, eine ganze Prüfung — auf kurzer Strecke liegt der Wert dadurch knapp unter 100 %, ohne dass irgendetwas nicht stimmt. Stichprobengröße undcoveragePctveröffentlichen wir in jedem dieser Fälle weiter; sie sind die Begründung für die fehlende Zahl. Einnullbei Flagfalsebedeutet etwas anderes: Es wurde noch überhaupt nichts gemessen. components[].stateist einer vonoperational,degraded,down,unknown.unknownheißt: Für diese Komponente liegt kein aktueller Sample vor — der Endpunkt füllt diese Lücke nie mit dem zuletzt bekannten Status auf. Eine Komponente aufunknownist keine ausgefallene Komponente; wie lange das im Fenster schon gilt, zeigt ihrcoveragePct.frozenMonthslistet jeden append-only Monatswert ausplatform_sli_month, identifiziert übermonth+sliKind+scopeKey.sliKindist einer voncheck_delivery,component_availability,alert_delivery,alert_endpoint_failureodermeasurement_coverage— das Laufzeit-Perzentil gehört bewusst nicht dazu (siehe oben). DerrowHashjeder Zeile ist an die vorherige Zeile mit demselbensliKind/scopeKeyverkettet, und ein Datenbank-Trigger weist jedes UPDATE oder DELETE an der Tabelle zurück. Wenn du eine frühere Kopie dieser Antwort gespeichert hast: EinrowHash, der für ein bestimmtesmonth/sliKind/scopeKeynicht mehr übereinstimmt, bedeutet, dass die Werte dieses Monats nach dem Einfrieren nachträglich verändert wurden.
Häufige Fehler
500 Unexpected server errorbei einem internen Fehler