Dispersa con Bre-B
Dispersar pagos con Bre-B consiste en entregar dinero en tiempo real a las cuentas de tus usuarios usando únicamente una llave de pago del destinatario — sin necesidad de conocer su número de cuenta bancaria. Si ya cuentas con la llave de tus destinatarios (su cédula, celular, correo, alias o código de comercio), puedes usar tu cuenta de dispersión de Kushki para depositar directamente usando la lógica que prefieras.
Ideal para:
- Pago a proveedores o vendedores
- Marketplaces
- Aplicaciones de delivery
- Plataformas gig economy
- Reembolsos y compensaciones
Detalles de operación
El proceso de dispersión con Bre-B en Colombia se realiza siguiendo el flujo: Comercio → Kushki → Banco de la República (SPBVI) → Banco Receptor → Beneficiario.
| Parámetro | Detalle |
|---|---|
| Monto mínimo por transacción | 1 COP |
| Monto máximo por transacción | Equivalente a 1.000 UVT (Unidades de Valor Tributario, actualizado anualmente por la DIAN). Cada entidad financiera o usuario puede establecer límites inferiores diarios o por transacción. |
| Moneda | COP |
| Bancos disponibles | Todos los bancos colombianos (reglamentación del Banco de la República) |
| Horario de procesamiento API | 24/7 |
| Tiempo de acreditamiento | Tiempo real (máximo 30 segundos desde el inicio) |
| Tipo de respuesta | Asíncrona — el resultado final llega por webhook o por consulta al endpoint Get Status |
Nota importante: La API de Kushki recibe y procesa las peticiones 24/7. A diferencia de ACH, Bre-B no utiliza ciclos bancarios — el procesamiento es en tiempo real a través del SPBVI del Banco de la República. No es necesario consultar el listado de bancos antes de tokenizar.
Flujo
El flujo que integrarás es el siguiente:
Aquí aprenderás cómo integrar las dispersiones de dinero con Bre-B.
1. Tokeniza la información
El primer paso es obtener un token enviando la llave del destinatario a Kushki. A diferencia de ACH, no necesitas consultar el listado de bancos antes de este paso — todos los bancos colombianos soportan transferencias a llaves por reglamentación del Banco de la República.
Deberás realizar la petición del token utilizando nuestro endpoint de tokenización.
Campos obligatorios para obtener el token
Ten en cuenta los campos requeridos en el cuerpo de la petición de token para Bre-B:
Dispersión con llave Bre-B (accountType = KI, KP, KE, KA, KM) |
|---|
- accountType - accountNumber - totalAmount - currency |
Los campos documentType, documentNumber, bankId y name son opcionales para Bre-B en Colombia.
Tipos de llave (accountType)
accountType | Tipo de llave |
|---|---|
KI | Número de identificación |
KP | Número de celular |
KE | Correo electrónico |
KA | Alias alfanumérico |
KM | Código de comercio |
Formatos válidos para accountNumber
El formato del accountNumber se valida antes de enviar cualquier solicitud a la red de pagos (fail-fast). Un formato inválido retorna HTTP 400 de inmediato, sin llegar a consultar la red.
accountType | Formato requerido en accountNumber |
|---|---|
KI | Alfanumérico en mayúsculas. Mínimo 1 carácter. Sin espacios ni caracteres especiales. |
KP | Exactamente 10 dígitos. Debe iniciar con 3, seguido de 9 dígitos. |
KE | Email válido. Máximo 30 caracteres antes de @ y 61 después. Debe incluir dominio válido. |
KA | Debe iniciar con @. Solo caracteres alfanuméricos en mayúsculas. Sin espacios ni caracteres especiales. |
KM | Exactamente 10 dígitos. Debe iniciar con 00, seguido de 8 dígitos. |
- Javascript
- Python
- PHP
var request = require('request');// Ejemplo con llave de celular (KP)var options = {'method': 'POST','url': 'https://api-uat.kushkipagos.com/payouts/transfer/v1/tokens', // Ambiente de prueba'headers': {'Public-Merchant-Id': '', // Reemplaza con tu Public Key'Content-Type': 'application/json'},body: JSON.stringify({"accountType": "KP","accountNumber": "3001234567","totalAmount": 1000,"currency": "COP"})};request(options, function (error, response) {if (error) throw new Error(error);var jsonData = JSON.parse(response.body);console.log('Token:', jsonData.token);// Muestra jsonData.keyResolution al usuario para confirmar el destinatarioconsole.log('Destinatario:', jsonData.keyResolution.ownerName);});
import requestsimport json# Ejemplo con llave de celular (KP)url = "https://api-uat.kushkipagos.com/payouts/transfer/v1/tokens" # Ambiente de pruebapayload = json.dumps({"accountType": "KP","accountNumber": "3001234567","totalAmount": 1000,"currency": "COP"})headers = {'Public-Merchant-Id': '', # Reemplaza con tu Public Key'Content-Type': 'application/json'}response = requests.request("POST", url, headers=headers, data=payload)data = response.json()print('Token:', data['token'])# Muestra data['keyResolution'] al usuario para confirmar el destinatarioprint('Destinatario:', data['keyResolution']['ownerName'])
$client = new http\Client;$request = new http\Client\Request;// Ejemplo con llave de celular (KP)$request->setRequestUrl('https://api-uat.kushkipagos.com/payouts/transfer/v1/tokens'); // Ambiente de prueba$request->setRequestMethod('POST');$body = new http\Message\Body;$body->append(json_encode(["accountType" => "KP","accountNumber" => "3001234567","totalAmount" => 1000,"currency" => "COP"]));$request->setBody($body);$request->setOptions(array());$request->setHeaders(array('Public-Merchant-Id' => '', // Reemplaza con tu Public Key'Content-Type' => 'application/json'));$client->enqueue($request)->send();$data = json_decode($client->getResponse()->getBody(), true);echo 'Token: ' . $data['token'];// Muestra $data['keyResolution'] al usuario para confirmar el destinatarioecho 'Destinatario: ' . $data['keyResolution']['ownerName'];
La respuesta incluye el token y el objeto keyResolution con los datos del destinatario resueltos por la red de pagos:
{"token": "53de1cb6bbb54011a0a98053d48677e0","keyResolution": {"keyValue": "3001234567","ownerName": "M**** G**** L****"}}
| Campo | Descripción |
|---|---|
token | Token de la transacción. Expira en 30 minutos. De un solo uso, independientemente del resultado. |
keyResolution.keyValue | Valor exacto de la llave, sin transformaciones. |
keyResolution.ownerName | Nombre del titular, retornado enmascarado por la red de pagos (ej: M**** G**** L****). |
2. Confirma el destinatario
Ya que has obtenido el token y el objeto keyResolution, debes mostrar al operador o usuario final la información del destinatario para confirmar que los datos son correctos antes de inicializar la transacción. Este paso es requerido por el Banco de la República.
Muestra al operador o usuario:
- El valor de la llave:
keyResolution.keyValue - El nombre del titular:
keyResolution.ownerName(enmascarado, ej:M**** G**** L****)
3. Inicializa la transacción
Una vez confirmados los datos del destinatario, debes enviar el token obtenido e iniciar el proceso de dispersión con Kushki. Deberás realizar una llamada a nuestro endpoint de inicialización para iniciar el pago. Este paso descuenta el saldo inmediatamente de tu cuenta de dispersión.
- Javascript
- Python
- PHP
var request = require('request');var options = {'method': 'POST','url': 'https://api-uat.kushkipagos.com/payouts/transfer/v1/init', // Ambiente de prueba'headers': {'Private-Merchant-Id': '', // Reemplaza con tu Private Key'Content-Type': 'application/json'},body: JSON.stringify({"token": "53de1cb6bbb54011a0a98053d48677e0", // Reemplaza con el token recibido"amount": {"subtotalIva": 0,"subtotalIva0": 1000,"iva": 0},"webhooks": [{"events": ["approvedTransaction", "declinedTransaction"],"urls": ["https://tu-endpoint.com/webhook"]}]})};request(options, function (error, response) {if (error) throw new Error(error);var jsonData = JSON.parse(response.body);console.log('ticketNumber:', jsonData.ticketNumber);console.log('status:', jsonData.status);// Guarda el ticketNumber para consultar el estado más adelante});
import requestsimport jsonurl = "https://api-uat.kushkipagos.com/payouts/transfer/v1/init" # Ambiente de pruebapayload = json.dumps({"token": "53de1cb6bbb54011a0a98053d48677e0", # Reemplaza con el token recibido"amount": {"subtotalIva": 0,"subtotalIva0": 1000,"iva": 0},"webhooks": [{"events": ["approvedTransaction", "declinedTransaction"],"urls": ["https://tu-endpoint.com/webhook"]}]})headers = {'Private-Merchant-Id': '', # Reemplaza con tu Private Key'Content-Type': 'application/json'}response = requests.request("POST", url, headers=headers, data=payload)data = response.json()print('ticketNumber:', data['ticketNumber'])print('status:', data['status'])# Guarda el ticketNumber para consultar el estado más adelante
$client = new http\Client;$request = new http\Client\Request;$request->setRequestUrl('https://api-uat.kushkipagos.com/payouts/transfer/v1/init'); // Ambiente de prueba$request->setRequestMethod('POST');$body = new http\Message\Body;$body->append(json_encode(["token" => "53de1cb6bbb54011a0a98053d48677e0", // Reemplaza con el token recibido"amount" => ["subtotalIva" => 0,"subtotalIva0" => 1000,"iva" => 0],"webhooks" => [["events" => ["approvedTransaction", "declinedTransaction"],"urls" => ["https://tu-endpoint.com/webhook"]]]]));$request->setBody($body);$request->setOptions(array());$request->setHeaders(array('Private-Merchant-Id' => '', // Reemplaza con tu Private Key'Content-Type' => 'application/json'));$client->enqueue($request)->send();$data = json_decode($client->getResponse()->getBody(), true);echo 'ticketNumber: ' . $data['ticketNumber'];echo 'status: ' . $data['status'];// Guarda el ticketNumber para consultar el estado más adelante
La respuesta entrega un número de ticket y el estado de la transacción:
{"status": "INITIALIZED","ticketNumber": "1234567890","transactionReference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}
4. Consulta el estado de la transacción
Ahora que la dispersión está en proceso, puedes conocer el estado de la transacción utilizando webhooks o consultando manualmente utilizando nuestra API.
Webhook
El estado de la transacción se notifica automáticamente en el momento en que la transferencia es aprobada o declinada. El payload incluye el objeto keyResolution con keyValue y ownerName.
API
Puedes utilizar nuestro endpoint Get Status para consultar manualmente el estado de una transacción específica.
- Javascript
- Python
- PHP
var request = require('request');var options = {'method': 'GET','url': 'https://api-uat.kushkipagos.com/payouts/transfer/v1/transaction/{{ticketNumber}}', // Reemplaza {{ticketNumber}}'headers': {'Private-Merchant-Id': '' // Reemplaza con tu Private Key}};request(options, function (error, response) {if (error) throw new Error(error);console.log(response.body);});
import requeststicket_number = "1234567890" # Reemplaza con el ticketNumber recibidourl = f"https://api-uat.kushkipagos.com/payouts/transfer/v1/transaction/{ticket_number}"headers = {'Private-Merchant-Id': '' # Reemplaza con tu Private Key}response = requests.request("GET", url, headers=headers)print(response.text.encode('utf8'))
$client = new http\Client;$request = new http\Client\Request;$ticketNumber = "1234567890"; // Reemplaza con el ticketNumber recibido$request->setRequestUrl("https://api-uat.kushkipagos.com/payouts/transfer/v1/transaction/{$ticketNumber}");$request->setRequestMethod('GET');$request->setOptions(array());$request->setHeaders(array('Private-Merchant-Id' => '' // Reemplaza con tu Private Key));$client->enqueue($request)->send();$response = $client->getResponse();echo $response->getBody();
5. Prueba tu integración
El ambiente UAT de Bre-B opera sobre un sandbox de la red de pagos. Las respuestas son simuladas y replican el comportamiento productivo, pero no generan movimientos reales de dinero ni operaciones en la red.
Resolución exitosa de llave
Usa estos valores para obtener un token con keyResolution resuelto. Todos retornan una transacción aprobada.
accountType | accountNumber de prueba | keyResolution.ownerName simulado |
|---|---|---|
KP | 3001234567 | JUAN PEREZ |
KE | USUARIO@CORREO.COM | MARIA LOPEZ |
KA | @COLOMBIA | ANA MARTINEZ |
KM | 0012345678 | COMERCIO PRINCIPAL SAS |
KI | CC12345678 | LUIS GOMEZ |
Errores en tokenización (PT060)
Usa estos valores para simular una llave inválida o suspendida durante el paso de tokenización. Retornan PT060 antes de que se inicie la transacción.
accountType | accountNumber de prueba | Escenario simulado |
|---|---|---|
KE | BLOCKED@TEST.COM | Llave suspendida |
KM | 0011111111 | Llave suspendida por el participante |
KP | 3000005001 | Error en la resolución de la llave |
KI | ERRDICE9994 | Error inesperado durante la resolución |
Simulación de escenarios de pago por monto
Para simular respuestas de error en el procesamiento de pago, envía el valor exacto indicado en el campo totalAmount del request de tokenización. Si el monto no coincide con ningún valor de la tabla, la transacción resultará aprobada.
Errores síncronos — llegan directamente en la respuesta del endpoint /init, sin necesidad de esperar el webhook:
totalAmount | responseCode Kushki | Descripción |
|---|---|---|
4001 | 002 | Ha ocurrido un error inesperado |
4002 | 068 | Monto Inválido |
5001 | 073 | Transacción no permitida |
5003 | 074 | Banco o cuenta no inscrita |
Errores asíncronos — llegan a través del webhook o al consultar Get Status, después de que el /init retorna INITIALIZED:
totalAmount | responseCode Kushki | Descripción |
|---|---|---|
6001 | 076 | Error al efectuar el pago |
4016 | 045 | Fondos insuficientes |
4017 | 077 | Pendiente respuesta de otros bancos |
4019 | 077 | Pendiente respuesta de otros bancos |
4020 | 041 | Ocurrió un error en el sistema. Por favor, vuelve a intentarlo |
9999 | 002 | Ha ocurrido un error inesperado |
4006 | 080 | Cuenta destino inválida |
4007 | 052 | Número de cuenta inválido |
4010 | 088 | Cuenta no existe |
4011 | 091 | Cuenta con bloqueo transaccional |
4012 | 071 | Valor de traslado inválido |
4013 | 071 | Valor de traslado inválido |
6. Prepara tu certificación
Toma en consideración las siguientes pautas para aprobar la certificación técnica (requerida para obtener credenciales productivas):
- Los cálculos de los montos son correctos (
subtotalIva,subtotalIva0,iva). - Mostrar mensajes en pantalla de acuerdo con las respuestas de Kushki.
- Guardar y registrar todas las respuestas de Kushki (requeridas en caso de necesitar soporte).
- Mostrar el objeto
keyResolutional operador o usuario y requerir confirmación explícita antes de inicializar la transacción. - El procesador configurado en la Consola corresponde a Bre-B.
- Si no se requiere enviar comprobante al correo del cliente, no se debe especificar el email en la solicitud del token.
- Si se reciben notificaciones por webhook correctamente, responder a la solicitud con un status 200.
- El botón de dispersión se deshabilita después del primer clic para evitar doble envío.
- El logo de Kushki debe ser visible para el cliente. Puedes encontrar nuestro logo en varios formatos aquí.
- Asegurarse de que en el cuerpo de la petición se envíen todos los campos requeridos en la referencia API.
Acepta webhooks
Maneja eventos post-dispersión de la manera correcta.
Códigos de error
Consulta los códigos de error para dispersiones con Bre-B.
Chile
Ecuador
Mexico
Peru