Skip to main content

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​

  1. Access cancellation flow — Settings tab → Billing section → "Cancel Plan" link (small text, not prominent). No immediate action — client shows inline note.

  2. 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).

  3. Stripe Customer Portal — Shows subscription details. Pastor clicks "Cancel subscription."

  4. Cancellation confirmation dialog — Stripe shows optional reason selector. Pastor selects reason, clicks "Cancel subscription." Feedback goes to Stripe's churn analytics.

  5. Stripe fires webhook — Sets cancel_at_period_end = true. Fires customer.subscription.updated. Webhook inbox enqueues event; cron processes within ~60 seconds. premium_churches.status = 'cancellation_pending', cancel_at = [end_date]. Cancellation confirmation email sent.

  6. 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.

  7. Service ends — Stripe fires customer.subscription.deleted. Cron sets premium_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​

  1. Cancellation is self-service — no support ticket required.
  2. Stripe confirmation is clear (not deceptive).
  3. Service continues working until the stated end date.
  4. All past call data accessible in read-only dashboard.
  5. "Reactivate anytime" link present throughout.
  6. No surprise charges after cancellation date.

Known failure modes​

  • Cancellation webhook not processed. If cron handling customer.subscription.deleted fails, subscription persists as active. Pastor is still charged. Monitor: cron logs, stripe_webhook_inbox for stuck rows.

  • Voice agent still answers after cancellation date. If resolve_route() doesn't check premium_churches.status or 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_releases job or equivalent.

  • Data purged before grace period ends. Any purge job touching voice_calls or voice_prayer_requests must check cancelled_at + 30 days < now(). Never auto-purge earlier.

  • Reactivation link broken. Cancelled dashboard and churn email must link to /pricing with utm_source=churn_email. Test: cancel a test subscription, click the link, confirm status returns to active.