parseWebhookEvent(sync, usesnode:crypto) — for Node.js servers (Express, Fastify, plainhttp, AWS Lambda on Node runtime, etc.)parseWebhookEventAsync(async, uses WebCrypto) — for any Fetch-API runtime: Next.js app router, Cloudflare Workers, Vercel Edge, Deno, Bun
WebhookVerificationError if the signature is invalid, the timestamp is stale (>5 min
default), or required headers are missing. Both return a typed WebhookEvent on success.
Why two functions? Most edge runtimes don’t ship Node’s
crypto module. WebCrypto is
universally available, but its API is async. Pick the one that matches your runtime; the
signing scheme is identical.The signature scheme
If you’re implementing in a non-TypeScript language, you’ll need the raw scheme. The HMAC is computed over:webhook_idis theWebhook-Idheadertimestampis theWebhook-Timestampheader (Unix seconds)bodyis the raw request body (not parsed JSON)
v1,. The Webhook-Signature header may contain
multiple space-separated signatures during key rotation — accept any match.
Framework recipes
Below: the minimum complete handler for each common partner runtime. Copy, paste, route your events.Next.js (app router)
Next.js (pages router)
Express
Fastify
Cloudflare Workers
Vercel Edge / Bun / Deno / Hono
Any runtime that ships the Fetch API uses the same shape as the Cloudflare Workers example — callparseWebhookEventAsync and return a Response. Hono example:
AWS Lambda (API Gateway / Function URL)
Plain Node.js http
Idempotency
Svix retries failed deliveries up to ~24h with exponential backoff. Each retry uses the sameWebhook-Id header, so your handler must be idempotent — track processed IDs in Redis, Postgres,
or any shared store and skip duplicates.
INSERT … ON CONFLICT if you
already have a transactional DB write per event, KV / Durable Objects on Cloudflare, etc.
Non-TypeScript implementations
If your backend isn’t TypeScript, here’s the raw scheme in Python and Go.- Python
- Go