Skip to main content
Darwin signs every delivery with Standard Webhooks. Darwin.webhooks.verify(payload, headers, secret, toleranceSeconds = 300) checks the signature and the timestamp and returns the parsed event, or throws a WebhookVerificationError whose reason says why.
verify is async (it returns a Promise), because it uses Web Crypto so that it runs the same on Node and edge runtimes. Always await it.
Pass the raw request body, exactly as received. A body that was parsed and turned back into JSON will not verify. Respond with a 2xx quickly and do slow work afterwards. Darwin retries failed deliveries with the same webhook-id, so dedupe on event.id. See Delivery and retries.
In Express, express.raw must run on this route before any JSON body parser, so req.body is a Buffer. The Next.js handler works in the Node.js and Edge runtimes alike.

Event payloads

event.data.object is the contact, conversation, meeting, experiment or knowledge source the event is about, as the REST API returns it, or null if it no longer exists. lead.captured also carries data.conversation; knowledge.source_failed carries data.error. After a privacy erasure an event’s payload becomes { erased: true }. Narrowing on event.type gives you the right type for data.object. Every type: Events and payloads. The test event sent by webhookEndpoints.test() has type webhook.test.

Test locally

To exercise your receiver locally, Darwin.webhooks.sign(body, secret) returns the headers Darwin would send.

Secret rotation

During a secret rotation (webhookEndpoints.rotateSecret), deliveries carry a signature for each secret; verify accepts the delivery if any of them matches the secret you pass.