Webhooks
Statt ständig nachzufragen, kann sich ein Programm Änderungen melden lassen. WorkOffice schickt dann eine kurze Nachricht an eine Adresse des Programms. Sie nennt nur Kennungen – den Stand holt der Empfänger selbst mit seinem Schlüssel ab. So kann eine verspätete oder doppelt zugestellte Meldung nichts Falsches behaupten: Abgeholt wird immer das Aktuelle.
Es gibt zwei Sorten, je nach Schnittstelle.
Webhooks der Lexware-kompatiblen Schnittstelle
Abonnieren mit einem allgemeinen API-Schlüssel:
curl -X POST https://buero.ihrbetrieb.de/api/lexware/v1/event-subscriptions \
-H "Authorization: Bearer wo_test_ab1.NurEinBeispielKeinEchterSchluessel000000000" \
-H "Content-Type: application/json" \
-d '{"eventType":"invoice.status.changed","callbackUrl":"https://programm.example.de/webhook"}'
Für jedes Ereignis braucht der Schlüssel das passende Leserecht (Kontakte customer:read, Artikel article:read, Eingangsbelege expense:read, Rechnungen, Angebote und Zahlungen document:read). Dasselbe Ereignis an dieselbe Adresse zweimal ergibt 409.
Ereignisse – dieselben Namen wie bei Lexware Office:
| Bereich | Ereignisse |
|---|---|
| Rechnungen | invoice.created, invoice.changed, invoice.status.changed, invoice.deleted |
| Angebote | quotation.created, quotation.changed, quotation.status.changed, quotation.deleted |
| Zahlungen | payment.changed |
| Kontakte | contact.created, contact.changed |
| Artikel | article.created, article.changed, article.deleted |
| Eingangsbelege | voucher.created (nach der Erkennung) |
| Schlüssel | token.revoked (einmal, beim Widerruf des Schlüssels) |
Der Leib:
{
"organizationId": "8e0c1f2a-0000-4000-8000-000000000001",
"eventType": "invoice.status.changed",
"resourceId": "5b7d9e10-0000-4000-8000-000000000002",
"eventDate": "2026-10-23T09:15:00.000+02:00"
}
Die Signatur steht im Kopffeld X-Lxo-Signature: RSA mit SHA-512 über genau die gesendeten Bytes, Base64 – wie bei Lexware. Den öffentlichen Schlüssel zum Prüfen gibt es ohne Anmeldung unter GET /api/v1/webhooks/oeffentlicher-schluessel; er ist nicht geheim. Den privaten Schlüssel trägt der Betreiber des Servers als WEBHOOK_PRIVATE_KEY in die .env ein. Fehlt er im Betrieb, werden keine Webhooks zugestellt – sie warten, bis ein Schlüssel da ist. Auf der Einstellungsseite steht dann:
Kein Schlüssel – Webhooks werden zurückgehalten.
Das betrifft nur die Lexware-Webhooks. Die Webhooks der WorkTime-Verbindung brauchen WEBHOOK_PRIVATE_KEY nicht – sie signieren mit einem eigenen Geheimnis je Verbindung (unten).
Webhooks der WorkTime-Verbindung
WorkTime meldet seine Adresse mit PUT /api/worktime/v1/webhook und bekommt ein Geheimnis zurück. Die Ereignisse:
| Ereignis | wann |
|---|---|
beleg.geaendert | ein von WorkTime angelegter Beleg wurde festgeschrieben, (teilweise) bezahlt, storniert, angenommen oder abgelehnt oder als Entwurf geändert |
beleg.geloescht | ein solcher Entwurf wurde in WorkOffice gelöscht |
kunde.geaendert | Kontakt angelegt, geändert oder archiviert |
artikel.geaendert | Artikel angelegt, geändert oder archiviert |
Der Leib: { "ereignis": "beleg.geaendert", "id": "…", "zeit": "…" }. Signiert wird im Kopf X-WorkOffice-Signatur: t=<Unix-Sekunden>,v1=<hex>, wobei v1 der HMAC-SHA256 mit dem Geheimnis über "<t>." + roher Leib ist. Der Zeitstempel steckt mit in der Signatur, damit niemand eine alte Zustellung später noch einmal abspielen kann; WorkTime lehnt ab, was älter als fünf Minuten ist. Diese Webhooks gehen nur hinaus, wenn der Betrieb den Datenaustausch mit WorkTime Pro im Paket hat (Komplett).
Zustellung und Wiederholung
Für beide Sorten gleich:
- Zugestellt wird sofort nach dem Ereignis. Als Erfolg gilt jede 2xx-Antwort innerhalb von zehn Sekunden.
- Sonst folgt der nächste Versuch nach 1, 2, 4 … 64 Minuten, höchstens acht Versuche; danach gilt die Zustellung als gescheitert. Die Reihenfolge ist nicht garantiert.
- Weiterleitungen werden nicht verfolgt.
Erlaubte Ziele
Die Rückrufadresse gibt ein fremdes Programm vor. Ohne Prüfung könnte es den Server Anfragen in das eigene Netz schicken lassen – an die Datenbank oder an interne Dienste. Deshalb:
- im Betrieb nur
https://, ohne Zugangsdaten in der Adresse; - keine privaten, lokalen oder reservierten Adressen – geprüft wird beim Abonnieren, vor jeder Zustellung und noch einmal beim Verbindungsaufbau selbst.
Läuft der Empfänger im eigenen Netz, etwa WorkTime Pro auf demselben Server, schaltet der Betreiber das mit WEBHOOK_INTERNE_ZIELE=true frei, Klartext mit WEBHOOK_HTTP_ERLAUBT=true.
In der Oberfläche
Unter Verwaltung → WorkTime Pro stehen für die Lexware-kompatiblen Webhooks die Abonnierten Ereignisse samt Schlüssel und letzter Zustellung sowie die Letzten Zustellungen mit Stand („Zugestellt“, „Wartet“, „Gescheitert“), Fehlermeldung des Empfängers und dem Knopf Erneut senden. Jede WorkTime-Verbindung zeigt oben ihre Webhook-Adresse, die letzte Zustellung und wie viele in den letzten sieben Tagen gescheitert sind. Erledigte Zustellungen werden nach 30 Tagen entfernt.