# MD for: https://www.mercadopago.com.uy/developers/es/docs/qr-code/payment-processing.md \# 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. :::::AccordionComponent{title="Create an order"} 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\](https://www.mercadopago.com.uy/developers/en/docs/qr-code/create-store-and-pos). Then, you can create the order. To do this, send a \*\*POST\*\* request to the endpoint :TagComponent{tag="API" text="/v1/orders API" href="/developers/en/reference/in-person-payments/qr-code/orders/create-order/post"}, including your :toolTipComponent\[test Access Token\]{link="/developers/en/docs/qr-code/create-application" linkText="Access test credentials" content="Private key of the application created in Mercado Pago, used in the backend. You can access it through \*Your integrations > Integration data > 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."}. 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.00, "description": "Smartphone", "external\_reference": "ext\_ref\_1234", "config": { "qr": { "external\_pos\_id": "STORE001POS001", "mode": "static" } }, "transactions": { "payments": \[ { "amount": 50.00 } \] }, "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 } \] } }' \`\`\` | 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. Can contain two decimals or none. Example: 50.00\. | 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\* | Specifies the order's validity period in ISO 8601 duration format (e.g., P3Y6M4DT12H30M5S). Minimum of 30 seconds and maximum of 3600 hours. Behavior varies by QR model. Dynamic QR defaults to 15 minutes and honors the value sent. Static QR defaults to 10 minutes and is capped at 10 minutes regardless of the value sent. Hybrid QR follows the same rules per type: the Dynamic QR honors the value sent, while the linked Static QR is always capped at 10 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. Can contain two decimals or none. Example: 50.00\. | Required | > NOTE > > For more details about the parameters that should be sent in this request, check our \[API Reference\](https://www.mercadopago.com.uy/developers/en/reference/in-person-payments/qr-code/orders/create-order/post). The response varies according to the QR model chosen for integration. Select below the option that corresponds to your case. ::::TabsComponent :::TabComponent{title="Static model"} 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. > NOTE > > During integration development, it is possible to scan the generated QR codes using the Mercado Pago app, accessing it with a buyer test account. For more information, check the documentation \[Test the integration\](https://www.mercadopago.com.uy/developers/en/docs/qr-code/test-integration). \`\`\`json { "id": "ORD01K371WBFDS4MD9JG0K8ZMECBE", "type": "qr", "processing\_mode": "automatic", "external\_reference": "ext\_ref\_1234", "description": "Smartphone", "total\_amount": "50.00", "expiration\_time": "PT16M", "country\_code": "URU", "user\_id": "{{USER\_ID}}", "status": "created", "status\_detail": "created", "currency": "UYU", "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.00", "status": "created", "status\_detail": "ready\_to\_process" } \] }, "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" } \] } } \`\`\` > WARNING > > Store the order \`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\](https://www.mercadopago.com.uy/developers/en/docs/qr-code/resources/status-order-transaction). 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. ::: :::TabComponent{title="Dynamic model"} When creating an order specifying the \`dynamic\` mode in the \`config.qr.mode\` field, the request response will include the additional \`type\_response.qr\_data\` field. This field contains a \*string\* in \[EMVCo\](https://www.emvco.com/emv-technologies/qr-codes/) format, which can be converted into a QR code to be printed or displayed on a screen or device. If the request is successful, the response will return an order with \`created\` status. > NOTE > > During integration development, it is possible to scan the generated QR codes using the Mercado Pago app, accessing it with a buyer test account. For more information, check the documentation \[Test the integration\](https://www.mercadopago.com.uy/developers/en/docs/qr-code/test-integration). See below a response example for a request to create an order for payments with \*\*dynamic QR code\*\*. \`\`\`json { "id": "ORD01K372G4J4FXZ9HGHZMJMGGPKE", "type": "qr", "processing\_mode": "automatic", "external\_reference": "ext\_ref\_1234", "description": "Smartphone", "total\_amount": "50.00", "expiration\_time": "PT16M", "country\_code": "URU", "user\_id": "{{USER\_ID}}", "status": "created", "status\_detail": "created", "currency": "UYU", "created\_date": "2025-08-21T19:43:10.13Z", "last\_updated\_date": "2025-08-21T19:43:10.13Z", "integration\_data": { "application\_id": "{{APPLICATION\_ID}}" }, "transactions": { "payments": \[ { "id": "PAY01K372G4J4FXZ9HGHZMKWSQS20", "amount": "50.00", "status": "created", "status\_detail": "ready\_to\_process" } \] }, "config": { "qr": { "external\_pos\_id": "STORE001POS001", "mode": "dynamic" } }, "type\_response": { "qr\_data": "00020101021226580014br.gov.bcb.qr01368ee55a9c-7db3-41e0-a8cd-fbff4d4765b5204000053039865802BR5925PABLO JOSE DE OLIVEIRA CA6009SAO PAULO61088051040062070503\*\*\*630442E4" }, "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" } \] } } \`\`\` > WARNING > > Store the order \`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\](https://www.mercadopago.com.uy/developers/en/docs/qr-code/resources/status-order-transaction). In this model, an exclusive QR code is generated for each created \`order\`, incorporating the specific transaction data. After payment, the transaction is processed in an integrated manner. ::: :::TabComponent{title="Hybrid model"} When creating an order by specifying the \`hybrid\` mode in the \`config.qr.mode\` field, the response to the request includes the additional \`type\_response.qr\_data\` field. Just like in the dynamic model, the value of this field contains a \*string\* in \[EMVCo\](https://www.emvco.com/emv-technologies/qr-codes/) format, which can be converted into a QR code for printing and customer payment. Additionally, the customer can also scan the QR code obtained in the response to the request for creating the checkout in order to make the payment, just as in the static model, since this is the code that will receive the information from the created order. This way, the payment can be made either through the \*\*static QR code at the checkout\*\* or through a \*\*dynamic QR code\*\* generated at the same time. The order is always linked to the static QR code, but the customer can choose to use either one. Once the payment is completed using one of them, the other is automatically disabled, preventing duplicate transactions. > NOTE > > During integration development, it is possible to scan the generated QR codes using the Mercado Pago app, accessing it with a buyer test account. For more information, check the documentation \[Test the integration\](https://www.mercadopago.com.uy/developers/en/docs/qr-code/test-integration). If the request is successful, the response will return an order with \`status created\`. See below for an example response to an order creation request for payments with a \*\*hybrid QR code model\*\*. \`\`\`json { "id": "ORD01K37A6R7EAD3BQQJZJD4Q5K0E", "type": "qr", "processing\_mode": "automatic", "external\_reference": "ext\_ref\_1234", "description": "Smartphone", "total\_amount": "50.00", "expiration\_time": "PT16M", "country\_code": "URU", "user\_id": "{{USER\_ID}}", "status": "created", "status\_detail": "created", "currency": "UYU", "created\_date": "2025-08-21T20:21:43.987Z", "last\_updated\_date": "2025-08-21T20:21:43.987Z", "integration\_data": { "application\_id": "{{APPLICATION\_ID}}" }, "transactions": { "payments": \[ { "id": "PAY01K37A6R7EAD3BQQJZK3PKA90", "amount": "50.00", "status": "created", "status\_detail": "ready\_to\_process" } \] }, "config": { "qr": { "external\_pos\_id": "STORE001POS001", "mode": "hybrid" } }, "type\_response": { "qr\_data": "00020101021226580014br.gov.bcb.qr01363f78b8c2-6f94-4c67-b593-4aad44e2ec51204000053039865802BR5925PABLO JOSE DE OLIVEIRA CA6009SAO PAULO61088051040062070503\*\*\*6304CAC0" }, "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" } \] } } \`\`\` > WARNING > > Store the order \`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\](https://www.mercadopago.com.uy/developers/en/docs/qr-code/resources/status-order-transaction). ::: ::::: :::AccordionComponent{title="Cancel order"} 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 :TagComponent{tag="API" text="/v1/orders/{order\_id}/cancel" href="/developers/en/reference/in-person-payments/qr-code/orders/cancel-order/post"}, including your :toolTipComponent\[test Access Token\]{link="/developers/en/docs/qr-code/create-application" linkText="Access test credentials" content="Private key of the application created in Mercado Pago, used in the backend. You can access it through \*Your integrations > Integration data > 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."}. 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.00", "expiration\_time": "PT16M", "country\_code": "URU", "user\_id": "{{USER\_ID}}", "status": "canceled", "status\_detail": "canceled", "currency": "UYU", "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.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" } \] } } \`\`\` ::: :::::AccordionComponent{title="Refund an order"} If needed, it is possible to refund an order created through our API. This endpoint allows you to make a \*\*total or partial\*\* refund of a payment transaction associated with the order. To request a total refund, you do not need to send a \`body\` in the request. For a partial refund, you must inform in the \`body\` the amount to be refunded and the transaction identifier. > WARNING > > An order can be refunded via API up to \*\*180 days after the payment is made\*\*. After this period, it will not be possible to make the refund. Choose the option that best suits your needs and follow the corresponding instructions. ::::TabsComponent :::TabComponent{title="Total refund"} To make a \*\*total\*\* refund of an order, send a \*\*POST\*\* to the endpoint :TagComponent{tag="API" text="/v1/orders/{order\_id}/refund" href="/developers/en/reference/in-person-payments/qr-code/orders/refund-order/post"} \*\*without sending a body\*\* in the request. Make sure to include your :toolTipComponent\[test Access Token\]{link="/developers/en/docs/qr-code/create-application" linkText="Access test credentials" content="Private key of the application created in Mercado Pago, used in the backend. You can access it through \*Your integrations > Integration data > 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."}. It is also necessary to inform the \`id\` of the order you want to refund, obtained in the response to its creation. \`\`\`curl curl -X POST \\ 'https://api.mercadopago.com/v1/orders/ORDER\_ID/refund' \\ -H 'Content-Type: application/json' \\ -H 'X-Idempotency-Key: 0d5020ed-1af6-469c-ae06-c3bec19954bb' \\ -H 'Authorization: Bearer ACCESS\_TOKEN' \`\`\` If the request is successful, the response will return \`status=refunded\` and a new node \`transactions.refunds\`, which will contain the details of the refund, along with the \`id\` of the original payment and the \`id\` of the refund transaction. \`\`\`json { "id": "ORD0000ABCD222233334444555566", "status": "refunded", "status\_detail": "refunded", "transactions": { "refunds": \[ { "id": "REF01J67CQQH5904WDBVZEM1234D", "transaction\_id": "PAY01J67CQQH5904WDBVZEM4JMEP3", "reference\_id": "12345678", "amount": "38.00", "status": "processed" } \] } } \`\`\` ::: :::TabComponent{title="Partial refund"} To make a \*\*partial\*\* refund of an order, send a \*\*POST\*\* to the endpoint :TagComponent{tag="API" text="/v1/orders/{order\_id}/refund" href="/developers/en/reference/in-person-payments/qr-code/orders/refund-order/post"}, including in the request \*\*body\*\* the array \`transactions\` with the payment transaction identifier (\`id\`) and the amount to be refunded (\`amount\`). Make sure to include your :toolTipComponent\[test Access Token\]{link="/developers/en/docs/qr-code/create-application" linkText="Access test credentials" content="Private key of the application created in Mercado Pago, used in the backend. You can access it through \*Your integrations > Integration data > 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."}. It is also necessary to inform the \`id\` of the order you want to refund, obtained in the response to its creation. \`\`\`curl curl -X POST \\ 'https://api.mercadopago.com/v1/orders/ORDER\_ID/refund' \\ -H 'Content-Type: application/json' \\ -H 'X-Idempotency-Key: 0d5020ed-1af6-469c-ae06-c3bec19954bb' \\ -H 'Authorization: Bearer ACCESS\_TOKEN' \\ -d '{ "transactions": \[ { "id": "TRANSACTION\_ID", "amount": "24.90" } \] }' \`\`\` | Attribute | Type | Description | Requirement | |-|-|-|-| | \`order\_id\` | \_String\_ | ID of the order containing the associated payment transaction to be refunded. This value is returned in the response to the \[Create an order\](https://www.mercadopago.com.uy/developers/en/docs/qr-code/payment-processing#:\~:text=Create%20an%20order-,To,-configure%20QR%20Code) request. | Required. | | \`transactions\` | \_Array\_ | Contains information about the transaction associated with the order to be refunded. | Required for partial refunds. | | \`transactions.id\` | \_String\_ | Identifier of the payment transaction created in the request, obtained in the response to the creation of the order (\`transactions.payments.id\`). | Required for partial refunds. | | \`transactions.amount\` | \_String\_ | Amount to be refunded. You can perform multiple partial refunds, as long as the sum does not exceed the total transaction amount. | Required for partial refunds. | If the request was successful, the response will show \`status=processed\` (if there is still balance in the order) and \`status\_detail=partially\_refunded\`, along with the \`transactions.refunds\` node containing the partial refund details. \`\`\`json { "id": "ORD01J49MMW3SSBK5PSV3DFR32959", "status": "processed", "status\_detail": "partially\_refunded", "transactions": { "refunds": \[ { "id": "REF01J49MMW3SSBK5PSV3DFR32959", "transaction\_id": "PAY01JEVQM06WDW16MAQ8B5SC0MSC", "reference\_id": "12345678", "amount": "24.90", "status": "processed" } \] } } \`\`\` ::: :::: ::::: :::AccordionComponent{title="Query order data"} 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 :TagComponent{tag="API" text="/v1/orders/{order\_id}" href="/developers/en/reference/in-person-payments/qr-code/orders/get-order/get"} including your :toolTipComponent\[test Access Token\]{link="/developers/en/docs/qr-code/create-application" linkText="Access test credentials" content="Private key of the application created in Mercado Pago, used in the backend. You can access it through \*Your integrations > Integration data > 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."}. 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/ORDER\_ID' \\ --header 'Authorization: Bearer {{ACCESS\_TOKEN}}' \`\`\` > WARNING > > This request is only available for orders created less than 3 months ago. To access information from older orders, it is necessary to contact our customer service. 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.00", "expiration\_time": "PT16M", "country\_code": "URU", "user\_id": "{{USER\_ID}}", "status": "canceled", "status\_detail": "canceled", "currency": "UYU", "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.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" } \] } } \`\`\` ::: After integrating payment processing, you can \[configure notifications\](https://www.mercadopago.com.uy/developers/en/docs/qr-code/notifications).