Ein Webhook ist eine Adresse in Ihrem System, die Hermetry aufruft, wenn ein Ereignis eintritt. Nutzen Sie ihn, um ein Ticketsystem, ein ERP, einen Message Bus oder Ihren eigenen Dienst zu versorgen. Webhooks werden von Administratoren unter Webhooks (im Bereich Developer des Menüs) verwaltet. Das Senden von Webhooks erfordert einen Tarif, der sie enthält.
Webhook erstellen
- Öffnen Sie Webhooks und wählen Sie New Webhook.
- Geben Sie einen Name ein und optional eine Description („What is this webhook for?“).
- Geben Sie die URL ein. Sie muss HTTPS sein: „Webhook-URL muss eine gültige HTTPS-URL sein.“
- Wählen Sie unter Events mindestens ein Ereignis aus. Die Liste zeigt nur die Ereignisse der Module, die Ihre Organisation nutzt.
- Optional:
- Custom headers (optional): bis zu 20 Header, die bei jedem Aufruf gesendet werden, zum Beispiel ein Autorisierungstoken, das Ihr Empfänger prüft.
Content-Type,User-Agent,Host,Content-LengthundX-Webhook-*können nicht gesetzt werden. Werte sind einzeilig und höchstens 1.000 Zeichen lang. - Event filters (optional, advanced): ein Ereignis nur dann zustellen, wenn seine Nutzdaten übereinstimmen (siehe unten).
- Tags (optional, comma-separated): Bezeichnungen zur Organisation Ihrer Webhooks, bis zu 20.
- Rate limit (optional, deliveries/minute): leer bedeutet unbegrenzt.
- Custom headers (optional): bis zu 20 Header, die bei jedem Aufruf gesendet werden, zum Beispiel ein Autorisierungstoken, das Ihr Empfänger prüft.
- Speichern. Kopieren Sie das Signing secret jetzt: Es wird nur einmal angezeigt.
Alle Ereignisse der IoT-Module sind mit Beispiel-Payloads in der Webhook event reference aufgeführt.
Event-Filter
Ein Event-Filter ist eine JSON-Zuordnung von einem Ereignis zu den Feldern der Nutzdaten, auf die es passen muss. Eine Zustellung wird übersprungen, wenn die Nutzdaten nicht passen. Ereignisse ohne Filter werden immer zugestellt.
{
"alarm.created": { "severity": "CRITICAL" },
"device.disconnected": { "profileId": "6f1c0a2e-0000-4000-8000-000000000001" }
}
Jeder Pfad benennt ein Feld der data des Ereignisses und darf mit Punkten geschrieben sein, zum Beispiel originator.type. Jedes aufgeführte Feld muss seinem Wert entsprechen (Zahlen und Text werden als Text verglichen, sodass "2" auf 2 passt). Höchstens 50 Ereignisse können einen Filter haben.
Wie eine Zustellung aussieht
Hermetry sendet ein POST mit diesen Headern:
| Header | Wert |
|---|---|
Content-Type | application/json (Standardformat) oder application/cloudevents+json; charset=utf-8 |
User-Agent | Hermetry-Webhooks/1.0 |
X-Webhook-Event | Der Ereignisname, zum Beispiel device.disconnected |
X-Webhook-Delivery | Die Zustell-ID. Sie ist bei jedem Wiederholungsversuch und jeder erneuten Zustellung derselben Zustellung gleich. |
X-Webhook-Timestamp | Unix-Sekunden, zu denen dieser Versuch signiert wurde |
X-Webhook-Signature-V2 | sha256= + HMAC-SHA256 von "<timestamp>.<body>" mit Ihrem Secret. Verwenden Sie diese. |
X-Webhook-Signature | HMAC-SHA256 nur über den Body. Ältere Form, für eine Übergangszeit beibehalten. |
X-Webhook-Signature-Prev, X-Webhook-Signature-V2-Prev | Dieselben Werte mit dem vorherigen Secret, während einer Secret-Rotation |
X-Webhook-Manual | true bei einem Ereignis, das ein Administrator manuell gesendet hat |
X-Idempotency-Key | Bei Nachrichten, die ein Flow über seinen Webhook-Block sendet |
Beim Standardformat ist der Body ein Envelope:
{
"webhookId": "…",
"tenantId": "…",
"event": "device.disconnected",
"createdAt": "2026-11-03T12:00:30.000Z",
"data": { "deviceId": "…", "name": "router-17", "reason": "timeout", "…": "…" }
}
Ein manuell von einem Administrator gesendetes Ereignis enthält außerdem "manual": true. Antworten Sie innerhalb des Timeouts mit einem beliebigen 2xx-Status. Die ersten 4 KB des Antwort-Bodys werden im Zustellprotokoll gespeichert.
CloudEvents-Format
Ein Endpunkt kann stattdessen CloudEvents 1.0 im Structured Mode empfangen. Das Webhook-Formular bietet noch keine Formatauswahl: Setzen Sie "format": "cloudevents" über die API (POST oder PATCH /api/webhooks/..., siehe unten). "json" ist der Standard.
{
"specversion": "1.0",
"id": "8d2c…",
"source": "urn:hermetry:tenant:<tenantId>",
"type": "com.hermetry.device.connected",
"datacontenttype": "application/json",
"time": "2026-11-03T10:00:30.000Z",
"data": { "deviceId": "…", "name": "router-17", "transport": "mqtts", "…": "…" },
"tenantid": "<tenantId>",
"webhookid": "<webhookId>"
}
data enthält genau das, was das Standardformat unter data enthält. id ist bei jedem Wiederholungsversuch und jeder erneuten Zustellung gleich, daher deduplizieren Sie über source und id. Die Signatur-Header sind in beiden Formaten gleich. Batch- und Binary-Modus werden nicht angeboten.
Signatur prüfen
Prüfen Sie gegen den unveränderten Body, bevor Sie ihn parsen, und lehnen Sie alte Zeitstempel ab.
import crypto from 'crypto';
function verifyWebhook(body: string, timestamp: string, signatureV2: string, secret: string): boolean {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${body}`).digest('hex');
// Reject deliveries older than 5 minutes.
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const a = Buffer.from(expected);
const b = Buffer.from(signatureV2);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Während einer Secret-Rotation akzeptieren Sie einen Aufruf, wenn entweder X-Webhook-Signature-V2 oder X-Webhook-Signature-V2-Prev passt.
Zustellung, Wiederholungen und Dead Letters
| Einstellung | Standard | Bereich |
|---|---|---|
| Request Timeout (ms) | 15,000 | 1.000 bis 120.000 |
| Max Delivery Attempts (der erste Versuch eingeschlossen) | 3 | 1 bis 10 |
| Retry Backoff (ms): die Wartezeit vor Wiederholung 1, 2, … | 60000,300000,900000 | 1 bis 9 Werte, jeweils 1.000 bis 86.400.000; danach gilt der letzte Wert |
| Circuit Breaker Threshold: aufeinanderfolgende Fehler, bevor der Endpunkt abgeschaltet wird | 10 | 1 bis 100.000 |
| Default Rate Limit (per minute): für Endpunkte ohne eigenes Limit | unbegrenzt | leer oder 0 = unbegrenzt |
Stellen Sie diese unter Webhooks > Einstellungen (Zahnrad-Schaltfläche) ein. Eine Zustellung hat einen der Status PENDING, SUCCESS, FAILED (wird wiederholt) oder DEAD_LETTERED (alle Versuche verbraucht).
- Jede Zustellung wird mit Status, Versuchen, Antwortcode, Fehler, Dauer und nächstem Wiederholungszeitpunkt protokolliert.
- Ein Endpunkt, der sein Rate Limit überschreitet, erhält seine Zustellungen etwa 60 Sekunden später; nichts wird verworfen.
- Nach dem Schwellenwert an aufeinanderfolgenden Fehlern wird der Endpunkt abgeschaltet und als auto-disabled angezeigt. Wartende Wiederholungen werden gestoppt. Schalten Sie ihn wieder ein, um den Zähler zurückzusetzen, und stellen Sie danach die fehlgeschlagenen Zustellungen erneut zu oder spielen Sie sie wieder ab.
- Zustellungen erfolgen mindestens einmal. Deduplizieren Sie über
X-Webhook-Delivery(oder die CloudEvents-id). - Ereignisse kommen nicht garantiert in der richtigen Reihenfolge an. Verwenden Sie die Zeitangaben in den Nutzdaten.
Ereignisse zu Geräteverbindung und Geräteänderung haben eine eigene Volumenbegrenzung: standardmäßig höchstens 600 jeder Art pro Organisation und Minute. Siehe Webhook event reference.
Secret rotieren
Wählen Sie Rotate signing secret (Rolle Owner). Das neue Secret wird einmal angezeigt. Das vorherige Secret bleibt 48 Stunden gültig; während dieser Zeit enthält jeder Aufruf beide Signaturen. Erneutes Rotieren während dieses Zeitfensters ersetzt nur das aktuelle Secret; das vorherige behält sein Enddatum.
Test
Aus der Zeilenaktion eines Webhooks oder über seine Seite:
- Send test event sendet sofort ein Ereignis namens
testund zeigt das Ergebnis an („Test delivered — HTTP 200 in 85 ms“). Ein Test zählt nie zum Circuit Breaker. - Trigger event… sendet ein echtes, signiertes Ereignis Ihrer Wahl mit einer Beispiel-Payload (JSON-Objekt, höchstens 64 KB), markiert mit
manual: trueundX-Webhook-Manual: true. Es berücksichtigt den Event-Filter des Endpunkts: Ein Beispiel, das der Filter verwerfen würde, wird abgelehnt. - View deliveries listet die Zustellungen auf; eine fehlgeschlagene oder als Dead Letter markierte kann erneut zugestellt werden, und alle Dead Letters können auf einmal erneut abgespielt werden.
Netzwerkregeln
Webhook-Adressen müssen öffentliche HTTPS-Adressen sein. Private, Loopback-, Link-Local- und Cloud-Metadaten-Adressen werden beim Speichern und erneut bei jedem Aufruf abgelehnt; Weiterleitungen werden nicht verfolgt. Für ein bewusst internes Ziel kann ein Administrator über die API eine explizite ipAllowlist (bis zu 50 Adressen oder CIDR-Bereiche) am Webhook setzen.
Die Webhook-API
Pfade liegen unter /tenant/<tenantId>. Alle erfordern die Berechtigungen eines Administrators.
| Methode | Pfad | Funktion |
|---|---|---|
| GET | /api/webhooks/events | Die Ereignisse, die Sie abonnieren können |
| GET, POST | /api/webhooks | Liste (page ab 1, pageSize, search, sort, isActive, autoDisabled); anlegen: 201 { webhook, secret } |
| GET, PATCH, DELETE | /api/webhooks/{webhookId} | Lesen, ändern, löschen |
| POST | /api/webhooks/{webhookId}/rotate-secret | { webhook, newSecret, overlapMs } (Owner) |
| POST | /api/webhooks/{webhookId}/test | { delivery } |
| POST | /api/webhooks/{webhookId}/trigger | { event, payload } → { message, deliveryId } |
| GET | /api/webhooks/{webhookId}/deliveries | { data, total }; Filter status, event, createdFrom, createdTo |
| POST | /api/webhooks/{webhookId}/deliveries/{deliveryId}/redeliver | Eine Zustellung mit dem Status FAILED oder DEAD_LETTERED erneut in die Warteschlange stellen |
| GET, POST | /api/webhooks/{webhookId}/deliveries/replay-dead-letter | Jeden Dead Letter zählen oder erneut in die Warteschlange stellen |
| GET | /api/webhooks/metrics, /api/webhooks/report | Zustellungsstatistik (?webhookId=&days=) |
Create-Body: name, description, url, events, headers, eventFilters, tags, rateLimitPerMinute (1 bis 100.000), ipAllowlist, format (json oder cloudevents).
| Ablehnung | Bedeutung |
|---|---|
403 WEBHOOKS_NOT_IN_PLAN | Ihr Tarif enthält keine Webhooks |
409 ENDPOINT_DISABLED | Der Endpunkt ist deaktiviert; aktivieren Sie ihn zuerst |
409 DELIVERY_NOT_REDELIVERABLE | Die Zustellung ist ausstehend oder war bereits erfolgreich |
422 EVENT_FILTERED_OUT | Der Filter des Endpunkts würde das von Ihnen ausgelöste Beispiel verwerfen |
422 | Ein Ereignis, das kein Modul Ihrer Organisation anbietet |

