How it works
When a watched user’s churn risk crosses their threshold, ChurnKit sends a signed HTTP POST to the webhook URL you registered with watch().
User's score crosses threshold
↓
ChurnKit signs payload with HMAC-SHA256
↓
POST https://yourapp.com/hooks/churn-alert
↓
Your server verifies signature → processes alert
Webhook payload
{
"event" : "churn_risk_alert" ,
"userId" : "user_123" ,
"score" : 0.84 ,
"tier" : "high" ,
"signals" : [ "no_login_7d" , "support_spike" , "export_all_data" ],
"recommendation" : "This user is at high risk. Reach out immediately." ,
"triggeredAt" : "2024-06-01T14:22:00Z"
}
Event types
Event When churn_risk_alertUser’s score crossed the watch threshold
Header Value Content-Typeapplication/jsonX-ChurnKit-Signaturesha256=<hmac_hex>X-ChurnKit-TimestampUnix timestamp (seconds)
Responding to webhooks
Return a 2xx status code to acknowledge receipt. ChurnKit retries failed deliveries (non-2xx or timeout) with exponential backoff for up to 72 hours.
// Always return 200 quickly — process async if needed
export async function POST ( req : Request ) {
const body = await req . text ()
// Verify first
const valid = await verifyWebhookSignature (
body ,
req . headers . get ( 'x-churnkit-signature' ) ?? '' ,
process . env . CHURNKIT_WEBHOOK_SECRET !
)
if ( ! valid ) return new Response ( 'Unauthorized' , { status: 401 })
// Acknowledge immediately, process async
const payload = JSON . parse ( body )
processAlertAsync ( payload ) // don't await
return Response . json ({ ok: true })
}
Getting your webhook secret
Your webhook signing secret is shown in the FlowsBuilt Console under API Keys. Add it to your environment:
CHURNKIT_WEBHOOK_SECRET = whsec_your_secret_here
Always verify signatures. Never process a webhook payload before confirming its authenticity.
Next steps
Verify Signature Step-by-step guide to signature verification in Node.js, Next.js, and Express.