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-keyImportant: 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
