ChurnCut/Docs

Installation

Complete guide to integrate ChurnCut into your application.

Architecture

ChurnCut works with two components:

  • Backend - Calls ChurnCut API to generate session URL
  • Frontend - JavaScript widget that displays the cancellation flow
text
Your Frontend  -->  Your Backend  -->  Churncut API
  (JS Widget)       (Get Session URL)

Step 1: Get credentials

In your ChurnCut dashboard, go to Settings and copy:

  • App ID: Unique identifier for your application
  • Secret Key: Secret key for API authentication (never expose on client)

Step 2: Call session URL API

Create an endpoint on your backend that calls the ChurnCut API to get the session URL.

Express.js

javascript
const express = require('express');
const axios = require('axios');

const app = express();
app.use(express.json()); // Fix #3: parse request body

const CHURNCUT_SECRET = process.env.CHURNCUT_SECRET_KEY;
const CHURNCUT_APP_ID = process.env.CHURNCUT_APP_ID;

app.post('/api/churncut-url', async (req, res) => {
  const { customerEmail } = req.body;

  const expiration = Math.floor(Date.now() / 1000) + 3600;

  const response = await axios.post(
    'https://app.churncut.com/churncut-client-integration/get-cancellation-session-url',
    {
      churncut_app_id: CHURNCUT_APP_ID,
      expiration_date_timestamp: expiration,
      customer_email: customerEmail
    },
    {
      headers: {
        'Authorization': `Bearer ${CHURNCUT_SECRET}`,
        'Content-Type': 'application/json'
      }
    }
  );

  const data = response.data; // axios parses JSON automatically, no .json() needed
  res.json({ url: data.url, hmac: data.hmac });
});

FastAPI (Python)

python
from fastapi import FastAPI
import os
import time

import requests

app = FastAPI()

CHURNCUT_SECRET = os.environ["CHURNCUT_SECRET_KEY"]
CHURNCUT_APP_ID = os.environ["CHURNCUT_APP_ID"]


@app.post("/api/churncut-url")
def get_cancellation_url(request: dict):
    customer_email = request.get("customer_email")
    expiration = int(time.time()) + 3600

    response = requests.post(
        "https://app.churncut.com/churncut-client-integration/get-cancellation-session-url",
        headers={"Authorization": f"Bearer {CHURNCUT_SECRET}", "Content-Type": "application/json"},
        json={
            "churncut_app_id": CHURNCUT_APP_ID,
            "expiration_date_timestamp": expiration,
            "customer_email": customer_email,
        },
    )

    data = response.json()
    return {"url": data["url"], "hmac": data["hmac"]}

Step 3: Integrate the widget

Add the ChurnCut script and connect it to your cancel button.

html
<script src="https://app.churncut.com/static/user_integration/js/integration_initiallizer.js"></script>

React

jsx
import { useCallback } from 'react';

function CancelButton({ customerEmail }) {
  const handleCancel = useCallback(async () => {
    // Get session URL and hmac from backend
    const res = await fetch('/api/churncut-url', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ customerEmail })
    });
    const { url, hmac } = await res.json();

    // Start cancellation flow
    window.starCancellationFromURl(url);
  }, [customerEmail]);

  return (
    <button onClick={handleCancel}>
      Cancel subscription
    </button>
  );
}

Vue

vue
<template>
  <button @click="handleCancel">Cancel subscription</button>
</template>

<script setup>
const props = defineProps(['customerEmail']);

async function handleCancel() {
  const res = await fetch('/api/churncut-url', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ customerEmail: props.customerEmail })
  });
  const { url, hmac } = await res.json();

  const urlObj = new URL(url);
  const params = new URLSearchParams(urlObj.search);

  window.starCancellationFromURl(data.url);
}
</script>

Environment variables

Configure these variables on your server:

bash
CHURNCUT_APP_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
CHURNCUT_SECRET_KEY=your-secret-key

Important: Never expose your Secret Key on the client. Always call the API from your backend.

Test the integration

  • Use test credentials in your development environment
  • Start a cancellation flow with a Stripe test customer
  • Verify the widget appears correctly
  • Check events in your ChurnCut dashboard