> For the complete documentation index, see [llms.txt](https://docs.verygoodsecurity.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.verygoodsecurity.com/cmp/products-and-services/3ds/3ds-authentication.md).

# 3DS Authentication

## 3DS Challenge Flow

Outlines the mandatory integration steps the Merchant (Frontend and Backend) must perform to execute a 3DS Authentication flow. The process is divided into two distinct phases:

* **Initialize** (device data collection).
* **Authentication** (final transaction submission).
* **3DS Status Check Request** for real-time status of a 3DS authentication and device fingerprinting process.

**Assumption:** Customers card is already created with CMP and a `card_id` has been generated.

For detailed API definitions and parameters, see the [3DS API Spec](/cmp/developer-resources/api/3d-secure-3ds.md).

### Initialize (Device Fingerprinting)

This is executed primarily on the Merchant Frontend to silently collect device-specific information from the cardholder’s browser. This process must be initiated when the checkout page first loads.

1. **Call the VGS Initialize Endpoint:**
   * **Action:** The Merchant Frontend sends a **POST** request to the VGS method endpoint (`/cards/{card_id}/3ds-initialize`).
   * **Data Required:** Include key identifiers such as `card_id, merchant_tx_id, and token_type.`
   * [Initialize API Spec](/cmp/developer-resources/api/3d-secure-3ds.md#post-cards-card_id-3ds-initialize).
2. **Embed the Hidden Iframe:**
   * **Action:** Upon receiving the response, which contains the tDSMethodContent (an iframe payload), the **Merchant Frontend** must immediately **embed this content into a hidden iframe** on the page.
   * **Purpose:** This iframe executes the necessary script for silent device fingerprinting and must remain active for up to 10 seconds.
3. **Collect Browser Data:**

   * **Action:** Concurrently, the **Merchant Frontend** must collect standard, non-fingerprint browser details, such as the **user agent** and the user's **IP** address. This data will be required for the subsequent Authentication request.

   <figure><img src="/files/x10afikQtVG8gcwDrupq" alt=""><figcaption></figcaption></figure>

### Authentication - Challenge Flow

This is triggered by the cardholder confirming the payment. Unlike the frictionless flow, the challenge flow introduces a mandatory user interaction step that must be handled by the Merchant Frontend.

1. **Trigger Authentication:**
   * **Action:** When the user clicks the "Pay" button, the **Merchant Frontend** collects and transmits all necessary data (card data, purchase info, and the browser data from Phase 1, Step 3) to the **Merchant Backend.**
2. **Call VGS Authenticate:**
   * **Action:** The **Merchant Backend** sends the core transaction request to the VGS `/cards/{card_id}/3ds-authenticate endpoint`.
   * **Data Required:** Include all collected data, transaction details (`purchase_info`), and set the type parameter to `challenge`.
   * [Challenge API Spec](/cmp/developer-resources/api/3d-secure-3ds.md#threeds-challenge).
3. **Receive Challenge HTML:**
   * **Action:** Instead of a final `status`, the Merchant Backend will receive an **Intermediate Response** (`status 'CHALLENGE_REQUIRED' or REJECTED`) containing the **Challenge HTML** (challengeHtml) and transaction IDs.
   * **Backend Responsibility:** The **Merchant Backend** must relay this Challenge HTML directly to the **Merchant Frontend**.
4. **Display the Challenge Window:**
   * **Action:** The **Merchant Frontend** must open a modal, pop-up, or dedicated iframe to display the received **Challenge HTML** to the cardholder.
   * **User Interaction:** The cardholder interacts directly with the **Issuer ACS** interface inside this challenge window (e.g., entering an OTP or password).
   * **Important - Rendering the Challenge HTML:**&#x20;
     * The `challengeHtml` returned by the VGS Authenticate API contains a redirect form generated by the issuer’s Access Control Server (ACS) and delivered through the 3DS server. This HTML initiates the cardholder challenge and must be rendered exactly as returned inside a browser context such as a modal, popup, or iframe.
     * The ACS redirect page may behave differently depending on the issuer implementation. Two common behaviors are possible:
       * The page displays a submit button that the cardholder must click to proceed to the issuer’s challenge screen.
       * The page automatically submits the form using JavaScript, immediately redirecting the browser to the issuer challenge without requiring any user interaction. In the auto-submit case, the “click here to continue” button only appears if JavaScript is blocked.
     * Both behaviors are valid and controlled entirely by the issuing bank. Your integration should not rely on the presence of a visible button or any specific UI elements within the challenge page.
     * **Implementation requirements:** When rendering the challenge HTML:
       * Treat the returned `challengeHtml` as opaque content and render it exactly as provided. Do not modify the form, scripts, or URLs contained within it.
       * Render the HTML inside a browser-capable environment (for example, an iframe, modal, popup window, or webview) that allows JavaScript execution and form redirects.
       * Allow the browser to follow any redirects initiated by the page.
       * After the form is submitted (either manually or automatically), the browser is redirected to the issuer’s ACS where the authentication may take place. Depending on the issuer’s risk decision, the cardholder may be presented with a challenge (for example OTP, banking app approval, or biometric verification), or the issuer may immediately return a final authentication result.
       * In some cases, the challenge UI may not appear even after the redirect. This can occur if the issuer makes a risk decision early in the authentication flow, or if there is a temporary technical issue with the ACS or a downstream service.
       * The final authentication result is determined by the issuer and delivered asynchronously. Once the authentication process is completed, abandoned, or times out, you will receive the final status via the VGS `cmp_threeds.challenge_result` webhook. Alternatively, you may retrieve the current status using the `/3ds-check` endpoint.
5. **Handle Challenge Completion (Client-Side Listener):**
   * **Action:** Once the user completes the challenge, the **Issuer ACS** redirects the browser within the frame to a VGS success/failure endpoint, which then passes the result to the Merchant’s pre-configured endpoint. The Merchant Frontend must have a listener or mechanism to detect when the challenge window closes or redirects.
6. **Receive Final Result (Asynchronous or Synchronous):**
   * **Action:** The **Merchant Backend** will receive an **asynchronous webhook** with the final success/failure `status` of the challenge, or if the challenge was abandoned/timed out, a final synchronous result may be returned. The backend must be configured to accept and process this final result.
   * **Key Data Received:** The final response contains the authentication `status` (e.g., `'APPROVED', 'UNABLE_TO_AUTHENTICATE'`), the cryptographic value (`cryptogram`), and `transaction_info`.
7. **Authorize Payment:**
   1. **Action:** The Merchant Backend uses the received final `status` to determine the final risk decision. If the challenge was successful (status `APPROVED` or equivalent), the backend must use the provided `cryptogram` to submit the final payment authorization request to the payment processor.

{% hint style="info" %}
VGS does not currently return `messageVersion` in the `3ds-authenticate` or `3ds-check` responses. For PSPs that require the 3DS version to be provided explicitly in the authorization request, customers should **use `2.2.0`.** This applies to both challenge and data-only flows.
{% endhint %}

<figure><img src="/files/U8KOs2zcAiwvybQMizTr" alt=""><figcaption></figcaption></figure>

### **3DS Status Check**

The VGS 3DS Status Check endpoint allows merchants to retrieve the **real-time status** of a transaction’s 3DS authentication and device fingerprinting flow. It provides **immediate visibility** into the authentication process and can be used as a **synchronous alternative to webhooks**.

* **Endpoint to Check Initialize Device Fingerprint Status:** **`GET`** `/cards/{card_id}/3ds-check?`**`inti_received={true}`**`&xid={xid}&merchant_transaction_id={merchant_transaction_id}`
* **Endpoint to Check Authentication Status:** **`GET`** `/cards/{card_id}/3ds-check?xid={xid}&merchant_transaction_id={merchant_transaction_id}`
* **3DS Flow & Real-Time Status Retrieval**

  * **3DS Flow Overview** – During a 3DS transaction, the customer may go through device fingerprinting or a challenge questionnaire as part of the authentication process.
  * **Client Polling for Status** – While the transaction is in progress, the client polls the `/3ds-check` endpoint with the following parameters:
    * `cardID`
    * `xid`
    * `merchant_transaction_id`
    * `inti_received` (<kbd>conditional</kbd>)
  * **Behavior based on `inti_received`**:
    * **`inti_received=true`** – Returns device fingerprinting initialization status. Call this after the iframe from the synchronous initialize response is rendered and the form containing the iframe is submitted on the front end. This allows the issuer to collect the device fingerprinting.
    * **`inti_received=false` or omitted** – Returns authentication status after the challenge questionnaire/html is submitted by the user.
  * **Status Retrieval** – VGS responds with the most up-to-date status, enabling the merchant to take immediate next steps:
    * Proceed to authorization
    * Update internal transaction state

  #### Using 3ds-check for completed challenges

  * Once the user completes the challenge, they are redirected to the configured `redirect_url`. At that point, calling `3ds-check` is the fastest and most reliable way to retrieve the final authentication result.
  * **This is the recommended approach for successfully completed challenges.**

  #### Handling abandoned challenges

  * Challenge flows involve human interaction, such as entering an OTP or approving a push notification. Because of this, issuers typically keep the challenge session open for **10 to 15 minutes** to allow the user time to complete it.
  * If the user closes the challenge window or abandons the transaction, the issuer may not send a final timeout or failure result until the issuer-side session expires. Because of this, polling `3ds-check` after only a few seconds of inactivity is not recommended, since the response will often remain `404` until a final result is available.
  * **Recommended approach:**
    * Use `redirect_url` or the webhook as the primary completion signal.
    * If you are rendering the returned challenge HTML in your own frontend container, implement a frontend listener to detect whether the user manually closes the challenge modal or iframe. If they do, you can immediately treat the transaction as canceled on your end without waiting for the checkout timeout or issuer-side timeout.
    * Keep your own checkout timeout based on your UX needs. For example, if your current timeout is **5 minutes**, it is fine to keep that as-is. It does not need to match the issuer’s **10 to 15 minute** timeout.
    * If your checkout session expires before you receive the redirect or webhook, make one final call to `3ds-check`.
    * If the response is still `404`, you can safely treat the transaction as expired on your end, cancel the order, and release the cart or inventory.
    * If a delayed webhook arrives later after the issuer timeout expires, it can be ignored if the order has already been canceled or expired in your system.
    * For Out-of-Band (OOB) authentication flows, the cardholder may complete authentication in their banking application and never return to the browser. In these scenarios, the final authentication result will become available through both the webhook and the `3ds-check` endpoint once VGS receives the result from the issuer. If your checkout session remains active, you may continue waiting for the webhook. If your checkout expires before receiving the webhook, make a final call to `3ds-check` before treating the transaction as expired.

  #### Best practice

  * Use `3ds-check` after redirect for completed challenges, use webhooks as a secondary signal, and rely on your own checkout timeout to handle abandoned sessions.

  #### Additional note

  * When you see significantly later completion signals, those cases are typically due to the user abandoning the challenge, closing the challenge window, or taking longer to complete the issuer challenge. This is why implementing `3ds-check` is the recommended approach for handling these scenarios reliably.

#### Non-Payment Authentication (NPA) and Card-Add Flows

VGS 3DS currently supports standard Payment Authentication (PA) flows only. EMV 3DS 2.2 defines Non-Payment Authentication (NPA / `messageCategory: 02`) specifically for card-add and card-on-file enrollment use cases, but VGS does not currently expose NPA-specific indicators. NPA support is on the roadmap.

In the meantime, if you need to perform card verification or card-on-file enrollment that satisfies PSD2 SCA requirements, you can use the VGS PA flow as follows:

* Initiate the `/3ds-authenticate` call by passing a nominal verification amount in the `purchase_info` object — for example, `amount: 0` or `amount: 1.00` with the corresponding currency code (for example, `978` for EUR).
* The issuer will treat this as a standard payment authentication and may step up the user if additional verification is required. VGS will return a CAVV and ECI, which can then be passed into the verification authorization request sent to your PSP or acquirer.
* Because this runs through the standard PA flow, it uses standard Risk-Based Authentication (RBA). You will not be able to explicitly pass NPA-specific indicators such as "Add Card" or "Mandate Challenge." However, the resulting CAVV and ECI can be used as Strong Customer Authentication (SCA) evidence during card verification and card-on-file enrollment flows.
* Although the request is processed as a Payment Authentication rather than an NPA transaction, the returned authentication data can be used to satisfy PSD2 SCA requirements for card verification and card-on-file enrollment use cases.

**Note:** The CAVV generated during a PA flow is tied to that specific authentication event. If the customer later returns to make a new active purchase (CIT), a separate payment authentication should be performed for that transaction.

{% hint style="info" %}
VGS does not currently return `messageVersion` in the `3ds-authenticate` or `3ds-check` responses. For PSPs that require the 3DS version to be provided explicitly in the authorization request, customers should **use `2.2.0`.** This applies to both challenge and data-only flows.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.verygoodsecurity.com/cmp/products-and-services/3ds/3ds-authentication.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
