Webhooks
Webhook security & verification
Every signed webhook includes X-VenPays-Signature: t=<unix>,v1=<hex>.
Algorithm
- Parse
tandv1from the header - Read the exact raw body string
- Compute HMAC-SHA256 over
"{t}.{raw_body}"using the full secret string (includingwhsec_if present) - Compare hex digests with a constant-time function
- Optionally reject old timestamps (for example skew > 5 minutes)
Do not re-serialize JSON before verifying. VenPays signs compact canonical JSON (separators=(",", ":"), sort_keys=True).
Node.js example
import crypto from 'crypto'
export function verifyVenPaysSignature(secret, header, rawBody) {
const parts = Object.fromEntries(
header.split(',').map((p) => p.trim().split('='))
)
const signed = `${parts.t}.${rawBody}`
const expected = crypto.createHmac('sha256', secret).update(signed).digest('hex')
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))
}
Additional headers: X-Webhook-Event, X-Webhook-Event-Id, User-Agent: V-Pay-Webhook/1.0.