Integration docs

Add churn prevention to your subscription app.

Connect Stripe, install the React SDK, launch adaptive cancel flows, recover failed payments, and send the customer signals Churnless needs to protect MRR.

Typical setup time
5 min
Create Churnless and Stripe keys
15 min
Place the cancel flow in billing settings
20 min
Add payment wall and product signal events
01

Create keys

Use a browser-safe publishable key in your app and a secret key only from your server.

02

Connect Stripe

Paste a restricted Stripe key so Churnless can read products, customers, subscriptions, invoices, and payment failures.

03

Install the SDK

Wrap your app with the provider, then drop the cancel flow where cancellation starts.

04

Send signals

Track usage, feedback, support, and lifecycle events so the save path can adapt to the customer.

Step 1

Create the right keys.

Churnless uses two key types. The publishable key can run in the browser. The secret key is only for server-side API calls, MCP, jobs, and customer imports.

Publishable key

Use `fk_pub_...` with the React SDK and pixel. It can start cancel flows and check payment state for known customers.

Secret key

Use `fk_live_...` only on your server. Never expose it to client bundles, mobile apps, or public config.

Stripe restricted key

In Churnless settings, paste a restricted Stripe key with the prefilled least-privilege permissions. Churnless uses read scopes to import customers, products, prices, subscriptions, invoices, and charges, plus limited write scopes for save actions such as pauses, discounts, and cancellation at period end. Start in test mode, run the import, then switch to your live Stripe key when the mapping looks right.

Step 2

Install the React SDK.

The SDK handles API calls, modal state, lifecycle events, and optional pixel forwarding. Use it anywhere your customer can manage billing.

Install
bash
npm install @furnkey/react
Provider
tsx
import { ChurnlessProvider } from "@furnkey/react";

export function AppProviders({ children, customer }) {
  return (
    <ChurnlessProvider
      publishableKey={process.env.NEXT_PUBLIC_CHURNLESS_KEY}
      customerId={customer.stripeCustomerId}
      productId="prod_adscreator"
      trackingConsent={customer.analyticsConsent}
    >
      {children}
    </ChurnlessProvider>
  );
}
Step 3

Replace the raw cancel button.

Pass the same customer ID you use in Stripe. Churnless starts a session, asks for the reason, chooses the next best step, and reports the outcome.

Cancel flow
tsx
import { CancelFlow } from "@furnkey/react";

export function BillingSettings({ customer }) {
  return (
    <CancelFlow
      customerId={customer.stripeCustomerId}
      onSaved={() => window.location.reload()}
      onCanceled={() => window.location.assign("/goodbye")}
      onError={(error) => console.error(error)}
    >
      {({ show, isLoading }) => (
        <button onClick={show} disabled={isLoading}>
          {isLoading ? "Loading..." : "Cancel subscription"}
        </button>
      )}
    </CancelFlow>
  );
}
Step 4

Block involuntary churn without blocking recovery.

Use the payment wall around authenticated app content. Customers with unresolved failures see a clear path to update payment details; everyone else sees the app.

Payment recovery wall
tsx
import { PaymentRecoveryWall } from "@furnkey/react";

export function ProtectedApp({ customer, children }) {
  return (
    <PaymentRecoveryWall
      customerId={customer.stripeCustomerId}
      fallback={children}
      pollInterval={60000}
    />
  );
}
Step 5

Send the product signals that predict churn.

The better the signal history, the better the cancellation path. Track meaningful usage, activation, support friction, billing friction, and feedback.

Browser pixel
html
<script>
  window.fk = window.fk || function(){(window.fk.q = window.fk.q || []).push(arguments)};
  fk("init", "fk_pub_...", {
    customerId: "cus_123",
    productId: "prod_adscreator",
    consent: true
  });
  fk("track", "feature_used", {
    feature: "campaign_export",
    value: 1
  });
</script>
<script async src="https://www.getchurnless.com/pixel/v1.js"></script>
Server event
ts
await fetch("https://www.getchurnless.com/api/v1/events", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": process.env.CHURNLESS_API_KEY
  },
  body: JSON.stringify({
    customerId: "cus_123",
    productId: "prod_adscreator",
    eventType: "feature_used",
    eventName: "campaign_exported",
    category: "usage",
    payload: {
      exportCount: 3,
      campaignId: "camp_789"
    }
  })
});

Usage

feature_used, project_created, export_completed

Lifecycle

trial_started, activation_completed, team_invited

Friction

support_ticket_opened, error_seen, downgrade_viewed

Advanced

Use the API and MCP server for automation.

Server-side integrations can import customers, push events, inspect health scores, list cancel sessions, and let internal AI tools query churn context.

Reference docs

OpenAPI reference

Browse every REST endpoint, schema, and request example in the generated API reference.

MCP server
bash
CHURNLESS_API_KEY=fk_live_...
npx -p @furnkey/mcp-server churnless-mcp
Integration checklist

Ready to test with a real customer?

Create keys, connect Stripe in test mode, install the SDK, open the cancel flow from your billing page, and send at least one usage event for the same customer ID.