Accepts Bre-B payments
Bre-B offers an alternative flow to accept bank transfer payments in Colombia. Instead of requiring the payer’s account details, Kushki generates a QR code that the user scans from their banking app to authorize the payment in real time.
This flow coexists with the existing ACH process — no changes are required in current integrations.
Operation details
| Parameter | Detail |
|---|---|
| Currency | COP |
| Additional required field | flowType = "BRE_B" in the token body |
| Bank list query | Not required for this flow |
| Init result | QR code (base64 PNG) for payment from banking app |
| QR validity | 10 minutes. After this time the QR becomes invalid and a new token and init must be generated. |
| Processing time | Real time |
| Cancellation | PATCH /transfer/v1/cancel/{token} — available while the transaction does not have a final status. Returns HTTP 204 No Content. |
| Webhook | No changes compared to the ACH flow |
| Error codes | No changes compared to the ACH flow |
1. Create the token
Make the token request using the same endpoint as the ACH flow. To activate the Bre-B flow, include the flow field. It is not necessary to query the bank list before this step.
Required fields
| Field | Type | Description |
|---|---|---|
amount.subtotalIva0 | number | Transaction amount (without VAT) |
amount.subtotalIva | number | Transaction amount (with VAT). Equal to subtotalIva0 if iva = 0 |
amount.iva | number | VAT amount (0 if it does not apply) |
currency | string | Currency. Must be “COP” |
flow.processorName | string | NEW required field. Must be “BRE-B” to activate this flow |
flow.type | string | NEW required field. Must be “QR” to activate this flow |
Optional fields
callbackUrl · userType · documentType · documentNumber · paymentDescription · email · bankId
- Javascript
- Python
- PHP
var options = {'method': 'POST','url': 'https://api-uat.kushkipagos.com/transfer/v1/tokens','headers': { 'Public-Merchant-Id': '', 'Content-Type': 'application/json' },body: JSON.stringify({"amount": { "subtotalIva0": 1000, "subtotalIva": 1000, "iva": 0 },"currency": "COP","flow":{"processorName":"BRE-B","type":"QR"}})};request(options, function(error, response) {var data = JSON.parse(response.body);console.log('token:', data.token);});
payload = json.dumps({"amount": { "subtotalIva0": 1000, "subtotalIva": 1000, "iva": 0 },"currency": "COP","flow":{"processorName":"BRE-B","type":"QR"}})headers = {'Public-Merchant-Id': '', 'Content-Type': 'application/json'}response = requests.post('https://api-uat.kushkipagos.com/transfer/v1/tokens',headers=headers, data=payload)print('token:', response.json()['token'])
$body->append(json_encode(["amount" => ["subtotalIva0" => 1000, "subtotalIva" => 1000, "iva" => 0],"currency" => "COP","flow" => ["processorName" => "BRE-B","type" => "QR"]]));// POST to /transfer/v1/tokens with Public-Merchant-Idecho json_decode($client->getResponse()->getBody(), true)['token'];
2. Generate the QR code
With the obtained token, initialize the transaction. Kushki returns a QR code in base64 format that you must show to the user so they can scan it from their banking app.
- Javascript
- Python
- PHP
var options = {'method': 'POST','url': 'https://api-uat.kushkipagos.com/transfer/v1/init','headers': { 'Private-Merchant-Id': '', 'Content-Type': 'application/json' },body: JSON.stringify({"token": "{{token}}","amount": { "subtotalIva": 0, "subtotalIva0": 1000, "iva": 0 },// "fullResponse": "v2" // optional — includes the details object in the response})};request(options, function(error, response) {var data = JSON.parse(response.body);console.log('qr:', data.qr);console.log('ref:', data.transactionReference);});
payload = json.dumps({"token": "{{token}}","amount": { "subtotalIva": 0, "subtotalIva0": 1000, "iva": 0 },# "fullResponse": "v2" # optional — includes the details object in the response})headers = {'Private-Merchant-Id': '', 'Content-Type': 'application/json'}data = requests.post('https://api-uat.kushkipagos.com/transfer/v1/init',headers=headers, data=payload).json()print('qr:', data['qr'])
$body->append(json_encode(["token" => "{{token}}","amount" => ["subtotalIva" => 0, "subtotalIva0" => 1000, "iva" => 0],// "fullResponse" => "v2" // optional]));// POST to /transfer/v1/init with Private-Merchant-Id$data = json_decode($client->getResponse()->getBody(), true);echo $data['qr'];
Response example — without fullResponse
{"qr": "data:image/png;base64,iVBORw0KGgoAAAANS...","transactionReference": "f2110170-8eec-4214-b2d0-38970d44f8e1"}
Response example — with fullResponse: “v2”
{"qr": "data:image/png;base64,iVBORw0KGgoAAAANS...","transactionReference": "f2110170-8eec-4214-b2d0-38970d44f8e1","details": {"status": "initializedTransaction","amount": { "currency": "COP", "iva": 0, "subtotalIva": 1000, "subtotalIva0": 1000 },"created": 1784125900901,"merchantId": "20000000106921087000","merchantName": "My Merchant Colombia"}}
How to render the qr field
The qr field contains a complete Data URI string (data:image/png;base64,...). To show it on the web:
<img src="{qr}" alt="Scan to pay" width="250" />
In native apps, decode the base64 and render the bitmap with your platform’s image component.
3. Show the QR to the user and wait for payment
The user scans the QR from their banking app and authorizes the payment. Kushki notifies the result asynchronously. The QR expires in 10 minutes. If the user does not scan within that time, you must generate a new token and init. To monitor the result: configure a webhook (see step 5) or query Get Status manually. While the payment is pending, you can cancel the transaction (see step 4).
4. Cancel the transaction (optional)
If the user cannot complete the payment or you need to invalidate the active QR, cancel the transaction before it reaches a final status.
When to use cancellation Use this endpoint when the user enters an incorrect amount, decides not to complete the payment, or you need to issue a new QR before the original QR expires (10 minutes validity). This is only possible if the transaction does not yet have a final status.
Endpoint
PATCH https://{api-url}/transfer/v1/cancel/{token}
Where {token} is the token obtained in step 1.
Successful response (HTTP 204 No Content) A successful cancellation returns HTTP 204 with no body in the response.
Error — transaction with final status (HTTP 400)
{"code": "T023","message": "Transaction has a final status."}
5. Check the transaction status
The final payment status arrives asynchronously. You can receive it in two ways:
- Webhook: Kushki automatically notifies when the payment is approved or declined. No changes compared to the ACH flow.
- Get Status: Manually query the status using the token in the path.
- Javascript
- Python
- PHP
var options = {'method': 'GET','url': 'https://api-uat.kushkipagos.com/transfer/v1/status/{{token}}', // token from step 1'headers': { 'Private-Merchant-Id': '' }};request(options, function(error, response) {console.log(response.body);});
token = '{{token}}' # token obtained in step 1url = f'https://api-uat.kushkipagos.com/transfer/v1/status/{token}'headers = {'Private-Merchant-Id': ''}response = requests.get(url, headers=headers)print(response.text)
$token = '{{token}}'; // token from step 1$request->setRequestUrl("https://api-uat.kushkipagos.com/transfer/v1/status/{$token}");$request->setRequestMethod('GET');$request->setHeaders(['Private-Merchant-Id' => '']);$client->enqueue($request)->send();echo $client->getResponse()->getBody();
6. Test your integration
The UAT environment simulates scenarios using the transaction_amount value, which corresponds to the sum of all fields in the amount object in the request (subtotalIva0 + subtotalIva + iva). For example, to activate scenario 1000, send subtotalIva0: 500, subtotalIva: 500, iva: 0. If the sum does not match any value in the table, the response is generically successful without a webhook.
| transaction_amount | HTTP status | Status | Webhook | Note |
|---|---|---|---|---|
| 10000 | 201 | SUCCESS | Triggers → PAID | Happy path with webhook |
| 9999 | 201 | SUCCESS | Does not trigger | The transaction remains initialized |
| 10000 | 201 | SUCCESS | Triggers → PAID | Happy path with webhook |
| 11000 | 500 | ERROR | Does not trigger | QR-CODE-0001 |
| 12000 | 201 | SUCCESS | Triggers → rejected | Declined transaction |
| 13000 | — | TIMEOUT | Does not trigger | The transaction is left initialized. Reuses the existing DELAY_MS. |
| 99999999 | 400 | ERROR | Does not trigger | QR-CODE-0059 — out of range amount |
| Any other | 201 | SUCCESS | Does not trigger | Generic successful response |
7. Prepare your certification
Consider the following guidelines to pass the technical certification:
- Amount calculations are correct (
subtotalIva,subtotalIva0,iva). - The
flowTypefield is sent as"BRE_B"in the token request. - The QR code is correctly shown to the user from the
qrfield in the init response. - The cancellation endpoint is implemented for flows where the user does not complete the payment.
- On-screen messages are displayed according to Kushki’s responses.
- If webhook notifications are received, respond with HTTP 200.
- The payment button is disabled after the first click to prevent double submission.
- All Kushki responses are saved and logged (required for support).
- The Kushki logo is visible. Download it at s3.amazonaws.com/kushki-cdn-production/docs/Logo+Kushki.zip
- All required fields are sent according to the API reference.
Related articles
Accept transfer payments (ACH)
Receive Wire Transfers
Configure webhooks
Receive notifications about your payment status.
Cancellation — Technical reference
Cancellation
Chile
Ecuador
Mexico
Peru