Webhooks
Webhooks senden Events aus dem CMS zu externen Systemen, sobald sie auftreten. Wird eine Bestellung erfasst, eine Seite veroeffentlicht oder ein Formular abgeschickt, feuert das CMS einen HTTP-POST an die URLs, die das Event abonniert haben. So verbindest du das CMS mit Zapier, Make, Slack, einem CRM oder einer eigenen Integration.
Webhook-Abonnements leben neben den API-Schluesseln. Oeffne Einstellungen → API-Schlüssel und wechsel auf den Webhooks-Tab.

1. Abonnement anlegen
Klick Neuer Webhook. Das Modal fragt nach:
| Feld | Zweck |
|---|---|
| Name | Sprechendes Label, z.B. Slack: orders channel. |
| URL | HTTPS-Endpunkt, der den POST empfaengt. Einfaches HTTP wird abgelehnt. |
| Events | Mehrfach-Auswahl. Haken bei jedem Event, das dieses Abonnement bekommen soll. |
| Secret | Auto-generiert. Nutz ihn zur Signatur-Pruefung auf der Empfaengerseite. |
| Aktiv | Schalter zum Pausieren ohne Loeschen. |

Klick Speichern. Das Abonnement empfaengt Events ab sofort.
2. Events waehlen
Events sind nach Domain gruppiert. System-Events sind immer verfuegbar:
| Event | Feuert wenn |
|---|---|
page.published | Ein Entwurf wird live geschaltet. |
page.draft_discarded | Ein Entwurf wird verworfen. |
media.uploaded | Eine Datei wird hochgeladen. |
media.deleted | Eine Datei wird geloescht. |
auth.login | Ein Backend-Benutzer meldet sich an. |
auth.logout | Ein Backend-Benutzer meldet sich ab. |
order.created | Eine Native-Shop-Bestellung wird erfasst. |
form.submitted | Ein Frontend-Formular wird abgeschickt. |
user.registered | Ein Frontend-Kundenkonto wird angelegt. |
elearning.purchased | Ein Teilnehmer kauft einen CME-Kurs. |
elearning.video_completed | Ein Teilnehmer sieht mindestens 95% einer Episode oder des Hauptvideos. |
elearning.exam_passed | Ein Teilnehmer besteht die CME-Pruefung. |
elearning.certificate_issued | Ein E-Learning-Zertifikat wird ausgestellt. |
shopware6.order_placed | Eine Shopware-6-Bestellung wird abgeschlossen. |
shopware6.product_updated | Ein Produkt im verbundenen Shopware-Shop wird aktualisiert. |
shopware6.cache_invalidated | Der lokale Shopware-Kategorie-/Produkt-Cache wird invalidiert. |
deployment.completed | Ein Staging-zu-Live-Deployment ist erfolgreich durchgelaufen. |
Plus Auto-Events fuer jede ueber das CMS verwaltete Content-Tabelle:
item.{table}.createditem.{table}.updateditem.{table}.deleted
Ein Blog-Artikel liefert also item.blog_articles.created.
3. Signatur-Pruefung
Jede Zustellung traegt den Header X-Webhook-Signature mit einer HMAC-SHA256-Signatur des rohen Request-Body, Schluessel ist das Secret des Abonnements.
Pruef die Signatur auf der Empfaengerseite, um Faelschungen abzulehnen:
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'];
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $body, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}Sensible Felder werden automatisch gefiltert
Der Dispatcher entfernt jedes Payload-Feld mit password, secret, hash, key, token oder salt im Namen. Diese Felder verlassen das CMS nie — Empfaenger muessen sie nicht behandeln.
4. Abonnement testen
Klick auf das Papierflieger-Icon Testen in der Zeile. Das System feuert eine einzelne webhook.test-Zustellung mit trivialem Payload an die URL. Response-Status und Body werden inline gezeigt.
Damit pruefst du:
- URL erreichbar.
- Server liefert
200(oder204). - Signatur-Pruefung akzeptiert das Test-Payload.
5. Zustell-Historie
Jeder Versuch wird geloggt. Oeffne im Task-Manager den Webhooks-Tab oder klick Zustellungen in einem Abonnement. Die Historie zeigt:
- Zeitstempel und Statuscode.
- Response-Body (auf 4 KB gekuerzt).
- Versuchsnummer.
Fehlgeschlagene Zustellungen werden mit exponentiellem Backoff wiederholt. Maximal 5 Versuche. Nach 10 Fehlschlaegen in Folge ueber alle Abonnements hinweg schaltet der Circuit Breaker das Abonnement automatisch auf Inactive — du siehst den Warn-Badge in der Liste. Fix den Empfaenger, reaktivier mit Aktiv, und die Warteschlange laeuft weiter.

6. Secret rotieren
Klick auf das Auffrischen-Icon Secret rotieren, um ein neues geteiltes Geheimnis zu generieren. Das alte greift ab sofort nicht mehr. Aktualisier den Empfaenger parallel.
7. Abonnement loeschen
Klick auf das Muell-Icon Löschen. Noch nicht gefeuerte Zustellungen werden verworfen. Die Historie bleibt, bis der Cleanup-Job sie trimmt.
Die Zustell-Warteschlange
Webhooks werden nicht inline gesendet — der ausloesende Request antwortet sofort, und ein Warteschlangen-Worker arbeitet die ausstehenden Zustellungen ab. Der Worker laeuft alle 30 Sekunden ueber den Cron-Scheduler (siehe Task-Manager).
Laeuft der Cron nicht, stauen sich Zustellungen, ohne zu scheitern. Fix zuerst den Cron, dann beobachte, wie die Warteschlange abgearbeitet wird.
HTTPS ist Pflicht
URLs muessen mit https:// starten. Einfache HTTP-Abonnements werden beim Speichern abgelehnt, weil der Signatur-Header ohne verschluesselten Transport keinen Schutz vor Man-in-the-Middle bietet.
Haeufige Fehler
Abonnement springt selbststaendig auf Inactive. Der Circuit Breaker hat nach 10 Fehlern ausgeloest. Oeffne die Zustell-Historie, fix den Empfaenger, reaktivier Aktiv.
Test-Ping klappt, echte Events kommen nie. Events sind zwar registriert, aber nicht im Abonnement aktiviert. Oeffne das Abonnement, kontrollier die Event-Liste, speicher.
Signatur-Pruefung schlaegt immer fehl. Lies den rohen Body, nicht das geparste JSON. Viele Frameworks veraendern den Body, bevor du ihn siehst — die HMAC rechnet gegen die exakten Bytes ueber den Draht.
Payload kommt an, ein Feld fehlt. Sensible Felder (password, secret, hash, key, token, salt) werden vor dem Dispatch entfernt. Das ist gewollt und laesst sich nicht abschalten.
Siehe auch
- API-Schluessel — der Pull-Gegenpart zu Webhooks.
- Task-Manager — der Worker, der die Warteschlange abarbeitet.
- Log — Audit-Trail fuer
auth.login/auth.logout.