Webhooks
Register:
POST /api/v1/webhooks {"url": "https://api.yourapp.com/onetrial", "events": []} (empty = all). The signing secret (whsec_...) is returned once.Events:
decision.created, challenge.completed, challenge.failed. Body: { id, type, createdAt, data }. Header OneTrial-Signature: t=<unix>,v1=<hex hmac-sha256 of "<t>.<raw body>">. Three attempts with backoff; endpoint must be public https.Verify (Node):
jsimport { createHmac, timingSafeEqual } from 'node:crypto';export function verify(secret, rawBody, header) {const m = /t=(\d+),v1=([0-9a-f]+)/.exec(header ?? '');if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;const expected = createHmac('sha256', secret).update(`${m[1]}.${rawBody}`).digest();const given = Buffer.from(m[2], 'hex');return expected.length === given.length && timingSafeEqual(expected, given);}
On
challenge.completed with data.outcome === "passed", unlock the trial for data.decisionId. On challenge.failed, treat as deny.