Channel: 17
Provider: Cobre
Payment Methods: Bank Transfer
Available Currencies
| Name | Code | Country |
|---|---|---|
| Colombian Pesos | COP | Colombia |
Available Payment Methods
| APM | filter_by | Payer experience |
|---|---|---|
| PSE | pse | Redirected straight to the selected bank's online banking |
| Nequi | nequi | Push notification sent to the payer's Nequi app |
| Bancolombia | bancolombia | Redirected to Bancolombia's payment page |
| Bre-B QR | breb_qr | QR code displayed on our checkout, scanned from any bank or wallet app |
| Bre-B Key | breb_key | Bre-B key (llave) displayed on our checkout, entered in the banking app |
If filter_by is not sent, the payer is taken to Cobre's checkout, where all available methods (PSE, Nequi, Bancolombia and Bre-B) are offered.
Request example
curl --location 'https://uat-payments.alps.cl/justpay/check-out/SecurePayment.php' \
--form 'public_key="{YOUR_PUBLIC_KEY}"' \
--form 'time="2026-08-04 16:33:11"' \
--form 'amount="50000"' \
--form 'currency="COP"' \
--form 'trans_id="1"' \
--form 'time_expired="120"' \
--form 'url_ok="https://bit.ly/3S5aOwc"' \
--form 'url_error="https://bit.ly/3S5aOwc"' \
--form 'channel="17"' \
--form 'signature="{YOUR_SIGNATURE}"' \
--form 'shopper_information="{
\"Phone\": \"3123456789\",
\"email\": \"[email protected]\",
\"name_shopper\": \"Fulano\",
\"Num_doc_identi\": \"112345678\",
\"type_doc_identi\": \"ce\",
\"last_name_Shopper\": \"Da Silva\",
\"country\":\"COL\",
\"country_code\":\"+57\"}"'<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://uat-payments.alps.cl/justpay/check-out/SecurePayment.php',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array('public_key' => "{YOUR_PUBLIC_KEY}",'time' => '2026-08-04 16:33:11','amount' => '50000','currency' => 'COP','trans_id' => '1','time_expired' => '120','url_ok' => 'https://bit.ly/3S5aOwc','url_error' => 'https://bit.ly/3S5aOwc','channel' => '17','signature' => "{YOUR_SIGNATURE}",'shopper_information' => '{
"Phone": "3123456789",
"email": "[email protected]",
"name_shopper": "Fulano",
"Num_doc_identi": "112345678",
"type_doc_identi": "ce",
"last_name_Shopper": "Da Silva",
"country":"COL",
"country_code":"+57"}'),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import requests
url = "https://uat-payments.alps.cl/justpay/check-out/SecurePayment.php"
payload = {'public_key': "{YOUR_PUBLIC_KEY}",
'time': '2026-08-04 16:33:11',
'amount': '50000',
'currency': 'COP',
'trans_id': '1',
'time_expired': '120',
'url_ok': 'https://bit.ly/3S5aOwc',
'url_error': 'https://bit.ly/3S5aOwc',
'channel': '17',
'signature': "{YOUR_SIGNATURE}",
'shopper_information': '{
"Phone": "3123456789",
"email": "[email protected]",
"name_shopper": "Fulano",
"Num_doc_identi": "112345678",
"type_doc_identi": "ce",
"last_name_Shopper": "Da Silva",
"country":"COL",
"country_code":"+57"}'}
files=[
]
headers = {}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
var request = require('request');
var options = {
'method': 'POST',
'url': 'https://uat-payments.alps.cl/justpay/check-out/SecurePayment.php',
'headers': {
},
formData: {
'public_key': "{YOUR_PUBLIC_KEY}",
'time': '2026-08-04 16:33:11',
'amount': '50000',
'currency': 'COP',
'trans_id': '1',
'time_expired': '120',
'url_ok': 'https://bit.ly/3S5aOwc',
'url_error': 'https://bit.ly/3S5aOwc',
'channel': '17',
'signature': "{YOUR_SIGNATURE}",
'shopper_information': '{\n "Phone": "3123456789", \n "email": "[email protected]", \n "name_shopper": "Fulano", \n "Num_doc_identi": "112345678", \n "type_doc_identi": "ce", \n "last_name_Shopper": "Da Silva",\n "country":"COL",\n "country_code":"+57"}'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
Response
The response body is the checkout URL, in plain text. Redirect the payer to it:
https://uat-payments.alps.cl/justpay/check-out/?channel=cobre&tokenID=Xk3p9MzRb2Lm7VtM4wYcJ8sH1dGfvB2q&alps=1The URL can only be opened while the operation is pending. Once the payment reaches a final state the link stops working, so generate a new operation for every payment attempt.
If you prefer to build your own payment screen instead of redirecting, see Direct Integration.
Mandatory Data
| Attribute | Mandatory | Data type | Description |
|---|---|---|---|
public_key | True | String (255) | Public key, unique value that identifies the commerce |
time | True | Datetime | Request date time |
channel | True | Integer | Payment Channel. Use 17 |
amount | True | Double | The amount of the transaction. COP is processed in whole pesos: send integers |
currency | True | String (3) | Transaction currency code. Only COP is accepted on this channel |
trans_id | True | String (255) | Transaction id |
time_expired | True | String (255) | Time in minutes to expire the token. Most methods on this channel use a fixed expiration set by the provider — see Expiration Times |
url_ok | True | String (255) | URL where shopper will be redirected from the online banking if payment was successful (Must be Https) |
url_error | True | String (255) | URL where shopper will be redirected from the online banking if payment was wrong.(Must be Https) |
signature | True | String (255) | Signature hash256: Review signature calculation |
shopper_information | True | JSON String | JSON String Data: Review JSON index & format |
Optional Data
| Attribute | Mandatory | Data type | Description |
|---|---|---|---|
filter_by | False | String (21) | Payment method. Only one value is accepted. If omitted, all methods are shown on Cobre's checkout. Required when direct_integration is used |
user_bank_code | False | String (4) | Bank code for PSE. Required when filter_by is pse. Ignored for every other method |
direct_integration | False | Boolean | Set to 1 to receive the payment data as JSON instead of a checkout URL. See Direct Integration |
shopper_information JSON format
shopper_information JSON format'{
"Phone": "3123456789",
"email": "[email protected]",
"name_shopper": "Fulano",
"Num_doc_identi": "112345678",
"type_doc_identi": "ce",
"last_name_Shopper": "Da Silva",
"country":"COL",
"country_code":"+57"
}'The shopper_information field is a column corresponding to a json with the next keys. All of them are mandatory on this channel: if any key is missing the request is rejected with SHOPPER_FIELD_REQUIRED.
| Parameter | Mandatory | Data Type | Description |
|---|---|---|---|
name_shopper | True | String (255) | Shopper's name |
last_name_Shopper | True | String (255) | Shopper's last name |
type_doc_identi | True | String (4) | Identification document. See Identification documents |
Num_doc_identi | True | String (20) | Identification document number. Length depends on the document type |
email | True | String (255) | Shopper's email. The domain must be a real, resolvable one |
country_code | True | String (4) | Country's phone code. Must be +57 |
Phone | True | String (10) | Shopper's phone number. 9 or 10 digits |
country | True | String (3) | Country ISO code. Must be COL |
Test emails such as[email protected]or[email protected]are rejected when the domain has no DNS records. Use a real domain in your integration tests.
Identification documents
type_doc_identi | Document Type | Accepted number format |
|---|---|---|
CC | Citizenship ID Card | 5 to 12 digits |
NIT | Tax Identification Number | Exactly 10 digits (dots and hyphens are allowed and ignored) |
CE | Foreigner Identification Card | 6 to 12 digits |
TI | Identity Card | 5 to 11 digits |
PAS | Passport | 6 to 14 alphanumeric characters |
PPT | Temporary Protection Permit | 6 to 15 digits |
NUIP | Unique Personal Identification Number | 8 to 12 digits |
IDC | Customer Identifier | 5 to 20 characters |
RCN | Civil Birth Registration | 6 to 14 characters |
DIE | Foreign Identification Document | 6 to 14 characters |
The value is case-insensitive: cc and CC are both accepted. A document type outside this list returns SHOPPER_INVALID_IDTYPE; a number that does not match the expected format returns SHOPPER_INVALID_ID.
Filters
Using the parameter filter_by you may select the APM the payer will use. Only one value is accepted. Sending two or more values — for example pse, nequi — returns INVALID_FILTER_BY.
| Currency | APM | filter_by | Notes |
|---|---|---|---|
| COP | PSE | pse | user_bank_code is required |
| COP | Nequi | nequi | The payer approves the charge from the Nequi app |
| COP | Bancolombia | bancolombia | — |
| COP | Bre-B QR | breb_qr | We render the QR code; time_expired is honoured |
| COP | Bre-B Key | breb_key | We display the Bre-B key; time_expired is honoured |
If the filter_by parameter is not provided or left empty, the payer is sent to Cobre's checkout with all methods available: PSE, Nequi, Bancolombia and Bre-B. This is the recommended option when you want the payer to choose.
Payment flow by method
The value of filter_by determines what the payer sees after being redirected to the checkout URL.
filter_by | What happens |
|---|---|
| (omitted) | Cobre's checkout opens with every method available, including the bank selector for PSE |
pse | The payer is sent directly to the online banking of the bank identified by user_bank_code |
bancolombia | The payer is sent directly to Bancolombia's payment page |
nequi | The charge is pushed to the payer's Nequi app. Our checkout shows the instructions and waits for approval |
breb_qr | Our checkout shows a QR code to be scanned from any bank or wallet app that supports Bre-B |
breb_key | Our checkout shows a Bre-B key. The payer transfers the exact amount to that key from their banking app |
For nequi, breb_qr and breb_key the payer stays on our checkout until the payment is confirmed, and is then redirected to url_ok. If the payment is rejected, cancelled or expires, they are redirected to url_error.
Withbreb_keythe payer must transfer the exact amount of the operation. Transfers for a different amount are not matched to the payment.
How to Specify a Bank for PSE Payments
When filter_by is pse the bank must be included in the request: the payer is redirected straight to that bank's platform, so there is no bank selection step.
Steps to Specify a Bank
- Find the Bank Code
Check the list of available banking entities and find the corresponding code. For example: Davivienda: 1051 - Add the Field to Your Request
Include theuser_bank_codefield in your request body.
curl --location 'https://uat-payments.alps.cl/justpay/check-out/SecurePayment.php' \
--form 'public_key="{YOUR_PUBLIC_KEY}"' \
--form 'time="2026-08-04 16:33:11"' \
--form 'amount="50000"' \
--form 'currency="COP"' \
--form 'trans_id="1"' \
--form 'time_expired="120"' \
--form 'url_ok="https://bit.ly/3S5aOwc"' \
--form 'url_error="https://bit.ly/3S5aOwc"' \
--form 'channel="17"' \
--form 'signature="{YOUR_SIGNATURE}"' \
--form 'filter_by="pse"' \
--form 'user_bank_code="1051"' \
--form 'shopper_information="{
\"Phone\": \"3123456789\",
\"email\": \"[email protected]\",
\"name_shopper\": \"Fulano\",
\"Num_doc_identi\": \"112345678\",
\"type_doc_identi\": \"ce\",
\"last_name_Shopper\": \"Da Silva\",
\"country\":\"COL\",
\"country_code\":\"+57\"}"'Available Payment Flows
With filter_by="pse" and a bank specified: direct redirect to the bank's platform.
Without filter_by: the payer selects their bank from all available options on the checkout.
Note: filter_by="pse" without user_bank_code returns INVALID_USER_BANK_CODE. If you don't know the payer's bank in advance, omit filter_by so the bank can be chosen during the payment process. user_bank_code is ignored when filter_by is any value other than pse.
Expiration Times
The provider enforces a fixed expiration for most methods on this channel. time_expired is only applied to Bre-B and to the checkout with all methods.
filter_by | Expiration |
|---|---|
pse | 10 minutes (fixed — time_expired is ignored) |
bancolombia | 10 minutes (fixed — time_expired is ignored) |
nequi | 15 minutes (fixed — time_expired is ignored) |
breb_qr | time_expired, between 5 and 4320 minutes (3 days). Default 120 |
breb_key | time_expired, between 5 and 4320 minutes (3 days). Default 120 |
| (omitted) | time_expired. Default 120 minutes |
Values below the minimum or above the maximum are adjusted to the closest accepted value. The expiration shown to the payer on our checkout is always the effective one.
Direct Integration
Send direct_integration=1 to receive the payment data as JSON and render the payment screen yourself. In this mode:
filter_bybecomes mandatory and must contain exactly one ofpse,nequi,bancolombia,breb_qrorbreb_key.user_bank_codeis mandatory forpseand is validated against the list of accepted codes.- No checkout URL is returned: you are responsible for showing the payment instructions and for tracking the result through the payment notification.
curl --location 'https://uat-payments.alps.cl/justpay/check-out/SecurePayment.php' \
--form 'public_key="zyssglikvtltbd2se2hudwl50jjomil2uytp7tpvjtxyfdw469jagk8yvnex9jks"' \
--form 'time="2026-08-04 16:33:11"' \
--form 'amount="50000"' \
--form 'currency="COP"' \
--form 'trans_id="1"' \
--form 'time_expired="120"' \
--form 'url_ok="https://bit.ly/3S5aOwc"' \
--form 'url_error="https://bit.ly/3S5aOwc"' \
--form 'channel="17"' \
--form 'signature="89d4443aadbf4c4d560a270e951336109ae24dfeaeb19b0451cdbb5ca582208f"' \
--form 'direct_integration="1"' \
--form 'filter_by="breb_qr"' \
--form 'shopper_information="{
\"Phone\": \"3123456789\",
\"email\": \"[email protected]\",
\"name_shopper\": \"Fulano\",
\"Num_doc_identi\": \"112345678\",
\"type_doc_identi\": \"ce\",
\"last_name_Shopper\": \"Da Silva\",
\"country\":\"COL\",
\"country_code\":\"+57\"}"'
In UAT,breb_qrandbreb_keyreturn fixed sample values (https://test.example.com/qr/12345and@TESTKEY123) and no charge is created with the provider. Use these responses to validate your integration contract only; end-to-end Bre-B tests must be run in Production.
PSE and Bancolombia response
{
"payment_link": "https://payment.link/12345"
}Redirect the payer to payment_link.
Bre-B QR response
{
"operation_id": 123456,
"qr_value": "0002010102...",
"qr_code": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0i..."
}| Field | Description |
|---|---|
operation_id | Our internal identifier for the operation |
qr_value | Payload to encode if you want to render the QR code with your own library |
qr_code | Ready-to-use QR image as a data URI, so you can display it without extra libraries |
Bre-B Key response
{
"operation_id": 123456,
"key_value": "@LLAVEGENERADA"
}Display key_value to the payer and instruct them to transfer the exact amount of the operation to that key from the Bre-B section of their banking app.
Nequi response
{
"operation_id": 123456,
"expired_at": "2026-08-04T18:48:11Z",
"amount": "50000.00",
"status": "pending",
"steps": [
{
"step_number": 1,
"title": "Desbloquea tu dispositivo",
"description": "Asegúrate de tener conexión a internet y tu celular activo."
},
{
"step_number": 2,
"title": "Revisa la notificación Push",
"description": "Busca la alerta emergente enviada por la app Nequi con el detalle del cobro."
},
{
"step_number": 3,
"title": "Accede al Centro de Notificaciones",
"description": "Si no ves la alerta, abre tu App Nequi, inicia sesión y presiona el ícono de la campanita (🔔)."
},
{
"step_number": 4,
"title": "Autoriza la transacción",
"description": "Selecciona la solicitud pendiente, verifica el monto y haz clic en Aceptar o Aprobar."
},
{
"step_number": 5,
"title": "Espera la confirmación",
"description": "La pantalla se actualizará automáticamente cuando el pago sea procesado con éxito."
}
]
}| Field | Description |
|---|---|
expired_at | UTC timestamp after which the charge can no longer be approved |
amount | Amount of the operation |
status | Status reported by the provider when the charge was created |
steps | Instructions, ready to display, describing how to approve the push notification |
The push notification is sent as soon as the operation is created, so show these instructions immediately.
Recommendations
- Send whole pesos. COP is processed without decimals. Fractional amounts are rounded before being sent to the provider.
- Create one operation per payment attempt. The checkout URL is single-use and stops working once the operation reaches a final state.
- Do not confirm orders on
url_ok. The payer may return to your site before the provider confirms the payment. Wait for the notification. - Keep
time_expiredconsistent with the method. For PSE, Nequi and Bancolombia the provider's fixed expiration applies regardless of the value you send. - Use lowercase in
filter_byand send exactly one value. - Use real email domains in every environment, including tests.
- Configure your rejection URL if you need to be notified of rejected, cancelled or expired payments; without it only successful payments are notified.
List of Banks and Financial Institutions in Colombia
Contains a list of the main banks and financial institutions that operate in Colombia, along with their respective identification codes. Use the code as the value of user_bank_code.
| Code | Entity Name |
|---|---|
| 1815 | Alianza fiduciaria |
| 1558 | Ban |
| 1059 | Bancamia s.a. |
| 1040 | Banco agrario |
| 1052 | Banco av villas |
| 1013 | Banco bbva colombia s.a. |
| 1032 | Banco caja social |
| 1066 | Banco cooperativo coopcentral |
| 1051 | Banco davivienda |
| 1001 | Banco de bogota |
| 1023 | Banco de occidente |
| 1062 | Banco falabella |
| 1063 | Banco finandina s.a. bic |
| 1012 | Banco gnb sudameris |
| 1006 | Banco itau |
| 1071 | Banco j.p. morgan colombia s.a. |
| 1047 | Banco mundo mujer s.a. |
| 1060 | Banco pichincha s.a. |
| 1002 | Banco popular |
| 1065 | Banco santander colombia |
| 1069 | Banco serfinanza |
| 1303 | Banco union antes giros |
| 1007 | Bancolombia |
| 1061 | Bancoomeva s.a. |
| 1283 | Cfa cooperativa financiera |
| 1009 | Citibank |
| 1370 | Coltefinanciera |
| 1292 | Confiar cooperativa financiera |
| 1289 | Cotrafa |
| 1816 | Crezcamos |
| 1097 | Dale |
| 1551 | Daviplata |
| 1637 | Iris |
| 1286 | JFK cooperativa financiera |
| 1070 | Lulo bank |
| 1801 | Movii s.a. |
| 1507 | Nequi |
| 1809 | Nu. colombia compañia de financiamiento s.a. |
| 1811 | Rappipay |
| 1019 | Scotiabank colpatria |
| 1804 | Ualá |
The following codes are also accepted: 1053, 1067, 1121, 1802, 1803, 1805, 1808, 1812 and 1814.
A code outside this list returns INVALID_BANK_CODE when direct_integration is used. In the standard integration the code is forwarded to the provider, which rejects the operation if the entity is not available for PSE.
Errors
To better error handling, we'll return the errors in the response body using the following fields:
{
"error":{
"code":"INVALID_FILTER_BY",
"message":"Invalid values in 'filter_by'. Allowed values: pse, nequi, bancolombia, breb_qr, breb_key"
}
}Error Codes
Request and authentication
| Code | HTTP | Description |
|---|---|---|
METHOD_NOT_ALLOWED | 405 | The request was not sent with POST |
MISSING_CONTENT_TYPE | 400 | The Content-Type header is missing |
UNSUPPORTED_CONTENT_TYPE | 415 | The Content-Type is not supported |
EMPTY_JSON_BODY | 400 | A JSON request was sent with an empty body |
INVALID_JSON | 400 | The JSON body could not be parsed |
INVALID_JSON_STRUCTURE | 400 | The JSON body is not an object with key-value pairs |
MISSING_FIELD | 400 | One or more mandatory fields are absent. The message lists them |
EMPTY_FIELD | 400 | One or more mandatory fields were sent empty. The message lists them |
INVALID_MERCHANT | 404 | No merchant matches the public_key |
INVALID_SIGNATURE | 400 | The signature does not match the expected value |
MERCHANT_DISABLED | 400 | The merchant account is not active. Contact [email protected] |
Channel, currency and amount
| Code | HTTP | Description |
|---|---|---|
INVALID_CHANNEL | 400 | The channel is not enabled |
DISABLED_CHANNEL | 400 | The channel is not available for your account |
INVALID_CHANNEL_CURRENCY | 400 | The channel and currency combination is not enabled for your account |
DISABLED_CURRENCY | 400 | The currency is not available for your account |
INVALID_CURRENCY | 400 | The currency code is not a valid three-character ISO code |
INVALID_CURRENCY_CHANNEL | 400 | The currency is not allowed on this channel. Channel 17 only accepts COP |
INVALID_AMOUNT | 400 | amount is not a valid number |
NEGATIVE_AMOUNT | 400 | amount must be greater than zero |
MAX_AMOUNT_LIMIT | 400 | amount exceeds the maximum allowed for your account |
Shopper information
| Code | HTTP | Description |
|---|---|---|
SHOPPERINFO_REQUIRED | 400 | shopper_information was not sent |
SHOPPERINFO_BAD_FORMAT | 400 | shopper_information is not a JSON encoded string |
SHOPPER_FIELD_REQUIRED | 400 | One or more keys of shopper_information are missing |
SHOPPER_COUNTRY_NOTALLOWED | 400 | country must be COL |
SHOPPER_INVALID_IDTYPE | 400 | type_doc_identi is not an accepted document type |
SHOPPER_INVALID_ID | 400 | Num_doc_identi does not match the format of the document type |
SHOPPER_INVALID_COUNTRY_CODE | 400 | country_code must be +57 |
SHOPPER_INVALID_PHONE | 400 | Phone must contain 9 or 10 digits |
SHOPPER_INVALID_EMAIL_FORMAT | 400 | email is not valid or its domain cannot be resolved |
BLACKLIST_DOCUMENT_ID | 400 | The document number is not allowed to transact |
Payment method
| Code | HTTP | Description |
|---|---|---|
INVALID_FILTER_BY | 400 | filter_by contains an unsupported value, or more than one value |
INVALID_USER_BANK_CODE | 400 | user_bank_code is required when filter_by is pse |
FILTER_BY_REQUIRED | 400 | filter_by is mandatory when direct_integration is used |
USERBANK_CODE_REQUIRED | 400 | user_bank_code is mandatory for pse when direct_integration is used |
INVALID_BANK_CODE | 400 | user_bank_code is not in the list of accepted codes. The message lists them |
Processing
| Code | HTTP | Description |
|---|---|---|
CREATION_ERROR | 400 | The payment could not be created with the provider. Retry with a new trans_id |
