Docs

Flow catalog

Every library template: trigger, filters, step-by-step timing, and the metric it moves.

Every lifecycle flow 8xSend ships as a one-click library template. Each is fully specified: trigger, entry filters, exit (flow) filters, re-entry rule, step-by-step sequence with exact delays and branches, send type, exit conditions, and the KPI it drives. Timings follow Klaviyo and current best-practice data, adapted for apps (behavior-triggered, not calendar-triggered).

How to read this

  • Trigger = the canonical ingest event (see events-api-handoff.md), a date/segment trigger, or an import: a flow that starts from an import only runs for people on a list someone uploads and picks it for.
  • Entry filters run once at entry. Flow filters re-run before every send; failing one exits the run (this is what prevents "reminder to buy after they bought").
  • Type: marketing sends only to consented, non-suppressed contacts and obeys smart sending, quiet hours, and frequency cap. Transactional always sends (receipts, security, account state).
  • Delays use ISO-8601 durations (PT1H = 1 hour, P3D = 3 days). Money is integer cents.

Priority key

  • P1 = enable by default on every project (highest ROI, build first).
  • P2 = enable when the project monetizes or has enough volume.
  • P3 = niche / later / optional.

Global guardrails applied to all marketing flows: smart sending window (default 16h), quiet hours, per-contact frequency cap, consent + suppression gates, one-click unsubscribe. Priority when a contact qualifies for several: Transactional > Abandoned Checkout > Welcome (first 1-2) > everything else.


P1 — Enable by default

1. Welcome Series · P1 · trigger user_signed_up

Goal: convert a new signup into an activated, engaged user; set sender reputation with an early open. Welcome flows are consistently the top revenue automation (Klaviyo: flows drive ~41% of email revenue from ~5% of sends).

Trigger: user_signed_up. Entry filters: consent = subscribed (or implied per project policy); not already in Welcome. Flow filters (exit if true): account_deleted; unsubscribed; became paying (hand off to Post-Purchase). Re-entry: once_ever. Type: marketing (email 1 may be transactional "confirm your email" if double opt-in is on).

#Wait after prevStepBranch / notesEmail intent
1none (<5 min)emailsend immediatelyWarm welcome, set expectations, one clear primary CTA (open the app / first action).
2P1Dconditional_split on behavior.user_activated in last 1dyes → path A, no → path B—
2A—email (activated)path AReinforce value, show a power feature, social proof.
2B—email (not activated)path BRemove friction: the single first action, a short how-to, help link.
3P3Dconditional_split on behavior.user_activatedyes → exit, no → email—
3B—emailnot activatedLast nudge + light incentive (free trial extension / starter perk), then exit.
4—exit

Exit when: activated + engaged, converts to paid, unsubscribes, or sequence completes. KPI: activation rate within 7 days; open rate on email 1.


2. Abandoned Checkout · P1 · trigger checkout_started

Goal: recover users who started buying (or upgrading) but did not finish. Highest-intent recovery flow. Best practice: 3 emails over 3-4 days; first email within 1-4h.

Trigger: checkout_started. Entry filters: has email; consent = subscribed. Flow filters (exit if true): checkout_completed / subscription_started / purchase_completed for the same checkout_id; unsubscribed; suppressed. Re-entry: cooldown(P3D) (do not re-trigger on rapid repeat attempts). Type: marketing.

#Wait after prevStepBranch / notesEmail intent
1—wait_event checkout_completed timeout PT1H15Mcompleted → exit; timeout → continue(accommodates sync lag; ≥1h15m recommended)
2—trigger_split on event.value_cents >= 5000high-value → path H; else → path Lroute high-value carts to a warmer, no-discount first touch
3H/3L—emailreminder 1"You left something": show the item/plan, one-click resume link, reassurance (security, guarantee). No discount yet.
4P1Dwait_event checkout_completed timeout P1Dcompleted → exit; timeout → continue
5—emailreminder 2Handle objections: FAQ, benefits, testimonials; still no discount for high-value path.
6P2Dwait_event checkout_completed timeout P2Dcompleted → exit; timeout → continue
7—emailreminder 3 (final)FOMO + incentive (time-limited discount / bonus). Low-value path may discount earlier.
8—exit

Exit when: purchase completes (any step), unsubscribe, or final email sent. KPI: recovered-checkout rate; revenue per recipient.


3. Trial / Premium-Expiry Reminder · P1 · trigger subscription_expiring (cron) or date_property trial_ends_at

Goal: convert trials and renew lapsing subscriptions before access ends. This is the pocketpal premium_expiry case.

Trigger: subscription_expiring (project fires N days before), or date-property flow on trial_ends_at/expires_at with offsets. Entry filters: has an active trial/subscription expiring; has email. Flow filters (exit if true): subscription_renewed / subscription_started (converted); account_deleted. Re-entry: once_per_trigger. Type: transactional-leaning (tied to account state; may send even to implied-consent), but honor unsubscribe.

#Wait / scheduleStepBranch / notesEmail intent
1at T-3 daysemail"Your access ends in 3 days": what they lose, what they have used/gained, one-tap renew/upgrade.
2at T-1 dayconditional_split behavior.subscription_renewedrenewed → exit; else → email
2B—emailnot renewedUrgency + summary of value + testimonial; renew CTA.
3at T (expiry)conditional_split renewedrenewed → exit; else → email
3B—emailday-ofFinal reminder + optional retention offer (discounted renewal / grace period).
4+P3Dconditional_split renewedrenewed → exit; else → hand off to Win-Backroute lapsed users into Win-Back (flow 5)

Exit when: renews/converts, deletes account, or handed to Win-Back. KPI: trial→paid conversion; renewal/retention rate.


4. Post-Purchase · P1 · trigger subscription_started / purchase_completed

Goal: confirm the purchase, drive product success (reduce refunds/churn), then request a review and cross-sell. Post-purchase messages see far higher open/click than average; 4-5 emails over weeks.

Trigger: subscription_started or purchase_completed. Entry filters: has email. Flow filters (exit if true): refund/chargeback event; account_deleted. Re-entry: always (each purchase can enter), but the receipt step is per-order idempotent. Type: email 1 transactional (receipt); emails 2-4 marketing.

#Wait after prevStepBranch / notesEmail intent
1noneemail (transactional)receiptThank you + order/plan summary + access details + support link. Always sends.
2P2DemailonboardingGet the most from it: top 3 things to do now, a tips link, a win to aim for.
3P7Dconditional_split behavior.activated / used featureused → review path; not used → re-onboard path
3A—emailreview requestAsk for a rating/review/referral now that they have used it.
3B—emailre-onboarding"Stuck? here is the fast path" + offer help/call.
4P14Demailcross-sell / upgradeRecommend the next plan/product based on usage.
5—exit

Exit when: refund, deletion, or sequence completes. KPI: repeat-purchase / upgrade rate; review volume; 30-day retention.


4a. Payment Failed (Dunning) · P1 · template payment-failed · trigger payment_failed

Goal: recover involuntary churn. A declined card is the most recoverable loss there is — the customer still wants the product. Usually the single highest-ROI flow a project can install.

Trigger: payment_failed. Entry filters: has email. Flow filters (exit if true): payment_recovered; account_deleted. Re-entry: always — every failed charge is its own incident. Type: transactional. A customer must be told their payment failed whether or not they take marketing email, so consent does not gate these and the frequency cap does not apply.

#Wait after prevStepBranch / notesEmail intent
1noneemail (transactional)"We couldn't process your payment" — expired card or bank hold, about a minute to fix.
2—wait_event payment_recovered, timeout P3Drecovered → exit immediately
3on timeoutemail"Still can't process your payment" — access is at risk.
4—wait_event payment_recovered, timeout P3Drecovered → exit
5on timeoutemailFinal notice before the subscription lapses.

Exit when: payment_recovered arrives at any point, or the third notice sends. The CTA is the whole outcome. The button points at whichever surface can actually take a new card — send store on the event when an app store bills the customer (APP_STORE, PLAY_STORE, …), or manage_billing_url when you know the exact per-subscriber page. Web billing falls back to the App URL. Overwriting cta_url with a project URL is what once made these emails unactionable. KPI: recovered revenue as a share of failed charges.


4b. Purchase Receipt · P1 · template purchase-receipt · trigger purchase_completed

Goal: confirm a one-off purchase, then one well-timed nudge to actually use what was bought. Distinct from Post-Purchase, which is the longer sequence for subscriptions.

Trigger: purchase_completed. Re-entry: always — each purchase gets its own receipt. Type: email 1 transactional (a receipt always sends); email 2 marketing.

#Wait after prevStepEmail intent
1noneemail (transactional)The receipt: what they bought, what it costs, how to get to it.
2P3Demail"Have you used it?" — the fastest path to the thing they paid for.

KPI: first-use rate within 7 days; refund rate.


4c. Trial Started · P1 · template trial-started · trigger trial_started

Goal: convert the trial while it is running, rather than reminding someone on the last day that it is ending. Hands over to Trial/Expiry Reminder (§3) for the end-of-trial push.

Trigger: trial_started. Re-entry: once_per_trigger. Type: marketing.

#Wait after prevStepBranch / notesEmail intent
1noneemailOrient them: what the trial includes and the first thing to do with it.
2P2Dconditional_split on activationactivated → power tip; not → unblock
2A—emailactivated pathGo deeper: the feature that makes people stay.
2B—emailnot-activated pathUnblock them: the one step they haven't taken.
3—exithands over to the expiry reminder

Exit when: the trial converts (subscription_started) or the sequence completes. KPI: trial-to-paid conversion.


5. Win-Back (Lapsed) · P1 · trigger subscription_expired / segment "lapsed"

Goal: reactivate users whose subscription ended or who stopped buying. Classic win-back targets 90-180 day lapses with escalating incentive.

Trigger: subscription_expired, or segment_enter "no active sub and last active > 60d". Entry filters: has email; consent = subscribed. Flow filters (exit if true): subscription_started / subscription_renewed; unsubscribed. Re-entry: cooldown(P90D). Type: marketing.

#Wait after prevStepBranch / notesEmail intent
1P3Demailsoft"We miss you" + what is new since they left, no discount.
2P7Dconditional_split behavior.returned/renewedreturned → exit; else → email
2B—emailincentiveA real reactivation offer (discount / bonus month), time-limited.
3P14Dconditional_split returnedreturned → exit; else → email
3B—emailfinal + stronger offerBest offer + deadline; then hand to Sunset if still silent.
4—exit → Sunset eligibility

Exit when: reactivates, unsubscribes, or moves to Sunset. KPI: reactivation rate; revenue per recipient.


P2 — Enable when monetizing / at volume

6. Onboarding / Activation · P2 · trigger user_signed_up (behavior-gated)

Goal: for apps where "activation" is a distinct milestone beyond the welcome, drive the user to the aha action. SaaS onboarding must be behavior-triggered; time-only sequences underperform by 2-4x.

Trigger: user_signed_up (can run parallel to Welcome, or replace Welcome emails 2-3 for product-led apps). Entry filters: not yet activated. Flow filters (exit if true): user_activated; account_deleted; unsubscribed. Re-entry: once_ever. Type: marketing.

#Wait after prevStepBranch / notesEmail intent
1PT6Hconditional_split behavior.user_activatedactivated → exit; else → email
1B—emailstep-1 nudgeThe single first action, with a 1-tap deep link and a 20-second how-to.
2P2Dconditional_split activatedactivated → exit; else → email
2B—emailfriction-busterAddress the common blocker; short video/GIF; offer help.
3P4Dconditional_split activatedactivated → exit; else → email
3B—emailvalue + incentiveShow the payoff of activating + a small perk; then exit.

Exit when: activates, deletes, unsubscribes, completes. KPI: activation rate; time-to-activate.


7. Cancellation Save (Pre-Churn) · P2 · trigger subscription_cancelled

Goal: save a user who turned off auto-renew but still has access. High-intent retention moment.

Trigger: subscription_cancelled (has access_until). Entry filters: still has access (access_until in future). Flow filters (exit if true): subscription_renewed/re-subscribed; account_deleted. Re-entry: once_per_trigger. Type: transactional-leaning (account state), honor unsubscribe.

#Wait / scheduleStepBranch / notesEmail intent
1noneemailacknowledgeConfirm cancellation + exactly what/when they lose; empathetic tone; "reactivate" CTA.
2P1Demailreason + saveAddress top churn reasons; offer help / pause option / downgrade instead of cancel.
3at access_until - 2dconditional_split renewedrenewed → exit; else → email
3B—emailfinal offerTime-limited retention incentive before access ends.
4at access_untilconditional_split renewedrenewed → exit; else → Win-Backroute to Win-Back once access ends

Exit when: reactivates, deletes, or access ends (→ Win-Back). KPI: save rate; involuntary-churn reduction.


8. Re-engagement (Inactive) · P2 · trigger user_inactive (cron)

Goal: pull back users who went quiet before they fully lapse. Keeps the active base warm and protects deliverability.

Trigger: user_inactive (project cron fires at N days no activity). Entry filters: consent = subscribed; not suppressed. Flow filters (exit if true): any activity event (feature_used, login, purchase); unsubscribed. Re-entry: cooldown(P30D). Type: marketing.

#Wait after prevStepBranch / notesEmail intent
1noneemailvalue reminder"Here is what you are missing" + one compelling reason to return + deep link.
2P5Dconditional_split behavior.active since entryactive → exit; else → email
2B—emailnew + incentiveWhat is new + a small perk to return; then exit or → Sunset if chronically unengaged.

Exit when: returns, unsubscribes, or → Sunset. KPI: reactivation within 14 days; engaged-base retention.


9. Waitlist → Launch Announcement · P2 · trigger waitlist_joined + manual launch

Goal: capture pre-launch leads, keep them warm, and convert them on launch day. (pocketpal already has a waitlist table.)

Trigger: waitlist_joined (nurture) and a manual "launch" campaign trigger (announcement). Entry filters: email present; consent captured at waitlist. Flow filters (exit if true): signed up (user_signed_up); unsubscribed. Re-entry: once_ever. Type: marketing.

#Wait / scheduleStepBranch / notesEmail intent
1noneemailconfirm"You are on the list" + what to expect + when.
2P7D (optional)emailbuild anticipationSneak peek / behind the scenes / early-access promise.
3on launch (manual)emaillaunch"It is live" + early-access offer + strong CTA to download/sign up.
4P3Dconditional_split behavior.user_signed_upsigned → exit; else → email
4B—emailreminderLast call on launch/early-bird offer; then exit.

Exit when: signs up, unsubscribes, or completes. KPI: waitlist→signup conversion on launch.


10. Browse / Feature Abandonment · P2 · trigger feature_used / checkout_started precursor

Goal: nudge users who showed interest (viewed a plan, used a gated feature, hit a paywall) but did not start checkout. Lower intent than abandoned checkout; keep it to 1-2 emails within hours.

Trigger: feature_used with feature in {paywall_viewed, plan_viewed, premium_feature_blocked} (project-defined). Entry filters: not currently paying; has email; consent = subscribed. Flow filters (exit if true): checkout_started (hand off to Abandoned Checkout), subscription_started, unsubscribed. Re-entry: cooldown(P3D). Type: marketing. Priority note: if the user later starts checkout, Abandoned Checkout takes over; this flow exits.

#Wait after prevStepBranch / notesEmail intent
1PT2Hemailinterest nudgeShow the feature/plan they looked at + its benefit + a soft CTA.
2P1Dconditional_split behavior.checkout_started or paidyes → exit; else → email
2B—emailreason to actAnswer the likely hesitation + gentle incentive; then exit.

Exit when: starts checkout (→ Abandoned Checkout), pays, unsubscribes, or completes. KPI: browse→checkout rate.


P3 — Niche / later / optional

11. Sunset (Unengaged Cleanup) · P3 · segment "chronically unengaged"

Goal: protect sender reputation by giving long-unengaged contacts one last chance, then suppressing them from marketing (not deleting).

Trigger: segment_enter "no opens/clicks/activity in 90-120 days across all flows". Entry filters: subscribed; not already sunset. Flow filters (exit if true): any engagement (open/click/activity); unsubscribed already. Re-entry: once_ever. Type: marketing.

#Wait after prevStepBranch / notesEmail intent
1noneemaillast chance"Do you still want to hear from us?" + one-tap "keep me subscribed".
2P5Dconditional_split behavior.engaged since entryengaged → exit; else → email
2B—emailfinal"This is our last email unless you click"; then update_property + suppress from marketing.
3—update_property marketing_consent = unsubscribed (sunset) + exitremove from active marketing audience

Exit when: re-engages (stays), or is sunset (suppressed from marketing). KPI: list health (engagement rate), deliverability (bounce/complaint down).


Goal: for projects under strict consent policy, confirm marketing opt-in before any marketing sends.

Trigger: user_signed_up or email_captured where project policy = explicit and consent = pending. Entry filters: consent = pending. Flow filters: consent becomes subscribed → exit into Welcome. Re-entry: once_ever. Type: transactional (the confirm request itself is allowed).

#Wait after prevStepBranch / notesEmail intent
1noneemail (transactional)confirm"Confirm your subscription" one-tap; sets marketing_consent = subscribed on click.
2P2Dconditional_split confirmedconfirmed → Welcome; else → email
2B—emailreminderGentle re-ask; if still unconfirmed after P5D, leave as pending (no marketing).

Exit when: confirmed (→ Welcome) or times out to pending. KPI: confirmed opt-in rate.


13. Birthday / Anniversary · P3 · trigger date_property

Goal: a warm, high-open moment; celebrate the user's birthday or signup anniversary with a perk.

Trigger: date-property flow on birthday or signup_date, offset 0 (or -2d for prep). Entry filters: date present; subscribed. Flow filters: suppressed/unsub → skip. Re-entry: always (annual). Type: marketing.

#Wait / scheduleStepNotesEmail intent
1on dateemailCelebratory message + a gift/discount/bonus valid for a short window.
2P5Dconditional_split redeemedredeemed → exit; else → reminderReminder before the gift expires.

KPI: redemption rate; incremental revenue.


14. Price-Drop / Back-in-Stock · P3 (ecommerce-only) · trigger custom with name: price_drop / back_in_stock

Goal: for website plays with catalogs, alert interested users when a watched item drops in price or restocks.

Trigger: the custom event with properties.name = price_drop or back_in_stock for an item on a contact's watch/browse list. (price_drop is not a canonical event name — the ingest API rejects it — so the app sends event: "custom" and the flow filters on event.name.) Entry filters: contact showed interest in the item; subscribed. Flow filters: item unavailable again → exit. Re-entry: always per item event. Type: marketing.

#Wait after prevStepNotesEmail intent
1noneemail"The thing you wanted is back / cheaper" + image + one-tap buy.
2P2Dconditional_split purchasedpurchased → exit; else → reminderLow-stock/limited-time urgency.

KPI: click→purchase on alert.


15. Active but Free → Upgrade · P1 · template active-free-upgrade · trigger feature_used

Goal: convert people who use the app but have never paid. The re-engagement flows talk to people who left; this one talks to people who stayed and never opened their wallet.

Trigger: feature_used. Entry filters: has email; no subscription_started and no purchase_completed in the last 365 days. Flow filters (exit if true): subscription_started or purchase_completed in the last 30 days. Re-entry: cooldown(P45D) — feature_used fires often; one sequence per six weeks at most. Type: marketing.

#Wait after prevStepEmail intent (brief)
1P1Demail — What the paid plan unlocksvalue prop + one specific benefit, named from the product facts
2P3Demail — How others use itsocial proof (a real number or quote) + the objections, answered, + the price
3P4Demail — Upgrade before the week is outone dated reason to decide now, reassurance that free stays free
4—exit

KPI: free → paid conversion among active users (conversion attribution credits subscription_started / purchase_completed within the window).


16. Pack Buyer → Subscriber · P1 · template pack-to-subscription · trigger purchase_completed

Goal: turn a one-off pack purchase into a subscription. A pack buyer has already paid once; the only question is whether the plan is the better deal for how they use it.

Trigger: purchase_completed (send item_name and price_cents — the emails name and price the pack). Entry filters: has email; no subscription_started in the last 365 days. Flow filters (exit if true): subscription_started in the last 30 days. Re-entry: cooldown(P30D). Type: marketing.

#Wait after prevStepEmail intent (brief)
1P3Demail — How is the pack goingnames the pack and its price; the quickest way to use what's left; plants the plan
2P7Demail — The maths: pack vs planreal prices side by side; what the plan includes; cancel-anytime reassurance
3P10Demail — Last noteone dated reason, then stop
4—exit

KPI: pack → subscription conversion.


17. Affiliate Invite · P3 · template affiliate-invite · starts from an import

Goal: invite people who already know you (creators who applied to work with you, a partner list) to your affiliate program, and stop the moment they apply.

Trigger: an import. Contacts → Import CSV, then pick this flow. App events never start it. Entry filters: has never sent affiliate_applied. Flow filters (exit if true): affiliate_applied (they applied while the flow waited). Re-entry: once_ever: importing the same person again never re-invites them. Type: marketing. Only import people who agreed to hear from you; never a bought or scraped list.

#Wait after prevStepBranch / notesEmail intent
1noneemailThe invite: what the program pays, that there's no posting schedule, one button to apply.
2—wait_event affiliate_applied, timeout P3Dapplied → exit
3on timeoutemailAnswers "what do I earn" and "what do I have to post".
4—wait_event affiliate_applied, timeout P4Dapplied → exit
5on timeoutemailThe last call, then stop.

Before going live: point every button at the program's apply page and name the real commission. Stop signal: whatever runs the apply form sends affiliate_applied to 8xSend. KPI: invite → application rate.


Persuasion briefs

Every email in every template carries a brief — goal, angle, and must_include drawn from value_prop, specific_benefit, social_proof, urgency, objection_handling, reassurance, personal_detail, single_cta. P1 templates spell theirs out per email; the rest inherit the template's goal with specific_benefit + single_cta. The brief is installed with the message, shown by get_flow, and checked by the copy lint in preview_email / validate_flow against the project's product facts (Settings → General, or set_product_facts). Library copy is deliberately plain where a fact belongs — "here is what changes the moment you upgrade" — so the copy agent has to fill in the real feature, price or number rather than ship filler.

Template versions

Each template has a version. Installing records it on the flow; when the library moves on, the flows page and list_flow_library say "vN available" and Reinstall from library archives the old flow (history intact) and installs the current template as a draft, optionally carrying edited copy onto emails of the same name.

A. Broadcasts / "New stuff" campaigns

One-off sends, not automations. Pick a segment (§ filter grammar), compose a message, schedule or send now. Used for product news, big features, seasonal promos. Obeys suppression, consent, frequency cap, quiet hours. Tracked in campaigns + sends. This replaces the "new stuff email" you described.

B. Transactional messages (always-on)

Receipts (purchase_completed, subscription_started/renewed), password/security, account-state notices. Sent regardless of marketing consent (as permitted by CAN-SPAM/GDPR), never counted against the marketing frequency cap, but still recorded in sends. Usually single messages, sometimes the first step of a P1 flow (e.g. Post-Purchase email 1).


Default enablement per project kind

FlowApp (mobile)WebsitePriority
Welcome Series✓✓P1
Abandoned Checkout✓ (IAP/upgrade)✓P1
Trial/Expiry Reminder✓✓ (if subs)P1
Post-Purchase✓✓P1
Payment Failed (Dunning)✓ (if subs)✓ (if subs)P1
Purchase Receipt✓ (if one-off sales)✓ (if one-off sales)P1
Trial Started✓ (if trials)✓ (if trials)P1
Win-Back✓✓P1
Active but Free → Upgrade✓ (freemium)✓ (freemium)P1
Pack Buyer → Subscriber✓ (if packs + a plan)✓ (if packs + a plan)P1
Onboarding/Activation✓optionalP2
Cancellation Save✓ (if subs)✓ (if subs)P2
Re-engagement✓✓P2
Waitlist → Launch✓ (pre-launch)✓ (pre-launch)P2
Browse/Feature Abandon✓ (paywall)✓ (catalog)P2
Sunset✓✓P3
Double Opt-InEU onlyEU onlyP3
Birthday/AnniversaryoptionaloptionalP3
Price-Drop/Back-in-Stockrarely✓ (catalog)P3
Affiliate Inviteif it runs an affiliate programif it runs an affiliate programP3

When you create a project, 8xSend offers the P1 set pre-selected; you reorder/toggle by priority, brand is auto-applied, and you set each live after reviewing copy.


Companion: events-api-handoff.md — the events each flow consumes, and how your app pushes them. list_flow_library reports which of these templates a project already has.