# MD for: https://www.mercadopago.com.uy/developers/en/docs/checkout-api-orders/payment-management/integrate-3ds.md \# 3DS 2.0 The 3DS 2.0 authentication (\_3-D Secure Authentication 2.0\_) validates the cardholder's identity during purchase, increasing transaction security and approval rate. This authentication reduces fraud risk for the buyer and prevents chargeback losses for the seller. ## Integrate 3DS 3DS authentication can be performed through two flows: \*\*with \_Challenge\_\*\* or \*\*without \_Challenge\_\*\*. The \_Challenge\_ is an additional verification step that the buyer must complete to confirm their identity. The decision to require the \_Challenge\_ or not depends on the card issuer and the transaction's risk profile. For \*\*low-risk transactions\*\*, the information submitted at checkout is sufficient and the \_Challenge\_ is \*\*not required\*\*. For \*\*high-risk transactions\*\*, the \_Challenge\_ is required to \*\*verify the buyer's identity\*\*, increasing the approval rate. To integrate 3DS 2.0 in Checkout API with the Orders API, follow the steps below. > WARNING > > Before proceeding, verify that the SDK JS is integrated into your application's frontend, as indicated in the \[Configure development environment\](https://www.mercadopago.com.uy/developers/en/docs/checkout-api-orders/development-environment) step. This integration allows you to securely collect card data and generate the encrypted token used when creating the order with 3DS. :::AccordionComponent{title="Configure 3DS authentication" pill="1"} The 3DS configuration is performed through the \`config.online.transaction\_security\` node when creating the order. To create an order with 3DS, send a \*\*POST\*\* to the endpoint :TagComponent{tag="API" text="/v1/orders" href="/developers/en/reference/online-payments/checkout-api/create-order/post"} including your :toolTipComponent\[Test Access Token\]{content="Private test key of the application created in Mercado Pago and used in the \_backend\_. You can access it through \*Your integrations > Integration data > Tests > Test credentials\*."}. The request must contain the required parameters listed below. * [curl ](#editor%5F1) curl ``` curl --request POST \ --url https://api.mercadopago.com/v1/orders \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --header 'X-Idempotency-Key: ' \ --data '{ "type": "online", "external_reference": "3ds_test", "processing_mode": "automatic", "capture_mode": "automatic", "total_amount": "150.00", "config": { "online": { "transaction_security": { "validation": "on_fraud_risk", "liability_shift": "required" } } }, "payer": { "email": "test@testuser.com" }, "transactions": { "payments": [ { "amount": "150.00", "payment_method": { "id": "master", "type": "credit_card", "token": "{{CARD_TOKEN}}", "installments": 1 } } ] } }' ``` Copiar | Attribute | Type | Description | Possible values | Requirement | |---|---|---|---|---| | \`capture\_mode\` | String | Defines the payment capture mode. | \`automatic\_async\`: automatic asynchronous capture. \`manual\`: manual capture. | Optional | | \`config.online.transaction\_security.validation\` | String | Defines when the 3DS flow should be executed. | \`on\_fraud\_risk\`: 3DS is required according to transaction risk. We recommend using this value to balance security and transaction approval. \`never\`: the 3DS flow and \_Challenge\_ are never executed (this is the default value if the field is not sent). | Required for 3DS integrations. | | \`config.online.transaction\_security.liability\_shift\` | String | Defines financial responsibility in case of \_chargeback\_. | \`required\`: the financial responsibility in case of \_chargeback\_ belongs to the card network. This is the only accepted value for 3DS. | Required for 3DS integrations. \*\*Must not be sent\*\* when \`validation\` is \`never\`. | > NOTE > > To learn in detail all the parameters sent and returned in this request, consult our \[API Reference\](https://www.mercadopago.com.uy/developers/en/reference/online-payments/checkout-api/create-order/post). ::: :::AccordionComponent{title="Process response and display Challenge" pill="2"} After creating the order, the response will indicate whether the \_Challenge\_ is required. If it is \*\*not required\*\*, the \`status\` field will have the value \`processed\`, allowing you to proceed normally with the application flow. If the \_Challenge\_ \*\*is required\*\*, the order will be returned with \`status: action\_required\`, \`status\_detail: pending\_challenge\`, and the \_Challenge\_ URL will be available in the \`payment\_method.transaction\_security.url\` field, as shown in the example below: * [json ](#editor%5F2) json ``` { "id": "ORDTST01KBD0NXX289XWW91Q9NNJ26V3", "type": "online", "processing_mode": "automatic", "external_reference": "ext_ref_3ds", "total_amount": "150.00", "total_paid_amount": "150.00", "country_code": "ARG", "user_id": "791690672", "status": "action_required", "status_detail": "pending_challenge", "capture_mode": "automatic", "currency": "ARS", "created_date": "2025-12-01T13:12:23.202Z", "last_updated_date": "2025-12-01T13:12:24.943Z", "integration_data": { "application_id": "8275829243271683" }, "config": { "online": { "transaction_security": { "validation": "on_fraud_risk", "liability_shift": "required" } } } "transactions": { "payments": [ { "id": "PAY01KBD0NXX289XWW91Q9P1BF71Q", "amount": "150.00", "paid_amount": "150.00", "reference_id": "0007aoefzk", "status": "action_required", "status_detail": "pending_challenge", "payment_method": { "id": "master", "type": "credit_card", "token": "adac6b95f1d22c51890499d1707f0f0a", "installments": 1, "transaction_security": { "url": "https://www.mercadopago.com.ar/auth/card/validation/pages/remedies/019ada0a-fe1f-7a82-ba1a-1ccb4e0232e7?display_mode=self_hosted&guest_token=0661345a-e0e1-4c09-aff9-b7929ca9a24a", "validation": "on_fraud_risk", "liability_shift": "required" } } } ] } } ``` Copiar To display the \_Challenge\_, create an iframe using the URL returned in \`transactions.payments\[i\].payment\_method.transaction\_security.url\`. This \_iframe\_ should be embedded in the checkout page, allowing the buyer to authenticate without leaving the flow. When the \_Challenge\_ is initiated, at the moment the URL is created, the buyer has \*\*40 minutes\*\* to complete it. If it is not completed within this period, the bank will decline the transaction and Mercado Pago will consider the payment expired. If less time is needed, it is possible to cancel the transaction before the default timeout. The status update is not immediate and may take a few moments. Check the next step for more details on how to verify the status of each transaction. ::: :::AccordionComponent{title="Verify transaction status" pill="3"} A transaction with 3DS can have different statuses depending on the type of authentication performed, with or without \_Challenge\_. For payments \*\*without \_Challenge\_\*\*, the transaction status will be directly \`processed\` or \`failed\`. For payments \*\*with \_Challenge\_\*\*, the transaction returns \`action\_required\` and \`status\_detail: pending\_challenge\`, initiating the authentication process with the bank. The final status will only be displayed after the \_Challenge\_ is completed. To verify the transaction result after the \_Challenge\_, you can \[configure Webhook notifications\](https://www.mercadopago.com.uy/developers/en/docs/checkout-api-orders/notifications) to receive automatic alerts and redirect the buyer to a confirmation screen. Another option, which \*\*we recommend\*\*, is to handle an \_iframe\_ event by implementing a JavaScript \_listener\_ to detect when the \_Challenge\_ has been completed and check the order status. > WARNING > > The \_iframe\_ event only indicates that the \_Challenge\_ has been completed, but \*\*does not guarantee that the payment has reached a final status\*\*. Verify via webhook or check the order through the endpoint :TagComponent{tag="API" text="/v1/orders/{id}" href="/developers/en/reference/online-payments/checkout-api/get-order/get"} to verify the updated status. To handle the \_iframe\_ event, follow the steps below. 1\. Implement the \_listener\_ to detect when the buyer has completed the \_Challenge\_: * [javascript ](#editor%5F3) javascript ``` window.addEventListener("message", (e) => { if (e.data.status === "COMPLETE") { // Challenge completed. Redirect to confirmation page window.location.href = "confirmation.html"; } }); ``` Copiar 2\. Use the code below to check the order's updated status and display it on the confirmation page: * [javascript ](#editor%5F4) javascript ``` document.addEventListener("DOMContentLoaded", async function (e) { await checkOrderStatus(); }); async function checkOrderStatus() { const orderId = localStorage.getItem("orderId"); try { const response = await fetch("/get_order/" + orderId, { method: "GET", }); const result = await response.json(); if (result.status !== 200) { throw new Error("Error querying order"); } // Display result document.getElementById("order-status").innerHTML = `Order ${result.data.id} - Status: ${result.data.status}`; } catch (error) { alert("Unexpected error: " + JSON.stringify(error)); } } ``` Copiar Check below the main possible statuses and their respective descriptions: | Status | Status detail | Description | |---|---|---| | \`processed\` | \`accredited\` | Transaction approved without authentication. | | \`failed\` | \`failed\` | Transaction declined without authentication. To verify the reasons, see the \[Transaction status\](https://www.mercadopago.com.uy/developers/en/docs/checkout-api-orders/payment-management/status/transaction-status) documentation. | | \`action\_required\` | \`pending\_challenge\` | Transaction pending authentication. The \_Challenge\_ has been initiated and the buyer has up to 40 minutes to complete it. | | \`failed\` | \`cc\_rejected\_3ds\_challenge\` | Transaction declined due to \_Challenge\_ failure. | | \`cancelled\` | \`expired\` | Transaction expired. The 40-minute \_Challenge\_ timeout has expired without the buyer completing it. A new order needs to be created. | In addition to the transaction's \`status\` and \`status\_detail\`, you can also check the specific 3DS authentication status in the \`transactions.payments\[i\].payment\_method.transaction\_security.status\` field returned in the endpoint :TagComponent{tag="API" text="GET /v1/orders/{id}" href="/developers/en/reference/online-payments/checkout-api/get-order/get"}, where the possible values and their descriptions are available. ::: :::AccordionComponent{title="Test the 3DS integration" pill="4"} To validate the 3DS integration, create a test order by sending a \*\*POST\*\* to the endpoint :TagComponent{tag="API" text="/v1/orders" href="/developers/en/reference/online-payments/checkout-api/create-order/post"} including your :toolTipComponent\[Test Access Token\]{content="Private test key of the application created in Mercado Pago and used in the \_backend\_. You can access it through \*Your integrations > Integration data > Tests > Test credentials\*."} and the required parameters, including the \`transaction\_security\` node with \`validation: on\_fraud\_risk\`. * [curl ](#editor%5F5) curl ``` curl --request POST \ --url https://api.mercadopago.com/v1/orders \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --header 'X-Idempotency-Key: ' \ --data '{ "type": "online", "external_reference": "3ds_test", "processing_mode": "automatic", "total_amount": "150.00", "config": { "online": { "transaction_security": { "validation": "on_fraud_risk", "liability_shift": "required" } } }, "payer": { "email": "test@testuser.com" }, "transactions": { "payments": [ { "amount": "150.00", "payment_method": { "id": "master", "type": "credit_card", "token": "{{CARD_TOKEN}}", "installments": 1 } } ] } }' ``` Copiar To test the created payment, use a \[test card\](https://www.mercadopago.com.uy/developers/en/docs/resourcestest-cards), entering one of the \*\*values below in the \`cardholder\_name\` field\*\* to simulate different \_Challenge\_ flows: > NOTE > > The \_Challenge\_ URL and the \`pending\_challenge\` status \*\*will only be returned\*\* when using the values \`APRO-CHOK\` or \`OTHE-CHNO\` in the \`cardholder\_name\` field. For the other values, the order will return directly with the final status (\`processed\` or \`failed\`), without going through the \`pending\_challenge\` status. | \`cardholder\_name\` value | 3DS Status | Status | Status detail | Description | |---|---|---|---|---| | \`APRO-AUTH\` | authenticated | processed | accredited | Successful \_Challenge\_ with authentication. | | \`APRO-ATMT\` | attempted | processed | accredited | \_Challenge\_ attempted. | | \`OTHE-NAUT\` | not\_authenticated | failed | failed | No authentication. | | \`APRO-CHOK\` | authenticated | processed | accredited | \_Challenge\_ authenticated. | | \`OTHE-CHNO\` | not\_authenticated | failed | failed | \_Challenge\_ not authenticated. | | \`APRO-foobar\` | not\_authenticated | failed | failed | Any other value results in failure. | In test flows with \`APRO-CHOK\` and \`OTHE-CHNO\`, the \_Challenge\_ will be displayed inside the \_iframe\_: !\[Challenge\](https://www.mercadopago.com.uy/images/api-orders/sandbox-v1-en.png) The verification code displayed is illustrative. To complete the test, click \*\*Confirm\*\* and then check the possible statuses in the \[Verify transaction status\](https://www.mercadopago.com.uy/(/developers/en/docs/checkout-api-orders/payment-management/integrate-3ds-bigmerchants)) step to check the result. After completing the 3DS integration and finishing the tests, your application will be ready for production. Before continuing, check the requirements in the \[Go to production\](https://www.mercadopago.com.uy/developers/en/docs/checkout-api-orders/go-to-production) documentation to ensure the integration is ready to receive real transactions. :::