# MD for: https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/payment-integration/pse.md \# PSE With Checkout API from Mercado Pago, you can offer payments with \*\*PSE (Pagos Seguros en Línea)\*\*. This electronic system allows customers to make online purchases and payments using funds directly from a savings account, checking account, or digital wallet, acting as a secure bridge between banks and stores, and thus eliminating the need for credit cards. If you have already \[configured your development environment\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/development-environment) and want to offer payments via PSE, follow the steps below. > NOTE > > Remember: before configuring payment methods, choose the mode in which you will process your transactions. The processing mode definition, whether \*\*manual or automatic\*\*, will be made at the time of order creation, using the \`processing\_mode\` parameter. For more information, access the \[Integration model\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/integration-model) section. :::AccordionComponent{title="Add payment form" pill="client-side"} To receive payments, you need to add a form to the \_frontend\_ that allows you to capture the payer's data securely. If you already have a development that includes a custom payment form, make sure to include PSE among the payment options you want to offer, as indicated below, and continue to the \[Get document types\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/payment-integration/pse#bookmark\_get\_document\_types) step. If you don't yet have a payment form, add the model below to your project and include the PSE identifier as an option to be offered. | Payment method | \`payment\_method\_id\`| |:---:|:---:| | PSE | \`pse\` | \`\`\`html Postal Code Street Name Number Neighborhood City Department Area Code Phone Email Person Type Natural Legal entity Document Type Document Number Bank Pay \`\`\` ::: :::AccordionComponent{title="Get document types" pill="client-side"} To facilitate the correct completion of the payment form, you need to get the document types that can be accepted. The function below allows you to automatically fill in the available options. To do this, simply include in the form the \`select\` element with \`id=form-checkout\_\_identificationType\`, used in the example from the previous step. If you already have a development that handles getting document types, as indicated below, proceed to the \[Send payment\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/payment-integration/pse#bookmark\_send\_payment) step. If you don't yet have this function, add the following code to your project. \`\`\`javascript document.getElementById('form-checkout\_\_personType').addEventListener('change', e => { const personTypesElement = document.getElementById('form-checkout\_\_personType'); updateSelectOptions(personTypesElement.value); }); function updateSelectOptions(selectedValue) { const naturalDocTypes = \[ new Option('C.C', 'CC'), new Option('C.E.', 'CE'), new Option('Pasaporte', 'PAS'), new Option('Tarjeta de Extranjería', 'TE'), new Option('Tarjeta de Identidad ', 'TI'), new Option('Registro Civil', 'RC'), new Option('Documento de Identificación', 'DI') \]; const juridicaDocTypes = \[ new Option('NIT', 'NIT') \]; const idDocTypes = document.getElementById('form-checkout\_\_identificationType'); if (selectedValue === 'natural') { idDocTypes.options.length = 0; naturalDocTypes.forEach(item => idDocTypes.options.add(item, undefined)); } else { idDocTypes.options.length = 0; juridicaDocTypes.forEach(item => idDocTypes.options.add(item, undefined)); } } \`\`\` ::: :::AccordionComponent{title="List banks" pill="client-side"} When creating a payment with PSE, you need to send the code of the bank that will be used for the transfer. To do this, you need to list the available banks and present these options to the payer, allowing them to choose their preferred bank. Send a \*\*GET\*\* with your :toolTipComponent\[test Access Token\]{content="Private key of the application created in Mercado Pago, used in the \_backend\_. You can access it through \*Your integrations > Integration details > Tests > Test credentials\*. The test Access Token starts with the prefix \`APP\_USR\`."} to the endpoint :TagComponent{tag="API" text="/v1/payment\_methods" href="/developers/en/reference/online-payments/checkout-api/payment-methods/get"} or, if you prefer, make the request using our SDKs below. * [csharp ](#editor%5F5) * [curl ](#editor%5F7) * [java ](#editor%5F3) * [node ](#editor%5F2) * [php ](#editor%5F1) * [python ](#editor%5F6) * [ruby ](#editor%5F4) php node java ruby csharp python curl ``` "); $client = new PaymentMethodClient(); $payment_method = $client->get(); ?> ``` Copiar ``` import { MercadoPagoConfig, PaymentMethods } from 'mercadopago'; const client = new MercadoPagoConfig({ accessToken: 'access_token' }); const paymentMethods = new PaymentMethods(client); paymentMethods.get().then((result) => console.log(result)) .catch((error) => console.log(error)); ``` Copiar ``` MercadoPagoConfig.setAccessToken(""); PaymentMethodClient client = new PaymentMethodClient(); client.list(); ``` Copiar ``` require 'mercadopago' sdk = Mercadopago::SDK.new('') payment_methods_response = sdk.payment_methods.get() payment_methods = payment_methods_response[:response] ``` Copiar ``` using MercadoPago.Client.PaymentMethod; using MercadoPago.Config; using MercadoPago.Resource; using MercadoPago.Resource.PaymentMethod; MercadoPagoConfig.AccessToken = ""; var client = new PaymentMethodClient(); ResourcesList paymentMethods = await client.ListAsync(); ``` Copiar ``` import mercadopago sdk = mercadopago.SDK("ACCESS_TOKEN") payment_methods_response = sdk.payment_methods().list_all() payment_methods = payment_methods_response["response"] ``` Copiar ``` curl -X GET \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ' \ 'https://api.mercadopago.com/v1/payment_methods' \ ``` Copiar The response will return the payment methods, where you can list the banks available for PSE payments through the \`financial\_institutions\` field inside the object with \`id=pse\`, as shown in the example below. \`\`\`json \[ { "id": "pse", "name": "PSE", "payment\_type\_id": "bank\_transfer", "status": "active", "secure\_thumbnail": "https://www.mercadopago.com/org-img/MP3/API/logos/pse.gif", "thumbnail": "https://www.mercadopago.com/org-img/MP3/API/logos/pse.gif", "deferred\_capture": "does\_not\_apply", "settings": \[\], "additional\_info\_needed": \[ "entity\_type" \], "min\_allowed\_amount": 1600, "max\_allowed\_amount": 340000000, "accreditation\_time": 30, "financial\_institutions": \[ { "id": "1040", "description": "Banco Agrario" }, { "id": "1507", "description": "NEQUI" }, { "id": "1052", "description": "Banco AV Villas" }, { "id": "1032", "description": "Banco Caja Social" } \], "processing\_modes": \[ "aggregator" \] } \] \`\`\` Then, create a \`select\` element in \_JavaScript\_ and populate it with the data returned in this request, as shown in the example below. \`\`\`javascript function setPse() { fetch('/payment\_methods') .then(async function(response) { const paymentMethods = await response.json(); const pse = paymentMethods.filter((method) => method.id === 'pse')\[0\]; const banksList = pse.financial\_institutions; const banksListElement = document.getElementById('banksList'); const selectElement = document.createElement('select'); selectElement.name = 'financialInstitution'; banksList.forEach(bank => { const option = document.createElement('option'); option.value = bank.id; option.textContent = bank.description; selectElement.appendChild(option); }); banksListElement.appendChild(selectElement); }).catch(function(reason) { console.error('Failed to get payment methods', reason); }); } \`\`\` To ensure the dynamic elements created with this \_JavaScript\_ are loaded when the page finishes rendering, add the following code: \`\`\`javascript (function initCheckout() { try { const docTypeElement = document.getElementById('form-checkout\_\_identificationType'); setPse(); updateSelectOptions('natural') } catch(e) { return console.error('Error getting identificationTypes: ', e); } })(); \`\`\` ::: :::AccordionComponent{title="Send payment" pill="server-side"} The payment submission must be performed by creating an order that contains the associated payment transaction. > NOTE > > Payment creation may occur asynchronously in an order. In this scenario, the order remains with status \`in\_process\` and without information. We recommend configuring \[Order topic notifications\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/notifications) to receive updates on status changes, including updated order data. Alternatively, you can opt to send a \*\*GET\*\* to the endpoint \[/v1/orders/{id}\](https://www.mercadopago.com.co/developers/en/reference/online-payments/checkout-api/get-order/get) to retrieve these updated data. To do this, send a \*\*POST\*\* with your :toolTipComponent\[test Access Token\]{content="Private key of the application created in Mercado Pago, used in the \_backend\_. You can access it through \*Your integrations > Integration details > Tests > Test credentials\*. The test Access Token starts with the prefix \`APP\_USR\`."} and the required parameters listed below to the endpoint :TagComponent{tag="API" text="/v1/orders" href="/developers/en/reference/online-payments/checkout-api/create-order/post"} and execute the request. \`\`\`curl curl --location --request POST 'https://api.mercadopago.com/v1/orders' \\ -H 'Authorization: Bearer ' \\ -H 'X-Idempotency-Key: ' \\ -H 'Content-Type: application/json' \\ -d '{ "type": "online", "total\_amount": "5000", "external\_reference": "ext\_ref\_1234", "processing\_mode": "automatic", "expiration\_time": "PT20M", "payer": { "email": "test\_user\_co@testuser.com", "entity\_type": "individual", "identification": { "type": "NIT", "number": "76262349" }, "first\_name": "John", "last\_name": "Doe", "phone": { "area\_code": "57", "number": "3001234567" }, "address": { "street\_name": "Calle 10", "street\_number": "100", "city": "Bogota", "zip\_code": "110111", "neighborhood": "Centro" } }, "transactions": { "payments": \[ { "amount": "5000", "payment\_method": { "id": "pse", "type": "bank\_transfer", "financial\_institution": "1051" } } \] }, "additional\_info": { "payer.ip\_address": "200.100.50.25" }, "config": { "online": { "callback\_url": "https://merchant.com/pse/return" } } }' \`\`\` See in the table below the descriptions of the parameters that are required in the request and those that, although optional, have some important particularities worth highlighting. | Attribute | Type | Description | Required | |---|---|---|---| | \`Authorization\` | \_Header\_ | Refers to your private key, the :toolTipComponent\[test Access Token\]{content="Private key of the application created in Mercado Pago, used in the \_backend\_. You can access it through \*Your integrations > Integration details > Tests > Test credentials\*. The test Access Token starts with the prefix \`APP\_USR\`."}. | Required | | \`X-Idempotency-Key\` | \_Header\_ | Idempotency key. This key ensures that each request is processed only once, avoiding duplicates. Use a unique value in the request \`header\`, such as a UUID V4 or a random \_string\_. | Required | | \`total\_amount\` | \_Body. String\_ | Total transaction amount. Must be greater than 0\. | Required | | \`external\_reference\` | \_Body. String\_ | External order reference, which can be, for example, a hashcode functioning as a transaction source identifier. | Required | | \`processing\_mode\` | \_Body. String\_ | Order processing mode. Possible values are: \- \`automatic\`: to create and process the order in automatic mode. \- \`manual\`: to create the order and process it later. For more information, access the \[Integration model\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/integration-model) section. | Required | | \`expiration\_time\` | \_Body. String\_ | Allows you to set the payment \*\*expiration time\*\* using ISO 8601 duration format. The maximum time for the buyer to complete the PSE payment is 20 minutes (\`"PT20M"\`). After this period, the payment expires automatically and the transaction status changes to \`expired\`. | Optional | | \`transactions.payments.payment\_method.id\` | \_Body. String\_ | Payment method identifier. The value must be \`pse\`. | Required | | \`transactions.payments.payment\_method.type\` | \_Body. String\_ | Payment method type. The value must be \`bank\_transfer\`. | Required | | \`transactions.payments.payment\_method.financial\_institution\` | \_Body. String\_ | Code of the bank used for the transfer. Available banks must be obtained through the \[List banks\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/payment-integration/pse#bookmark\_list\_banks) step. | Required | | \`payer.email\` | \_Body. String\_ | Buyer's email address. | Required | | \`payer.entity\_type\` | \_Body. String\_ | Person type (natural or legal). Possible values are: \`individual\` or \`association\`. | Required | | \`payer.identification.type\` | \_Body. String\_ | Buyer's document type. Accepted values: \`RC\` (Registro Civil de Nacimiento), \`TI\` (Tarjeta de Identidad), \`CC\` (Cedula de Ciudadania), \`TE\` (Tarjeta de Extranjeria), \`CE\` (Cedula de Extranjeria), \`PAS\` (Pasaporte), \`NIT\` and \`DI\` (Documento de Identificación). | Required | | \`payer.identification.number\` | \_Body. String\_ | Buyer's identification number. | Required | | \`payer.address.zip\_code\` | \_Body. String\_ | Payer's address postal code. | Required | | \`payer.address.street\_name\` | \_Body. String\_ | Payer's address street name. | Required | | \`payer.address.street\_number\` | \_Body. String\_ | Payer's address number. If there is no number, send "S/N". | Required | | \`payer.address.neighborhood\` | \_Body. String\_ | Neighborhood where the payer's address is located. | Required | | \`payer.address.city\` | \_Body. String\_ | City where the payer's address is located. | Required | | \`payer.phone.area\_code\` | \_Body. String\_ | Buyer's phone area code. Must have 3 digits. | Required | | \`payer.phone.number\` | \_Body. String\_ | Buyer's phone number. Must have 1 to 5 digits and only accepts numeric characters. | Required | | \`additional\_info.payer.ip\_address\` | \_Body. String\_ | IP address of the buyer where the payment is generated. | Required | | \`config.online.callback\_url\` | \_Body. String\_ | URL to which the buyer will be redirected after making the payment on the bank's page. Must not be null or empty and must have a maximum of 512 characters. | Required | > SUCCESS\_MESSAGE > > To learn in detail about all parameters sent and returned in this request, consult our \[API Reference\](https://www.mercadopago.com.co/developers/en/reference/online-payments/checkout-api/create-order/post). Also, if you receive an error when sending the payment, consult our \[error list\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/payment-management/integration-errors) for more information. The response will return the \`redirect\_url\` parameter, which contains the URL with the instructions for the buyer to complete the payment. You must redirect them to that page, following the instructions in the \[Make the payment available\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/payment-integration/pse#bookmark\_make\_the\_payment\_available) step. Additionally, it will show the \`action\_required\` status with \`status\_detail=waiting\_transfer\` until the payment is made. \`\`\`json { "id": "ORDOMG01KNSWP75YHQJ9EKKB13QCFF25", "total\_amount": "5000", "total\_paid\_amount": "0", "status": "action\_required", "status\_detail": "waiting\_transfer", "config": { "online": { "callback\_url": "https://merchant.com/pse/return" } }, "transactions": { "payments": \[ { "payment\_method": { "id": "pse", "type": "bank\_transfer", "financial\_institution": "1051", "redirect\_url": "https://www.mercadopago.com.co/sandbox/payments/154019160992/bank\_transfer?caller\_id=2676136474&hash=fd05e480-3f06-4f41-90dc-b6910946e196" } } \] } } \`\`\` Among the returned parameters, we have those indicated in the table below. | Attribute | Type | Description | |---|---|---| | \`status\` | \_String\_ | Returns the transaction status. In this case, it will return \`action\_required\` to indicate the need for an action to complete the processing, that is, until the payment is made. | | \`status\_detail\` | \_String\_ | In cases of bank transfer, as is the case with PSE payments, the \`status\_detail\` obtained is \`waiting\_transfer\`, waiting for the user to complete the payment process at the bank. | | \`transactions.payments.payment\_method.redirect\_url\` | \_String\_ | URL to which the buyer must be redirected to complete the payment flow on the chosen bank's platform. See more information in \[Make the payment available\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-orders/payment-integration/pse#bookmark\_make\_the\_payment\_available). | > WARNING > > If you created the order in manual mode, remember that payment processing requires an additional step, the call to the endpoint :TagComponent{tag="API" text="Process order" href="/developers/en/reference/online-payments/checkout-api/process-order/post"}. ::: :::AccordionComponent{title="Make the payment available" pill="client-side"} After the payment is created, and for the client to be able to make the transfer, it is necessary to redirect them to the URL returned in the response to the order creation under the parameter \`redirect\_url\`. \`\`\`json { \[...\] "transactions": { "payments": \[ { "payment\_method": { "id": "pse", "type": "bank\_transfer", "financial\_institution": "1051", "redirect\_url": "https://www.mercadopago.com.co/sandbox/payments/154019160992/bank\_transfer?caller\_id=2676136474&hash=fd05e480-3f06-4f41-90dc-b6910946e196" } } \] } } \`\`\` To do this, you have two options: - You can automatically redirect the user. - You can provide that URL to the user through a clickable button, following the example below. \`\`\`html [Pay with PSE](https://www.mercadopago.com.co/payments/154019160992/bank%5Ftransfer?caller%5Fid=2676136474&hash=fd05e480-3f06-4f41-90dc-b6910946e196)\`\`\` ::: :::AccordionComponent{title="Cancel payment" pill="server-side"} If you wish, you can cancel a payment created, as long as it is pending or in process; that is, with \`status=action\_required\`. Additionally, we recommend canceling payments that were not made by the established due date to avoid billing and reconciliation issues. > WARNING > > If 30 days pass after the established due date for a payment and it has not been made, Mercado Pago will consider it expired. In these cases, it is not possible to perform a manual cancellation, and the payment status will change to canceled or expired. For more information, please consult the \[Refunds and cancellations\](https://www.mercadopago.com.co/developers/en/docs/checkout-api-payments/payment-management/refunds-cancellations) section. :::