Webhook-Ereignisse
Alle Ereignisse, die Revisio per Webhook meldet, wann sie ausgelöst werden und welche Daten sie enthalten.
Stand:
Jeder Webhook abonniert eines oder mehrere der folgenden Ereignisse. Neue Webhooks abonnieren beim Anlegen alle Ereignisse; die Auswahl lässt sich unter Bearbeiten jederzeit ändern. Ereignisse entstehen unabhängig davon, wo die Änderung passiert: im Büro, in der Techniker-App, im Kundenportal, beim Import oder über die API.
| Ereignis | Bezeichnung in Revisio | ausgelöst, wenn |
|---|---|---|
order.created |
Auftrag angelegt | ein Auftrag angelegt wird, auch aus Fälligkeiten, Störungen oder über die API |
order.status_changed |
Auftragsstatus geändert | sich der Status eines Auftrags ändert |
order.rescheduled |
Auftragstermin geändert | geplanter Beginn oder geplantes Ende eines bestehenden Auftrags sich ändern |
order.completed |
Auftrag abgeschlossen | ein Techniker oder das Büro den Auftrag abschließt |
report.created |
Bericht erzeugt | das PDF eines Berichts vorliegt, auch bei Korrekturversionen |
report.sent |
Bericht versendet | ein Bericht an die Berichtsempfänger versendet wurde |
fault.created |
Störung angelegt | eine Störung oder ein Mangel erfasst wird |
fault.status_changed |
Störungsstatus geändert | sich der Status einer Störung ändert |
asset.created |
Anlage angelegt | eine Anlage angelegt wird |
asset.updated |
Anlage geändert | sich Felder einer Anlage ändern |
customer.created |
Kunde angelegt | ein Kunde angelegt wird |
customer.updated |
Kunde geändert | sich Felder eines Kunden ändern, auch beim Archivieren |
site.created |
Objekt angelegt | ein Objekt angelegt wird |
site.updated |
Objekt geändert | sich Felder eines Objekts ändern, auch beim Archivieren |
quote.accepted |
Angebot angenommen | der Kunde ein Angebot im Kundenportal annimmt oder das Büro die Annahme erfasst |
quote.declined |
Angebot abgelehnt | ein Angebot abgelehnt wird, ebenso im Portal oder durch das Büro |
invoice.created |
Rechnung erstellt | eine Rechnung, Rechnungskorrektur oder Stornorechnung in Revisio festgeschrieben oder ins Rechnungsprogramm übertragen wurde |
appointment.responded |
Terminantwort eingegangen | ein Empfänger der Terminankündigung den Termin bestätigt oder einen anderen Termin wünscht |
maintenance.due |
Wartung fällig | der Zeitraum einer offenen Wartung beginnt, also die Fälligkeit (abzüglich einer Karenz vorher) erreicht ist |
maintenance.overdue |
Wartung überfällig | eine offene Wartung auch nach Ablauf der Toleranz nicht erledigt ist |
fault.sla_breached |
Reaktionszeit überschritten | eine offene Störung ihre Reaktionszeit laut Kategorie überschreitet |
records.trashed |
In den Papierkorb verschoben | Kunde, Objekt, Kontakt, Anlage oder Auftrag in den Papierkorb verschoben wird |
records.restored |
Aus dem Papierkorb wiederhergestellt | ein Eintrag aus dem Papierkorb zurückgeholt wird |
Zusätzlich gibt es webhook.test für Test senden; es lässt sich nicht abonnieren.
Alle Nachrichten haben denselben Rahmen (id, event, created_at, test, data), beschrieben unter
Webhooks empfangen. Unten steht jeweils nur
data. Zeitpunkte sind UTC nach ISO 8601, IDs ULIDs. Namen, Adressen und Texte enthalten die Nachrichten nie; laden
Sie diese bei Bedarf über die API.
Aufträge#
Alle Auftragsereignisse enthalten den Auftrag in derselben Form:
{
"order": {
"id": "01k7b2c4d6e8f0g2h4j6k8m0n2",
"number": "A-2026-00012",
"status": "open",
"priority": "normal",
"order_type_id": "01k79z8y7x6w5v4t3s2r1q0p9n",
"customer_id": "01k7a3m9x2c4d5e6f7g8h9j0k1",
"site_id": "01k7a3n4q8r2s6t0v4w8x2y6z0",
"fault_id": null,
"asset_ids": ["01k7a3p1b5c9d3e7f1g5h9j3k7"],
"scheduled_start": "2026-11-03T07:00:00+00:00",
"scheduled_end": "2026-11-03T09:00:00+00:00",
"completed_at": null,
"overall_result": null
}
}
Statuswerte und Felder wie unter API: Aufträge. Details wie
Techniker und Berichte liefert GET /orders/{id}.
order.created#
data wie oben. Neue Aufträge haben den Status open, aus Fälligkeiten erzeugte zunächst draft.
order.status_changed#
data wie oben, dazu der vorige Status:
{
"order": { "id": "01k7b2c4d6e8f0g2h4j6k8m0n2", "number": "A-2026-00012", "status": "in_progress" },
"previous_status": "open"
}
Das Ereignis kommt bei jedem Wechsel, also auch bei Abschluss, Prüfung, Berichtsversand, Abrechnung und Storno.
Beim Abschluss kommen order.status_changed und order.completed; abonnieren Sie bei Bedarf nur eines davon.
order.rescheduled#
data wie oben mit dem neuen Termin, dazu der vorige:
{
"order": { "id": "01k7b2c4d6e8f0g2h4j6k8m0n2", "scheduled_start": "2026-11-05T07:00:00+00:00", "scheduled_end": "2026-11-05T09:00:00+00:00" },
"previous": { "scheduled_start": "2026-11-03T07:00:00+00:00", "scheduled_end": "2026-11-03T09:00:00+00:00" }
}
Ein Auftrag ohne Termin hat null; das erste Einplanen ergibt deshalb previous mit null-Werten, das Entfernen
des Termins null im Auftrag. Beim Anlegen kommt kein order.rescheduled, nur order.created.
order.completed#
data wie oben mit status completed, completed_at und overall_result (operational,
operational_with_defects, not_operational). Der Bericht folgt mit report.created, sobald sein PDF erzeugt ist.
Berichte#
{
"report": {
"id": "01k7c5d7e9f1g3h5j7k9m1n3p5",
"number": "B-2026-00211",
"version": 1,
"full_number": "B-2026-00211",
"status": "generated",
"work_order_id": "01k7b2c4d6e8f0g2h4j6k8m0n2",
"supersedes_report_id": null,
"generated_at": "2026-11-03T10:41:05+00:00",
"pdf_sha256": "9f2c4e1a7b3d5f6e8a0c2b4d6f8e0a1c3b5d7f9e1a2c4b6d8f0e2a4c6b8d0f1e"
}
}
report.created#
Das PDF liegt vor. Den Download-Link liefert GET /reports/{id}
(PDF herunterladen). Bei einer Korrekturversion verweist
supersedes_report_id auf die ersetzte Fassung.
report.sent#
Der Bericht wurde an die Berichtsempfänger versendet, status ist sent. Geeignet für Ablagesysteme, die nur
versendete Berichte übernehmen sollen. Schlug der Versand an einen Empfänger fehl (delivery_failed) und wird
erneut versendet, kommt das Ereignis noch einmal.
Störungen#
{
"fault": {
"id": "01k7d8e0f2g4h6j8k0m2n4p6q8",
"number": "S-2026-00041",
"status": "open",
"state": "open",
"priority": "high",
"level": "elevated",
"source": "app",
"customer_id": "01k7a3m9x2c4d5e6f7g8h9j0k1",
"site_id": "01k7a3n4q8r2s6t0v4w8x2y6z0",
"asset_id": "01k7a3p1b5c9d3e7f1g5h9j3k7",
"component_id": null,
"category_id": "01k79y6x5w4v3t2s1r0q9p8n7m",
"work_order_id": null,
"reported_at": "2026-11-03T05:44:10+00:00"
}
}
Bedeutung von status, state, priority, level und source unter
API: Störungen.
fault.created#
data wie oben. Kommt auch für Störungen, die über die API gemeldet wurden; ein Fremdsystem, das selbst meldet,
erkennt seine eigenen an source api.
fault.status_changed#
data wie oben, dazu der vorige Status in beiden Schreibweisen:
{
"fault": { "id": "01k7d8e0f2g4h6j8k0m2n4p6q8", "status": "resolved", "state": "resolved" },
"previous_state": "in_progress",
"previous_status": "in_progress"
}
Damit verfolgt eine Leitstelle ihre Meldung bis zur Behebung, ohne die Liste regelmäßig abzufragen.
Anlagen#
{
"asset": {
"id": "01k7a3p1b5c9d3e7f1g5h9j3k7",
"number": "SW17 36033",
"status": "active",
"customer_id": "01k7a3m9x2c4d5e6f7g8h9j0k1",
"site_id": "01k7a3n4q8r2s6t0v4w8x2y6z0",
"asset_type_id": "01k79x1y2z3a4b5c6d7e8f9g0h"
},
"changed": ["location", "status"]
}
asset.created#
data mit asset, ohne changed.
asset.updated#
changed nennt die Namen der geänderten Felder, nicht ihre Werte. Verwaltungsfelder wie updated_at zählen nicht;
ändert sich nur so ein Feld, kommt kein Ereignis. Die neuen Werte liefert GET /assets/{id}.
Kunden und Objekte#
{
"customer": { "id": "01k7a3m9x2c4d5e6f7g8h9j0k1", "number": "K100231", "status": "active" },
"changed": ["email", "phone"]
}
{
"site": { "id": "01k7a3n4q8r2s6t0v4w8x2y6z0", "customer_id": "01k7a3m9x2c4d5e6f7g8h9j0k1", "number": "O-0042", "status": "archived" },
"changed": ["status"]
}
customer.created und site.created#
data mit customer bzw. site, ohne changed.
customer.updated und site.updated#
changed nennt die Namen der geänderten Felder wie bei asset.updated. Archivieren und Wiederherstellen erscheinen
als Änderung von status. Die neuen Werte liefern GET /customers/{id} und GET /sites/{id}.
Angebote#
{
"quote": {
"id": "01k7f2g4h6j8k0m2n4p6q8r0s2",
"number": "ANG-2026-00017",
"status": "accepted",
"customer_id": "01k7a3m9x2c4d5e6f7g8h9j0k1",
"site_id": "01k7a3n4q8r2s6t0v4w8x2y6z0",
"valid_until": "2026-11-30",
"net_total": "1200.00",
"gross_total": "1428.00",
"decision_channel": "portal",
"decided_at": "2026-11-04T08:31:12+00:00",
"fault_ids": ["01k7d8e0f2g4h6j8k0m2n4p6q8"]
}
}
quote.accepted und quote.declined#
decision_channel sagt, wie die Entscheidung kam: portal (Kundenportal), email, phone, letter oder
in_person. Beträge sind Dezimalzahlen als Text mit Punkt. fault_ids nennt die Störungen, deren Behebung das
Angebot umfasst. Wer angenommen hat und eine Bemerkung des Kunden stehen nicht in der Nachricht, sondern in Revisio
beim Angebot.
Rechnungen#
{
"invoice": {
"id": "01k7g3h5j7k9m1n3p5q7r9s1t3",
"number": "RE-2026-0042",
"kind": "invoice",
"status": "issued",
"provider": null,
"customer_id": "01k7a3m9x2c4d5e6f7g8h9j0k1",
"contract_id": null,
"corrects_id": null,
"voucher_date": "2026-11-05",
"net_total": "500.00",
"tax_total": "95.00",
"gross_total": "595.00",
"order_ids": ["01k7b2c4d6e8f0g2h4j6k8m0n2"]
}
}
invoice.created#
| Feld | Bedeutung |
|---|---|
kind |
invoice (Rechnung), credit_note (Rechnungskorrektur), cancellation (Stornorechnung) |
status |
issued: in Revisio mit eigener Nummer festgeschrieben; transferred: an das Rechnungsprogramm übertragen |
provider |
Rechnungsprogramm bei transferred, sonst null |
contract_id |
Wartungsvertrag bei Vertragsrechnungen |
corrects_id |
Rechnung, die eine Korrektur oder Storno betrifft |
order_ids |
abgerechnete Aufträge |
Das Ereignis kommt einmal je Beleg. Die Rechnung selbst holen Sie aus Revisio oder dem Rechnungsprogramm; über die API gibt es keine Rechnungsdaten.
Terminantworten#
{
"appointment": {
"notice_id": "01k7h4j6k8m0n2p4q6r8s0t2v4",
"recipient_id": "01k7h4j6k8m0n2p4q6r8s0t2v6",
"version": 1,
"work_order_id": "01k7b2c4d6e8f0g2h4j6k8m0n2",
"response": "change_requested",
"responded_at": "2026-11-01T16:20:44+00:00",
"scheduled_start": "2026-11-03T07:00:00+00:00",
"scheduled_end": "2026-11-03T09:00:00+00:00",
"preferred_dates": [{ "date": "2026-11-10", "time": "09:00" }]
}
}
appointment.responded#
response ist confirmed (Termin bestätigt) oder change_requested (anderer Termin gewünscht, mit
preferred_dates). version zählt die Terminnachrichten zum Auftrag; eine Antwort bezieht sich immer auf den Termin
in scheduled_start und scheduled_end. Antwortet derselbe Empfänger später noch einmal, kommt ein weiteres
Ereignis. E-Mail-Adresse, Name und Nachricht des Empfängers stehen nur in Revisio
(Terminbestätigung).
Fälligkeiten und Reaktionszeiten#
Diese drei Ereignisse entstehen nicht durch eine Änderung, sondern durch Zeitablauf. Revisio prüft alle fünf Minuten und meldet jeden Fall genau einmal. Berücksichtigt werden Fälle der letzten sieben Tage; ältere Rückstände kommen nicht nachträglich, auch wenn ein Webhook erst später angelegt wird.
{
"maintenance": {
"id": "01k7j5k7m9n1p3q5r7s9t1v3w5",
"asset_id": "01k7a3p1b5c9d3e7f1g5h9j3k7",
"customer_id": "01k7a3m9x2c4d5e6f7g8h9j0k1",
"site_id": "01k7a3n4q8r2s6t0v4w8x2y6z0",
"rule_id": "01k79w2x4y6z8a0b2c4d6e8f0g",
"due_date": "2026-11-01",
"window_from": "2026-10-18",
"tolerance_until": "2026-11-30",
"status": "open",
"work_order_id": null
}
}
maintenance.due#
Eine offene oder eingeplante Wartung ist fällig. Das ist der Fall ab window_from: dem Fälligkeitsdatum due_date
abzüglich der Karenz vorher, die in der Wartungsregel eingestellt ist; ohne Karenz ist window_from gleich
due_date. status planned mit
work_order_id heißt: Es gibt schon einen Auftrag dafür. Erledigte und übersprungene Fälligkeiten melden sich nicht.
Mehr zu Fälligkeiten unter Fälligkeiten.
maintenance.overdue#
Die Toleranz tolerance_until ist abgelaufen und die Wartung noch nicht erledigt. Gleicher Inhalt wie
maintenance.due.
fault.sla_breached#
Eine Störung ist noch offen, aber ihre Reaktionszeit (sla_due_at, aus der Störungskategorie) ist verstrichen.
data enthält die Störung wie bei fault.created und zusätzlich sla_due_at.
Papierkorb#
{
"trash": {
"id": "01k7k6m8n0p2q4r6s8t0v2w4x6",
"subject_type": "site",
"subject_id": "01k7a3n4q8r2s6t0v4w8x2y6z0",
"purge_at": "2026-12-04T09:15:00+00:00"
},
"records": {
"customer_ids": [],
"site_ids": ["01k7a3n4q8r2s6t0v4w8x2y6z0"],
"asset_ids": ["01k7a3p1b5c9d3e7f1g5h9j3k7"],
"order_ids": ["01k7b2c4d6e8f0g2h4j6k8m0n2"]
}
}
records.trashed#
Ein Datensatz liegt im Papierkorb. subject_type (customer, site, contact,
asset, order) und subject_id nennen, was gelöscht wurde; records listet alles, was mit ihm in den Papierkorb
ging, den Datensatz selbst eingeschlossen. Wird ein Kunde gelöscht, stehen also auch seine Objekte, Anlagen und
Aufträge darin. Die API liefert diese Datensätze nicht mehr. purge_at ist der Zeitpunkt, an dem Revisio sie
endgültig löscht.
records.restored#
Der Eintrag wurde aus dem Papierkorb zurückgeholt. records nennt dieselben Datensätze; die API liefert sie wieder.
Welche Ereignisse wofür#
| Anbindung | sinnvolle Ereignisse |
|---|---|
| ERP oder Warenwirtschaft (Abrechnung) | order.completed, order.status_changed, report.sent, invoice.created |
| Vertrieb, CRM | quote.accepted, quote.declined |
| Wartungsplanung im ERP | maintenance.due, maintenance.overdue, appointment.responded |
| Dokumentenablage (DMS) | report.created oder report.sent |
| Leitstelle, Hausmeister- oder Störungsportal | fault.created, fault.status_changed, fault.sla_breached, order.created, order.rescheduled |
| Kalender, Ressourcenplanung | order.created, order.rescheduled, order.status_changed |
| Stammdatenabgleich mit CRM oder ERP | customer.*, site.*, asset.*, records.trashed, records.restored |
| Auswertung, Data Warehouse | alle; nächtlicher Abgleich über die API als Sicherheitsnetz |