Cómo usar Kushki.js para reducir tu scope PCI a cero: tokenización en el frontend sin que los datos de tarjeta toquen tus servidores
Usando Kushki.js correctamente, tus servidores nunca tocan datos de tarjeta — eliminando prácticamente todo el scope PCI de tu infraestructura.
Andrés Mejía
Senior Backend Engineer
21 de abril de 2026
·4 minLa certificación PCI DSS es uno de los requisitos más costosos y complejos de cumplir si tu integración maneja datos de tarjeta directamente. La buena noticia: si usas Kushki.js correctamente, tus servidores nunca tocan datos de tarjeta — y eso elimina prácticamente todo el scope PCI de tu infraestructura.
Este artículo explica cómo funciona la tokenización en el frontend con Kushki.js, cómo implementarla correctamente y los errores que anulan su beneficio de seguridad sin que te des cuenta.
Por qué el scope PCI importa
PCI DSS define el alcance de cumplimiento según qué sistemas tocan datos de tarjeta. Si tu backend recibe, transmite o almacena números de tarjeta (PAN), fechas de expiración o CVV — aunque sea por milisegundos — toda esa infraestructura entra en scope y requiere auditoría anual.
Reducir el scope no es solo un ejercicio de compliance. Es menos infraestructura que auditar, menos controles que implementar y menos superficie de ataque en caso de una brecha.
Kushki.js resuelve esto haciendo la tokenización directamente en el browser del usuario, antes de que cualquier dato llegue a tu backend.
Cómo funciona Kushki.js
El flujo es simple: el usuario ingresa sus datos de tarjeta en campos controlados por Kushki.js. La librería los envía directamente a los servidores de Kushki y devuelve un token de un solo uso. Tu frontend solo maneja ese token — nunca el PAN, nunca el CVV.
Usuario ingresa datos → Kushki.js tokeniza → Token llega a tu backend → Charge con token
Tu backend solo maneja el token. Kushki maneja los datos sensibles.
Implementación paso a paso
1. Instala Kushki.js
<script src="https://cdn.kushki.com/api/v1/kushki.js"></script>O vía npm si usas un framework moderno:
npm install @kushki/js2. Inicializa la librería con tu public key
import { Kushki } from "@kushki/js";
const kushki = new Kushki({
merchantId: "TU_PUBLIC_MERCHANT_ID",
inTestEnvironment: false, // true en sandbox
});Usa siempre tu public key en el frontend — nunca tu private key. Son distintas y están en tu consola de Kushki.
3. Tokeniza la tarjeta
1const tokenResponse = await kushki.requestToken({
2 amount: {
3 subtotalIva: 0,
4 subtotalIva0: 1200.00,
5 iva: 0,
6 ice: 0,
7 currency: "MXN"
8 },
9 card: {
10 name: cardholderName, // valor del input del usuario
11 number: cardNumber, // solo dígitos, sin espacios
12 expiryMonth: expiryMonth, // "MM"
13 expiryYear: expiryYear, // "YY"
14 cvv: cvv
15 }
16});
17
18if (tokenResponse.token) {
19 // Envía este token a tu backend
20 await submitPayment(tokenResponse.token);
21} else {
22 // Maneja el error en el frontend
23 showError(tokenResponse.message);
24}4. Procesa el cargo en tu backend
Tu backend recibe el token y hace el charge sin ver ningún dato de tarjeta:
1// Backend — Node.js ejemplo
2app.post('/pay', async (req, res) => {
3 const { token, amount } = req.body;
4
5 const charge = await fetch('https://api.kushki.com/v1/charges', {
6 method: 'POST',
7 headers: {
8 'Private-Merchant-Id': process.env.KUSHKI_PRIVATE_KEY,
9 'Content-Type': 'application/json'
10 },
11 body: JSON.stringify({
12 token,
13 amount: { subtotalIva0: amount, currency: 'MXN' },
14 fullResponse: true
15 })
16 });
17
18 const result = await charge.json();
19 res.json(result);
20});Los errores que anulan el beneficio de seguridad
Implementar Kushki.js no garantiza automáticamente un scope PCI reducido. Estos son los errores más comunes que meten tus servidores en scope de todas formas:
Error 1: Loggear el request completo del frontend
Si tu backend loggea el body de todos los requests entrantes y el frontend te envía los datos de tarjeta antes de tokenizar, los tienes en tus logs. Revisa que tu frontend tokeniza primero y envía solo el token al backend.
Error 2: Pasar datos de tarjeta por tu propio backend
Algunos equipos construyen un endpoint propio que recibe los datos de tarjeta 'para validarlos' y luego llama a Kushki. Eso mete completamente tu backend en scope. La tokenización debe suceder en el browser del usuario — no en tu servidor.
Error 3: Usar la private key en el frontend
La private key nunca debe estar en el código del cliente. Si la expones, cualquiera puede hacer cargos en nombre de tu cuenta. Kushki.js solo necesita tu public merchant ID.
Error 4: No validar en el frontend antes de tokenizar
Si el usuario ingresa un número de tarjeta inválido y Kushki.js lo rechaza, ese error llega como tokenResponse.message. Manéjalo en el frontend — no hagas el request de todas formas esperando que el backend lo rechace.
Kushki.js con frameworks modernos
Si usas React, el patrón recomendado es inicializar Kushki una sola vez y mantener el token en estado local hasta el submit:
1const [token, setToken] = useState(null);
2
3const handleTokenize = async () => {
4 const response = await kushki.requestToken({ amount, card });
5 if (response.token) {
6 setToken(response.token);
7 } else {
8 setError(response.message);
9 }
10};
11
12const handleSubmit = async () => {
13 if (!token) return;
14 await submitPayment(token); // envía solo el token al backend
15};No almacenes el token más tiempo del necesario — son de un solo uso y expiran. Tokeniza justo antes del submit, no al cargar el formulario.
Reducir el scope PCI no es solo una decisión de compliance — es una decisión de arquitectura que simplifica tu infraestructura y reduce tu riesgo operativo. Kushki.js hace el trabajo pesado; tu responsabilidad es no introducir los datos de tarjeta en tu propio pipeline por error.
Para la referencia completa de Kushki.js y sus opciones de configuración, visita la documentación de Kushki.
Tags