Webhooks: eine signierte Nachricht, wenn ein Dokument erstellt oder geteilt wird
Im Konto-Menü → Webhooks hinterlegen Sie eine URL, die für zwei Ereignisse einen signierten POST erhält, document.created und document.shared. Verwaltet wird das absichtlich nur aus einer Sitzung — es bleibt außerhalb der skriptbaren API, damit ein geleakter API-Schlüssel nicht zu einem dauerhaften Strom aller folgenden Dokumente werden kann.
Zwei Dinge geschehen in einem Konto, von denen ein anderes Programm sofort erfahren möchte: Ein Dokument wurde erstellt, und ein Dokument wurde geteilt. Im Konto-Menü → Webhooks hinterlegen Sie eine https://-URL, die davon hören soll, und lesen das Geheimnis, mit dem signiert wird.
Was ankommt
Ein POST, dessen JSON-Rumpf drei Schlüssel hat — das Ereignis, den Zeitpunkt und die Daten:
{
"event": "document.created",
"created_at": "2026-09-11T09:12:44.000Z",
"data": { "id": "…", "name": "release-notes.md", "kind": "markdown-to-html", "size": 4193 }
}
document.shared trägt id und name, den mode, in dem das Dokument jetzt ist, die url zum Teilen und notified — die Adressen, an die wirklich eine Nachricht ging. Den Text des Dokuments trägt keines der Ereignisse: Ein Empfänger, der ihn braucht, hat die id und einen API-Schlüssel.
Die Signatur prüfen
Jede Zustellung hat einen Header x-transformpipe-signature in der Form t=<Unix-Sekunden>,v1=<hex>. v1 ist HMAC-SHA256 über die Zeichenkette <t>.<Rumpf>, mit dem Geheimnis dieses Webhooks als Schlüssel — dieselbe Form, die Stripe und GitHub verwenden, sodass vorhandener Prüfcode meist nur ein anderes Geheimnis braucht.
import { createHmac, timingSafeEqual } from 'node:crypto';
// `raw` ist der Rumpf, wie er ankam. Neu kodiert ergibt er einen anderen Hash.
export function verify(raw, header, secret) {
const [t, v1] = header.split(',').map((part) => part.split('=')[1]);
const want = createHmac('sha256', secret).update(`${t}.${raw}`).digest('hex');
return (
v1.length === want.length &&
timingSafeEqual(Buffer.from(v1, 'hex'), Buffer.from(want, 'hex'))
);
}
Weisen Sie ein t zurück, das älter als ein paar Minuten ist, und eine mitgeschnittene Zustellung lässt sich später nicht wiederholen. Das Geheimnis beginnt mit whsec_ und lässt sich im Dialog wieder anzeigen: Anders als ein API-Schlüssel wird es von uns Ihnen gegenüber vorgezeigt, es beim Einrichten zweimal zu lesen ist also legitim.
Ein Versuch, keine Warteschlange
Eine Zustellung ist eine Anfrage mit fünf Sekunden Zeitlimit. Es gibt keinen zweiten Versuch und keine Warteschlange: Ein Empfänger, der gerade nicht läuft, verpasst dieses Ereignis, das nächste versucht es von sich aus wieder. Der Dialog nennt pro URL den letzten Status oder den letzten Fehler. Weiterleitungen werden nicht verfolgt, und die Adresse wird beim Senden erneut geprüft, nicht nur beim Anlegen.
Warum ein API-Schlüssel keinen anlegen kann
Webhooks werden ausschließlich aus einer angemeldeten Sitzung verwaltet. Ein Schlüssel, der einen Webhook anlegen könnte, würde aus einem punktuellen Leck einen dauerhaften Strom aller künftigen Dokumente machen — ein schlimmerer Verlust als der eines Schlüssels.
Weiter: Dokumente über eine API konvertieren und aus GitHub Actions veröffentlichen.