3DS

3D Secure (3DS) Testing Guide

This guide explains how to test 3DS initialize and authentication flows in a controlled environment. You can simulate various responses, including challenge flows, frictionless flows, and HTTP error scenarios, to see how your application behaves.

Testing can be performed in two ways:

  1. Mock Card Testing – using static card IDs that simulate specific responses.

  2. Sandbox Testing – using test PANs in a sandbox environment.

General Setup

  • Content-Type Header: application/vnd.api+json

  • HTTP Method: POST

  • Each request includes a unique merchant_transaction_id to track transactions.

  • Initialize Responses typically include a 3DS Method Form (device fingerprinting) that must be submitted to the ACS.

  • Challenge responses usually contain a Challenge Form which is submitted to display the challenge questionnaire to the user.

  • Asynchronous notifications (webhooks) are sent once device fingerprinting and the user’s authentication challenge are completed and processed by the ACS.

3DS Initialize API - Mock Card Testing

Test different 3DS scenarios without using real cards. Each static cardID returns a predefined response (success, frictionless, challenge, or error). When using these mock card IDs, you do not need 3DS enabled on your account and you do not need to generate a JWT auth token. Simply replace {cardID} with one of the static mock values.

Base URL:

https://gw-01-sandbox.vgsapi.com/3ds-mocks

Initialize API Endpoint:

POST /cards/{cardID}/3ds-initialize

Example Request:

curl -X POST "https://gw-01-sandbox.vgsapi.com/3ds-mocks/cards/CRAbcDefGhijKlmNoPqrStuVw/3ds-initialize" \
-H "Content-Type: application/vnd.api+json"
Test cardID
Expected HTTP Status
Expected Response / Notes

CRAbcDefGhijKlmNoPqrStuVw

200 OK

Returns the synchronous response with the iframe/data needed to proceed with authentication.

CRnOiFrAmEqDxRgXU3TFmtcD

206 OK

Returns a synchronous response without iframe/data, confirming that initialization is not required and the authentication process can proceed immediately.

CRaZcXeVtBrNnMpLoKjIhUgYt

400 Bad Request

Simulates a 400 error from the initialize endpoint.

CRdFhJkLmNoPqRsTuVwXyZ012

401 Unauthorized

Simulates a 401 error from the initialize endpoint.

CRpOiUytRewQAzXswEdcRfVtB

403 Forbidden

Simulates a 403 error from the initialize endpoint.

CRuYtRewQAzWsXeDcRfVtGbYh

404 Not Found

Simulates a 404 error from the initialize endpoint.

CRiKoLpMnBvCxZaQsWeRdTfYg

422 Unprocessable Entity

Simulates a 422 error from the initialize endpoint.

CRzXaScVbNmLkJhgFdSaQwErT

500 Internal Server Error

Simulates a 500 error from the initialize endpoint.

CRbNtMvCxZlKjHgFdSaQwErTy

503 Service Unavailable

Simulates a 503 error from the initialize endpoint.

3DS Initialize API - Sandbox Testing

Test 3DS flows using test PANs in a sandbox environment. This is closer to production and safe for testing. When using Sandbox, 3DS must be enabled on your account. You’ll also need a service account with the required 3DS scopes and must use it to generate a JWT auth token.

Base URL:

https://sandbox.vgsapi.com

Initialize API Endpoint:

POST /cards/{card_id}/3ds-initialize

Sample Request Body:

{
  "data": {
    "attributes": {
      "token_type": "pan",
      "transaction_info": {
        "merchant_transaction_id": "12346586",
        "xid": "UgG20AB6E6dceR1gDg8I8VtxoHk="
      }
    }
  }
}
Test Card/Pan
Expiration Date
Expected Response / Notes
HTTP Status Code

4016360000000493

Any Future Date

Returns the synchronous response with the iframe/form needed to proceed with authentication.

Look for tds_method_content field in the Initialize sync response.

200

5188340000000969

Any Future Date

Returns the synchronous response with the iframe/form needed to proceed with authentication.

Look for tds_method_content field in the Initialize sync response.

200

4016365555555493

Any Future Date

Returns a synchronous response without iframe/data, confirming that initialization is not required and the authentication process can proceed immediately.

tds_method_content field will not be present in the Initialize sync response.

206 (Partial Content)

Invoking 3DS Device Fingerprinting:

  1. Prepare Request

    • Ensure merchant_transaction_id is unique for each request.

    • The synchronous response will include a 3DS Method Form in tds_method_content with a hidden field threeDSMethodData.

  2. Run Device Fingerprinting

    • This simulates the device fingerprinting between the browser and the ACS/Issuer.

    • Posting threeDSMethodData to the ACS allows it to collect device/browser info and triggers an asynchronous 3DS Method Completion notification to your configured webhook. Extract <input type="hidden" name="threeDSMethodData" value="..."/> from tds_method_content.

    • Create a local HTML file and embed the value in this snippet:

<!doctype html>
<html lang="en">
<body onload="document.forms[0].submit()">
  <form action="https://3ds-acs.test.modirum.com/mdpayacs/3ds-method" method="post" target="hiddenFrame">
    <input type="hidden" name="threeDSMethodData" value="<threeDSMethodData>" />
  </form>
  <iframe name="hiddenFrame" style="display:none"></iframe>
  <p>The form has been submitted to ACS. View the callback <a href="https://play.svix.com/view/e_y4H4J9EA18Hm1Y1Ws5XeVaU45Lq" target="_blank">here</a>.</p>
</body>
</html>
  1. Execute and Observe

    • Open the HTML file in a browser; it auto-submits to ACS.

    • Observe the asynchronous 3DS Method Completion notification at your configured notification URL.

    • Refer to the VGS Dashboard to set up notification URL and configure 3DS events.

3DS Authenticate API - Mock Card Testing

The 3DS Authenticate API (/cards/{cardID}/3ds-authenticate) simulates the final authentication response.

  • For frictionless flows, this will be the synchronous response.

  • For challenge flows, this response will be sent in the asynchronous webhook notification.

You can test various authentication outcomes and error scenarios by providing the corresponding cardID as part of the URL path.

Example Request URL: POST https://gw-01-sandbox.vgsapi.com/3ds-mocks/cards/CRAbcDefGhijKlmNoPqrStuVw/3ds-authenticate

Example CURL:

curl -X POST "https://gw-01-sandbox.vgsapi.com/3ds-mocks/cards/CRcHaLlEnGeReQdXU3TFmtcD/3ds-authenticate"
-H "Content-Type: application/vnd.api+json"

Test cardIDs and Expected Responses

Test cardID
Expected HTTP Status
Expected status (in JSON response)
Notes

CRAbcDefGhijKlmNoPqrStuVw

200 OK

AUTHENTICATED

Simulates a successful authentication (final auth response).

CRcHaLlEnGeReQdXU3TFmtcD

200 OK

CHALLENGE_REQUIRED

Simulates a response that includes the prebuilt HTML form (challenge_form) to directly render the challenge or build your own form using challenge_url, challenge_request, and challenge_session_data.

CRXyZ0123456789abcDEfGhij

200 OK

INFORMATIONAL_ONLY

Simulates an informational-only status for a frictionless auth result.

CRMnOpQrStUvWxYzABCdefGhi

200 OK

REJECTED

Simulates a rejected status for the auth result.

CRQrStUvWxYz0123456789AbC

200 OK

UNABLE_TO_AUTHENTICATE

Simulates an unable to authenticate status for the auth result.

CRDecqZp3xRgXU3TFmtcDdzQs

200 OK

DENIED

Simulates a denied status for the auth result.

CRaZcXeVtBrNnMpLoKjIhUgYt

400 Bad Request

N/A (Error Response)

Simulates a 400 error from the authenticate endpoint.

CRdFhJkLmNoPqRsTuVwXyZ012

401 Unauthorized

N/A (Error Response)

Simulates a 401 error from the authenticate endpoint.

CRpOiUytRewQAzXswEdcRfVtB

403 Forbidden

N/A (Error Response)

Simulates a 403 error from the authenticate endpoint.

CRuYtRewQAzWsXeDcRfVtGbYh

404 Not Found

N/A (Error Response)

Simulates a 404 error from the authenticate endpoint.

CRiKoLpMnBvCxZaQsWeRdTfYg

422 Unprocessable Entity

N/A (Error Response)

Simulates a 422 error from the authenticate endpoint.

CRzXaScVbNmLkJhgFdSaQwErT

500 Internal Server Error

N/A (Error Response)

Simulates a 500 error from the authenticate endpoint.

CRbNtMvCxZlKjHgFdSaQwErTy

503 Service Unavailable

N/A (Error Response)

Simulates a 503 error from the authenticate endpoint.

3DS Authentication API – Sandbox Testing

Use the 3DS Authentication API to simulate different challenge flow responses in Sandbox. As with Initialize, Sandbox behavior closely mirrors production and is safe for end-to-end testing.

To test Auth in Sandbox, ensure:

  • 3DS is enabled for the network you are testing

  • Your account has a notification URL configured

  • You are using a service account with the required 3DS scopes to generate a JWT

Base URL

https://sandbox.vgsapi.com

Auth API Endpoint

POST /cards/{card_id}/3ds-authenticate

Headers

Accept: text 
Accept-Language: text (e.g. en-US)
Content-Type: application/vnd.api+json

Sample Auth Request

(Must reuse the merchant_transaction_id and xid from your initialize call)

{
  "data": {
    "attributes": {
      "purchase_info": {
        "amount": 123,
        "currency_code": "USD"
      },
      "transaction_info": {
        "merchant_transaction_id": "12346586",
        "xid": "UgG20AB6E6dceR1gDg8I8VtxoHk="
      },
      "browser_info": {
        "color_depth": 24,
        "screen_height": 1000,
        "screen_width": 1000,
        "java_enabled": true,
        "javascript_enabled": false,
        "tz": -140
      },
      "auth_type": "challenge",
      "notification_url": "https://example.com/notifications"
    }
  }
}

Understanding the Auth Response

After calling Auth, you will get one of two outcomes:

#
Type
Description
Example / Notes

1

Synchronous Auth Result

For certain test PANs, the final 3DS result is returned directly in the auth response. No browser interaction is required.

  1. APPROVED

  2. DENIED

  3. ATTEMPTS_PERFORMED

  4. REJECTED

  5. UNABLE_TO_AUTHENTICATE

2

Challenge Flow (Async)

If the response includes data.attributes.challenge_info.challenge_form, a browser-based challenge must be performed.

N/A

How to Execute the challenge_form Returned in the Auth Response

If the Auth API returns a challenge, you’ll receive:

data.attributes.challenge_info.challenge_form

This is ready-to-run HTML that must be rendered exactly as provided.

To execute it, inject the challenge_form HTML directly into your checkout page or an iframe you control. Examples include:

  • Setting it as the innerHTML of a container

  • Writing it into an iframe

  • Rendering it inside a modal that can execute HTML

The HTML already includes:

  • The ACS form

  • All required hidden fields

  • Auto-submit behavior

  • Redirect/iframe handling

  • Any UI needed for the challenge (password entry or simulation buttons)

Do not save it to a file, modify or sanitize it, wrap it in another form, or rebuild the structure. This breaks the challenge because the ACS expects the exact form layout, the auto-submit must run inside a real browser DOM, and the HTML may rely on specific parent/iframe context.

Render it as-is to ensure the ACS challenge runs correctly. Once the challenge is executed and completed, the authentication flow proceeds, and the final 3DS result is returned to the configured async webhook.

Auth Testing Cards (Sandbox)

Below are all supported test cards and their expected behaviors.

Mastercard

Test Card PAN
Result Type
Expected Status
Notes

5239290700000151

Async

APPROVED

Password challenge → use secret!33

5239290700000102

Sync

APPROVED

5188340000000629

Sync

DENIED

5188340000000937

Sync

ATTEMPTS_PERFORMED

5188340000000952

Sync

REJECTED

5188340000000222

Sync

UNABLE_TO_AUTHENTICATE

No acs_info

5188340000000445

Sync

UNABLE_TO_AUTHENTICATE

With acs_info

Visa

Test Card PAN
Result Type
Expected Status
Notes

4016360000000493

Async

APPROVED / ATTEMPTED / DENIED / REJECTED / UNAVAILABLE

Buttons simulate every result

4147463011110134

Sync

APPROVED

4147463011110142

Sync

DENIED

4147463011110159

Sync

ATTEMPTS_PERFORMED

4147463011110175

Sync

REJECTED

4147463011110167

Sync

UNABLE_TO_AUTHENTICATE

With acs_info

Last updated