REST-API

Lesen und schreiben Sie Ihre Monitore, lesen und aktualisieren Sie Vorfälle, und laden Sie Source Maps hoch. Alles hier nutzt dieselben Berechtigungsprüfungen und denselben Mandantenfilter wie das Dashboard — es gibt keine getrennte Umsetzung auf der API-Seite, die davon abweichen könnte.

In jedem Tarif enthalten, auch im kostenlosen. Es gibt nichts dazuzukaufen und keine Stufe, die es freischaltet.

Basis-URL

https://vitrinaengine.com/api/v1

Maschinenlesbare Beschreibung

/openapi.json ist ein OpenAPI-3.1-Dokument, das jede Route auf dieser Seite abdeckt. Richten Sie einen Client-Generator darauf, oder geben Sie es einem Agenten, der diese API aufrufen soll, ohne sie erklärt zu bekommen.

Es wird aus dem Dienst erzeugt und nicht daneben geschrieben: die Routen stammen aus der Oberfläche, die die API unter GET / selbst veröffentlicht, die Datenstrukturen und ihre Erläuterungen aus denselben .proto-Dateien unter /api/proto, und die Ratenbegrenzungen aus dem Code, der sie durchsetzt. Ein Build schlägt fehl, wenn das eingecheckte Dokument und die API auseinanderlaufen — es beschreibt also, was ausgeliefert wird, und nicht, was zuletzt jemand hineingeschrieben hat.

Es beschreibt die Datenstrukturen. Die Gründe stehen auf dieser Seite — dass eine fremde ID mit 404 antwortet, dass config nie zurückgegeben wird — und die kann kein Generator schreiben.

Für Agenten: MCP

https://vitrinaengine.com/mcp ist ein Model-Context-Protocol-Server. Tragen Sie ihn mit einem API-Schlüssel als Bearer-Token in einen MCP-Client ein, und ein Agent kann Ihre Monitore, Vorfälle, Fehler und Analysen lesen — und Monitore anlegen, ändern und löschen —, ohne dass ihm jemand erklärt, wie diese API funktioniert.

{
  "mcpServers": {
    "vitrina-engine": {
      "type": "http",
      "url": "https://vitrinaengine.com/mcp",
      "headers": { "Authorization": "Bearer vte_your_key_here" }
    }
  }
}

Er liest alles und schreibt drei Dinge. Jede GET-Operation auf dieser Seite ist ein Werkzeug, ebenso POST /monitors, PATCH /monitors/{id} und DELETE /monitors/{id}. Sonst ist nichts Schreibendes erreichbar — kein Arbeitsbereich, kein Mitglied, kein API-Schlüssel, keine Statusseite und nicht Ihr Konto —, denn dafür existiert kein Werkzeug; und die Liste der erlaubten Schreibzugriffe sind drei Zeilen, die jemand bewusst ergänzen muss.

Ein Schlüssel ohne Schreibrecht wird weiterhin abgewiesen. Ein Werkzeugaufruf ist dieselbe Anfrage, die der Schlüssel direkt stellen würde, durch dieselbe Berechtigungsprüfung und denselben Mandantenfilter — ein Agent mit einem Nur-Lese-Schlüssel liest also. Geben Sie ihm einen solchen, sofern er Ihre Überwachung nicht verändern soll, und rechnen Sie damit, dass ein Client vor dem Löschen nachfragt: Mit einem Monitor verschwindet seine Historie, und es gibt kein Zurück. Um einen Monitor stillzulegen, ohne ihn zu verlieren, pausieren Sie ihn per PATCH.

Weil es dieselbe Anfrage ist, sieht sie genau das, was der Schlüssel sieht, schreibt denselben Audit-Eintrag wie das Dashboard und zählt gegen dasselbe Ratenlimit — und zwar doppelt: einmal für den Aufruf und einmal für die Anfrage darin. Ein Schreibzugriff zählt gegen das Schreiblimit.

Eines sollte man wissen, bevor ein Agent einen Monitor bearbeitet: config wird vollständig ersetzt, nicht zusammengeführt. Lesen Sie den Monitor zuerst, ändern Sie das eine Feld und senden Sie das ganze Objekt zurück. Eine unvollständige Konfiguration verwirft stillschweigend die Header und Zugangsdaten, von denen die Prüfung abhängt — und lässt sie weiterlaufen.

Authentifizierung

Erstellen Sie einen Schlüssel unter Einstellungen → API-Schlüssel und senden Sie ihn als Bearer-Token. Der Schlüssel wird einmal angezeigt, bei der Erstellung, und nur als Hash gespeichert — wenn Sie ihn verlieren, erstellen Sie einen neuen.

curl https://vitrinaengine.com/api/v1/summary \
  -H "Authorization: Bearer vte_your_key_here"

Ein Schlüssel gewährt nie mehr, als die Person hatte, die ihn erstellt hat. Er ist an deren Mitgliedschaft gebunden und trägt daher deren Rolle: Ein Schlüssel, den jemand mit einer Nur-Lese-Rolle erstellt hat, kann nicht schreiben, was auch immer Sie senden. Ein Schlüssel kann außerdem auf einen einzelnen Arbeitsbereich beschränkt werden; in dem Fall wird jede Antwort auf diesen Arbeitsbereich gefiltert, und was außerhalb liegt, existiert für diesen Schlüssel nicht.

Jemanden aus Ihrer Organisation zu entfernen widerruft im selben Vorgang die Schlüssel, die diese Person erstellt hat. Einen Zugang zu entziehen muss die Zugangsdaten mitnehmen, sonst behält die Person einen funktionierenden.

Konventionen

Jede erfolgreiche Antwort ist ein JSON-Objekt mit einer Eigenschaft data. Jeder Fehlschlag ist ein JSON-Objekt mit einer Eigenschaft error, die einen für Menschen gedachten Satz enthält.

{ "data": { "id": "8f14e45f-…", "name": "Marketing site" } }

{ "error": "This key cannot create monitors." }

Antworten werden mit Cache-Control: private, no-store gesendet. Es handelt sich um schlüsselbezogene Daten auf einem gemeinsamen Ursprung, und sie dürfen von keinem Proxy aufbewahrt werden.

Protobuf und gzip

Jeder Endpunkt unter /api/v1 spricht auch Protocol Buffers. Mit Accept: application/x-protobuf kommt die Antwort als Protobuf; wer einen Protobuf-Body mit Content-Type: application/x-protobuf sendet, erhält die Antwort im selben Format zurück. Ohne beides bleibt es JSON, genau wie bisher.

curl https://vitrinaengine.com/api/v1/monitors \
  -H "Authorization: Bearer vte_your_key_here" \
  -H "Accept: application/x-protobuf" \
  --compressed -o monitors.pb

Die Nachrichten sind veröffentlicht: /api/proto listet jede Datei auf. Laden Sie sie unter ihren Pfaden herunter und richten Sie protoc -I auf das Verzeichnis. Drei Dinge weichen von dem ab, was man bei Protobuf erwarten würde: Ein Feld, das leer sein kann, ist in JSON null und fehlt in Protobuf; einige Felder, deren Form variiert — etwa das config eines Monitors oder eines Kanals —, sind JSON-Dokumente in einem String; und StringList umschließt eine Liste, die selbst null sein kann.

Gzip funktioniert in beide Richtungen: Accept-Encoding: gzip für Antworten, Content-Encoding: gzip für Anfragen. Weil zwei Aufrufer von derselben URL jetzt unterschiedliche Bytes erhalten können, trägt jede Antwort Vary: Accept, Content-Type.

Statuscodes

CodeBedeutung
200Alles in Ordnung. 201, wenn etwas angelegt wurde.
400Der Body war kein JSON, ein Feld fehlt, oder es wurde nichts verlangt.
401Kein Schlüssel, oder kein gültiger. Sagt bewusst nie, welches von beidem — eine Meldung, die das unterscheidet, ist ein Weg, Schlüssel auszuprobieren.
403Ein gültiger Schlüssel ohne die Berechtigung für diese Aktion. Die Meldung nennt sie.
404Kein solcher Datensatz für Sie. Siehe unten.
413Eine Source Map über der Größenobergrenze.
429Über einer Ratenbegrenzung. Trägt Retry-After. Siehe unten.

Refusal-Codes

Jeder Nicht-2xx-Body trägt neben dem Satz einen code — not_found, limit_reached, rate_limited — und das ist das Feld, auf das Sie verzweigen. Der error-Text ist Prosa für jemanden, der ein Log liest, und kann jederzeit umformuliert werden; der Code ist stabil. Wo der Satz einen Wert nennt, trägt vars diese Werte als Zeichenketten, sodass Sie sie dorthin setzen können, wo Ihre eigene Grammatik sie haben will, statt sie aus dem Englischen zurückzuparsen.

{
  "error": "The Pro plan includes 50 monitors, and you have 50.",
  "code": "limit_reached",
  "vars": { "plan": "pro", "limit": "50", "current": "50", "resource": "monitors" }
}

Daraus stellen unsere eigenen Apps eine Absage in der Sprache des Lesers dar. Behandeln Sie einen Code, den Sie nicht kennen, genauso — fallen Sie auf error zurück — denn Codes kommen ohne Versionssprung hinzu.

Ratenbegrenzungen

Pro Organisation, nicht pro Schlüssel — einen weiteren Schlüssel zu erstellen hebt sie nicht an.

KategorieGrenze
Lesezugriffe (GET)120 pro Minute
Schreibzugriffe (POST, PATCH, DELETE)30 pro Minute
Hochgeladene Source Maps300 pro Stunde

Über der Grenze antwortet 429 mit einem Retry-After-Header, der ganze Sekunden bis zum Zurücksetzen des Fensters angibt. Halten Sie sich daran, statt sofort erneut zu versuchen.

Sie sind dort angesetzt, wo eine normale Integration sie nie erreicht: Eine Wandtafel, die alle zehn Sekunden abfragt, verbraucht sechs der 120 Lesezugriffe. In allen Tarifen sind sie gleich, weil die Sammelendpunkte alles in einer Antwort zurückgeben — ein Konto mit fünfhundert Monitoren braucht nicht mehr Anfragen als eines mit zwanzig. Source Maps haben ein Stundenkontingent, weil sie beim Deployment im Schwung ankommen, wo ein Frontend leicht hundert Fragmente haben kann.

404 statt 403, mit Absicht

Eine Kennung, die einem anderen Kunden gehört, wird mit „Not found.“ beantwortet, nicht mit „Forbidden.“ Ein 403 würde bestätigen, dass der Datensatz existiert, und damit würde der Endpunkt zu einem Mittel, um zu prüfen, ob eine Kennung echt ist. Lesen Sie einen 404 nicht als Beleg dafür, dass nirgends etwas existiert — nur dafür, dass nichts existiert, was dieser Schlüssel sehen darf.

Endpunkte

Alles im Konto, das auf ?q= passt: Monitore, Vorfälle und ihre Nachbetrachtungen, Server, Statusseiten, Arbeitsbereiche, Benachrichtigungskanäle, Wartungsfenster, Fehlerprojekte und Probleme, Analyse-Websites, Mitglieder und Einladungen, API-Schlüssel, Agenten und private Sonden. Eine Anfrage statt einer pro Art.

?type= grenzt auf eine kommagetrennte Liste von Arten ein, ?limit= begrenzt die Treffer je Art auf 1 bis 20 (Standard 5). Jede Art erfordert dieselbe Berechtigung wie ihr eigener Endpunkt; eine Art, die Ihr Schlüssel nicht lesen darf, fehlt genauso, wie eine Art ohne Treffer fehlt. Nichts Versiegeltes, Gehashtes oder Geheimes wird durchsucht oder zurückgegeben.

Parameter und Antworten
NameOrtTyp
limitqueryinteger
qquerystring
typequerystring
AntwortSearchResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /summary

Zählwerte, für eine Wandtafel oder eine Tageszusammenfassung. Erfordert monitor:read.

{
  "data": {
    "total": 42, "up": 39, "degraded": 1, "down": 1,
    "paused": 1, "pending": 0,
    "openIncidents": 2, "suppressedIncidents": 1
  }
}

suppressedIncidents zählt Vorfälle, die zurückgehalten werden, weil sie der Auswirkungsbereich eines anderen sind. Sie sind echt, und sie sind keine eigenständigen Ausfälle.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortGetSummaryResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /setup

Was ein neues Konto noch zu tun hat — dieselben vier Fragen, die die Einrichtungsliste im Dashboard stellt, bei jedem Abruf neu abgeleitet. Erfordert monitor:read.

{
  "data": {
    "hasMonitor": true,
    "hasConfirmedChannel": false,
    "hasStatusPage": false,
    "hasColleague": false,
    "dismissedAt": null
  }
}

hasConfirmedChannel fragt, ob ein Alarm tatsächlich ankommen könnte, und nicht, ob ein Kanal existiert. Das ist einmal übel auseinandergefallen, und eine Liste, die einen Kanal, den wir gar nicht beliefern, als erledigte Alarmierung abhakt, würde denselben Fehler als Beruhigung wiederholen.

hasColleague zählt Mitgliedschaften und nie Einladungen: eine verschickte und nicht angenommene Einladung hat niemanden hinzugefügt.

Nicht in /summary eingebaut, denn jener Endpunkt sind Zählungen nach Status und sonst nichts — eine Wandtafel, die ihn im Sekundentakt abfragt, will keine fünf zusätzlichen Abfragen, nur um einen Hinweis zu zeigen, der an jemanden gerichtet ist, der das Konto vor Monaten eingerichtet hat.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortGetSetupResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

DELETE /setup

Überspringt die Liste. Erfordert org:update, weil das Ausblenden eine organisationsweite Zeile ist und keine persönliche Einstellung — wer danach dazukommt, bekommt sie nicht noch einmal gezeigt.

Sonst ändert sich nichts am Konto, und es wird kein Audit-Eintrag geschrieben: einen Hinweis auszublenden ändert nichts daran, wie das Produkt sich verhält, alarmiert oder abrechnet.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortDismissedResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /monitors

Alle Monitore, die der Schlüssel sehen kann. Erfordert monitor:read. Jeder trägt id, name, kind, status, statusSince, enabled, intervalSeconds, tags, workspace, lastCheckedAt, lastResponseTimeMs, lastMessage, uptime24h, uptime30d und openIncidentId.

?tag=prod,eu schränkt die Liste auf Monitore ein, die jedes genannte Tag tragen — UND, nicht ODER, sodass ein zweites Tag immer weniger Monitore zurückgibt statt mehr. Der Filter im Dashboard liest sich genauso. Tags werden in Kleinbuchstaben gespeichert, und der Wert hier wird vor dem Vergleich ebenso umgewandelt, also findet ?tag=Prod sie. Ein Eintrag, der kein Tag sein kann — leer oder länger als ein Tag sein darf —, wird verworfen und der Rest des Filters gilt weiter, statt den Aufruf abzulehnen: ein Link soll nicht aufhören zu funktionieren, weil eines seiner Tags umbenannt wurde.

config wird nie zurückgegeben. Bei manchen Arten enthält es Anfrage-Header und Zugangsdaten, und ein nur zum Lesen berechtigter Schlüssel soll kein Weg sein, die Geheimnisse zurückzulesen, die jemand in ein Formular getippt hat.

Parameter und Antworten
NameOrtTyp
tagquerystring
AntwortListMonitorsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

POST /monitors

Erfordert monitor:create. Verlangt name, kind, workspaceId und config. Optional: intervalSeconds (Standard 300), confirmations, dependsOn.

curl -X POST https://vitrinaengine.com/api/v1/monitors \
  -H "Authorization: Bearer vte_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Marketing site",
    "kind": "http",
    "workspaceId": "…",
    "intervalSeconds": 60,
    "config": {
      "url": "https://example.com",
      "assertions": [{ "type": "status_code", "operator": "lt", "value": "400" }]
    }
  }'

Antwortet 201 mit der neuen Kennung. Das Intervall wird auf die Untergrenze Ihres Tarifs angehoben statt abgelehnt: 10 Sekunden in einem Tarif mit einer Untergrenze von 60 ergeben 60 — lesen Sie es zurück, wenn es darauf ankommt.

Parameter und Antworten
NameOrtTyp
namebodystring
kindbodystring
workspaceIdbodystring
configbodystring
intervalSecondsbodyinteger
confirmationsbodyinteger
dependsOnbodystring[]
probeIdbodystring
tagsbodystring[]
AntwortCreatedResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /monitors/{id}

Ein Monitor, mit allem, was die Liste liefert, plus paused. Erfordert monitor:read.

Für mail_posture, tls_audit und snmp kommt zusätzlich lastCheckDetail hinzu, das Ergebnis der letzten Prüfung selbst: die Befunde hinter dem Status, jeweils mit stabilem code und einer severity, dazu eine TLS-Note oder die SNMP-Messwerte. Bis zur ersten Prüfung ist es null, bei allen anderen Arten fehlt es.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
AntwortGetMonitorResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

PATCH /monitors/{id}

Senden Sie nur, was Sie ändern wollen: name, intervalSeconds, confirmations, enabled, config oder paused.

paused wird gegen monitor:pause geprüft und alles Übrige gegen monitor:update, jeweils getrennt — ein Schlüssel, der pausieren, aber nicht bearbeiten darf, kann trotzdem pausieren. Eine leere Änderung zu senden ergibt einen 400.

Der Monitor wird neu gelesen und zurückgegeben, statt die Eingabe zurückzuspiegeln — was Sie sehen, ist also das, was gespeichert wurde.

# Silence a monitor for the length of a deploy.
curl -X PATCH https://vitrinaengine.com/api/v1/monitors/$ID \
  -H "Authorization: Bearer vte_…" \
  -H "Content-Type: application/json" \
  -d '{"paused": true}'
Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
namebodystring
intervalSecondsbodyinteger
confirmationsbodyinteger
enabledbodyboolean
pausedbodyboolean
configbodystring
tagsbodyStringList
AntwortUpdatedMonitorResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /monitors/{id}

Erfordert monitor:delete. Antwortet { "data": { "id": "…", "deleted": true } }.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /hosts · POST /hosts

Server sind die zweite Art, Monitore zu gruppieren: der Arbeitsbereich sagt, wem ein Monitor gehört, der Server sagt, worauf er läuft. Völlig optional — ein Konto, das nie einen anlegt, verliert nichts, und die meisten Monitore nennen gar keinen Server.

Jeder Server trägt status, pinned und spanning. status stammt ausschließlich von Monitoren, die nur auf diesem Server laufen. Ein Monitor über mehrere Maschinen zählt zu spanning und färbt keine davon: Fällt ein lastverteilter Endpunkt aus, sagt das, dass der Dienst kaputt ist, nicht welche Maschine ihn kaputt gemacht hat. Ein Server ohne eigene Monitore antwortet "status": null statt up.

POST braucht monitor:create und einen name. Die optionalen Felder provider, address und notes gehören Ihnen — das Produkt wertet sie nicht aus. Ein Name, der auf einen vorhandenen fällt — Groß- und Kleinschreibung und ein abschließender Punkt werden ignoriert — antwortet 409.

Parameter und Antworten

GET /hosts

Keine deklarierten Parameter oder Body-Felder.

AntwortListHostsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

POST /hosts

NameOrtTyp
namebodystring
providerbodystring
addressbodystring
notesbodystring
AntwortCreatedResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /hosts/{id} · PATCH /hosts/{id} · DELETE /hosts/{id}

Das Detail trägt den Server und seine Monitore, jeder mit pinned markiert und, wenn er das nicht ist, mit alsoOn: den anderen Maschinen, von denen er antwortet — genau das liest man, bevor man eine neu startet. DELETE nimmt den Server außer Dienst, und jeder Monitor darauf läuft weiter: ein Server hat weder einen eigenen Zeitplan noch eine eigene Historie.

Parameter und Antworten

GET /hosts/{id}

NameOrtTyp
id Pflichtpathstring
AntwortGetHostResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

PATCH /hosts/{id}

NameOrtTyp
id Pflichtpathstring
namebodystring
providerbodystring
addressbodystring
notesbodystring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /hosts/{id}

NameOrtTyp
id Pflichtpathstring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

POST /hosts/{id}/monitors · DELETE /hosts/{id}/monitors

Ein Monitor auf oder von einem Server, per monitorId im Body oder ?monitorId=. Bewusst keine ganze Liste: auf einem Agenturkonto trägt ein Server Monitore aus mehreren Arbeitsbereichen, und wer „die Liste“ ersetzte, ersetzte Zeilen, die ihm nie gezeigt wurden. Beide Richtungen sind idempotent.

Parameter und Antworten

POST /hosts/{id}/monitors

NameOrtTyp
id Pflichtpathstring
monitorIdbodystring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /hosts/{id}/monitors

NameOrtTyp
id Pflichtpathstring
monitorIdquerystring
monitorIdbodystring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /monitors/{id}/hosts · PUT /monitors/{id}/hosts

Die andere Seite derselben Beziehung, und diese ist eine ganze Liste: Diese Verknüpfungen gehören einem einzigen Monitor, am anderen Ende ist also nichts, was ein anderer Arbeitsbereich sehen könnte. Senden Sie hostIds; ein leeres Array ist eine echte Anfrage und heißt, dass der Monitor auf keinem bestimmten Server läuft. Fremde Ids werden verworfen statt abgelehnt. Jede Monitor-Antwort trägt außerdem hosts, leer wenn es keine gibt.

Parameter und Antworten

GET /monitors/{id}/hosts

NameOrtTyp
id Pflichtpathstring
AntwortListMonitorHostsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

PUT /monitors/{id}/hosts

NameOrtTyp
id Pflichtpathstring
hostIdsbodystring[]
AntwortListMonitorHostsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /incidents

Erfordert incident:read. Nimmt ?status= — eines von open, acknowledged, resolved oder suppressed — und ?open=true für die drei, die nicht behoben sind. Ein unbekannter Status wird ignoriert statt abgelehnt, genauso wie ?limit= (Standard 50) bei 200 gedeckelt und nicht zurückgewiesen wird.

Jeder trägt id, monitorId, monitorName, title, cause, status, severity, startedAt, resolvedAt, durationSeconds, acknowledgedAt und rootIncidentId.

rootIncidentId ist das Feld, auf das es ankommt, wenn Sie einen Alarmstrom bauen. Ist es gesetzt, ist dieser Vorfall der Auswirkungsbereich eines anderen — der Datenbankhost ist ausgefallen, und dies ist einer der zwölf Dienste dahinter. Überspringen Sie sie, und Sie bekommen einen Alarm statt dreizehn.

Parameter und Antworten
NameOrtTyp
limitqueryinteger
openqueryboolean
statusquerystring
AntwortListIncidentsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /incidents/{id}

Ein Vorfall. Erfordert incident:read. Dieselben Felder wie in der Liste, plus workspaceId.

Er gibt den Verlauf des Vorfalls nicht zurück — die Kommentare und Statusänderungen, die im Dashboard zu sehen sind, liegen nicht auf diesem Endpunkt. Wenn Sie sie brauchen, sagen Sie es, dann lassen sie sich ergänzen; sie hier zu dokumentieren, solange es sie nicht gibt, wäre schlimmer als die Lücke.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
AntwortGetIncidentResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

PATCH /incidents/{id}

Senden Sie einen status von "acknowledged" oder "resolved", oder einen comment, oder beides. Jedes wird gegen seine eigene Berechtigung geprüft: incident:acknowledge, incident:resolve, incident:comment. Einem Kommentar "publish": true hinzuzufügen stellt ihn auf die Statusseite und erfordert zusätzlich status_page:manage.

# A runbook that fixed the thing itself can close its own incident.
curl -X PATCH https://vitrinaengine.com/api/v1/incidents/$ID \
  -H "Authorization: Bearer vte_…" \
  -H "Content-Type: application/json" \
  -d '{"status": "resolved", "comment": "Restarted by runbook.", "publish": true}'
Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
statusbodystring
commentbodystring
publishbodyboolean
AntwortGetIncidentResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

PUT /incidents/{id}/postmortem

Schreibt oder ersetzt die Nachbetrachtung des Vorfalls. Erfordert incident:resolve, und der Vorfall muss bereits behoben sein — sonst 409 mit dem Code incident_not_resolved. Senden Sie body als Markdown, nach dem Trimmen 1 bis 50.000 Zeichen (postmortem_required, postmortem_too_long). Es gibt eine pro Vorfall, jeder Aufruf ersetzt also die vorherige. Die Antwort ist der Vorfall, so wie GET /incidents/{id} ihn liefert.

GET /incidents/{id} enthält sie als postmortem: { body, authorName, updatedAt } oder null, und die Liste enthält hasPostmortem. Stellen Sie body als Markdown dar und niemals als HTML: Es ist Text, den ein Mensch getippt hat. Eine Nachbetrachtung ist intern und erscheint nie auf einer Statusseite.

curl -X PUT https://vitrinaengine.com/api/v1/incidents/$ID/postmortem \
  -H "Authorization: Bearer vte_…" \
  -H "Content-Type: application/json" \
  -d '{"body": "## What happened\n\nThe connection pool ran dry after a deploy."}'
Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
bodybodystring
AntwortGetIncidentResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /probes

Die eigenen privaten Sonden Ihrer Organisation: id, name, lastSeenAt, version, hostname, monitorCount, revoked und createdAt. Erfordert agent:read. Genau das bietet die Sondenauswahl eines Monitors an.

Es gibt kein Regionsfeld, und es wird keins geben. Sie wählen eine Sonde nach Namen; wo eine Prüfung dahinter läuft, entscheiden und ändern wir. Widerrufene Sonden erscheinen mit revoked: true und erhalten keine Arbeit mehr, bieten Sie sie also nicht an.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortListProbesResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /monitors/{id}/push-url

Die Ping-URL eines Heartbeat-Monitors, erneut angezeigt. Erfordert monitor:read. url ist null für eine Art, die nicht angepingt wird, und für ein Token, das sich nicht mehr entschlüsseln lässt — der Monitor arbeitet weiter, und ein im Dashboard erneuertes Token liefert eine URL, die angezeigt werden kann.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
AntwortGetPushUrlResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /organizations · PUT /organizations/active

Die Organisationen, denen die angemeldete Person angehört, jeweils mit ihrer dortigen role und active bei der aktuell genutzten, sowie der Wechsel zwischen ihnen. Senden Sie organizationId; die Antwort ist die nun genutzte Mitgliedschaft.

Nur mit angemeldeter Sitzung. Ein Schlüssel gehört zu genau einer Mitgliedschaft und erhält 403 mit session_required. Der Wechsel betrifft jede Sitzung dieser Person, auch das Dashboard, und eine Organisation, der sie nicht angehört, ergibt 404.

Parameter und Antworten

GET /organizations

Keine deklarierten Parameter oder Body-Felder.

AntwortListOrganizationsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

PUT /organizations/active

NameOrtTyp
organizationIdbodystring
AntwortActiveOrganizationResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

POST /sms/enrolment · POST /sms/enrolment/confirm

Registrieren Sie Ihre eigene Mobilnummer für SMS-Warnungen: Senden Sie phone (optional name), und wir schicken einen sechsstelligen Code dorthin; senden Sie diesen code an die zweite Route, um zu bestätigen. Erfordert notification_channel:manage und eine angemeldete Sitzung — eine Nummer fügt die Person hinzu, die das Telefon hält, nie ein Schlüssel.

Die Nummer wird unbestätigt gespeichert und erhält nichts, bis der Code zurückkommt. Eine erneute Registrierung ersetzt Ihre bisherige Nummer. Ablehnungen: sms_not_included (402, der Tarif enthält kein SMS-Kontingent), not_a_phone_number, sms_country_unsupported, sms_route_not_open, verification_code_not_sent (502; erneut aufrufen für einen neuen Code), verification_code_malformed und verification_code_incorrect. Ein erfolgreicher Start liefert country und caveat — sender-replaced, registration-pending, unverified oder null —, was man zeigen sollte, bevor sich jemand auf die Nummer verlässt.

Parameter und Antworten

POST /sms/enrolment

NameOrtTyp
phonebodystring
namebodystring
AntwortSmsEnrolmentResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

POST /sms/enrolment/confirm

NameOrtTyp
codebodystring
AntwortSmsConfirmedResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

POST /channels/{id}/confirmation

Sendet die Bestätigungsnachricht eines E-Mail-Kanals erneut. Erfordert notification_channel:manage. Jeder Aufruf erzeugt einen neuen Link, der vorherige funktioniert dann nicht mehr. sent: false heißt, es gab nichts zu senden — die Adresse hat bereits bestätigt —, und eine bestätigte Adresse wird auf diesem Weg nie erneut angeschrieben. Lehnt der Mailanbieter den Versand ab, lautet die Antwort 502 mit confirmation_not_sent.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
AntwortChannelConfirmationResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

PATCH /workspaces/{id}

Benennt einen Arbeitsbereich um. Erfordert workspace:update. name ist Pflicht (1 bis 80 Zeichen), clientReference optional — null löscht sie. Der Slug ändert sich nie, denn er steht in Statusseiten-URLs. Die Antwort ist der Arbeitsbereich in seinem neuen Zustand.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
namebodystring
clientReferencebodyrequests.NullableString
AntwortUpdatedWorkspaceResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

POST /sourcemaps

Laden Sie eine Source Map hoch, damit minifizierte Aufruflisten aufgelöst werden. Erfordert monitor:create. Verlangt projectRef (eine Zahl) und filename sowie die Map selbst, entweder als map (JSON) oder als mapGzipBase64. Optional: debugId und release.

Senden Sie eine debug id oder ein release. Eine Map ohne beides lässt sich keiner Aufrufliste zuordnen und liegt dann nutzlos herum. Zugeordnet wird zuerst über debugId, dann über release und Dateiname.

Maps werden beim Lesen eines Problems aufgelöst, nicht beim Hochladen; eine Map, die nach den Fehlern ankommt, hilft also trotzdem — und das ist die übliche Reihenfolge.

Parameter und Antworten
NameOrtTyp
projectRefbodyinteger
filenamebodystring
debugIdbodystring
releasebodystring
mapbodystring
mapGzipBase64bodystring
AntwortUploadedSourceMapResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung300 pro Stunde

POST /symbols

Dasselbe für eine native App: Laden Sie ein iOS-.dSYM oder ein Android-R8-mapping.txt hoch, damit Absturz-Aufruflisten aufgelöst werden. Erfordert monitor:create. Zwanzig Uploads pro Stunde, und zwanzig Builds werden je Projekt aufbewahrt.

Anders als bei /sourcemaps ist der Body die gzip-komprimierte Datei selbst, und die Metadaten stehen in Headern: X-Vitrina-Project-Ref, X-Vitrina-Platform (ios oder android), X-Vitrina-Symbol-Name und X-Vitrina-Release. Ein dSYM ist zig Megabyte groß, und Base64 in einem JSON-Feld kostet ein weiteres Drittel an Übertragung.

Die beiden Plattformen werden unterschiedlich zugeordnet. Ein iOS-Frame nennt die Mach-O-UUID des Images, zu dem er gehört; ein iOS-Upload muss deshalb X-Vitrina-Debug-Ids tragen und wird exakt darüber zugeordnet. R8 gibt keine solche Kennung aus, daher wird ein Android-Mapping allein über das Release zugeordnet — und das muss genau das sein, was die App meldet: <applicationId>@<versionName>+<versionCode>. Eine Ziffer daneben, und Frames werden auf Zeilen aufgelöst, die plausibel aussehen und falsch sind.

Denselben Build erneut hochzuladen ersetzt dessen Symbole, statt fehlzuschlagen; ein wiederholter Release-Job ist also kein Fehler. Wie bei Source Maps geschieht die Auflösung beim Lesen eines Problems.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortUploadedSymbolsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung20 pro Stunde

GET /errors/projects

Die Fehler-Tracking-Projekte dieses Kontos. Erfordert monitor:read. Jedes trägt ref — die Zahl im DSN — sowie publicKey, unresolved und eventsLast24h. Nur lesend: Ein Projekt wird mit einem Schlüssel angelegt, der ohnehin noch in die Konfiguration einer Anwendung eingefügt werden muss, es gibt hier also nichts, was ein Endpunkt zu Ende bringen würde.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortListErrorProjectsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /errors/issues

Gruppierte Fehler, neueste Aktivität zuerst. Erfordert monitor:read. Ein Problem ist ein Fingerabdruck und kein Ereignis, tausend Vorkommen eines Wurfs sind also eine einzige Zeile mit timesSeen auf tausend. ?status= steht standardmäßig auf unresolved und nimmt außerdem resolved, ignored oder all; ?project= filtert nach Projektkennung, ?q= durchsucht Typ, Wert und Verursacher, und ?limit= ist bei 200 gedeckelt. spark sind vierundzwanzig Stundenwerte, ältester zuerst.

Parameter und Antworten
NameOrtTyp
limitqueryinteger
projectquerystring
qquerystring
statusquerystring
AntwortListIssuesResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /errors/issues/{id}

Ein Problem mit seiner Aufrufliste. Erfordert monitor:read. exceptions ist die Kette des SDK selbst, der geworfene Fehler zuletzt und seine Ursachen davor, und ihre Frames werden gegen jede von Ihnen hochgeladene Source Map aufgelöst — dieselbe Auflösung wie im Dashboard, damit ein Skript und die Person, mit der Sie sprechen, nie auf unterschiedliche Aufruflisten schauen. Lässt sich eine Map nicht anwenden, fällt die Antwort auf die ursprünglichen Frames zurück, statt fehlzuschlagen.

lastEvent trägt mit Absicht zwei Zeitstempel. occurredAt ist das, was das SDK gemeldet hat, und receivedAt, wann die Aufnahme es geschrieben hat; ein Gerät, das offline war, oder eine Warteschlange, die sich gestaut hat, ist genau der Abstand dazwischen.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
AntwortGetIssueResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

PATCH /errors/issues/{id}

Beheben, ignorieren oder wieder öffnen: { "status": "resolved" }. Erfordert monitor:update. ignoreHours darf ignored begleiten, um es später wieder aufzuheben, und ist bei 90 Tagen gedeckelt.

Beim Beheben wird festgehalten, in welchem Release es behoben wurde, damit ein Nachzügler aus einem älteren Deployment das Problem nicht wieder öffnet. Hat das SDK kein Release gesendet, gibt es nichts zu vergleichen, und jedes spätere Ereignis öffnet es wieder — ohne die Möglichkeit, einen Nachzügler von einem Rückfall zu unterscheiden, ist die sichere Annahme, dass der Fehler zurück ist.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
statusbodystring
ignoreHoursbodyinteger
AntwortIssueStatusResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /analytics

Die Websites, die dieses Konto misst. Erfordert monitor:read. Trägt publicId — den Wert, der in das Script-Tag gehört und der von vornherein öffentlich ist — sowie viewsLast24h und trafficAlerting, das wahr ist, solange der Verkehr einer Website unter dem liegt, was diese Stunde üblicherweise sieht.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortListAnalyticsSitesResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /analytics/{id}

Die Zahlen einer Website, für eine Tabelle oder einen Bericht. Erfordert monitor:read. ?days= steht standardmäßig auf 7 und ist bei 365 gedeckelt. ?dimensions= nimmt eine kommagetrennte Liste aus path, referrer, country, browser, os, device, utm_source, utm_medium, utm_campaign und event; eine unbekannte ergibt einen 400 und keine leere Antwort, denn ein Tippfehler, der nichts zurückgibt, liest sich wie „kein Verkehr“.

Die Besucherzahl heißt dailyUniqueVisitors, und genau das ist sie. Sie ist die Summe der täglich eindeutigen Besucher und kann nichts anderes sein: Das Geheimnis hinter einem Besucher-Hash wird am Ende seines UTC-Tages vernichtet, wer also an zwei Tagen kam, zählt zweimal, und es gibt keinen Schlüssel, der beides zusammenführen würde. Das ist der Datenschutzentwurf bei der Arbeit und keine Näherung — aber ein Feld namens visitors neben einem Zeitraum von 30 Tagen würde dazu einladen, eine Zahl zu berichten, die etwas anderes bedeutet.

curl "https://vitrinaengine.com/api/v1/analytics/$ID?days=30&dimensions=path,referrer" \
  -H "Authorization: Bearer vte_…"
Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
daysqueryinteger
AntwortGetAnalyticsSiteResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /billing

Der Tarif, und wo er abgerechnet wird. Erfordert billing:read. Trägt plan, status, cadence, currentPeriodEnd, cancelAt, addOnPacks und die letzten zwölf Belege.

source ist paddle, apple, manual oder none. Das ist wichtig: Ein in der iOS-App gekauftes Abonnement zu ändern ist Apples Sache, und Tarif, Karte und Kündigung liegen allesamt in den App-Store- Einstellungen der Kundin oder des Kunden und nicht hier. canCheckoutOnWeb und canPurchaseInApp sagen, welche Angebote gefahrlos gezeigt werden können, damit ein Client diese Regel nicht selbst herleiten und in der Richtung falsch machen muss, die jemandem zweimal etwas berechnet.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortGetBillingResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /monitors/{id}/history

Tägliche Verfügbarkeit für einen Monitor. Erfordert monitor:read. Nimmt days, bis zur Aufbewahrungsdauer Ihres Tarifs.

Berechnet aus täglichen Rollups statt aus einzelnen Prüfergebnissen; deshalb antwortet der Endpunkt auch für Zeiträume weiter, deren Rohergebnisse die Aufbewahrung bereits gelöscht hat.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
daysqueryinteger
AntwortGetMonitorHistoryResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /monitors/{id}/graph · GET /monitors/graphs

Die letzten Stunden eines Monitors, Stunde für Stunde, oder aller Monitore, die dieser Schlüssel sieht, in einer Antwort — das, was das Dashboard in einer Monitorzeile und auf der Monitorseite zeichnet. Erfordert monitor:read. Nimmt hours, standardmäßig 24 und höchstens 168.

Ein uptime-Diagramm trägt den Anteil erfolgreicher Prüfungen je Stunde, null für eine Stunde ohne Prüfung; ein value-Diagramm trägt für die quantitativen Arten seine Messwerte als Reihen mit Einheit. Jede Stunde des Fensters ist enthalten, ob etwas aufgezeichnet wurde oder nicht, damit eine Lücke als Lücke sichtbar bleibt. Messwerte kommen so, wie sie gemessen wurden: Eine raw-Reihe hat keine bekannte Skala — zeichnen Sie sie gegen ihren eigenen Höchstwert und geben Sie diesen Anteil nie als Messwert aus.

Parameter und Antworten

GET /monitors/{id}/graph

NameOrtTyp
id Pflichtpathstring
hoursqueryinteger
AntwortGetMonitorGraphResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /monitors/graphs

NameOrtTyp
hoursqueryinteger
AntwortListMonitorGraphsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /monitors/{id}/channels · PUT /monitors/{id}/channels

Welche Kanäle dieser Monitor alarmiert, und das Setzen ebendieser. Lesen erfordert notification_channel:read; Schreiben erfordert monitor:update.

PUT ersetzt den ganzen Satz — senden Sie jede Kanalkennung, die Sie haben wollen, nicht die, die Sie hinzufügen. Ein leeres Array heißt, dass der Monitor niemanden alarmiert; das kann man wollen, und es aus Versehen zu tun ist schlecht.

Parameter und Antworten

GET /monitors/{id}/channels

NameOrtTyp
id Pflichtpathstring
AntwortGetMonitorChannelsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

PUT /monitors/{id}/channels

NameOrtTyp
id Pflichtpathstring
channelIdsbodyStringList
AntwortGetMonitorChannelsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /incidents/{id}/events

Der Verlauf eines Vorfalls: Statuswechsel, Bestätigungen, Kommentare, Eskalationsschritte. Erfordert incident:read. Das ist der Verlauf, den GET /incidents/{id} nicht enthält.

Parameter und Antworten
NameOrtTyp
id Pflichtpathstring
AntwortListIncidentEventsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /channels · POST /channels

Lesen erfordert notification_channel:read; Anlegen erfordert notification_channel:manage. Jeder trägt id, kind, name, target und workspaceId.

secret wird nur beim Anlegen eines Kanals zurückgegeben und nie wieder. Es ist der Signaturschlüssel für einen Webhook; ihn irgendwo abzulegen, wo man ihn zurücklesen kann, machte einen nur zum Lesen berechtigten Schlüssel zu einem Weg, signierte Anfragen zu fälschen.

Sie können die Arten anlegen, die eine Person auch im Dashboard anlegen kann: email, webhook, telegram, slack, teams, discord, pagerduty und jsm. SMS, WhatsApp, Satellit und Push werden von der Person eingerichtet, die sie empfängt, und lassen sich nicht über die API anlegen — genau das macht sie zu einer Einwilligung und nicht zu einem Feld, das jemand ausgefüllt hat.

Ein E-Mail-Kanal wird unbestätigt angelegt und erhält eine einzige Nachricht mit der Frage, ob er Alarme möchte. Bis er zustimmt, wird nichts weiter gesendet; einen über die API anzulegen setzt eine Adresse also nicht von allein auf Ihren Alarmplan.

Parameter und Antworten

GET /channels

Keine deklarierten Parameter oder Body-Felder.

AntwortListChannelsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

POST /channels

NameOrtTyp
kindbodystring
namebodystring
targetbodystring
workspaceIdbodyrequests.NullableString
AntwortCreatedChannelResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

PATCH /channels/{id} · DELETE /channels/{id} · POST /channels/{id}/test

Alle erfordern notification_channel:manage. Der Testversand wird für eine Adresse verweigert, die nicht bestätigt hat — sonst wäre er ein unbegrenzter Weg, eine Adresse ohne Einwilligung anzuschreiben, mit einer hilfsbereiten Aufschrift.

Parameter und Antworten

PATCH /channels/{id}

NameOrtTyp
id Pflichtpathstring
enabledbodyboolean
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /channels/{id}

NameOrtTyp
id Pflichtpathstring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

POST /channels/{id}/test

NameOrtTyp
id Pflichtpathstring
AntwortTestDeliveryResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /status-pages · POST /status-pages

Lesen erfordert status_page:read; Schreiben erfordert status_page:manage. Jede trägt id, name, slug, visibility, customDomain, domainVerifiedAt, subscribersEnabled, componentCount, workspace und createdAt.

Parameter und Antworten

GET /status-pages

Keine deklarierten Parameter oder Body-Felder.

AntwortListStatusPagesResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

POST /status-pages

NameOrtTyp
namebodystring
workspaceIdbodystring
AntwortCreatedResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /status-pages/{id} · PATCH /status-pages/{id} · DELETE /status-pages/{id}

Lesen erfordert status_page:read; Ändern oder Löschen erfordert status_page:manage.

Parameter und Antworten

GET /status-pages/{id}

NameOrtTyp
id Pflichtpathstring
AntwortGetStatusPageResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

PATCH /status-pages/{id}

NameOrtTyp
id Pflichtpathstring
namebodystring
headlinebodyrequests.NullableString
descriptionbodyrequests.NullableString
logoUrlbodyrequests.NullableString
themeAccentbodystring
languagebodystring
historyDaysbodyinteger
showResponseTimesbodyboolean
showIncidentHistorybodyboolean
subscribersEnabledbodyboolean
visibilitybodystring
passwordbodyrequests.NullableString
customCssbodyrequests.NullableString
hideVitrinaBrandingbodyboolean
groupByHostbodyboolean
AntwortUpdatedStatusPageResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /status-pages/{id}

NameOrtTyp
id Pflichtpathstring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

POST /status-pages/{id}/components · DELETE /status-pages/{id}/components

Einen Monitor zu einer Seite hinzufügen oder von ihr entfernen. Erfordert status_page:manage.

Der Monitor muss im selben Arbeitsbereich liegen wie die Seite, nicht bloß in derselben Organisation. In einem Agenturkonto ist das es, was verhindert, dass der Monitor eines Kunden auf der Seite eines anderen Kunden veröffentlicht wird.

Parameter und Antworten

POST /status-pages/{id}/components

NameOrtTyp
id Pflichtpathstring
monitorIdbodystring
displayNamebodystring
AntwortComponentAckResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /status-pages/{id}/components

NameOrtTyp
id Pflichtpathstring
componentquerystring
componentIdbodystring
AntwortComponentAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /workspaces · POST /workspaces · DELETE /workspaces/{id}

Lesen erfordert workspace:read, der Rest jeweils eigene Berechtigungen. Jeder trägt id, name, slug, clientReference und isDefault.

Ein Schlüssel, der zu einem beschränkten Mitglied gehört, sieht nur die Arbeitsbereiche, auf die dieses Mitglied beschränkt ist. Der Standard-Arbeitsbereich kann nicht gelöscht werden.

Parameter und Antworten

GET /workspaces

Keine deklarierten Parameter oder Body-Felder.

AntwortListWorkspacesResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

POST /workspaces

NameOrtTyp
namebodystring
clientReferencebodystring
AntwortCreatedResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /workspaces/{id}

NameOrtTyp
id Pflichtpathstring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /members · POST /members

Lesen erfordert member:read; Einladen erfordert member:invite. Die Antwort führt members und invitations getrennt — eine Einladung, die niemand angenommen hat, hat niemanden hinzugefügt, und beides zusammenzuführen ergäbe eine Platzzahl, die dem widerspricht, was Ihnen berechnet wird.

POST verschickt eine Einladung und legt kein Konto an. Es nimmt eine E-Mail-Adresse, eine Rolle und optional workspaceIds, um die Person zu beschränken.

Parameter und Antworten

GET /members

Keine deklarierten Parameter oder Body-Felder.

AntwortListMembersResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

POST /members

NameOrtTyp
emailbodystring
rolebodystring
workspaceIdsbodystring[]
AntwortAckResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

PATCH /members/{id} · DELETE /members/{id} · DELETE /invitations/{id}

Eine Rolle zu ändern erfordert member:update_role; jemanden zu entfernen erfordert member:remove; eine Einladung zu widerrufen erfordert member:invite.

Ein Mitglied zu entfernen löscht dessen persönliche Alarmkanäle — das Telefon, den privaten Chat, die Mobilnummer — zusammen mit dessen API-Schlüsseln. Gemeinsam genutzte Kanäle bleiben unberührt. Die letzte Eigentümerin oder der letzte Eigentümer kann weder entfernt noch herabgestuft werden.

Parameter und Antworten

PATCH /members/{id}

NameOrtTyp
id Pflichtpathstring
rolebodystring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /members/{id}

NameOrtTyp
id Pflichtpathstring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /invitations/{id}

NameOrtTyp
id Pflichtpathstring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /maintenance · POST /maintenance · DELETE /maintenance

Zeitfenster, in denen niemand alarmiert wird. Standardmäßig laufen die Prüfungen weiter und zeichnen weiter auf, diese Minuten zählen also wie alle anderen in die Verfügbarkeit; steht keepChecking auf false, wird währenddessen gar nicht geprüft, was im Verlauf eine Lücke hinterlässt statt einer Delle. Lesen erfordert incident:read; Schreiben erfordert maintenance:manage.

Trägt title, startsAt, endsAt, timezone, monitorIds, recurrenceRule, keepChecking, showOnStatusPage und notifySubscribers. Ein wiederkehrendes Fenster ist eine Zeile und nicht viele.

Eine Regel wiederholt das Fenster zur selben Uhrzeit in seiner eigenen timezone, ein Fenster über eine Zeitumstellung hinweg bleibt also zur geplanten Stunde. FREQ=DAILY, FREQ=WEEKLY und FREQ=MONTHLY werden aufgelöst, wahlweise mit INTERVAL, COUNT, UNTIL sowie einem BYDAY oder BYMONTHDAY, das den Tag nennt, an dem das Fenster selbst beginnt. Jede andere Regel wird unverändert gespeichert und zurückgegeben und hält Warnungen nur für die erste Wiederkehr zurück — geraten wird nie.

Parameter und Antworten

GET /maintenance

NameOrtTyp
pastqueryboolean
AntwortListMaintenanceResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

POST /maintenance

NameOrtTyp
titlebodystring
descriptionbodystring
workspaceIdbodystring
monitorIdsbodystring[]
startsAtbodystring
endsAtbodystring
recurrenceRulebodystring
timezonebodystring
keepCheckingbodyboolean
showOnStatusPagebodyboolean
notifySubscribersbodyboolean
AntwortCreatedResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /maintenance

NameOrtTyp
idquerystring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /on-call

Dienstpläne, Eskalationsrichtlinien, Vertretungen und wer gerade Rufbereitschaft hat. Erfordert oncall:read.

onCallNow wird in dem Moment aufgelöst, in dem Sie fragen, wobei viaOverride sagt, ob es aus der Rotation kam oder daher, dass jemand vertritt. unreachable nennt die Beteiligten, die über keinen Kanal verfügen, der sie tatsächlich erreichen könnte — das ist der Fehler, den man besser vor einem Vorfall findet als während eines solchen.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortGetOnCallResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /agents · POST /agents · DELETE /agents · GET /agents/{id}/metrics

Server-Agenten melden CPU, Arbeitsspeicher und Festplatte von Ihren eigenen Maschinen. Das Einrichten erfordert agent:enroll, das Lesen agent:read, das Entfernen agent:delete.

Beim Einrichten kommt einmalig ein Token zurück. Damit authentifiziert sich der Agent, es ist danach also nie wieder lesbar.

Parameter und Antworten

GET /agents

Keine deklarierten Parameter oder Body-Felder.

AntwortListAgentsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

POST /agents

NameOrtTyp
namebodystring
workspaceIdbodyrequests.NullableString
AntwortEnrolledAgentResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /agents

NameOrtTyp
idquerystring
idbodystring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /agents/{id}/metrics

NameOrtTyp
id Pflichtpathstring
hoursqueryinteger
limitqueryinteger
AntwortGetAgentMetricsResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /api-keys · POST /api-keys · DELETE /api-keys

Lesen erfordert api_key:read; Anlegen und Widerrufen erfordern api_key:manage. Jeder trägt id, name, prefix, scopes, workspaceIds, owner, createdAt, lastUsedAt, expiresAt und revokedAt.

token wird nur beim Anlegen zurückgegeben. prefix ist der anzeigbare Teil, und der ist es, mit dem sich zwei Schlüssel in einer Liste auseinanderhalten lassen, ohne dass einer von beiden lesbar wäre.

Ein Schlüssel erbt die Rolle und die Arbeitsbereichsbeschränkung der Mitgliedschaft, die ihn erstellt hat; ein Schlüssel kann also kein Weg um eine Grenze herum sein, die für seine Urheberin oder seinen Urheber gilt.

Parameter und Antworten

GET /api-keys

Keine deklarierten Parameter oder Body-Felder.

AntwortListApiKeysResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

POST /api-keys

NameOrtTyp
namebodystring
scopesbodystring[]
workspaceIdsbodystring[]
expiresInDaysbodyrequests.NullableInt64
AntwortCreatedApiKeyResponse
Statuscodes201 400 401 403 404 429
Ratenbegrenzung30 pro Minute

DELETE /api-keys

NameOrtTyp
idquerystring
idbodystring
AntwortAckResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /audit

Konfigurationsänderungen, mit Angabe, wer sie vorgenommen hat und was sich geändert hat. Erfordert audit_log:read, was es ab Business gibt.

Seitenweise über nextBefore statt über Seitenzahlen, damit sich eine Seitengrenze nicht verschiebt, während Sie lesen. Einträge werden in jedem Tarif aufgezeichnet — der Tarif steuert das Lesen, ein Upgrade öffnet also die ganze Historie, statt eine zu beginnen.

Zugangsdaten, Hashes und Geheimnisse werden nie in changes geschrieben.

Parameter und Antworten
NameOrtTyp
limitqueryinteger
AntwortListAuditResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

GET /me

Wer dieser Schlüssel ist, was er erreichen kann und was der Tarif erlaubt. Es ist keine Berechtigung nötig — jeder Schlüssel darf sich selbst beschreiben.

Trägt user, organization, membership(Rolle und Arbeitsbereichsbeschränkung), entitlements (die aufgelösten Tarifgrenzen, mit allen Zusatzpaketen bereits eingerechnet) und usage. Nutzen Sie es, um eine Grenze vor einem Anlegeversuch zu prüfen statt nach einer Ablehnung.

Eine Sitzung erhält zusätzlich organizations mit allen Organisationen, denen die Person angehört. Ein API-Schlüssel nicht: Ein Schlüssel wird gegen eine Mitgliedschaft ausgestellt und ist darauf beschränkt, die anderen aufzuführen würde also Organisationen bewerben, die diese Zugangsdaten nicht erreichen können.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortGetMeResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung120 pro Minute

DELETE /account

Löscht die Organisation und alles darin. Keine Berechtigungskonstante schützt diesen Endpunkt, denn die Eigentümerschaft ist die Prüfung: Er wird allen verweigert, die nicht Eigentümer sind.

Das ist nicht umkehrbar und keine Pause. Setzen Sie es mit Bedacht ein.

Parameter und Antworten

Keine deklarierten Parameter oder Body-Felder.

AntwortAccountDeletedResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

POST /billing/apple/verify

Bestätigt einen In-App-Kauf, der in unserer eigenen mobilen App getätigt wurde. Erfordert billing:manage.

Der Vollständigkeit halber dokumentiert und nicht zur Verwendung: Er ist nur mit einem Beleg aufrufbar, den Apple unserer App ausgestellt hat, eine fremde Integration kann damit also nichts anfangen. Hier aufgeführt, weil eine Route, die existiert und nirgends beschrieben ist, von einer vergessenen nicht zu unterscheiden ist.

Parameter und Antworten
NameOrtTyp
transactionIdbodystring
AntwortAppleVerifyResponse
Statuscodes200 400 401 403 404 429
Ratenbegrenzung30 pro Minute

GET /

Das Verzeichnis. Führt die Routen auf, die diese Installation ausliefert — die maschinenlesbare Fassung dieser Seite, und immer aktuell, denn es wird aus dem erzeugt, was tatsächlich eingehängt ist.

Vorfalls-Feed (RSS und Atom)

Jeder Vorfall in Ihrem Konto als Feed, für einen Reader statt für eine Client-Bibliothek. Die URL legen Sie im Dashboard unter Einstellungen → Benachrichtigungen an:

https://vitrinaengine.com/feeds/incidents/vtf_…/feed.xml
https://vitrinaengine.com/feeds/incidents/vtf_…/atom.xml

Die URL ist das Zugangsmittel. Es gibt keinen Header zu senden: Wer den Link hat, kann jeden Vorfall im Konto lesen, über alle Arbeitsbereiche hinweg. Sie wird im Dashboard jederzeit wieder angezeigt, weil sie in einem Feed-Reader liegt, den jemand irgendwann neu aufsetzt — und sie lässt sich ersetzen oder widerrufen, mit Wirkung ab der nächsten Anfrage statt erst, wenn ein Cache abläuft.

Sie enthält ausschließlich Fakten auf Vorfallsebene: den Namen des Monitors, die Ursache, Schweregrad, Status, Beginn und Ende sowie die als öffentlich markierten Aktualisierungen. Nie eine Nachbetrachtung, nie die Monitor-Konfiguration und nie den Ort, von dem aus geprüft wurde. Die meisten Reader synchronisieren über fremde Server, deshalb ist das Dokument so geschrieben, als verlasse es Ihr Haus — was es tut.

Ein Abruf pro Minute ist vorgesehen. Ab sechzig Anfragen pro Minute für eine URL antwortet sie mit 429; eine URL, die nie gültig war, ersetzt oder widerrufen wurde, antwortet mit 404 — für alle drei Fälle dieselbe Antwort, damit sich damit nicht herausfinden lässt, welche Token einmal echt waren.

Was diese API bewusst nicht zurückgibt

  • Das config eines Monitors. Es kann Zugangsdaten enthalten.
  • Aus welcher Region eine Prüfung lief. Von wo wir prüfen, entscheiden wir, und wir ändern es, während Sonden aufgestellt und verschoben werden. Es wäre ein Versprechen über unsere Infrastruktur, mit dem Sie nichts anfangen könnten, und es wird auch sonst nirgends im Produkt angezeigt.

Exporting your data

Two routes hand back a file rather than a message, so that taking your data out does not mean paging through a collection endpoint a thousand times. Both are on every plan, the free one included — what a plan changes is how much history there is to export, not whether you may.

GET /export/{entity}

Eine Art von Zeilen, als CSV oder JSON. entity ist eines von monitors, hosts, status-pages, notification-channels, members, incidents, incident-events, postmortems, audit-log, error-issues, uptime-daily, uptime-hourly oder analytics-hourly. Alles andere antwortet mit 404.

format ist csv (Standard) oder json. from und to sind RFC-3339-Zeitstempel. bom stellt einer CSV-Datei eine UTF-8-Bytereihenfolge-Marke voran: Excel braucht sie für Namen mit Sonderzeichen, die meisten Skriptsprachen lesen sie als Teil der ersten Spaltenüberschrift — deshalb ist sie standardmäßig aus.

Parameter und Antworten
NameOrtTyp
entity Pflichtpathstring
bomqueryboolean
formatquerystring
fromquerystring
toquerystring
Statuscodes200 400 401 403 404 429
Ratenbegrenzung6 pro Stunde

GET /export

Alles, was der Schlüssel lesen darf, als ZIP: eine Datei pro Entität plus manifest.json mit dem Inhalt des Archivs, der Zeilenzahl je Datei und den fehlenden Entitäten. Was die Rolle des Schlüssels nicht lesen darf, fehlt, statt die ganze Anfrage abzulehnen — das Manifest sorgt dafür, dass das nicht stillschweigend geschieht.

Parameter und Antworten
NameOrtTyp
bomqueryboolean
formatquerystring
fromquerystring
toquerystring
Statuscodes200 400 401 403 404 429
Ratenbegrenzung6 pro Stunde

What an export does not contain

Ein Export enthält nichts, was authentifiziert: keine Kanal-Konfiguration, keine Heartbeat-Token, keine Passwort-Hashes. Die Konfiguration eines Monitors ist enthalten, ohne alles, was nach Zugangsdaten aussieht — Anfrage-Body, Header, SNMP-Community, Postfach-Login. Rohe Prüfergebnisse fehlen ebenfalls: Sie verfallen durch die Aufbewahrungsfrist, deshalb stammt die Verfügbarkeit aus den Rollups.

Size, and the one refusal you may meet

Die stündlichen Reihen sind auf 92 Tage pro Anfrage begrenzt; ein größeres Fenster wird mit export_window_too_wide abgelehnt statt still gekürzt. Eigener Grenzwert: 6 Exporte pro Stunde je Organisation.

Versionierung

Die Version steht im Pfad. Den Antworten werden Felder hinzugefügt — behandeln Sie unbekannte als etwas zu Ignorierendes und nicht als Fehler —, aber aus v1 wird nichts entfernt und ändert darin seine Bedeutung.

Fehlt etwas?

Die Oberfläche ist bewusst klein: Sie deckt eine Wandtafel, eine Zusammenfassung im Chat und ein Deployment-Skript ab, das einen Monitor für die Dauer eines Rollouts stummschaltet. Wenn Sie etwas bauen, das sie nicht erreicht, schreiben Sie an support@vitrinaengine.com — zu wissen, was die Leute wirklich wollen, ist die Art, wie der nächste Endpunkt ausgewählt wird.

Preise · Nutzungsbedingungen