Si tus usuarios no tienen tarjeta de crédito o prefieren usar el saldo disponible en sus cuentas bancarias para comprar en línea, la transferencia bancaria es la opción de pago ideal.Transfer In permite a tus clientes pagar directamente desde su cuenta bancaria, sin tarjeta. En Colombia 🇨🇴 hay dos flujos sobre el mismo conjunto de endpoints: ACH, una redirección segura al banco del cliente a través de PSE (Pagos Seguros en Línea), y Bre-B, un pago en tiempo real que el cliente autoriza escaneando un código QR. ACH es el flujo por defecto; Bre-B se activa solicitud por solicitud.Por nuestras políticas de riesgo, los métodos de pago disponibles y el tipo de integración pueden variar una vez completes la afiliación. Te indicaremos cómo proceder si este proceso aplica a tu comercio.
Flujo de pago#
Un pago Transfer In en Colombia consta de 5 pasos secuenciales: obtener la lista de bancos, tokenización, inicialización, redirección al banco y confirmación del estado.
Obtén la lista de bancos
Antes de solicitar un token, tu backend debe llamar al endpoint
Get Bank List con tu
Public Merchant ID para obtener los bancos PSE disponibles.
⚠️ Este paso es obligatorio en Colombia. A diferencia de otros países, siempre debes llamar a este endpoint y mostrarle la lista a tu cliente para que elija su banco antes de continuar.
Muéstrale la lista de bancos al cliente y guarda el code que elija: lo enviarás como bankId en la solicitud del token.
Solicita un token de Transfer In
Tu backend llama al endpoint del token con tu
Public Merchant ID. Debes incluir el monto de la transacción, los datos de documento del cliente, el
bankId elegido y un
callbackUrl: la URL a la que llega el cliente después de completar el pago del lado del banco.
Reglas del token: los tokens expiran en 30 minutos y son de un solo uso. Si la transacción falla o el token expira, debes solicitar uno nuevo.
Campos obligatorios para Colombia:| Campo | Descripción |
|---|
bankId | Código del banco que el cliente eligió de la lista de bancos. Obligatorio en Colombia. |
amount | Objeto con subtotalIva, subtotalIva0 e iva |
callbackUrl | URL de redirección después de la confirmación del banco |
userType | 0 = Persona Natural · 1 = Persona Jurídica |
documentType | CC, NIT, CE, TI o PP (ver más abajo) |
documentNumber | Número de documento del cliente |
email | Correo electrónico del cliente |
currency | Siempre COP para Colombia |
Tipos de documento aceptados en Colombia:| Valor | Documento |
|---|
CC | Cédula de Ciudadanía 🇨🇴 |
NIT | Número de Identificación Tributaria 🇨🇴 |
CE | Cédula de Extranjería 🇨🇴 |
TI | Tarjeta de Identidad 🇨🇴 |
PP | Pasaporte 🇨🇴 |
Inicia la transacción
Con tu
Private Merchant ID, llama al endpoint Init Transaction con el
token que obtuviste en el paso anterior. Kushki valida el token y devuelve un
redirectUrl.
El redirectUrl es de un solo uso: redirige a tu cliente a esa URL en cuanto la recibas. El cliente llega a la interfaz de PSE para autorizar la transferencia con su banco.Campos de la respuesta para Colombia:| Campo | Descripción |
|---|
redirectUrl | URL de un solo uso para redirigir al cliente a PSE |
trazabilityCode | También se llama CUS: código único de referencia de pago asignado por PSE. |
bankId | Código del banco elegido para la transacción |
bankName | Nombre del banco elegido para la transacción |
transactionReference | Referencia única de esta transacción |
El cliente completa el pago en PSE
El cliente es redirigido a PSE y luego al portal de su banco, donde autoriza (o rechaza) la transferencia. Este paso ocurre por completo del lado de PSE y el banco: tu backend no tiene que hacer nada.Cuando el cliente termina, PSE lo devuelve a tu callbackUrl.
Consulta el estado de la transacción
Cuando el cliente llegue a tu
callbackUrl, llama al endpoint
Get Status usando el
token original como parámetro de ruta para confirmar el resultado final de la transacción.
Estados posibles en Colombia:| Estado | Significado |
|---|
initializedTransaction | La transacción se creó pero aún no se completa |
approvedTransaction | Transferencia autorizada: los fondos están en camino |
declinedTransaction | La transferencia fue rechazada |
La respuesta también incluye el trazabilityCode (CUS), que puedes usar para conciliar la transacción con los registros de PSE.
Objeto amount#
El objeto amount es obligatorio en la solicitud del token. Usa la siguiente estructura según si la transacción tiene impuestos o no:Con impuestos adicionales
{
"amount": {
"subtotalIva": 100000,
"subtotalIva0": 0,
"iva": 10000
}
}
Pon en subtotalIva la base gravable y en iva el valor del impuesto. Pon subtotalIva0 en 0. Todos los montos en COP.
Notificaciones por webhook#
Puedes recibir notificaciones de la transacción en tiempo real incluyendo el objeto webhooks en tu solicitud de Init Transaction. Esto es independiente de los webhooks configurados en la Kushki Console: los dos canales se disparan al mismo tiempo.{
"webhooks": [
{
"events": ["approvedTransaction", "declinedTransaction"],
"headers": [
{ "label": "Authorization", "value": "Bearer your-token" }
],
"urls": [
"https://merchant.example.com/webhooks/transfer-in"
]
}
]
}
🇨🇴 Bre-B — pagos con QR en tiempo real#
Bre-B es el sistema de pagos inmediatos de bajo valor de Colombia, operado por el Banco de la República.
Es un flujo alternativo dentro de los mismos endpoints de Transfer In: en vez de recoger los
datos bancarios del cliente y redirigirlo a su banco, Kushki devuelve un código QR que el
cliente escanea desde su app bancaria para autorizar el pago en tiempo real.El flujo ACH no cambia: las integraciones existentes no requieren modificaciones.Bre-B está disponible solo para Colombia y solo en los merchant IDs que tengan habilitado el
procesador Bre-B. Contacta a tu ejecutivo de cuenta para activarlo.
ACH vs. Bre-B#
| ACH (PSE) | Bre-B |
|---|
| Cómo paga el cliente | Se le redirige al sitio de su banco | Escanea un QR en su app bancaria |
| Activación | Por defecto: no envíes flowType | flowType: "BRE_B" en la solicitud del token |
| Requiere lista de bancos | Sí | No |
Resultado de init | redirectUrl | qr (PNG en base64) |
| Ventana de vigencia | Token: 30 minutos | QR: 10 minutos |
| Liquidación | Diferida | En tiempo real |
| Se puede cancelar | No | Sí, mientras no esté en un estado final |
| Webhook y códigos de error | — | Idénticos a ACH |
Los campos obligatorios también cambian: en Bre-B solo amount, currency y flowType son obligatorios, así que
bankId, callbackUrl, userType, documentType, documentNumber, paymentDescription y
email pasan a ser opcionales.El flujo, paso a paso#
1 · Solicita el token. El mismo endpoint que ACH, más flowType. No necesitas la lista de bancos.{
"amount": { "subtotalIva0": 1000, "subtotalIva": 0, "iva": 0 },
"currency": "COP",
"flowType": "BRE_B"
}
La solicitud del token acepta dos formas: elige Bre-B en el selector del cuerpo de la solicitud para ver los
campos que este flujo realmente exige: solo amount, currency y flowType.2 · Genera el QR. Llama a Init Transaction con ese token, repitiendo el mismo monto
que enviaste en el paso 1:{
"token": "A3pKwX200000yzQR9146362rJMCBSt7n",
"amount": { "subtotalIva0": 1000, "subtotalIva": 0, "iva": 0 }
}
La respuesta trae qr en vez de redirectUrl:{
"qr": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQ...",
"transactionReference": "f2110170-8eec-4214-b2d0-38970d44f8e1"
}
Agrega "fullResponse": "v2" a la solicitud de init para recibir también el objeto details.3 · Muestra el QR. El campo qr es un Data URI completo, así que en web va directo a una
etiqueta img:En apps nativas, decodifica el base64 y renderiza el bitmap con el componente de imagen de tu plataforma.4 · Espera el resultado. El cliente escanea y autoriza; el resultado llega de forma
asíncrona. Configura un webhook o consulta Get Status con el mismo token. El QR expira en
10 minutos: después de eso, solicita un token nuevo y vuelve a hacer el init.5 · Cancela si hace falta. Mientras la transacción no tenga un estado final, Cancel Transaction
invalida el QR activo. Devuelve 204 No Content si todo va bien, o 400 con el código T023 si la
transacción ya llegó a un estado final.Pruebas en UAT#
El sandbox elige el escenario a partir de transaction_amount: la suma de todos los campos del objeto
amount (subtotalIva0 + subtotalIva + iva). Para caer en el escenario 1000, envía
subtotalIva0: 500, subtotalIva: 500, iva: 0, o subtotalIva0: 1000 por sí solo.Estos montos son identificadores de escenario en el sandbox. No tienen ningún significado económico: nunca los uses
en producción.
transaction_amount | HTTP | Resultado | Webhook |
|---|
1000 | 201 | Éxito | Se dispara: pago aprobado |
9999 | 201 | Éxito | No se dispara; la transacción queda inicializada |
11000 | 500 | Error QR-CODE-0001 | No se dispara |
15000 | — | La solicitud expira por timeout; la transacción queda inicializada | No se dispara |
99999999999 | 400 | Error QR-CODE-0059: monto fuera de rango | No se dispara |
| Cualquier otro valor | 201 | Éxito | No se dispara |
Checklist de certificación#
Antes de salir a producción, confirma que:Los montos cuadran correctamente entre subtotalIva, subtotalIva0 e iva.
flowType se envía como "BRE_B" en la solicitud del token.
El QR del campo qr se renderiza correctamente para el cliente.
Cancel Transaction está integrado para los casos en que el cliente abandona el pago.
Los mensajes en pantalla reflejan las respuestas de Kushki.
Las notificaciones por webhook se responden con HTTP 200.
El botón de pago se deshabilita después del primer clic, para evitar el envío doble.
Todas las respuestas de Kushki se almacenan y registran: es requisito para soporte.
El logo de Kushki está visible.
Se envían todos los campos obligatorios, según la referencia de la API.