Pastor cancels voice subscription
Persona
A pastor leaving the platform — budget cuts, low call volume, a bad experience, or a staffing change. They've made their decision and want a fast, frictionless exit with no sales call or mid-cycle charge. They may return if circumstances change.
Entry points
- Admin dashboard Settings → Billing: "Cancel Plan" text link opens an inline note, then links to Stripe Customer Portal.
- Stripe Customer Portal: Direct cancellation from Stripe's interface.
- Email churn campaign: Founder's win-back email links to Stripe portal or a support form.
Click-through flow
Steps
-
Access cancellation flow — Settings tab → Billing section → "Cancel Plan" link (small text, not prominent). No immediate action — client shows inline note.
-
Cancellation terms shown inline — "Your plan continues until [date]. No refunds for the current period. Data preserved — reactivate anytime." Button: "Manage My Subscription →" (links to Stripe Customer Portal).
-
Stripe Customer Portal — Shows subscription details. Pastor clicks "Cancel subscription."
-
Cancellation confirmation dialog — Stripe shows optional reason selector. Pastor selects reason, clicks "Cancel subscription." Feedback goes to Stripe's churn analytics.
-
Stripe fires webhook — Sets
cancel_at_period_end = true. Firescustomer.subscription.updated. Webhook inbox enqueues event; cron processes within ~60 seconds.premium_churches.status = 'cancellation_pending',cancel_at = [end_date]. Cancellation confirmation email sent. -
Service continues during notice period — Dashboard shows amber banner: "Cancelling — service ends on [date]. [X days] remaining." Voice agent continues answering calls. All transcripts saved, prayer requests captured, staff notifications sent — everything works normally until the cancellation date.
-
Service ends — Stripe fires
customer.subscription.deleted. Cron setspremium_churches.status = 'cancelled'. Dashboard enters read-only (transcripts visible, no new calls). Service ended email: "Your subscription ended on [date]. 30-day data retention begins now. Come back anytime." Telnyx phone number held 30 days before release. LiveKit dispatch rule set to inactive — inbound calls rejected with SIP 486.
Acceptance spec
Canonical: knowledge/acceptance/cancelled.md (all tiers and channels).
Cancellation is uniform across Starter Voice, Pro Voice, Pro Both, Suite Both. Grace period (30 days) is the same for all.
Success criteria
- Cancellation is self-service — no support ticket required.
- Stripe confirmation is clear (not deceptive).
- Service continues working until the stated end date.
- All past call data accessible in read-only dashboard.
- "Reactivate anytime" link present throughout.
- No surprise charges after cancellation date.
Known failure modes
-
Cancellation webhook not processed. If cron handling
customer.subscription.deletedfails, subscription persists asactive. Pastor is still charged. Monitor: cron logs,stripe_webhook_inboxfor stuck rows. -
Voice agent still answers after cancellation date. If
resolve_route()doesn't checkpremium_churches.statusor if the dispatch rule isn't deactivated, calls continue routing. Check:lk.exe sip dispatch list --project cwa-voice— cancelled churches should be marked inactive. -
Phone number released too early. Telnyx release must be scheduled as a task for day 31 post-cancellation, not on day 0. Verify a
scheduled_telnyx_releasesjob or equivalent. -
Data purged before grace period ends. Any purge job touching
voice_callsorvoice_prayer_requestsmust checkcancelled_at + 30 days < now(). Never auto-purge earlier. -
Reactivation link broken. Cancelled dashboard and churn email must link to
/pricingwithutm_source=churn_email. Test: cancel a test subscription, click the link, confirmstatusreturns toactive.