Skip to main content

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:
There is no merchant-side “create portal session” call — the customer authenticates themselves via the emailed link.

2. Build the flow (steps)

A cancel flow is a name plus ordered steps. Each step has a step_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.
Manage the flow with the rest of the Cancel Flows API: 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:
The session object reports progress: Aggregate outcomes (saves vs. cancels) come from GET /v1/cancel-flows/stats.

Confirmation behavior

The confirmation step’s behavior 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 emits subscription.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.