X-ListenLand-Signature header signed with HMAC-SHA256 using your endpoint’s secret. Always verify this signature before processing the event — it confirms the request genuinely came from ListenLand and has not been tampered with in transit.
How the signature works
TheX-ListenLand-Signature header has the format:
- Extract the
t(Unix timestamp in seconds) andv1(hex-encoded HMAC) values from the header. - Construct the signed string by concatenating the timestamp, a literal
., and the exact raw request body: - Compute an HMAC-SHA256 of that string using your webhook secret (
whsec_…) as the key. - Compare your computed HMAC to the
v1value — they must match exactly. - Check the timestamp — reject any event where
tis more than 5 minutes in the past (or future) to guard against replay attacks.
Always read the raw request body as a string before calling any JSON parser — parsing first will change the exact bytes and invalidate the signature check.
TypeScript verification example
webhook.ts
Using in an Express / Next.js handler
Express
Read the raw body buffer before your JSON middleware touches it, then pass it as a string toverifyWebhookSignature:
express-handler.ts
Next.js App Router (Route Handler)
Next.js Route Handlers exposerequest.text() to get the raw body before parsing:
app/webhooks/listenland/route.ts