Introduction
This document describes the PSE API. This API offers a REST service for:
- Get available banks
- Generate charge
- Get/Query charge
We also can configure a webhook to notify the API clients when a Charge status has changed. See the Webhook section for details.
Environments
We have two independent environments for development and production applications.
- Staging: https://staging.apiv2.tpaga.co
- Production: https://production.apiv2.tpaga.co
Flow chart
Quick Start Guide
Once you have an active access_token you can start to use our API to process charges.
Here is the detail of each service offered by the API:
Authentication
cURL Example:
CLIENT_ID="OXSXZTIC60nB1ghmPevapPWxNT6twIQUeRVLQaCp"
CLIENT_SECRET="XW7qm73qFohu9vT8zObQ0JNb8tS4UfMIg1iepeLw7VmXAHidyEbZbwFEo4ehYeZ3o3GLuKTJhvICZ3RsIgPyDbNlTWnKsz3gkkGrZ66FZOak0nTqfCVvviho7NNLvwyg"
AUTH_STRING=$(echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64 | tr -d '\n')
curl -v --location POST 'https://staging.apiv2.tpaga.co/o/token/' \
--header "Authorization: Basic $AUTH_STRING" \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials'
A successful response returns a JSON object in the following format:
{
"access_token": "<JWT token>",
"token_type": "Bearer",
"expires_in": 3600,
"scope":"read write"
}
An example of a valid request sending the Bearer token:
curl -X GET 'https://staging.apiv2.tpaga.co/api/pse/v1/public/banks' \
--header 'Authorization: Bearer <JWT token>'
Example to revoke an access token:
curl -X POST 'https://staging.apiv2.tpaga.co/o/revoke_token/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token=<JWT token>' \
--data-urlencode 'client_id=<your-client-id>' \
--data-urlencode 'client_secret=<your-client-secret>'
This API uses OAuth 2.0 with JWT-based access tokens. Clients must first obtain an access token using the client credentials flow and then include it in subsequent API requests via the Authorization
header.
Obtaining an Access Token
Endpoint: /o/token/
HTTP Method: POST
Description: To obtain an access token, send a POST request to the /o/token/
endpoint using HTTP Basic Authentication with your client credentials. Your CLIENT_ID
and CLIENT_SECRET
must be combined, base64-encoded, and included in the Authorization
header.
Request Parameters
Field | Description | Type | Nullable |
---|---|---|---|
grant_type | The OAuth2 grant type. Must be set to client_credentials . |
String | No |
Note: Client credentials are provided via the HTTP Basic Authentication header.
Response Parameters
Field | Description | Type | Nullable |
---|---|---|---|
access_token | The generated JWT token | String | No |
token_type | The type of token, e.g. "Bearer" | String | No |
expires_in | The duration (in seconds) for which the token is valid | Integer | No |
HTTP Responses
Code | Description |
---|---|
200 | The access token was issued successfully. |
400 | The request is missing required parameters or includes invalid values. |
401 | Client authentication failed. |
Using the Access Token
Include the obtained JWT access token in the Authorization
header for subsequent API requests
Token Expiration and Renewal
Access tokens are valid for a limited period (as specified by the expires_in
value). We recommend caching your access token and reusing it until it is near expiration. Avoid requesting a new token on every API call. When the token is close to expiring, request a new one to maintain uninterrupted service.
Revoking an Access Token
Endpoint: /o/revoke_token/
HTTP Method: POST
Description: If you need to revoke an access token, send a POST request to the /o/revoke_token/
endpoint.
Request Parameters
Field | Description | Type | Nullable |
---|---|---|---|
token | The access token to be revoked. | String | No |
client_id | The client ID. | String | No |
client_secret | The client secret. | String | No |
Response Parameters
The response body is empty if the token revocation is successful.
HTTP Responses
Code | Description |
---|---|
200 | The access token was revoked successfully. The response body will be empty. |
400 | The request is missing required parameters or is malformed. |
401 | Client authentication failed. |
404 | The provided token was not found. |
Environment Considerations
Get available banks
Endpoint: /public/banks
HTTP Method: GET
Description: To generate a charge in the pse API it is necessary to send the code of the bank that will be used, this code is obtained making a GET request to this service.
Example request
curl --location 'https://staging.apiv2.tpaga.co/api/pse/v1/public/banks' \
--header 'Authorization: Bearer <JWT token>'
Example response:
[
{
"name": "ALIANZA FIDUCIARIA S A",
"code": "5016"
},
{
"name": "BAN100",
"code": "1558"
},
{
"name": "BANCAMIA",
"code": "1059"
},
{
"name": "BANCO AGRARIO",
"code": "1040"
},
{
"name": "BANCO AGRARIO DESARROLLO",
"code": "1081"
},
{
"name": "BANCO AGRARIO QA DEFECTOS",
"code": "1080"
},
{...}
]
Response parameters
Field | Description | Type | Nullable |
---|---|---|---|
name | Bank's name | String | no |
code | Code of the bank that will be used in Generate a charge | String | no |
HTTP responses
Code | Description |
---|---|
200 | The Bank's list was queried successfully |
401 | Invalid authorization token provided |
403 | You do not have enough permissions to perform this action, please contact the support team |
422 | You did not provide valid data for this operation, please check response body for details |
5XX | Internal sever error, it's safe to retry the request |
The service will deliver a list of banks which can be used later to generate a charge.
Generate a charge
Endpoint: /public/charge
HTTP Method: POST
Description:
At this point, you will need to show the buyer a form to select the type of person (NATURAL or LEGAL) and the bank you want to use to process your charge.
Once you have the code of the bank that will be used, you must generate the charge by making a POST request to this service.
Example request
curl -X POST \
https://staging.apiv2.tpaga.co/api/pse/v1/public/charge \
-H 'Authorization: Bearer <JWT token>' \
-H 'Content-Type: application/json' \
-d '{
"bank_code": "1022",
"order_id": "abc-123",
"amount": "10000.0",
"vat_amount": "10.0",
"description": "Compra de producto ABC",
"user_type": "NATURAL",
"buyer_email": "demo@demo.com",
"buyer_full_name": "Miguel Rodriguez",
"document_type": "CE",
"document_number": "987654321",
"redirect_url": "http://where-to-go-after-finish-payment-at-pse.com",
"buyer_phone_number": "3057788996"
}'
The following is the definition of each of the fields received by this service, each of these values must be sent in the body of the request in json format
Request parameters
Field | Description | Type | Mandatory |
---|---|---|---|
bank_code | Identifier of the bank obtained in the Get available banks service | String - max 35 characters | Yes |
order_id | Unique identifier of the charge in the external system. Here you can send any identifier for the charge | String - max 20 characters | Yes |
amount | Amount of money for which the charge will be generated | Decimal of maximum two decimal places | Yes |
vat_amount | Sales TAX – IVA | Decimal < amount | Yes |
description | Charge description | String – max 80 characters | Yes |
user_type | Person type (NATURAL or LEGAL) | String – max 10 characters | Yes |
buyer_email | Buyer email | String – max 255 characters | Yes |
buyer_full_name | Name of the buyer | String – max 255 characters | Yes |
document_type | Buyer document type – CC, CE, NIT, TI or PP | String – max 20 characters | Yes |
document_number | Buyer document number | String – max 20 characters | Yes |
redirect_url | Redirect URL | String – max 500 characters | Yes |
buyer_phone_number | Buyer phone number, avoid to add the country code and the plus (+) sign | String – max 20 characters | Yes |
Example response:
{
"token": "pse-c542f18edadb441d8b4639edbfb566e5",
"order_id": "abc-123",
"amount": "10000.00",
"vat_amount": "10.00",
"description": "Cobro de prueba 2",
"user_type": "NATURAL",
"bank_code": "1022",
"status": "pending",
"buyer_email": "demo@demo.com",
"buyer_full_name": "Miguel Rodriguez",
"document_type": "CE",
"document_number": "987654321",
"redirect_url": "http://where-to-go-after-finish-payment-at-pse.com",
"traceability_code": "3416207",
"return_code": "SUCCESS",
"bank_url": "https://registro.desarrollo.pse.com.co/PSENF/index.html?enc=CCnGKyvG0W%2bjZeSCRKHPd1UtFV9Ku20LmblpVQAEyoY%3d",
"transaction_state": null,
"rejected_reason": null
}
Response parameters
Field | Description | Type | Nullable |
---|---|---|---|
token | Unique identifier of the charge in the external system used in | String - max 255 characters | No |
order_id | Unique identifier of the charge in the external system | String - max 20 characters | No |
amount | Amount of money for which the charge will be generated | Decimal of maximum two decimal places | No |
vat_amount | Sales TAX – IVA | Decimal < amount | No |
description | Charge description | String – max 80 characters | No |
user_type | Person type (NATURAL or LEGAL) | String – max 10 characters | No |
bank_code | Identifier of the bank obtained in the Get available banks service | String - max 35 characters | No |
status | Shows the actual status of the charge | String - max 35 characters | No |
buyer_email | Buyer email | String – max 255 characters | No |
buyer_full_name | Name of the buyer | String – max 255 characters | No |
document_type | Buyer document type – CC, CE, NIT, TI or PP | String – max 20 characters | No |
document_number | Buyer document number | String – max 20 characters | No |
redirect_url | Corresponds to the url that the API Client wants the bank to return at the end of the transaction | String – max 500 characters | No |
traceability_code | Unique number assigned by the PSE to each transaction processed | String – max 255 characters | No |
return_code | Contains error messages found, example: SUCCESS, FAIL_INVALIDSTATE | String – max 255 characters | Yes |
bank_url | Internet address of the financial institution | String – max 20 characters | Yes |
transaction_state | Transaction status in PSE | String – max 20 characters | Yes |
rejected_reason | Reason for the rejection of the charge | String – max 150 characters | Yes |
HTTP responses
Code | Description |
---|---|
201 | The charge was created successfully |
401 | Invalid authorization token provided |
403 | You do not have enough permissions to perform this action, please contact the support team |
408 | The charge already exist |
409 | The charge was not successfull and return a failed status |
422 | You did not provide valid data for this operation, please check response body for details |
502 | Timed out occurred processing request to PSE, the charge returns with a failed status |
5XX | Internal sever error, it's safe to retry the request |
Error Details
When the response code is 422
, the response body includes details about the invalid data provided. The response will follow this structure:
{
"error_message": "A descriptive message about the error.",
"field": "The specific field where the error occurred, or 'non_field_errors' for general validation issues.",
"value": "The invalid value that caused the error."
}
Example Errors
Field | Description | Example Value | Example Error Message |
---|---|---|---|
user_type |
The value provided is not a valid choice. | INVALID |
"INVALID" no es una elección válida. |
buyer_email |
The email address provided is not valid. | invalidemail.co |
Introduzca una dirección de correo electrónico válida. |
amount |
The value must be a valid number. | 12c |
Se requiere un número válido. |
bank_code |
The bank code does not exist in the system. | XXXX |
Objeto con code=XXXX no existe. |
non_field_errors |
The VAT amount cannot be greater than the total amount. | N/A |
vat_amount no puede ser mayor a amount. |
amount |
The transaction amount exceeds the allowed maximum. | 40000001.0 |
El valor de la transacción debe estar entre 0.00 y 40000000.00. |
amount |
The transaction amount is below the allowed minimum. | 999 |
El valor de la transacción debe estar entre 1000.00 y 40000000.00. |
Get Query charge
Endpoint: /public/charge/token
HTTP Method: GET
Description: This service allows to consult all the information of a charge.
Example request:
curl --location --request GET 'https://staging.apiv2.tpaga.co/api/pse/v1/public/charge/pse-c542f18edadb441d8b4639edbfb566e5' \
--header 'Authorization: Bearer <JWT token>'
Request parameters
Field | Description | Type | Mandatory |
---|---|---|---|
token | Unique identifier of the charge in the external system got in Generate a charge | String - max 255 characters | Yes |
Response parameters
The response is the same as the one returned at Generate a charge, except the following fields:
Field | Description | Type | Nullable |
---|---|---|---|
status | Shows the actual status of the charge | String - max 35 characters | No |
transaction_state | Transaction status in PSE, example: OK | String – max 20 characters | Yes |
rejected_reason | Reason for the rejection of the charge, example: Transacción no concluída en el banco | String – max 150 characters | Yes |
HTTP responses
Code | Description |
---|---|
200 | The charge information was queried successfully |
401 | Invalid authorization token provided |
403 | You do not have enough permissions to perform this action, please contact the support team |
422 | You did not provide valid data for this operation, please check response body for details |
5XX | Internal sever error, it's safe to retry the request |
Webhook
This service allows the API client to receive notifications via HTTP requests when a charge has reached a final status.
This is an example of the request that we will send to the configured API client endpoint:
curl -X POST 'https://clienthost.com/some/defined/endpoint' \
--header 'Content-Type: application/json' \
--data-raw '{
{'charge_token': 'pse-c542f18edadb441d8b4639edbfb566e5'}
}'
How it works
When a charge reaches a final status (authorized
, charge-rejected
or settled
) an HTTP POST request will be sent to a (previously configured) client endpoint. That request will have the following body:
Field | Description | Type |
---|---|---|
charge_token | Charge token that has reached a final status | String |
When a webhook notification is sent, the API client should use the received charge_token along with the Get Query charge endpoint to get the complete information related to the charge.
Charge statuses
Status | Description |
---|---|
pending | The transaction was successfully registered in the PSE system and it is pending that the buyer authorizes the charge |
rejected | The transaction was rejected by PSE |
failed | The transaction was not registered due to communication problems between Tpaga and PSE |
authorized | The buyer made the charge on the bank's website |
charge-rejected | The charge failed or was not made by the buyer |
settled | Tpaga reported the transaction as completed to PSE (this happens automatically when the charge goes to authorized status) |
Operation of charges in PSE
When the buyer completes the charge on the bank's website, they are redirected to the URL that they specified in the field redirect_url when generating the charge.
At this point, you should receive a GET request to the URL you specified, indicating that you are ready to perform a request to the Check a charge service to find out its final status (settled or charge-rejected). Because it's possible that the user abandons the flow without completing the charge, it is important to know that the lifetime of a charge within PSE is about 30 minutes, so that during this maximum period of time a charge can be in a non-final status.
As an API client, you are gonna recieve a webhook notification when a charge has reached a final status. You should be aware that the time it takes for a charge to reach a final state will depend on the actions that make the buyer within the page of the bank.
QA Testing
It is necessary that you previously have credentials assigned, in case you do not have it, please contact with TPAGA operators.
To simulate the charge flow with PSE in the staging environment, the bank "BANCO UNION COLOMBIANO" must be used, whose corresponding bank_code can be obtained using the Get available banks service.
Errors
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
401 | Unauthorized -- Your API key is wrong. |
403 | Forbidden -- The kitten requested is hidden for administrators only. |
404 | Not Found -- The specified kitten could not be found. |
405 | Method Not Allowed -- You tried to access a kitten with an invalid method. |
406 | Not Acceptable -- You requested a format that isn't json. |
410 | Gone -- The kitten requested has been removed from our servers. |
418 | I'm a teapot. |
429 | Too Many Requests -- You're requesting too many kittens! Slow down! |
500 | Internal Server Error -- We had a problem with our server. Try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |