Quickstart
Integra ChurnCut en tu aplicación en minutos y comienza a retener clientes.
Requisitos previos
- Una cuenta activa de Stripe con suscripciones (live o test)
- Tu App ID y Secret Key de ChurnCut (disponibles en Settings)
- Posibilidad de añadir un snippet de JavaScript a tu app web
- Un desarrollador disponible para la configuración de HMAC

Paso 1: Generar firma HMAC
Para mantener el flujo de cancelación seguro y accesible solo para tus usuarios autenticados, necesitas generar un token HMAC en tu backend.
El token se genera concatenando:
external_user_id- Customer ID de Stripechurncut_app_id- Tu App ID de ChurnCutexpiration_timestamp- Timestamp Unix de expiración
const crypto = require('crypto');
function generateChurncutToken(secretKey, customerId, appId, expirationTimestamp) {
const message = customerId + appId + expirationTimestamp;
return crypto
.createHmac('sha256', secretKey)
.update(message)
.digest('hex');
}
// Example usage
const secretKey = "your-secret-key";
const customerId = "cus_XXXXXXXXXXXXXX";
const appId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
const expirationTimestamp = "1767139200";
const token = generateChurncutToken(secretKey, customerId, appId, expirationTimestamp);
console.log(token);Important: El token HMAC debe generarse en tu backend. Nunca expongas tu Secret Key en el cliente.
Paso 2: Añadir el script
Incluye el script de ChurnCut en tu aplicación web:
<script src="https://app.churncut.com/static/js/churncut.js"></script>Paso 3: Iniciar el flujo de cancelación
Una vez que tengas el token HMAC, puedes iniciar el flujo de cancelación:
startCancellationFlow(
"cus_XXXXXXXXXXXXXX", // Stripe customer ID
"sub_XXXXXXXXXXXXXX", // Current Stripe subscription ID
"your-hmac-token", // HMAC token generated in step 1
"1767139200", // Expiration timestamp (same used to generate token)
"your-app-id" // Your ChurnCut App ID
);Ejemplos completos por framework
Elige tu framework para ver un ejemplo completo con botón de cancelación y token HMAC:
import { useCallback } from 'react';
function CancelButton({ customerId, subscriptionId }) {
const handleCancel = useCallback(async () => {
// 1. Get HMAC token from your backend
const res = await fetch(
\`/api/churncut-token?customerId=\${customerId}&subscriptionId=\${subscriptionId}\`
);
const { token, expiration, appId } = await res.json();
// 2. Start the cancellation flow
window.startCancellationFlow(
customerId,
subscriptionId,
token,
expiration,
appId
);
}, [customerId, subscriptionId]);
return (
<button onClick={handleCancel} className="cancel-btn">
Cancel subscription
</button>
);
}Botón de cancelación con preview de suscripción
Un patrón común es mostrar los detalles de la suscripción del usuario con un botón para cancelar. Aquí tienes un componente completo que puedes adaptar:
Pro Plan
$49/month · Renews Feb 28, 2026
import { useCallback, useState, useEffect } from 'react';
function SubscriptionSettings({ customerId }) {
const [subscription, setSubscription] = useState(null);
useEffect(() => {
// Fetch subscription details from your backend
fetch(`/api/subscription?customerId=${customerId}`)
.then(res => res.json())
.then(data => setSubscription(data));
}, [customerId]);
const handleCancel = useCallback(async () => {
// 1. Get HMAC token from your backend
const res = await fetch(
`/api/churncut-token?customerId=${customerId}&subscriptionId=${subscription.id}`
);
const { token, expiration, appId } = await res.json();
// 2. ChurnCut handles the rest — shows personalized offers,
// collects feedback, and only cancels if the user confirms
window.startCancellationFlow(
customerId,
subscription.id,
token,
expiration,
appId
);
}, [customerId, subscription]);
if (!subscription) return <div>Loading...</div>;
return (
<div className="subscription-card">
<h3>{subscription.planName}</h3>
<p>${subscription.amount}/month · Renews {subscription.renewalDate}</p>
<div className="subscription-details">
<div><span>Status</span><span>{subscription.status}</span></div>
<div><span>Payment</span><span>•••• {subscription.last4}</span></div>
</div>
<div className="subscription-actions">
<button onClick={() => navigate('/change-plan')}>
Change plan
</button>
<button onClick={handleCancel} className="cancel-btn">
Cancel subscription
</button>
</div>
</div>
);
}Tip: ChurnCut se encarga de mostrar ofertas personalizadas, recoger feedback y solo cancela si el usuario lo confirma. Tú solo necesitas llamar a startCancellationFlow.
Método alternativo: Cancelación por email
Si prefieres identificar usuarios por email en lugar de IDs de Stripe:
startCancellationFlow(
null, // No customer ID
null, // No subscription ID
"your-hmac-token", // HMAC token
"1767139200", // Expiration timestamp
"your-app-id", // Your App ID
"user@example.com" // User email
);Warning: Usa este método solo si cada usuario tiene un email único en Stripe y solo tiene una suscripción activa a la vez.
