Events
Webhooks
Durable, signed, at-least-once delivery of every meaningful platform event.
Webhooks are how Pierflow tells your system the world has changed — without you polling. Every event carries a signature; verify it before acting.
Event catalogue#
| Event | When it fires |
|---|---|
| member.created | A new member record was created |
| policy.issued | Policy confirmed and active |
| policy.renewed | Renewal premium collected |
| policy.lapsed | Premium collection failed after grace |
| policy.cancelled | Policy terminated |
| premium.paid | Successful premium collection |
| premium.failed | Failed premium collection attempt |
| claim.submitted | Claim received by platform |
| claim.approved | Claim approved by HMO |
| claim.rejected | Claim rejected by HMO |
| commission.credited | Commission posted to your ledger |
Subscribing#
POST
/v1/webhooks/endpointsjson
json{
"url": "https://example.com/webhooks/pierflow",
"events": ["policy.issued", "premium.paid", "claim.approved"]
}Signature verification#
Every delivery includes X-Pierflow-Signature: t=...,v1=.... Recompute the signature over <timestamp>.<raw-body> with your endpoint secret using HMAC-SHA256 and compare in constant time.
verify.ts
tsimport crypto from 'node:crypto';
export function verifyPierflow(rawBody: string, header: string, secret: string) {
const [tPart, sigPart] = header.split(',');
const t = tPart.split('=')[1];
const sig = sigPart.split('=')[1];
const expected = crypto
.createHmac('sha256', secret)
.update(`${t}.${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
}Retries#
Pierflow retries failed deliveries with exponential backoff: immediate, then 30s, 2m, 10m, 1h, 6h, 24h. After 7 failures the webhook is marked dead and an alert email is sent.
Idempotent processing
Webhooks are at-least-once. Always dedupe on
event.id before mutating state.