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.