Webhooks (ausgehend)

FreeMaint-Ereignisse in Echtzeit an Ihre eigenen Systeme senden

4 Min. Lesezeit
Diesen Abschnitt drucken

Webhooks sind die Push-Hälfte von Integrationen: Statt dass Ihr System FreeMaint abfragt, sendet FreeMaint ein POST an Ihre URL, sobald etwas passiert. Einrichtung unter Unternehmenseinstellungen > Webhooks (/company-settings/webhooks). Ab Starter verfügbar (100 Zustellungen/Tag; ab Business unbegrenzt).

Verfügbare Ereignisse

  • work_order.created — ein Arbeitsauftrag wurde erstellt
  • work_order.completed — ein Arbeitsauftrag wurde auf Abgeschlossen gesetzt
  • work_order.status_changed — ein Arbeitsauftrag hat in einen beliebigen Status gewechselt; die Nutzlast enthält new_status. Wird zusätzlich zu work_order.completed ausgelöst, das unverändert bleibt
  • request.created — eine Wartungsanfrage wurde eingereicht
  • request.status_changed — eine Anfrage wurde genehmigt, abgelehnt oder storniert
  • part.low_stock — ein Ersatzteil hat seinen Meldebestand erreicht oder unterschritten
  • part.out_of_stock — ein Ersatzteil ist auf null gefallen
  • part.low_stock_summary — eine tägliche Zusammenfassung je Unternehmen mit allen Ersatzteilen auf oder unter ihrem Meldebestand, einschließlich der nie bewegten
  • part.out_of_stock_summary — dieselbe tägliche Zusammenfassung für Ersatzteile mit Bestand null
  • part.consumed — ein Ersatzteil wurde auf einem Arbeitsauftrag verbraucht oder zurückgegeben
  • compliance.chain_divergence — die Audit-Hashkette ist gebrochen (Enterprise)
  • asset.downtime_started — ein Maschinenstillstand wurde eröffnet
  • asset.downtime_ended — ein Maschinenstillstand wurde beendet; die Dauer lässt sich nun verbuchen
  • report.daily_summary — die abgeschlossenen Arbeiten des Tages, einmal täglich zur von Ihnen gewählten Uhrzeit
  • purchase_order.created — eine Bestellung wurde angelegt; die Nutzlast enthält die Bestellung (reference, status, total_cost, currency, expected_date, erp_reference) und ihren Lieferanten
  • purchase_order.status_changed — eine Bestellung hat den Status gewechselt (genehmigt, bestellt, storniert …); die Nutzlast enthält previous_status und new_status
  • purchase_order.received — eine Lieferung zu einer Bestellung wurde empfangen (wird bei jeder Lieferung gesendet, auch bei Teillieferungen); die Nutzlast listet jede Position mit quantity_ordered, quantity_received (diese Lieferung), quantity_received_total und quantity_remaining sowie receipt_id, fully_received und closed_short; new_status ist PARTIALLY_RECEIVED, solange noch Ware erwartet wird, und RECEIVED, sobald die Bestellung vollständig oder abgeschlossen ist

part.consumed — Bestand in ein ERP spiegeln

Dies ist das Ereignis, das Sie abonnieren, wenn ein anderes System (ERP, Fakturierung, Lagerhaltung, Buchhaltung) abbilden muss, was die Instandhaltung tatsächlich verbraucht hat. quantity ist vorzeichenbehaftet: negativ bei Ausgabe an den Auftrag, positiv bei Rückgabe durch Entfernen aus dem Arbeitsauftrag — so erzeugt eine Stornierung in FreeMaint einen passenden Stornobeleg im Zielsystem. stock_movement_id bleibt über Wiederholungen und erneute Zustellungen hinweg gleich: Nutzen Sie sie als Idempotenzschlüssel, dann buchen Sie dieselbe Entnahme nie doppelt. Wichtig, wenn der Verkehr in beide Richtungen läuft: Die GraphQL-Mutation adjustStock löst dieses Ereignis NICHT aus. Das ist Absicht – eine Bestandskorrektur, die Ihr eigenes System in FreeMaint schreibt, darf Ihnen nie als Echo zurückkommen und doppelt gebucht werden. Nur ein auf einem Arbeitsauftrag in FreeMaint erfasster Verbrauch löst part.consumed aus. Das Teil enthält außerdem custom_reference: Ihren eigenen Code dafür, die über createPart oder updatePart gesetzte customReference, damit ein System, das den Katalog führt, jede Zeile ohne eine Tabelle der FreeMaint-IDs zuordnen kann.

{ "event": "part.consumed", "timestamp": "2026-08-19T21:04:11.000Z", "data": { "part": { "id": 812, "name": "Lager 6204", "part_number": "RLM-204", "reference": "PART-812", "custom_reference": "BC-10045", "unit_cost": 12.5, "unit_of_measure": "St" }, "quantity": -2, "previous_quantity": 48, "new_quantity": 46, "work_order": { "id": 5521, "reference": "WO-2026-0412", "title": "Lagerwechsel" }, "asset": { "id": 91, "name": "Separator 2" }, "location": { "id": 7, "name": "Werkslager" }, "user": { "id": 5627, "name": "A. Techniker" }, "stock_movement_id": 88213, "occurred_at": "2026-08-19T21:04:11.000Z" } }

Zustellung und Signatur

Jede Zustellung ist ein POST mit JSON-Body und einem Header X-FreeMaint-Signature in der Form t=<Unix-Sekunden>,v1=<hex>, wobei v1 der HMAC-SHA256 der Zeichenkette "<t>.<Rohbody>" mit Ihrem Webhook-Secret als Schlüssel ist. Prüfen Sie gegen den ROHEN Body, vor jedem JSON-Parsen oder erneutem Serialisieren. Wir senden außerdem X-FreeMaint-Event und X-FreeMaint-Delivery-Id. Ein 2xx gilt als zugestellt; Netzwerkfehler und 5xx werden bis zu 3-mal mit exponentiellem Backoff wiederholt (etwa 2 s, 4 s, 8 s); ein 4xx gilt als endgültige Ablehnung und wird NICHT wiederholt.

Eine Zustellung erneut senden

Jeder Versuch bleibt im Zustellverlauf des Webhooks erhalten, mit Status und Antwortcode. Jede abgeschlossene Zustellung kann von dort erneut gesendet werden: Die gespeicherte Nutzlast geht unverändert erneut raus, die enthaltenen Geschäftsschlüssel (darunter stock_movement_id) bleiben also gleich, und ein korrekt deduplizierender Empfänger bucht nicht doppelt. So holen Sie nach, was während eines Ausfalls Ihres Endpunkts oder einer irrtümlichen Ablehnung verloren ging.

Fotos (optional)

Ist „Fotos einschließen“ für einen Webhook aktiviert (standardmäßig aus), enthalten die Objekte "work_order" und "request" ein Array "photos": bis zu 4 HTTPS-Links zu JPG-, PNG-, GIF- oder WebP-Bildern, die neuesten zuerst. Jeder Link öffnet das Bild 7 Tage lang ohne Anmeldung – speichern Sie die Datei bei sich, wenn Sie sie länger brauchen. Eine erneute Zustellung sendet dieselben Links. Andere Ereignisse und andere Webhooks bleiben unverändert. Bei "work_order.created" und "request.created" wird ein Webhook mit „Fotos einschließen“ 90 Sekunden nach dem Ereignis gesendet (das Feld "timestamp" behält die Zeit des Ereignisses), damit die direkt danach hochgeladenen Fotos enthalten sind.

Anforderungen an die URL

  • Nur https:// — einfaches http wird abgelehnt
  • Nur Port 443 oder 8443
  • Der Host muss öffentlich erreichbar sein — Loopback-, private und CGNAT-Bereiche werden abgelehnt
  • Keine Zugangsdaten in der URL (https://user:pass@host wird abgelehnt)
  • Ein System, das nur in Ihrem internen Netz existiert, braucht einen öffentlichen Endpunkt oder ein Relais (n8n, Make, Zapier) davor

Grenzwerte

  • Starter — 100 Zustellungen/Tag pro Unternehmen
  • Business — unbegrenzt
  • Enterprise — unbegrenzt
  • Gezählt werden Zustellversuche: Drei Webhooks auf dasselbe Ereignis verbrauchen drei Einheiten
  • Der Tageszähler wird um 00:00 UTC zurückgesetzt

Tipp

Prüfen Sie den Header X-FreeMaint-Signature bei jeder Anfrage gegen den rohen Body, damit ein gefälschter Aufruf keinen Bestand in Ihrem ERP bewegen kann.

War diese Seite hilfreich?