SPEI en México, PSE en Colombia, TEF en Chile: cómo adaptar tu integración con la API de Kushki al rail de transferencias de cada mercado
SPEI, PSE y TEF se comportan de forma completamente distinta. Te explicamos los tiempos, estados y webhooks que necesitas manejar para cada mercado.
Diego Ramírez
Staff Engineer
7 de abril de 2026
·6 minCuando integras pagos con tarjeta, la lógica es casi universal: un endpoint, una respuesta, el mismo flujo en todos los países. Las transferencias bancarias son otra historia.
Cada mercado en LATAM tiene su propio rail de pagos, su propio esquema de tiempos, sus propias reglas de conciliación y su propia forma de fallar. Si estás integrando transferencias bancarias con Kushki, esto es lo que tienes que saber antes de llegar a producción.
El error más común: tratar todas las transferencias igual
La API de Kushki unifica los métodos de pago bajo una misma interfaz y eso es una ventaja enorme. Pero la unificación de la API no significa que el comportamiento del pago sea idéntico en cada país.
Las diferencias no están en el endpoint. Están en los tiempos de confirmación, en cómo se genera la referencia de pago, en cuánto tiempo tiene el usuario para completar la transferencia, y en qué estados intermedios debes manejar. Si no las conoces, vas a tener problemas en producción que son difíciles de diagnosticar.
SPEI — México
SPEI (Sistema de Pagos Electrónicos Interbancarios) es el rail de pagos en tiempo real del Banco de México. Opera las 24 horas, los 7 días de la semana, incluyendo fines de semana y días festivos.
El flujo con Kushki genera una CLABE interbancaria de 18 dígitos a la que el usuario debe transferir el monto exacto. Esta CLABE es de uso único — no reutilices CLABEs entre sesiones de pago.
1POST /v1/transfer/init
2{
3 "totalAmount": 1500.00,
4 "currency": "MXN",
5 "returnUrl": "https://tuapp.com/confirmacion",
6 "description": "Orden #8821"
7}La respuesta incluye el paymentUrl donde el usuario completa la transferencia, y el ticketNumber que usarás para rastrear el estado.
{
"ticketNumber": "TRX-MX-00293847",
"paymentUrl": "https://pay.kushki.com/spei/TRX-MX-00293847",
"expirationTime": "2025-05-05T23:59:59Z"
}Tiempo de expiración: Por defecto, la referencia SPEI expira en 24 horas. Para tickets de alto valor o B2B, considera extenderlo configurando este valor en el request.
Confirmación: SPEI es en tiempo real. En condiciones normales, la confirmación llega vía webhook en segundos. Sin embargo, existen ventanas de mantenimiento del sistema bancario (generalmente entre las 23:00 y 01:00 hrs) donde las transacciones pueden quedar en PENDING por hasta 2 horas.
{
"ticketNumber": "TRX-MX-00293847",
"transactionStatus": "APPROVAL",
"paymentMethod": "transfer",
"amount": 1500.00
}Si recibes PENDING, no canceles la orden automáticamente. Espera la confirmación o implementa un job de reconciliación que consulte el estado 30 minutos después.
PSE — Colombia
PSE (Pagos Seguros en Línea) es la red de pagos bancarios en línea de Colombia, operada por ACH Colombia. A diferencia de SPEI, PSE redirige al usuario al portal de su banco para autenticar la transacción.
El usuario selecciona su banco antes de ser redirigido. Esto significa que en el request inicial debes incluir el listado de bancos disponibles — o recuperarlo previamente con el endpoint de bancos de Kushki — y presentárselo al usuario en tu checkout.
1POST /v1/transfer/init
2{
3 "totalAmount": 85000,
4 "currency": "COP",
5 "returnUrl": "https://tuapp.com/confirmacion",
6 "userType": "0",
7 "documentType": "CC",
8 "documentNumber": "1234567890",
9 "bankId": "1007"
10}Nota los campos adicionales: userType (0 = persona natural, 1 = empresa), documentType y documentNumber. PSE requiere identificación del pagador — no es opcional. Si omites estos campos, el request fallará con un error de validación.
Tiempos de confirmación: PSE no es en tiempo real. Después de que el usuario completa la autenticación en su banco, la confirmación puede tardar entre 10 segundos y varios minutos dependiendo del banco. Estados intermedios a manejar: INITIALIZED (el usuario fue redirigido al banco), PENDING (el banco recibió la instrucción, esperando procesamiento), APPROVAL (pago confirmado), DECLINED (rechazado por el banco). Implementa tu webhook para todos estos estados, no solo para APPROVAL y DECLINED.
TEF — Chile
TEF (Transferencia Electrónica de Fondos) es el mecanismo de transferencias bancarias en Chile. Opera sobre la infraestructura de los bancos locales, con confirmación generalmente dentro del mismo día hábil.
En Chile, el flujo es distinto: Kushki genera un número de cuenta y un código de referencia que el usuario usa para hacer la transferencia desde su banco. No hay redirección al portal bancario como en PSE — el usuario hace la transferencia desde su propia aplicación o banca en línea.
1POST /v1/transfer/init
2{
3 "totalAmount": 25000,
4 "currency": "CLP",
5 "returnUrl": "https://tuapp.com/confirmacion",
6 "description": "Suscripción mensual"
7}La respuesta incluye los datos bancarios de destino que debes mostrarle al usuario:
1{
2 "ticketNumber": "TRX-CL-00847231",
3 "bankAccount": "12345678",
4 "bankName": "Banco de Chile",
5 "accountType": "Cuenta Corriente",
6 "rut": "76.XXX.XXX-X",
7 "amount": 25000,
8 "expirationTime": "2025-05-06T17:00:00Z"
9}Tiempo de expiración: Las referencias TEF expiran típicamente al final del día hábil. Si tu negocio tiene tickets de alto valor, considera mostrar esta fecha de expiración claramente en la interfaz — el usuario necesita saber que tiene un plazo para completar la transferencia.
Confirmación: TEF no es en tiempo real. La confirmación puede tomar desde minutos hasta varias horas dependiendo del banco del pagador. Para e-commerce, considera enviar el producto o activar el servicio solo después de recibir el webhook de APPROVAL.
Manejo unificado de webhooks para los tres países
Aunque el comportamiento es distinto, el formato del webhook de Kushki es consistente entre países. Puedes usar un solo handler y discriminar por paymentMethod y currency para aplicar la lógica específica de cada mercado.
1app.post('/kushki/webhook', (req, res) => {
2 const { ticketNumber, transactionStatus, currency, amount } = req.body;
3
4 switch (transactionStatus) {
5 case 'APPROVAL':
6 // Confirmar orden, enviar email de confirmación
7 confirmOrder(ticketNumber, amount);
8 break;
9 case 'DECLINED':
10 // Notificar al usuario, liberar inventario reservado
11 declineOrder(ticketNumber);
12 break;
13 case 'PENDING':
14 // No hacer nada todavía — esperar confirmación
15 // Opcional: programar job de reconciliación
16 schedulePendingCheck(ticketNumber, currency);
17 break;
18 }
19
20 res.status(200).send('OK');
21});El 200 OK inmediato es importante: si tu endpoint tarda en responder o devuelve un error, Kushki reintentará el webhook. Procesa la lógica de negocio de forma asíncrona.
Las transferencias bancarias tienen tasas de conversión más bajas que las tarjetas, pero en B2B y tickets altos son el método preferido en toda la región. Implementarlas correctamente — con los estados intermedios, los tiempos de expiración y el webhook unificado — marca la diferencia entre una integración funcional y una lista para producción.
Para el detalle completo de cada endpoint y los códigos de error específicos por país, consulta la documentación de Kushki.
Tags