Integrate transaction processing
Transaction processing with QR code is performed through the creation of orders that include payment transactions, either with additional cash withdrawals or withdrawals without an associated purchase. When creating an order, the customer will be able to perform transactions in person by scanning the code.
There are three QR Code models available for integration, defined at the time of order creation:
- Static model: In this model, a single QR code associated with the previously created POS receives the information from each generated order.
- Dynamic model: An exclusive and single-payment QR code is generated for each transaction, containing the specific data of the created order.
- Hybrid model: Allows the payment to be made both through the static QR and the dynamic one. The order is linked to the static QR code of the POS, while a dynamic QR is also generated simultaneously. Once the payment is made with either code, the other will be automatically disabled for use.
This integration allows you to create, process and cancel orders, in addition to making refunds and querying information and status updates for cash-out and extra-cash transactions.
To configure cash withdrawal transaction processing with QR Code, it is necessary to identify the store and POS to which the order will be associated. Remember that both the store and the POS must have been previously created.
Next, you can create the order for cash-out. To do this, send a POST request to the endpoint /v1/ordersAPI, including your Test Access TokenPrivate key of the application created in Mercado Pago, which is used in the backend. You can access it through Your integrations > Application details > Test > Test credentials. During integration, use the Test Access Token and, when finished, replace it with the Production Access Token if it is your own integration, or with the Access Token obtained through OAuth in the case of third-party integrations. For more information, go to the documentation.Access test credentials. Also, make sure to include the external_pos_id of the POS to which you want to assign the order, obtained in the previous step.
curl
curl --location --request POST 'https://api.mercadopago.com/v1/orders' \ --header 'X-Idempotency-Key: 02ff8cd0-c4e9-4fe8-a977-6c3c2bc6336c' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer {{ACCESS_TOKEN}}' \ --data '{ "type": "qr", "transactions": { "cash_outs": [ { "amount": "100" } ] }, "external_reference": "ExtRef_123456", "config": { "qr": { "external_pos_id": "POSDOC", "mode": "static" } } }'
| Parameter | Type | Description | 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 (Universally Unique Identifier) V4 or a random string. | Required |
type | string | Type of order, associated with the Mercado Pago solution for which it was created. For Mercado Pago QR Code transactions, the only possible value is qr, which is the value associated with creating orders for Mercado Pago QR Code transactions. | Required |
external_reference | string | It is the external reference of the order, assigned at the time of creation. The maximum allowed limit is 64 characters and the allowed ones are: uppercase and lowercase letters, numbers and the hyphen (-) and underscore (_) symbols. The field cannot be used to send PII data. | Required |
config.qr.external_pos_id | string | External identifier of the POS, defined by the integrator during its creation. By including it, the order information is associated with the POS and store previously created within the Mercado Pago system. Important: The external_pos_id field must have the same value defined as external_id when creating your POS. | Required |
config.qr.mode | string | QR code mode associated with the order. The possible values are listed below and, if none is sent, the default value will be static. static: Static mode, where the static QR code associated with the POS defined in the external_pos_id field receives the order information. dynamic: Dynamic mode, where a unique QR code is generated for each transaction, including the specific data of the created order. This code must be built from the information returned in the qr_data field of the response, whose value is unique for each order. hybrid: Allows the transaction to be performed using either mode, static or dynamic, since the order will be linked to the static QR code associated with the POS (external_pos_id), and a QR will be generated dynamically in parallel. However, only one of the generated QRs can be used by the customer. | Optional |
transactions.cash_outs | array | Array with information about the cash withdrawal transactions associated with the order. | Required |
transactions.cash_outs.amount | string | Withdrawal amount. Should not contain decimals. | Required |
The response varies according to the QR model chosen for integration. Select below the option that corresponds to your case.
When creating an order by specifying the config.qr.mode field as static, the QR that should be scanned by the customer is the one obtained in the response to the POS creation request, since it is the one that receives the information from the created order. If the request is successful, the response will return an order with created status.
Check below an example response for a request to create an order for cash withdrawal (cash-out) in the static model.
json
{ "id": "ORD01JYHP5MGKC5PMPZBHSTMLNDQX", "type": "qr", "processing_mode": "automatic", "external_reference": "ExtRef_123456", "total_amount": "100", "expiration_time": "PT15M", "country_code": "CHL", "user_id": "1898180000", "status": "created", "status_detail": "created", "currency": "CLP", "created_date": "2025-06-24T19:20:52.429Z", "last_updated_date": "2025-06-24T19:20:52.429Z", "integration_data": { "application_id": "8950412930770000" }, "transactions": { "cash_outs": [ { "id": "CAS01JYHP5MGKC5PMPZBHSW42LLPA", "amount": "100", "status": "created", "status_detail": "ready_to_process" } ] }, "config": { "qr": { "external_pos_id": "POSDOC", "mode": "static" } } }
The created order will be automatically linked to the POS specified in the request, allowing the customer to perform the transaction at the physical point of sale. Additionally, the linking also facilitates reconciliation. After the transaction, it will be processed in an integrated way.
id returned in the creation. It is necessary for future operations and to validate notifications. Check Resources for more details about the order and transaction status.To configure payment processing with QR Code, it is necessary to identify the store and POS to which the order will be associated. Remember that both the store and the POS must have been previously created.
Next, you can create the order for payment. To do this, send a POST request to the endpoint /v1/ordersAPI, including your Test Access TokenPrivate key of the application created in Mercado Pago, which is used in the backend. You can access it through Your integrations > Application details > Test > Test credentials. During integration, use the Test Access Token and, when finished, replace it with the Production Access Token if it is your own integration, or with the Access Token obtained through OAuth in the case of third-party integrations. For more information, go to the documentation.Access test credentials. Also, make sure to include the external_pos_id of the POS to which you want to assign the order, obtained in the previous step.
curl
curl -X POST \ 'https://api.mercadopago.com/v1/orders'\ -H 'Content-Type: application/json' \ -H 'X-Idempotency-Key: 0d5020ed-1af6-469c-ae06-c3bec19954bb' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -d '{ "type": "qr", "total_amount": 50, "description": "Smartphone", "external_reference": "ext_ref_1234", "config": { "qr": { "external_pos_id": "STORE001POS001", "mode": "static" } }, "transactions": { "payments": [ { "amount": 50 } ] }, "items": [ { "title": "Smartphone", "unit_price": 50, "unit_measure": "kg", "external_code": "777489134", "quantity": 1, "external_categories": [ { "id": "device" } ] } ], "discounts": { "payment_methods": [ { "type": "account_money", "new_total_amount": 47 } ] } }'
| Parameter | Type | Description | 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 (Universally Unique Identifier) V4 or a random string. | Required |
type | string | Type of order, associated with the Mercado Pago solution for which it was created. For Mercado Pago QR Code transactions, the only possible value is qr, which is the value associated with creating orders for Mercado Pago QR Code transactions. | Required |
total_amount | string | Total order amount. Represents the sum of transactions. Should not contain decimals. | Optional |
description | string | Product or service description. The maximum limit is 150 characters and cannot be used to send PII data. | Optional |
external_reference | string | It is the external reference of the order, assigned at the time of creation. The maximum allowed limit is 64 characters and the allowed ones are: uppercase and lowercase letters, numbers and the hyphen (-) and underscore (_) symbols. The field cannot be used to send PII data. | Required |
config.qr.external_pos_id | string | External identifier of the POS, defined by the integrator during its creation. By including it, the order information is associated with the POS and store previously created within the Mercado Pago system. Important: The external_pos_id field must have the same value defined as external_id when creating your POS. | Required |
config.qr.mode | string | QR code mode associated with the order. The possible values are listed below and, if none is sent, the default value will be static. static: Static mode, where the static QR code associated with the POS defined in the external_pos_id field receives the order information. dynamic: Dynamic mode, where a unique QR code is generated for each transaction, including the specific data of the created order. This code must be built from the information returned in the qr_data field of the response, whose value is unique for each order. hybrid: Allows the transaction to be performed using either mode, static or dynamic, since the order will be linked to the static QR code associated with the POS (external_pos_id), and a QR will be generated dynamically in parallel. However, only one of the generated QRs can be used by the customer. | Optional |
transactions.payments | array | Array with information about the payment transactions associated with the order. | Required |
transactions.payments.amount | string | Payment amount. Should not contain decimals. | Required |
The response varies according to the QR model chosen for integration. Select below the option that corresponds to your case.
When creating an order by specifying the config.qr.mode field as static, the QR that should be scanned by the customer is the one obtained in the response to the POS creation request, since it is the one that receives the information from the created order. If the request is successful, the response will return an order with created status.
Check below an example response for a request to create an order for payments in the static model.
json
{ "id": "ORD01K371WBFDS4MD9JG0K8ZMECBE", "type": "qr", "processing_mode": "automatic", "external_reference": "ext_ref_1234", "description": "Smartphone", "total_amount": "50", "expiration_time": "PT16M", "country_code": "CHL", "user_id": "240424235", "status": "created", "status_detail": "created", "currency": "CLP", "created_date": "2025-08-21T19:32:21.621Z", "last_updated_date": "2025-08-21T19:32:21.621Z", "integration_data": { "application_id": "147632494144930" }, "transactions": { "payments": [ { "id": "PAY01K371WBFDS4MD9JG0KCV6PRKQ", "amount": "50", "status": "created", "status_detail": "ready_to_process" } ] }, "config": { "qr": { "external_pos_id": "STORE001POS001", "mode": "static" } }, "items": [ { "title": "Smartphone", "unit_price": "50", "unit_measure": "kg", "external_code": "777489134", "quantity": 1, "external_categories": [ { "id": "device" } ] } ], "discounts": { "payment_methods": [ { "type": "account_money", "new_total_amount": "47" } ] } }
The created order will be automatically linked to the POS specified in the request, allowing the buyer to make the payment at the physical point of sale. Additionally, the linking also facilitates reconciliation. After the payment, the transaction will be processed in an integrated way.
id and payment id (transactions.payments.id) returned in the creation. They are necessary for future operations and to validate notifications. Check Resources for more details about the order and transaction status.To configure combined transaction processing (payment + withdrawal) with QR Code, it is necessary to identify the store and POS to which the order will be associated. Remember that both the store and the POS must have been previously created.
Next, you can create the extra-cash order. To do this, send a POST request to the endpoint /v1/ordersAPI, including your Test Access TokenPrivate key of the application created in Mercado Pago, which is used in the backend. You can access it through Your integrations > Application details > Test > Test credentials. During integration, use the Test Access Token and, when finished, replace it with the Production Access Token if it is your own integration, or with the Access Token obtained through OAuth in the case of third-party integrations. For more information, go to the documentation.Access test credentials. Also, make sure to include the external_pos_id of the POS to which you want to assign the order, obtained in the previous step.
discounts.payment_methods.new_total_amount field must be the sum of the cash_out amount plus the payment amount with the discount applied, and cannot be less than or equal to the cash_out amount.To create an extra-cash order, you must include both transactions (cash_outs and payments) in the request, according to the following example:
curl
curl --location --request POST 'https://api.mercadopago.com/v1/orders' \ --header 'X-Idempotency-Key: 02ff8cd0-c4e9-4fe8-a977-6c3c2bc6336c' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer {{ACCESS_TOKEN}}' \ --data '{ "type": "qr", "total_amount": "140.00", "transactions": { "cash_outs": [ { "amount": "110.00" } ], "payments": [ { "amount": "30.00" } ] }, "external_reference": "ExtRef_123456", "config": { "qr": { "external_pos_id": "POSDOC", "mode": "static" } }, "description": "Description test", "items": [ { "title": "Item test", "unit_price": "30.00", "quantity": 1, "unit_measure": "unit", "external_code": "1234567" } ] }'
| Parameter | Type | Description | 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 (Universally Unique Identifier) V4 or a random string. | Required |
type | string | Type of order, associated with the Mercado Pago solution for which it was created. For Mercado Pago QR Code transactions, the only possible value is qr, which is the value associated with creating orders for Mercado Pago QR Code transactions. | Required |
total_amount | string | Total order amount. Represents the sum of transactions, therefore, must be the sum of the cash_out amount plus the payment amount. Should not contain decimals. | Required |
external_reference | string | It is the external reference of the order, assigned at the time of creation. The maximum allowed limit is 64 characters and the allowed ones are: uppercase and lowercase letters, numbers and the hyphen (-) and underscore (_) symbols. The field cannot be used to send PII data. | Required |
config.qr.external_pos_id | string | External identifier of the POS, defined by the integrator during its creation. By including it, the order information is associated with the POS and store previously created within the Mercado Pago system. Important: The external_pos_id field must have the same value defined as external_id when creating your POS. | Required |
config.qr.mode | string | QR code mode associated with the order. The possible values are listed below and, if none is sent, the default value will be static. static: Static mode, where the static QR code associated with the POS defined in the external_pos_id field receives the order information. dynamic: Dynamic mode, where a unique QR code is generated for each transaction, including the specific data of the created order. This code must be built from the information returned in the qr_data field of the response, whose value is unique for each order. hybrid: Allows the transaction to be performed using either mode, static or dynamic, since the order will be linked to the static QR code associated with the POS (external_pos_id), and a QR will be generated dynamically in parallel. However, only one of the generated QRs can be used by the customer. | Optional |
transactions.cash_outs | array | Array with information about the cash withdrawal transactions associated with the order. | Required |
transactions.cash_outs.amount | string | Withdrawal amount. Should not contain decimals. | Required |
transactions.payments | array | Array with information about the payment transactions associated with the order. | Required |
transactions.payments.amount | string | Payment amount. Should not contain decimals. | Required |
description | string | Product or service description. The maximum limit is 150 characters and cannot be used to send PII data. | Optional |
items | array | Array with information about the order items. | Optional |
Check below an example response for a request to create an extra-cash order (combining payment and withdrawal).
json
{ "id": "ORD01JYHP5MGKC5PMPZBHSTMLNDQX", "type": "qr", "processing_mode": "automatic", "external_reference": "ExtRef_123456", "total_amount": "140.00", "expiration_time": "PT15M", "country_code": "URY", "user_id": "1898180000", "status": "created", "status_detail": "created", "created_date": "2025-06-24T19:20:52.429Z", "last_updated_date": "2025-06-24T19:20:52.429Z", "integration_data": { "application_id": "8950412930770000" }, "transactions": { "cash_outs": [ { "id": "CAS01JYHP5MGKC5PMPZBHSW42LLPA", "amount": "110.00", "status": "created", "status_detail": "ready_to_process" } ], "payments": [ { "id": "PAY01JYHP5MGKC5PMPZBHSW42LLPA", "amount": "30.00", "status": "created", "status_detail": "ready_to_process" } ] }, "config": { "qr": { "external_pos_id": "POSDOC", "mode": "static" } }, "description": "Description test", "items": [ { "title": "Item test", "unit_price": "30.00", "quantity": 1, "unit_measure": "unit", "external_code": "1234567" } ] }
Store the order id returned in the creation. It is necessary for future operations and to validate notifications. Check Resources for more details about the order and transaction status.
Order cancellation can only be performed when its status is created. If the cancellation request is made with another status, the API will return an error informing the conflict.
To cancel an order, send a POST to the endpoint /v1/orders/{order_id}/cancelAPI, including your Test Access TokenPrivate key of the application created in Mercado Pago, which is used in the backend. You can access it through Your integrations > Application details > Test > Test credentials. During integration, use the Test Access Token and, when finished, replace it with the Production Access Token if it is your own integration, or with the Access Token obtained through OAuth in the case of third-party integrations. For more information, go to the documentation.Access test credentials. It is also necessary to send the id of the order you want to cancel, obtained in the response to its creation.
curl
curl -X POST \ 'https://api.mercadopago.com/v1/orders/ORD01K371WBFDS4MD9JG0K8ZMECBE/cancel'\ -H 'Content-Type: application/json' \ -H 'X-Idempotency-Key: 0d5020ed-1af6-469c-ae06-c3bec19954bb' \ -H 'Authorization: Bearer TEST-751********69209-05********101e5ea9********17b9d2fb********0424235' \
If the request is successful, the response will include the status field with the value canceled.
json
{ "id": "ORD01K371WBFDS4MD9JG0K8ZMECBE", "type": "qr", "processing_mode": "automatic", "external_reference": "ext_ref_1234", "description": "Smartphone", "total_amount": "50.00", "expiration_time": "PT16M", "country_code": "BRA", "user_id": "240424235", "status": "canceled", "status_detail": "canceled", "currency": "BRL", "created_date": "2025-08-21T19:32:21.621Z", "last_updated_date": "2025-08-21T19:33:52.012Z", "integration_data": { "application_id": "147632494144930", "integrator_id": "dev_1234", "platform_id": "dev_1234567890" }, "transactions": { "payments": [ { "id": "PAY01K371WBFDS4MD9JG0KCV6PRKQ", "amount": "50.00", "status": "canceled", "status_detail": "canceled_by_api" } ] }, "config": { "qr": { "external_pos_id": "STORE001POS001", "mode": "static" } }, "items": [ { "title": "Smartphone", "unit_price": "50.00", "unit_measure": "kg", "external_code": "777489134", "quantity": 1, "external_categories": [ { "id": "device" } ] } ], "discounts": { "payment_methods": [ { "type": "account_money", "new_total_amount": "47.28" } ] } }
It is possible to refund an order created through our API. In this case, the refund will always be a total return of the order amount. To make a refund of an order via API, it must have the status processed. If the status is different, the API will return an error message indicating the conflict.
To make a full refund of an order, send a POST to the endpoint /v1/orders/{order_id}/refundAPI, including your Test Access TokenPrivate key of the application created in Mercado Pago, which is used in the backend. You can access it through Your integrations > Application details > Test > Test credentials. During integration, use the Test Access Token and, when finished, replace it with the Production Access Token if it is your own integration, or with the Access Token obtained through OAuth in the case of third-party integrations. For more information, go to the documentation.Access test credentials. It is also necessary to inform the id of the order you want to refund, obtained in the response to its creation.
curl
curl --location --request POST 'https://api.mercadopago.com/v1/orders/ORDER_ID/refund' \ --header 'X-Idempotency-Key: 91b59be9-27b8-449f-a6bd-32dca8b424cd' \ --header 'Authorization: Bearer {{ACCESS_TOKEN}}'
If the request is successful, the response will bring the status accredited and a new node transactions.refunds, which will contain the refund details, in addition to the original payment id and the refund transaction id.
json
{ "id": "ORD01JYHREYXTR31HRB5S9Q9G8QS7", "status": "processed", "status_detail": "accredited", "transactions": { "refunds": [ { "id": "REF01JYHRNEK69845P0E6VBXKXAKK", "transaction_id": "CAS01JYHREYXTR31HRB5S9QE68G0N", "reference_id": "116228240060", "amount": "100.00", "status": "processing" } ] } }
In the refund request response, a new transaction of type refund with status processing is created. To follow the final status of the refund, wait for the update notification or check the order data to verify its status. When the refund is confirmed, the status will be changed to refunded.
After the refund is confirmed, the status of the order can be checked through a GET request, as shown in the example below:
json
{ "id": "ORD01JYHREYXTR31HRB5S9Q9G8QS7", "type": "qr", "processing_mode": "automatic", "external_reference": "ExtRef_123456", "total_amount": "100.00", "expiration_time": "PT15M", "country_code": "URY", "user_id": "1898180608", "status": "refunded", "status_detail": "refunded", "created_date": "2025-06-24T20:00:55.137Z", "last_updated_date": "2025-06-24T20:04:27.622Z", "integration_data": { "application_id": "8950412930771472" }, "transactions": { "cash_outs": [ { "id": "CAS01JYHREYXTR31HRB5S9QE68G0N", "reference_id": "116228240060", "amount": "100.00", "status": "refunded", "status_detail": "refunded" } ], "refunds": [ { "id": "REF01JYHRNEK69845P0E6VBXKXAKK", "transaction_id": "CAS01JYHREYXTR31HRB5S9QE68G0N", "reference_id": "116228240060", "amount": "100.00", "status": "processed" } ] }, "config": { "qr": { "external_pos_id": "SUC001POS001", "mode": "static" } } }
The transaction_id field in the refund identifies which transaction (payments or cash_outs) is being refunded. If it identifies a payment transaction, the value will start with the PAY prefix, and if it identifies a withdrawal transaction, the value will start with the CAS prefix.
It is possible to query the data of an order and its associated transactions, whether payments, cash withdrawals or refunds, including their status or values.
To make the query, send a GET to the endpoint /v1/orders/{order_id}API including your Test Access TokenPrivate key of the application created in Mercado Pago, which is used in the backend. You can access it through Your integrations > Application details > Test > Test credentials. During integration, use the Test Access Token and, when finished, replace it with the Production Access Token if it is your own integration, or with the Access Token obtained through OAuth in the case of third-party integrations. For more information, go to the documentation.Access test credentials. Also, make sure to include the order id obtained in the response to its creation.
curl
curl --location --request GET 'https://api.mercadopago.com/v1/orders/ORDER_ID' \ --header 'Authorization: Bearer {{ACCESS_TOKEN}}'
If the request is successful, the response will return all the order information, including its status, payment status and/or refund status in real time.
json
{ "id": "ORD01JYHP5MGKC5PMPZBHSTMLNDQX", "type": "qr", "processing_mode": "automatic", "external_reference": "ExtRef_123456", "total_amount": "100.00", "expiration_time": "PT15M", "country_code": "CHL", "user_id": "1898180608", "status": "created", "status_detail": "created", "created_date": "2025-06-24T19:46:02.381Z", "last_updated_date": "2025-06-24T19:46:02.381Z", "integration_data": { "application_id": "8950412930771472" }, "transactions": { "cash_outs": [ { "id": "CAS01JYHQKQ2D39PCBEK3K36G0SQD", "amount": "100.00", "status": "created", "status_detail": "ready_to_process" } ] }, "config": { "qr": { "external_pos_id": "SUC001POS001", "mode": "static" } } }
After integrating transaction processing, you will be able to configure notifications.