Endpunkte
`webhooks.list`, `get`, `create`, `update`, `delete`, `rotateSecret`, `test` und `listDeliveries`.
Alle Methoden
const endpoint = await openemail.webhooks.create({ url: 'https://acme.com/hooks/mail', eventTypes: ['email.sent', 'email.bounced'], description: 'Billing service',}) await store(endpoint.secret) await openemail.webhooks.list()await openemail.webhooks.get(endpoint.id)await openemail.webhooks.update(endpoint.id, { enabled: false })await openemail.webhooks.test(endpoint.id)const rotated = await openemail.webhooks.rotateSecret(endpoint.id)await openemail.webhooks.delete(endpoint.id)create ist – abgesehen von rotateSecret – der EINZIGE Zeitpunkt, an dem das Secret zurückgegeben wird. Ein Lesevorgang gibt es nie wieder aus; es sollte daher gespeichert werden, bevor irgendetwas anderes geschieht. Ohne eventTypes werden alle Events empfangen, auch später hinzukommende.
rotateSecret hat kein Überlappungsfenster. Das alte Secret funktioniert sofort nicht mehr; das neue sollte daher vor der Rotation ausgerollt werden. Der Aufruf wird nie automatisch wiederholt: Ein Wiederholungsversuch würde ein zweites Mal rotieren und das Secret ungültig machen, das der erste Versuch zurückgegeben hat.
Was abonniert werden kann
WEBHOOK_EVENTS wird exportiert, damit sich die Liste rendern lässt. Events sind Events des **Postfachs**, nicht dieser API: email.received feuert für Mail, die in der App eingeht, und email.sent feuert für eine Nachricht, die der Composer gesendet hat. Ein Abonnement ist nicht dasselbe wie das Beobachten des eigenen API-Verkehrs.
Nachweisen, dass es funktioniert
const result = await openemail.webhooks.test('whe_…')console.log(result.delivery?.status, result.delivery?.responseCode) const deliveries = await openemail.webhooks.listDeliveries('whe_…')for (const d of deliveries) console.log(d.eventType, d.status, d.responseCode, d.error)Ein responseCode von null bedeutet, dass es überhaupt keine Antwort gab (DNS, TLS, ein Timeout), was etwas anderes ist als eine Antwort, die 0 lautete. Jede Zeile führt attempt und maxAttempts mit, sodass mehrere Zeilen ein Event beschreiben können: Die gleiche payload.id über sie hinweg ist das Event, und die Versuchsnummer ist der Versuch.
Parameter: webhooks.create
urlstringerforderlich- Wohin Zustellungen ge-POSTet werden. Nur HTTPS, und der Host darf nicht `localhost`, ein `.localhost`/`.local`/`.internal`-Name oder ein Loopback-, privates, CGNAT- oder Link-Local-IP-Literal sein. Dies ist ein serverseitiger fetch an eine selbst angegebene Adresse, daher ergeben diese ein 422 auf `url`; die Prüfung liest den Hostnamen so, wie er geschrieben steht, und löst nie DNS auf. Gespeichert wird die Serialisierung des URL-Parsers für das Gesendete, `https://acme.com` liest sich also als `https://acme.com/` zurück.
eventTypesWebhookEvent[]- Welche Events diesen Endpunkt erreichen: beliebige der Namen aus `WEBHOOK_EVENTS`. `POST /webhooks` begrenzt das Array auf die Anzahl der existierenden Events, eines mehr ist also ein 422 auf `eventTypes`; `PATCH` begrenzt es nicht. Begrenzt wird nur die Länge, und ein wiederholter Name wird genau so gespeichert und zurückgelesen, wie er gesendet wurde. Weggelassen oder leer wird als leere Liste gespeichert, weshalb sie sich als `['*']` zurückliest, und das bedeutet jedes `email.*`-Event außer `email.replied`, heute vierzehn, und nie die Domain- oder Suppression-Familien. Eine später hinzugefügte Familie erreicht nie einen Endpunkt, der sie nicht benannt hat; eine Integration kann also nicht durch ein Release beginnen, eine Form zu empfangen, die sie nie gesehen hat.
descriptionstring- Eine Bezeichnung für den Endpunkt, höchstens 200 Zeichen, damit sich eine Liste von Webhooks als Namen liest und nicht als Spalte von URLs. Ohne Angabe wird sie als null gespeichert und zurückgegeben.
Antwort: CreatedWebhookResource
object'webhook'- Immer `'webhook'`, derselbe Diskriminator, den ein einfaches Lesen zurückgibt, denn das Secret ist ein zusätzlicher Key auf der gewöhnlichen Form und kein eigener Objekttyp. Ob `secret` vorhanden ist, entscheidet die aufgerufene Methode und nicht dieses Feld.
idstring- Der Bezeichner des Endpunkts: `whe_` gefolgt von 24 Hexadezimalzeichen. Jeder andere Webhook-Aufruf nimmt ihn entgegen: `get`, `update`, `delete`, `rotateSecret`, `test` und `listDeliveries`.
urlstring- Der Endpunkt, wie er gespeichert ist, nachdem er die HTTPS- und Blocked-Host-Prüfungen bestanden hat. Es ist die erneut serialisierte, geparste URL; verglichen werden sollte daher mit diesem Wert und nicht mit dem gesendeten String.
descriptionstring | null- Die vergebene Bezeichnung, oder null, wenn keine vergeben wurde. Ein `update`, das ein ausdrückliches null sendet, setzt sie wieder auf null zurück.
eventTypesWebhookEvent[] | ['*']- Die abonnierten Events, oder `['*']`, wenn der Endpunkt keine benannt hat. `['*']` ist die Darstellung einer leer gespeicherten Liste beim Lesen und kann nicht zurückgesendet werden; es steht für die dreizehn Nachrichten-Events und nicht für den gesamten Katalog. `create` und `update` akzeptieren ausschließlich die wörtlichen Event-Namen.
enabledboolean- Ob Zustellungen versucht werden; ein deaktivierter Endpunkt wird beim Verteilen von Events übersprungen und behält sein Secret und seine Zustellhistorie. Hier immer true, da `WebhookCreate` kein `enabled` hat und nur `WebhookPatch` eines besitzt.
lastDeliveryAtstring | null- ISO 8601-Zeitstempel des letzten Zustell-VERSUCHS, nicht des letzten Erfolgs. Er wird auch nach einem fehlgeschlagenen POST gesetzt und sagt damit, dass der Endpunkt versucht wurde; wie es ausging, sagt `listDeliveries`. Null bis zum ersten Versuch und daher bei `create` immer null.
createdAtstring- ISO 8601-Zeitstempel der Registrierung des Endpunkts. `list` gibt Endpunkte nach diesem Feld sortiert zurück, neueste zuerst.
secretstring- Der HMAC-SHA-256-Schlüssel, der die `X-OpenEmail-Signature` jeder Zustellung signiert: `whsec_` gefolgt von 32 zufälligen Bytes in base64url, und das, was an `verifyWebhookSignature` übergeben wird. Wird von `create` und `rotateSecret` zurückgegeben und von nichts sonst. Ein Lesevorgang gibt ihn nie wieder aus, er sollte also jetzt gespeichert werden; ein verlorenes Secret lässt sich nur mit `rotateSecret` ersetzen, was das alte sofort ungültig macht.