Accept Bre-B payments

Bre-B is one of the APM (alternative payment methods) processors in Colombia: instead of asking for the payer’s bank details and redirecting them to their bank, Kushki generates a QR code that the user scans from their banking app to authorize the payment in real time.

Which processors your merchant has is answered by the configuration endpoint (GET /transfer/v1/config) — the full model is in How do APM payments work?. Existing ACH integrations do not change: they keep following their bank transfer guide.

What your customer’s payment experience looks like

Your store shows the QR code at checkout, the customer scans it from their bank’s app, reviews the amount and confirms, and the payment is approved in real time.

breb EN

Operation details

ParameterDetail
CurrencyCOP
Integration type100% API — the token is requested from your backend. Kajita and Kushki.js do not support this flow yet.
Additional required fieldThe processor object (name + flowType) in the token body
Bank list queryNot required for this flow
Init resultQR code (base64 PNG) for payment from banking app
QR validity10 minutes. After this time the QR becomes invalid and a new token and init must be generated.
Processing timeReal time
CancellationPATCH /transfer/v1/cancel/{token} — available while the transaction does not have a final status. Returns HTTP 204 No Content.
WebhookNo changes compared to the ACH flow
Error codesSee section 7. API errors of this guide

1. Check your processors

This step is optional if Bre-B is your only processor, but always recommended: it will be the rule as more processors and flows are enabled. Before tokenizing, call Get Transfer In configuration (GET /transfer/v1/config) with your public credential. The Bre-B entry comes with supportedFlows: copy its name and the flow type into the token’s processor object.

{
"processors": [
{ "name": "Pse Processor", "currency": "COP" },
{
"name": "Bre-B Credibanco Processor",
"currency": "COP",
"supportedFlows": [
{ "type": "QR", "name": "QR Code", "description": "QR code payment" }
]
}
]
}

2. Create the token

Make the token request using the same endpoint as the ACH flow. To activate the Bre-B flow, include the processor object with the name and flowType properties, copied exactly from the processor query response. You do not need to query the bank list before this step.

Required fields

FieldTypeDescription
amount.subtotalIva0numberTransaction amount (without VAT)
amount.subtotalIvanumberTransaction amount (with VAT). Equal to subtotalIva0 if iva = 0
amount.ivanumberVAT value (0 if not applicable)
currencystringCurrency. Must be “COP”
processor.namestringNEW required field. Must be "Bre-B Credibanco Processor", exactly as returned by the processor query — no short aliases
processor.flowTypestringNEW required field. Must be "QR". It has no default value

The processor object does not allow additional properties: any other property returns 400.

Optional fields

callbackUrl · userType · documentType · documentNumber · paymentDescription · email

The bankId field does not apply to this flow.

If you send userType, documentType or documentNumber, the conditional rules for COP apply — see How do APM payments work?.

  • 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",
"processor":{
"name":"Bre-B Credibanco Processor",
"flowType":"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",
"processor":{
"name":"Bre-B Credibanco Processor",
"flowType":"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",
"processor" => [
"name" => "Bre-B Credibanco Processor",
"flowType" => "QR"
]
]));
// POST to /transfer/v1/tokens with Public-Merchant-Id
echo json_decode($client->getResponse()->getBody(), true)['token'];

3. 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.

4. 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 6) or query Get Status manually. While the payment is pending, you can cancel the transaction (see step 5).

5. 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 2.

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."
}

6. 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 2
'headers': { 'Private-Merchant-Id': '' }
};
request(options, function(error, response) {
console.log(response.body);
});
token = '{{token}}' # token obtained in step 2
url = 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 2
$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();

7. API errors

When operating with the multiprocessor flow you may receive API errors when querying processors, tokenizing, or initializing the transaction. The error response fields are code and message.

EndpointHTTPCodeWhen does it happen?What should the merchant do?
GET /transfer/v1/config500E002Error querying the merchant configuration. Message: «Ha ocurrido un error inesperado.»Retry; if it persists, contact support.
POST /transfer/v1/tokens400—The body does not meet the contract: missing required field, value outside the enumeration (processor.name, processor.flowType) or a property not allowed inside processor.Fix the body according to the processor query and the contract of the chosen flow.
POST /transfer/v1/init422E046The token is not compatible with the resolved processor.Check the processor query and regenerate the token with the correct processor.
POST /transfer/v1/init404E049The merchant has no Bre-B processor configured (no keys).Verify the processor configuration with Kushki.
All401—Invalid or missing public credential.Check the Public-Merchant-Id.

ACH bank transfer errors are in Error codes for transfers.

8. 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 10000, send subtotalIva0: 5000, subtotalIva: 5000, iva: 0. If the sum does not match any value in the table, the response is generically successful without a webhook.

transaction_amountHTTP statusStatusWebhookNote
10000201SUCCESSTriggers → PAIDHappy path with webhook
9999201SUCCESSDoes not triggerThe transaction remains initialized
11000500ERRORDoes not triggerQR-CODE-0001
12000201SUCCESSTriggers → rejectedDeclined transaction
13000—TIMEOUTDoes not triggerThe transaction is left initialized. Reuses the existing DELAY_MS.
99999999400ERRORDoes not triggerQR-CODE-0059 — out of range amount
Any other201SUCCESSDoes not triggerGeneric successful response

9. Prepare your certification

Consider the following guidelines to pass the technical certification:

  • Amount calculations are correct (subtotalIva, subtotalIva0, iva).
  • The processor object is sent with name: "Bre-B Credibanco Processor" and flowType: "QR" in the token request.
  • The QR code is correctly shown to the user from the qr field 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.