The portal cancel flow
Cancel self-service lets customers end a subscription from the portal without contacting support. Recurso runs a cancel flow — a sequence of steps (survey → retention offer → confirmation) designed to reduce churn while respecting the customer’s intent. The flow you build with the Cancel Flows API is what the customer walks through.1. Authenticate the customer
Cancellation happens inside a portal session — get the customer signed in with a magic link first:2. Build the flow (steps)
A cancel flow is a name plus ordered steps. Each step has astep_type and a free-form config; cooldown_days sets how long a saved
customer waits before re-entering the flow. Survey, offer, and confirmation
are simply three step types:
config is stored as-is and rendered by your portal UI, so the exact keys
(reasons, type, coupon_code, behavior, …) are your convention —
these are conventions the reference portal uses, not enforced schema.
Offer types you’ll commonly model: discount (a coupon), pause,
downgrade.PUT /v1/cancel-flows/{id}, POST /v1/cancel-flows/{id}/steps,
PUT|DELETE /v1/cancel-flows/steps/{id}.
3. Run a cancel session
When the customer clicks “Cancel”, start a session and advance it step by step. The session carries the state your portal reads:
Aggregate outcomes (saves vs. cancels) come from
GET /v1/cancel-flows/stats.
Confirmation behavior
The confirmation step’sbehavior decides timing:
Which actions the portal exposes
Whether the cancel button appears, and which flow it uses, is a dashboard setting (Settings → Portal) — there is no/v1/settings/portal endpoint.
Gift redemption
The portal also redeems gift codes. Customers do this in the portal UI (POST /portal/api/redeem); the merchant-side equivalent is:
Events
Recurso emitssubscription.canceled when a cancellation takes effect
(and subscription.renewed if a saved customer’s billing continues). The
per-step cancel-session state (survey answer, offer outcome, saved_by_offer)
lives on the session object above and in GET /v1/cancel-flows/stats —
not as separate webhook events.
Best Practices
Always survey
The cancellation reason is your most valuable churn signal — capture it
on every cancel.
Match offers to reasons
A “too expensive” customer responds to a discount, not a feature
announcement.
Keep it short
Survey, one offer, confirm. Extra friction on someone who wants to leave
backfires.
Respect the decision
If they decline the offer, let them confirm and go gracefully.