Compliance and audit trail
Cancel-flow tools fail compliance reviews when they pretend that “we recorded the request” is the same as “we canceled the subscription.” Unchurn keeps the two states separate. This page covers how that works, what gets logged, and where the audit trail lives.
Cancel-flow regulations vary by jurisdiction and change over time. Check the current rules with your counsel before making claims to customers.
The two cancel paths
Every cancel flow ends in one of two paths. Both are immediate from the customer’s point of view. They differ in what happens on Stripe.
Automated cancel
The customer clicks Cancel Now (or accepts the cancel option after declining offers). Unchurn schedules a cancel-at-period-end on Stripe in the same request. Stripe records the cancellation. The customer keeps access through the period they paid for.
The session is recorded as a scheduled cancel, your onComplete callback fires, and the customer sees “Your subscription will end on <date>.”
Manual cancellation request
Some subscription shapes can’t be cancelled by an automated Stripe write — multi-item subscriptions, attached schedules, Stripe-paused subscriptions, past-due invoices. For those, the cancel CTA doesn’t call Stripe. Instead Unchurn:
- Records a manual cancellation request on the session in a single database transaction.
- Creates a task in your dashboard with the subscription ID, customer ID, and the reason the automated path was blocked.
- Sends the customer a confirmation email through a durable outbox.
- Shows the customer “Your cancellation request has been received” — never “your subscription is canceled.”
A deterministic request ID is recorded with the session so double-clicks and retries collapse to one request. You complete the Stripe-side cancellation when you’re ready; until then, the customer’s intent is captured and dated, and your team has a task with everything they need to finish in Stripe.
The full list of subscription shapes that route here lives in Supported subscriptions.
What “received, not completed” means
Unchurn does not market manual-request fallback as automated legal completion. Honest copy beats clever copy here.
| State | What happened on Stripe | Customer copy | Counts as a cancel in analytics? |
|---|---|---|---|
| Scheduled cancel | Stripe set to cancel at period end | ”Subscription will end on <date>.” | Yes |
| Already scheduled | Already scheduled before the session | ”Subscription will end on <date>.” | Yes (counted on the original event) |
| Manual cancellation request | Nothing | ”Your cancellation request has been received.” | No — counted as a manual request |
The third row is the one most cancel-flow tools get wrong. Unchurn keeps it separate so your numbers stay honest and your compliance review stays clean.
Direct cancel access
When direct cancel access is on for a session, the cancel CTA appears one click from the cancel-flow open. No surveys, no offers, no “are you sure?” interstitial.
It’s on by default for everyone. When the customer’s location resolves to a covered jurisdiction, the session is tagged with legal_jurisdiction as the access source — that tag is recorded in the audit trail.
Covered jurisdictions:
- California (US-CA)
- New York (US-NY)
- Any EU member state
- France
- Germany
The location resolver runs once at session creation and reads, in priority order:
- Merchant-supplied customer attributes.
- Stripe Tax customer location.
- The Stripe customer address.
- Payment-method billing details.
- Browser/IP geolocation as a final fallback.
Card-issuer country is stored for audit but never used to infer state-specific labels.
When direct access is on, the Cancel Now button sits on every screen of the flow. One click takes the customer to either the automated cancel path or the manual cancellation request path, depending on the subscription shape. The widget never inserts retention friction — survey, offer, confirm — between that click and the result screen.
What gets logged
Every cancel-flow session writes one row to your dashboard. It carries:
- The session ID, subscription ID, and merchant ID.
- The Stripe mode (test or live).
- Every offer evaluation — eligible, ineligible, the reason — at session-create and again when the change is applied.
- The outcome (one of the values listed in Events).
- The compliance jurisdictions the resolver picked, plus every signal it considered (including conflicts).
- Whether the customer reached cancel via the persistent Cancel Now CTA or the standard waterfall.
- For manual requests: the request ID and the timestamps for when the request was recorded and when your team was notified.
Each step the customer views, accepts, or declines also gets recorded. That gives you a per-step funnel — how many sessions saw the discount offer, how many accepted, how many declined and went to the next step.
Deterministic request IDs prevent double-counting on retries. A network blip that causes the widget to retry commits exactly one Stripe mutation and writes exactly one outcome.
Where the audit trail lives
- Cancellations view. One row per cancel-flow session, surfaced in your dashboard with a 30-day rolling window.
- Dashboard tasks. Manual cancellation requests show up as tasks tied to the subscription ID, each carrying the reason and the timestamp.
- Customer confirmation email. Sent through a durable outbox on every manual cancellation request. The first attempt happens inline; if it fails, a background worker retries with exponential backoff for up to 24 hours.
- Audit timestamps. Each session row records the request timestamp and the merchant-notification timestamp in a single transaction. Queryable through your dashboard.
What Unchurn does not promise
- Automated legal completion for blocked shapes. Manual cancellation requests are tracked as received, not completed. Your team finishes the Stripe-side cancellation within your own legal SLA.
- Statement of regulatory compliance. Unchurn provides the audit trail, the routing policy, and the UI access. Your counsel decides which regulations apply to your business.
- Backfilled compliance labels. The location resolver runs once at session creation. Mutation-time changes don’t retroactively change the labels on a session that already started.
Cross-references
- Supported subscriptions — the full list of shapes that route to manual cancel.
- Eligibility — the rationale behind the routing rules.
- Events — the outcome vocabulary used in your analytics.