Integrate payment processing
Payment processing with QR code is carried out through the creation of orders that include an associated payment transaction. When creating an order, the buyer can make the payment 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 cash register 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 payment to be made both through static and dynamic QR. The order is linked to the static QR code of the cash register, while a dynamic QR is also generated simultaneously. Once 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 consulting information and status updates of transactions.
To configure QR Code payment processing, it is necessary to identify the store and cash register to which the order will be associated. Remember that both the store and cash register must have been previously created.
Then, you can create the order. To do this, send a POST request to the endpoint /v1/orders APIAPI, including your test Access TokenPrivate key of the application created in Mercado Pago, used in the backend. You can access it through Your integrations > Application details > Tests > Test credentials. During integration, use the test Access Token and, upon completion, replace it with the production Access Token if it is your own integration, or with the Access Token obtained through OAuth in case of third-party integrations. For more information, access the documentation.Access test credentials. Additionally, make sure to include the external_pos_id of the cash register 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 payments, the only possible value is qr. | Required |
total_amount | string | Total value of the order. Represents the sum of transactions. Must not contain decimals. | Optional |
description | string | Description of the product or service. 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. Additionally, this value must be unique for each order, as it acts as the identifier of that order. | Required |
expiration_time | string | Allows you to specify the order's expiration date; that is, the maximum amount of time it can be active. The valid format is ISO 8601, a duration format. For example, "P3Y6M4DT12H30M5S" represents a duration of 3 years, 6 months, 4 days, 12 hours, 30 minutes, and 5 seconds. The minimum time that can be set is 30 seconds, and the maximum is 3600 hours. If not sent, the default value will be 15 minutes. | Opcional |
config.qr.external_pos_id | string | External identifier of the cash register, defined by the integrator during its creation. By including it, the order information is associated with the cash register 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 cash register. | Required |
mode | string | QR code mode associated with the order. Possible values are listed below and, if none is sent, the default value will be static. static: Static mode, in which the static QR code associated with the cash register defined in the external_pos_id field receives the order information. dynamic: Dynamic mode, in which 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 payment to be made using either mode, static or dynamic, since the order will be linked to the static QR code associated with the cash register (external_pos_id), and a QR will be generated dynamically in parallel. However, only one of the generated QRs can be paid by the customer. | Optional |
transactions.payments | array | The transactions node contains information about the transaction associated with the order. When the type is qr, payment transactions payments can be included, which in turn contain information about the payment order. Only one payment transaction can be sent per order. | Required |
transactions.payments.amount | string | Payment amount. Must 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 specifying the config.qr.mode field as static, the QR code that should be scanned by the customer is the one obtained in the response to the cash register creation request, as it is the one that will receive the information of the created order. If the request is successful, the response will return an order with status created.
See below an example of a response for a static QR code payment order creation request.
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": "{{USER_ID}}", "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": "{{APPLICATION_ID}}" }, "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" } ] } }
id and payment id (transactions.payments.id) returned upon creation. They are necessary for future operations and to validate notifications. Check Resources for more details about order and transaction status.The created order will be automatically linked to the cash register specified in the request, allowing the buyer to make payment at the physical point of sale. Additionally, the linking also facilitates reconciliation. After payment, the transaction will be processed in an integrated manner.
Canceling an order can only be done when its status is created. If the cancellation request is made with another status, the API will return an error informing about the conflict.
To cancel an order, send a POST to the endpoint Cancel order by IDAPI, including your test Access TokenPrivate key of the application created in Mercado Pago, used in the backend. You can access it through Your integrations > Application details > Tests > Test credentials. During integration, use the test Access Token and, upon completion, replace it with the production Access Token if it is your own integration, or with the Access Token obtained through OAuth in case of third-party integrations. For more information, access 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 --location --request PUT 'https://api.mercadopago.com/v1/orders/ORD01K371WBFDS4MD9JG0K8ZMECBE' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer {{ACCESS_TOKEN}}' \ --data-raw '{ "status": "canceled" }'
If the request is successful, the response will include the status field with the canceled value.
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": "{{USER_ID}}", "status": "canceled", "status_detail": "canceled", "currency": "CLP", "created_date": "2025-08-21T19:32:21.621Z", "last_updated_date": "2025-08-21T19:33:52.012Z", "integration_data": { "application_id": "{{APPLICATION_ID}}" }, "transactions": { "payments": [ { "id": "PAY01K371WBFDS4MD9JG0KCV6PRKQ", "amount": "50", "status": "canceled", "status_detail": "canceled_by_api" } ] }, "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" } ] } }
It is possible to refund an order created through our API. In this case, the refund will always be a total refund of the order value. To make a refund of an order via API, it must have status processed. If the status is different, the API will return an error message indicating the conflict.
To make a total refund of an order, send a POST to the endpoint Refund an orderAPI, including your test Access TokenPrivate key of the application created in Mercado Pago, used in the backend. You can access it through Your integrations > Application details > Tests > Test credentials. During integration, use the test Access Token and, upon completion, replace it with the production Access Token if it is your own integration, or with the Access Token obtained through OAuth in case of third-party integrations. For more information, access 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/ORD01JV391F8YM8EDEAG8CWZ0GM0N/refunds' \ --header 'Content-Type: application/json' \ --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 transactions.refunds node, which will contain the refund details, in addition to the id of the original payment and the id of the refund transaction.
json
{ "id": "ORD01JV391F8YM8EDEAG8CWZ0GM0N", "status": "processed", "status_detail": "accredited", "transactions": { "refunds": [ { "id": "REF01JW7YS4YHV543DJ6JGYZBX6A0", "transaction_id": "PAY01JVMKQQE6YW97CEQN3MJ666HD", "reference_id": "{{REFERENCE_ID}}", "amount": "50", "status": "processing" } ] } }
In the response to the refund request, a new transaction of type refund is created with status processing. To track 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.
It is possible to query the data of an order and its associated transactions, whether payments or refunds, including their status or values.
To perform the query, send a GET to the endpoint Get order by IDAPI including your test Access TokenPrivate key of the application created in Mercado Pago, used in the backend. You can access it through Your integrations > Application details > Tests > Test credentials. During integration, use the test Access Token and, upon completion, replace it with the production Access Token if it is your own integration, or with the Access Token obtained through OAuth in case of third-party integrations. For more information, access the documentation.Access test credentials. Additionally, 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/ORD01K371WBFDS4MD9JG0K8ZMECBE \ --header 'Authorization: Bearer {{ACCESS_TOKEN}}'
If the request is successful, the response will return all order information, including its status, payment status and/or refund status in real time.
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": "{{USER_ID}}", "status": "canceled", "status_detail": "canceled", "currency": "CLP", "created_date": "2025-08-21T19:32:21.621Z", "last_updated_date": "2025-08-21T19:33:52.012Z", "integration_data": { "application_id": "{{APPLICATION_ID}}" }, "transactions": { "payments": [ { "id": "PAY01K371WBFDS4MD9JG0K8ZMECBE", "amount": "50", "status": "canceled", "status_detail": "canceled_by_api" } ] }, "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" } ] } }
After integrating payment processing, you can configure notifications.