verifyWebhook checks that a request to your endpoint was signed with the signing secret of your webhook subscription, and returns the event. This page gives the two functions of the SDK, what they check, the type of the event, and two complete handlers. Read it when you write the endpoint that receives deliveries. Webhooks overview describes subscriptions and what your endpoint must do, and Verifying signatures gives the algorithm and a test vector.
The two functions
verifyWebhook checks the signature and the timestamp of a delivery, then checks the body and returns the event. It is synchronous. It throws WebhookSignatureError on any failure.
parseWebhookEvent applies the same checks to the body and verifies no signature. Use it on a body that verifyWebhook accepted before, for example one you stored. Do not use it on an incoming request.
Both functions are named exports of @isnap/sdk. They need no client and no API key.
Arguments of verifyWebhook
Tolerance
webhook-timestamp must be within 300 seconds of the clock of your server, earlier or later. options.tolerance changes that window. A tolerance of 0 does not turn the check off: it requires the same second.
iSnap renews webhook-timestamp on every attempt, so the tolerance never rejects a legitimate retry or replay when the clock of your server is synchronized.
Several secrets
Each attempt is signed with the current secret of the subscription, and with that one only. Afterwebhooks.rotateSecret, every delivery is signed with the new secret, retries included. Passing [newSecret, oldSecret] matters only for the requests signed before the rotation and still in transit. Secret rotation describes the rotation.
Failures
WebhookSignatureError carries a message and no code. Its causes are:
Treat every failure the same way: do not process the body, and respond
400. Any status outside 2xx is a failed attempt. iSnap retries the delivery on its retry schedule, except after a 410: a 410 is not retried, and it makes the subscription inactive. Never respond 410.
The event
Both functions return aWebhookEventBase:
The return type is not the
WebhookEvent union, and a switch on event.event_type does not narrow data. Narrow the event with a type guard. Envelope describes these fields.
Type guards
There are nine guards, one per event family. Each matches on the prefix ofevent_type, so a new event type of a known family matches without an SDK upgrade.
Only two families have a typed
data. For the seven others, read each value of data as unknown and check it. In a message.* event, the keys of data other than message, such as chat_id, are in the payload and not in the type: read them through a cast. The fields of every event are on the pages of the event catalog.
MessageEventType, ReactionEventType, LineEventType, TypingIndicatorEventType, TrialEventType, PreOrderEventType, BindingEventType, MacosSessionEventType and AdminEventType list the 37 event types that version 2.2.1 of the SDK knows. The API can add event types: see Unknown event types.
Unknown event types
An event type the SDK does not know is accepted and returned. No guard matches it, and nothing throws. Ignore response fields, enum values and event types you do not know.Duplicates and order
verifyWebhook does not deduplicate. A retry or a replay carries the same event_id. Deduplicate on event_id. See Duplicates.
Delivery order is not guaranteed. Order events by the timestamps inside data, not by arrival. See Order.
Events do not announce every change: see What events do not announce, and reconcile from the resource operations.
A handler for the Node.js http module
The handler reads the raw body, verifies it, and skips anevent_id it has already processed. It records an event_id only after the work on the event succeeded. The set of processed ids lives in memory: Example: handling webhooks says what to replace it with.
A handler for a fetch-style Request
Use this form where a runtime or a framework passes a Request and expects a Response. The requirements of the SDK apply there too: verifyWebhook needs node:crypto and a global Buffer.
Personal data
A verified event can carry handles, message text, names and a secret:
The page of each event family lists the personal data of each event. Subscribe to these events only when needed. Do not copy their content into logs, tickets or other tools, and refer to a contact by an id of your own. The two handlers above log the event type and the event id only.