Transfer In collects payments directly from a customer's bank account, with no card. In Colombia it runs on processors, PSE (bank redirect) and Bre-B (real-time QR), through the same endpoints under /transfer/v1. Every integration starts by asking which processors the merchant has.The available processors and the integration type depend on the merchant's affiliation and risk policies.
Endpoints#
| Endpoint | Method and path | Credential | Purpose | Used by |
|---|
| Get Transfer In configuration | GET /transfer/v1/config | Public | Start here. Lists the processors enabled for the merchant and, when applicable, the supportedFlows of each one | All |
| Get Bank List | GET /transfer/v1/bankList | Public | Supported banks (code, name) | PSE |
| Request a Transfer In Token | POST /transfer/v1/tokens | Public | Creates a single-use token | All |
| Init Transaction | POST /transfer/v1/init | Private | Starts the transaction with the token | All |
| Get Status | GET /transfer/v1/status/{token} | Private | Final status of the transaction | All |
| Cancel Transaction | PATCH /transfer/v1/cancel/{token} | Private | Cancels a transaction while it has no final status | Bre-B |
Integration flow#
1
Get the processors
Call Get Transfer In configuration with the Public-Merchant-Id credential. processors[] lists the processors enabled for the merchant. This is the starting point of every direct API integration.
2
Choose the processor
An entry without supportedFlows is PSE. An entry with supportedFlows is a processor with payment flows (Bre-B). If the merchant has several, use the supportedFlows of each entry to decide how to build each token.
3
Request the token
The body depends on the processor; see Processors at a glance below. Tokens are single-use.
4
Init the transaction
Send the token and repeat the same amount. The response depends on the processor: redirectUrl (PSE) or qr (Bre-B).
5
Confirm the final status
Through the webhook or with Get Status.
These tools do not support the processor object: with them there is no processor query and tokenization follows the PSE process. Bre-B requires a direct API integration, where the token is requested from your backend.
Processors at a glance#
Processors with payment flows, like Bre-B, are also referred to as APM (alternative payment methods). | PSE | Bre-B |
|---|
| Identified by | config entry without supportedFlows | config entry with supportedFlows |
| Token request | bankId, callbackUrl, userType, documentType, documentNumber, email, plus amount and currency. No processor object. | amount, currency and processor: { name, flowType }, copied verbatim from config. The rest are optional; bankId does not apply. |
| Bank list | Required | Not used |
init response | redirectUrl | qr |
| Customer experience | Redirected to PSE and then to their bank | Scans a QR in their banking app |
| Validity | Token: 30 minutes, single-use | QR: 10 minutes |
| Cancellation | Not available | Available while there is no final status |
| Integration types | Direct API, Kajita, Kushki.js | Direct API only |
| Availability | General | Beta, on merchants with the processor enabled |
The token is bound to the processor it was generated with, and Init Transaction validates it:| Generated token | Merchant's processor | Result |
|---|
Without processor | PSE | Continues; the response includes redirectUrl. |
With Bre-B processor | Bre-B | Continues; the response includes qr. |
With processor | Another processor | 422 E046 |
Without processor | Bre-B | 422 E046 |
With Bre-B processor | Bre-B without keys configured | 404 E049 |
Processor details#
Token request fields| Field | Required | Description |
|---|
bankId | Yes | Bank code selected from the Bank List. |
amount | Yes | Object with subtotalIva, subtotalIva0 and iva. See Amount object below. |
currency | Yes | Always COP. |
callbackUrl | Yes | URL where the customer lands after paying at the bank. |
userType | Yes | 0 = natural person · 1 = company. |
documentType | Yes | CC, NIT, CE, TI or PP. |
documentNumber | Yes | Customer's document number. |
email | Yes | Customer's email. |
Tokens expire in 30 minutes and are single-use. If the transaction fails or the token expires, request a new one.documentType | Document |
|---|
CC | Cédula de Ciudadanía |
NIT | Número de Identificación Tributaria |
CE | Cédula de Extranjería |
TI | Tarjeta de Identidad |
PP | Passport |
The redirectUrl is single-use: redirect the customer right after receiving it.| Field | Description |
|---|
redirectUrl | Single-use URL to redirect the customer to PSE. |
trazabilityCode | Also called CUS: unique PSE payment reference code. |
bankId | Code of the bank selected for the transaction. |
bankName | Name of the bank selected for the transaction. |
transactionReference | Unique reference of the transaction. |
The status response also includes the trazabilityCode (CUS), which you can use to reconcile the transaction with PSE records. Statuses#
Confirm the final result with Get Status, using the original token as a path parameter. The webhook and the statuses are the same for every processor.| Status | Meaning |
|---|
initializedTransaction | The transaction was created but not completed. |
approvedTransaction | The transfer was authorized. |
declinedTransaction | The transfer was rejected. |
Amount Object#
The amount object is required in the Token request. Use the following structure depending on whether the transaction has taxes:{
"amount": {
"subtotalIva": 100000,
"subtotalIva0": 0,
"iva": 10000
}
}
Set subtotalIva to the taxable base amount and iva to the tax value. Set subtotalIva0 to 0. All amounts in COP.Webhook Notifications#
You can receive real-time transaction notifications by including the webhooks object in your Init Transaction request. This is independent of any webhooks configured in the Kushki Console — both channels will fire simultaneously.{
"webhooks": [
{
"events": ["approvedTransaction", "declinedTransaction"],
"headers": [
{ "label": "Authorization", "value": "Bearer your-token" }
],
"urls": [
"https://merchant.example.com/webhooks/transfer-in"
]
}
]
}
Errors#
| Processor | Endpoint | HTTP | Code | When it happens | What to do |
|---|
| All | GET /transfer/v1/config | 500 | E002 | Error querying the merchant configuration («Ha ocurrido un error inesperado.»). | Retry; contact support if it persists. |
| Bre-B | POST /transfer/v1/tokens | 400 | — | The body does not meet the contract: missing required field, value outside the enum (processor.name, processor.flowType), or extra property inside processor. | Fix the body according to config. |
| All | POST /transfer/v1/init | 422 | E046 | The token is not compatible with the resolved processor. | Regenerate the token for the right processor. |
| Bre-B | POST /transfer/v1/init | 404 | E049 | The merchant has no Bre-B processor configured (missing keys). | Verify the processor configuration with Kushki. |
| Bre-B | PATCH /transfer/v1/cancel/{token} | 400 | T023 | The transaction already reached a final status. | No action: it cannot be cancelled. |
| All | Any | 401 | — | Missing or invalid credential. | Check Public-Merchant-Id or Private-Merchant-Id, depending on the endpoint. |
Authentication and environments#
Credentials are sent in a header; each endpoint uses one of them (see the Credential column above):| Header | Credential | Use |
|---|
Public-Merchant-Id | Public | Configuration, bank list and tokenization. Safe for backends and, in the traditional flow, for client tools. |
Private-Merchant-Id | Private | Init, status and cancellation. Never expose it in frontend code. |
https://api.kushkipagos.com/