Pre-built, multi-step recovery flows for every revenue-critical moment — triggered by typed intents and delivered across email, SMS, and push.
Each workflow targets a specific revenue-critical moment, with built-in message variations to A/B test.
Each workflow fires on a typed intent — payment failed, trial ending, checkout abandoned, and more.
Chain messages and timed waits into a sequence — across email, SMS, and push.
Thompson sampling shifts send volume toward the best-performing copy variation as results come in.
Call resolveConversion() to connect conversions back to the workflow that triggered them.
Type-safe intents with structured signals. Each workflow knows exactly what data it needs.
Convert trial users before expiration
TRIAL_ENDINGConversion5 signals · 1 requiredWin back expired trial users
TRIAL_EXPIREDConversion3 signals · 1 requiredEncourage completion when user selects a plan
PLAN_SELECTEDExpansion1 signal · 1 requiredRecover abandoned checkouts
CHECKOUT_STARTEDExpansion5 signals · 2 requiredRecover failed payments with smart retries
PAYMENT_FAILEDRecovery7 signals · 2 requiredRemind users before subscription ends
SUBSCRIPTION_ENDINGChurn7 signals · 1 requiredWin back cancelled subscribers
SUBSCRIPTION_CANCELLEDChurn7 signals · 1 requiredRe-engage downgraded users
SUBSCRIPTION_DOWNGRADEDChurn5 signals · 2 requiredType-safe workflow triggers with structured signals and automatic attribution.
Each intent has structured payload fields with compile-time validation
Conversion, Expansion, Recovery, and Churn paths
Each workflow defines success criteria for attribution tracking
Resolve conversions back to the workflow that drove them
Structured signals with compile-time type checking. No more stringly-typed events.
import { Fourbyfour } from '@fourbyfour/sdk'; const client = new Fourbyfour({ apiKey: process.env.FOURBYFOUR_API_KEY!,}); // Type-safe intent with structured signalsawait client.start('PAYMENT_FAILED', { userId: 'user_123', signals: { invoiceId: 'inv_abc123', amount: 99.00, },}); // Other intents with their typed signalsawait client.start('TRIAL_ENDING', { userId: 'user_456', signals: { planId: 'pro', daysRemaining: 3, },}); // Resolve conversion for attributionawait client.resolve({ userId: 'user_123', amount: 99.00,});Deploy your first workflow in 5 minutes. No credit card required.