Dispersa con Bre-B
Disbursing payments with Bre-B means delivering funds in real time to your users using only the recipient’s payment key — without needing to know their bank account number. The key can be their national ID, phone number, email address, alphanumeric alias, or merchant code.
Ideal for:
- Supplier or vendor payments
- Marketplaces
- Delivery applications
- Gig economy platforms
- Refunds and compensations
Operation details
The Bre-B disbursement process in Colombia follows this flow: Merchant → Kushki → Banco de la República (SPBVI) → Receiving Bank → Beneficiary.
| Parameter | Detail |
|---|---|
| Minimum amount per transaction | 1 COP |
| Maximum amount per transaction | Equivalent to 1,000 UVT (Tax Value Units, updated annually by the DIAN). Each financial institution or user may set lower daily or per-transaction limits. |
| Currency | COP |
| Available banks | All Colombian banks (Banco de la República regulation) |
| API processing hours | 24/7 |
| Settlement time | Real-time (maximum 30 seconds from initiation) |
| Response type | Asynchronous — the final result is delivered via webhook or by querying the Get Status endpoint |
Important note: The Kushki API accepts and processes requests 24/7. Unlike ACH, Bre-B does not use banking cycles — processing is real-time through the SPBVI of the Banco de la República. You do not need to query the bank list before tokenizing.
Flow
The flow you will integrate is the following:
Here you will learn how to integrate Bre-B money disbursements.
1. Tokenize the information
The first step is to obtain a token by sending the recipient’s key to Kushki. Unlike ACH, you do not need to query the bank list before this step — all Colombian banks support key-based transfers by Banco de la República regulation.
You must make the token request using our tokenization endpoint.
Required fields to obtain the token
Take into account the required fields in the token request body for Bre-B:
Disbursement with Bre-B key (accountType = KI, KP, KE, KA, KM) |
|---|
- accountType - accountNumber - totalAmount - currency |
The fields documentType, documentNumber, bankId, and name are optional for Bre-B in Colombia.
Key types (accountType)
accountType | Key type |
|---|---|
KI | National identification number |
KP | Mobile phone number |
KE | Email address |
KA | Alphanumeric alias |
KM | Merchant code |
Valid formats for accountNumber
The accountNumber format is validated before sending any request to the payment network (fail-fast). An invalid format returns HTTP 400 immediately, without reaching the network.
accountType | Required format for accountNumber |
|---|---|
KI | Uppercase alphanumeric characters. Minimum 1 character. No spaces or special characters. |
KP | Exactly 10 digits. Must start with 3, followed by 9 digits. |
KE | Valid email address. Maximum 30 characters before @ and 61 after. Must include a valid domain. |
KA | Must start with @. Uppercase alphanumeric characters only. No spaces or special characters. |
KM | Exactly 10 digits. Must start with 00, followed by 8 digits. |
- Javascript
- Python
- PHP
var request = require('request');// Example with mobile phone key (KP)var options = {'method': 'POST','url': 'https://api-uat.kushkipagos.com/payouts/transfer/v1/tokens', // Test environment'headers': {'Public-Merchant-Id': '', // Replace with your 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);// Show jsonData.keyResolution to the user to confirm the recipientconsole.log('Recipient:', jsonData.keyResolution.ownerName);});
import requestsimport json# Example with mobile phone key (KP)url = "https://api-uat.kushkipagos.com/payouts/transfer/v1/tokens" # Test environmentpayload = json.dumps({"accountType": "KP","accountNumber": "3001234567","totalAmount": 1000,"currency": "COP"})headers = {'Public-Merchant-Id': '', # Replace with your Public Key'Content-Type': 'application/json'}response = requests.request("POST", url, headers=headers, data=payload)data = response.json()print('Token:', data['token'])# Show data['keyResolution'] to the user to confirm the recipientprint('Recipient:', data['keyResolution']['ownerName'])
$client = new http\Client;$request = new http\Client\Request;// Example with mobile phone key (KP)$request->setRequestUrl('https://api-uat.kushkipagos.com/payouts/transfer/v1/tokens'); // Test environment$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' => '', // Replace with your Public Key'Content-Type' => 'application/json'));$client->enqueue($request)->send();$data = json_decode($client->getResponse()->getBody(), true);echo 'Token: ' . $data['token'];// Show $data['keyResolution'] to the user to confirm the recipientecho 'Recipient: ' . $data['keyResolution']['ownerName'];
The response includes the token and the keyResolution object with the recipient’s data resolved by the payment network:
{"token": "53de1cb6bbb54011a0a98053d48677e0","keyResolution": {"keyValue": "3001234567","ownerName": "M**** G**** L****"}}
| Field | Description |
|---|---|
token | Transaction token. Expires in 30 minutes. Single-use, regardless of the transaction result. |
keyResolution.keyValue | Exact value of the key, without any transformations. |
keyResolution.ownerName | Account holder name, returned masked by the payment network (e.g. M**** G**** L****). |
2. Confirm the recipient
Once you have obtained the token and the keyResolution object, you must show the operator or end user the recipient’s information to confirm it is correct before initializing the transaction. This step is required by the Banco de la República.
Show the operator or user:
- The key value:
keyResolution.keyValue - The account holder name:
keyResolution.ownerName(masked, e.g.M**** G**** L****)
3. Initialize the transaction
Once the recipient’s data has been confirmed, you must send the obtained token to start the disbursement process with Kushki. You must make a call to our initialization endpoint to start the payment. This step deducts the balance immediately from your disbursement account.
- Javascript
- Python
- PHP
var request = require('request');var options = {'method': 'POST','url': 'https://api-uat.kushkipagos.com/payouts/transfer/v1/init', // Test environment'headers': {'Private-Merchant-Id': '', // Replace with your Private Key'Content-Type': 'application/json'},body: JSON.stringify({"token": "53de1cb6bbb54011a0a98053d48677e0", // Replace with the token you received"amount": {"subtotalIva": 0,"subtotalIva0": 1000,"iva": 0},"webhooks": [{"events": ["approvedTransaction", "declinedTransaction"],"urls": ["https://your-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);// Save the ticketNumber to query the status later});
import requestsimport jsonurl = "https://api-uat.kushkipagos.com/payouts/transfer/v1/init" # Test environmentpayload = json.dumps({"token": "53de1cb6bbb54011a0a98053d48677e0", # Replace with the token you received"amount": {"subtotalIva": 0,"subtotalIva0": 1000,"iva": 0},"webhooks": [{"events": ["approvedTransaction", "declinedTransaction"],"urls": ["https://your-endpoint.com/webhook"]}]})headers = {'Private-Merchant-Id': '', # Replace with your 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'])# Save the ticketNumber to query the status later
$client = new http\Client;$request = new http\Client\Request;$request->setRequestUrl('https://api-uat.kushkipagos.com/payouts/transfer/v1/init'); // Test environment$request->setRequestMethod('POST');$body = new http\Message\Body;$body->append(json_encode(["token" => "53de1cb6bbb54011a0a98053d48677e0", // Replace with the token you received"amount" => ["subtotalIva" => 0,"subtotalIva0" => 1000,"iva" => 0],"webhooks" => [["events" => ["approvedTransaction", "declinedTransaction"],"urls" => ["https://your-endpoint.com/webhook"]]]]));$request->setBody($body);$request->setOptions(array());$request->setHeaders(array('Private-Merchant-Id' => '', // Replace with your 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'];// Save the ticketNumber to query the status later
The response delivers a ticket number and the transaction status:
{"status": "INITIALIZED","ticketNumber": "1234567890","transactionReference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}
4. Query the transaction status
Now that the disbursement is in process, you can check the transaction status using webhooks or by querying manually using our API.
Webhook
The transaction status is automatically notified at the moment the transfer is approved or declined. The payload includes the keyResolution object with keyValue and ownerName.
API
You can use our Get Status endpoint to manually query the status of a specific transaction.
- Javascript
- Python
- PHP
var request = require('request');var options = {'method': 'GET','url': 'https://api-uat.kushkipagos.com/payouts/transfer/v1/transaction/{{ticketNumber}}', // Replace {{ticketNumber}}'headers': {'Private-Merchant-Id': '' // Replace with your Private Key}};request(options, function (error, response) {if (error) throw new Error(error);console.log(response.body);});
import requeststicket_number = "1234567890" # Replace with the ticketNumber you receivedurl = f"https://api-uat.kushkipagos.com/payouts/transfer/v1/transaction/{ticket_number}"headers = {'Private-Merchant-Id': '' # Replace with your 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"; // Replace with the ticketNumber you received$request->setRequestUrl("https://api-uat.kushkipagos.com/payouts/transfer/v1/transaction/{$ticketNumber}");$request->setRequestMethod('GET');$request->setOptions(array());$request->setHeaders(array('Private-Merchant-Id' => '' // Replace with your Private Key));$client->enqueue($request)->send();$response = $client->getResponse();echo $response->getBody();
5. Test your integration
The Bre-B UAT environment runs on a payment network sandbox. Responses are simulated and replicate production behavior, but do not generate real money movements or network operations.
Successful key resolution
Use these values to obtain a token with a resolved keyResolution. All of them return an approved transaction.
accountType | Test accountNumber | Simulated keyResolution.ownerName |
|---|---|---|
KP | 3001234567 | JUAN PEREZ |
KE | USUARIO@CORREO.COM | MARIA LOPEZ |
KA | @COLOMBIA | ANA MARTINEZ |
KM | 0012345678 | COMERCIO PRINCIPAL SAS |
KI | CC12345678 | LUIS GOMEZ |
Tokenization errors (PT060)
Use these values to simulate an invalid or suspended key during the tokenization step. They return PT060 before the transaction is initiated.
accountType | Test accountNumber | Simulated scenario |
|---|---|---|
KE | BLOCKED@TEST.COM | Suspended key |
KM | 0011111111 | Key suspended by the participant |
KP | 3000005001 | Error during key resolution |
KI | ERRDICE9994 | Unexpected error during resolution |
Payment scenario simulation by amount
To simulate error responses in payment processing, send the exact value indicated in the totalAmount field of the tokenization request. If the amount does not match any value in the table, the transaction will result in approved.
Synchronous errors — returned directly in the /init endpoint response, without waiting for the webhook:
totalAmount | Kushki responseCode | Description |
|---|---|---|
4001 | 002 | An unexpected error occurred |
4002 | 068 | Invalid amount |
5001 | 073 | Transaction not permitted |
5003 | 074 | Bank or account not registered |
Asynchronous errors — delivered via webhook or when querying Get Status, after /init returns INITIALIZED:
totalAmount | Kushki responseCode | Description |
|---|---|---|
6001 | 076 | Error processing the payment |
4016 | 045 | Insufficient funds |
4017 | 077 | Pending response from other banks |
4019 | 077 | Pending response from other banks |
4020 | 041 | A system error occurred. Please try again |
9999 | 002 | An unexpected error occurred |
4006 | 080 | Invalid destination account |
4007 | 052 | Invalid account number |
4010 | 088 | Account does not exist |
4011 | 091 | Account with transaction block |
4012 | 071 | Invalid transfer amount |
4013 | 071 | Invalid transfer amount |
6. Prepare your certification
Take the following guidelines into account to pass the technical certification (required to obtain production credentials):
- Amount calculations are correct (
subtotalIva,subtotalIva0,iva). - On-screen messages are shown in line with Kushki responses.
- All Kushki responses are saved and logged (required in case support is needed).
- The
keyResolutionobject is shown to the operator or user and explicit confirmation is required before initializing the transaction. - The processor configured in the Console corresponds to Bre-B.
- If a receipt does not need to be sent to the client’s email, the email should not be included in the token request.
- If webhook notifications are received correctly, respond to the request with status 200.
- The disbursement button is disabled after the first click to prevent double submission.
- The Kushki logo must be visible to the client. You can find our logo in various formats here.
- Ensure that the request body includes all required fields as specified in the API reference.
Accept webhooks
Handle post-disbursement events the right way.
Error codes
Check the error codes for Bre-B disbursements.
Chile
Ecuador
Mexico
Peru