NAV
shell

Introduction

This document describes the PSE API. This API offers a REST service for:

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.

Flow chart

Diagram

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:

  1. Authentication

  2. Get available banks

  3. Generate a charge

  4. Get/Query charge

  5. Webhook

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.