3D Secure (3DS) Authentication

Authenticate cardholders using 3D Secure (3DS) before submitting a payment to shift fraud liability to the issuer and reduce fraudulent chargebacks.

3D Secure (3DS) is an additional authentication step for card-not-present transactions that verifies a cardholder's identity directly with their issuing bank before a payment is authorized — shifting fraud liability away from your business and onto the card issuer.

Common use cases include:

  • E-commerce Checkouts: Authenticate cardholders during online purchases to reduce the risk of fraudulent chargebacks on high-value transactions.
  • Recurring Billing: Apply 3DS authentication on the first transaction of a subscription to establish a verified credential for future charges.
  • High-Risk Transactions: Trigger 3DS for transactions that exceed a defined amount threshold or originate from high-risk geographies.
  • Regulatory Compliance: Meet Strong Customer Authentication (SCA) requirements for markets where two-factor authentication is mandated for online payments.

How it Works

Processing a 3DS-authenticated payment involves two stages — authenticating the cardholder and submitting the payment with the authentication result.

Step 1: Authenticate the Cardholder

Authentication verifies the cardholder's identity with their issuing bank before the payment is submitted. The issuer evaluates risk signals and either authenticates the cardholder silently (frictionless flow) or presents a verification challenge (challenge flow).

An authentication session is valid for a single transaction only. Do not reuse eci, cavv, or xid values across multiple payments — each transaction requires a fresh authentication.

How to Authenticate

  1. Call ThreeDSSDK.create() on your frontend using the clientSecret generated by your backend. This initializes the 3DS session and begins device fingerprinting in the background.
const threeDSSession = ThreeDSSDK.create({
  clientSecret: clientSecret,
  containerId: '#3ds-container',
  onSuccess: (result) => {
    // Authentication complete — proceed to Step 2
    submitPayment(result.eci, result.cavv, result.xid, result.authenticationStatus);
  },
  onChallenge: () => {
    // Challenge modal presented — wait for customer to complete
  },
  onFailure: (error) => {
    // Authentication failed — handle gracefully
    console.error('3DS failed:', error.message);
  }
});
  1. Call threeDSSession.authenticate() when the customer submits their card details. Pass the card details and billing information required for the issuer lookup.
ParameterRequiredDescription
cardNumberFull card number passed in memory only — never stored or logged.
expiryMonthCard expiry month (e.g., 12).
expiryYearCard expiry year (e.g., 2027).
billingAddressCardholder billing address including firstName, lastName, line1, city, state, postalCode, and country.
emailCardholder email address. Recommended — improves frictionless authentication rates.

  1. Once authentication completes, the onSuccess callback returns the authentication result. Store the following values — they are required to submit the payment in Step 2.
    1. eci: The Electronic Commerce Indicator. Indicates the authentication outcome and determines whether liability shift applies. See ECI Codes for the full reference.
    2. cavv: Cardholder Authentication Verification Value. Cryptographic proof issued by the ACS that the cardholder was authenticated.
    3. xid: Unique transaction identifier assigned by the 3DS Server. Links the payment to the authentication record.
    4. authenticationStatus: The outcome of the authentication exchange. See Authentication Status for all possible values.
📘

Frictionless vs. Challenge Flow — In a frictionless flow, the issuer authenticates the cardholder silently using device and risk signals — no customer action is required. In a challenge flow, the issuer presents a verification step (typically a one-time passcode) that the customer must complete before the payment can proceed. Both flows return an onSuccess callback with the same result structure.


Step 2: Submit the Payment with 3DS Data

Once authentication is complete, submit the payment to the /checkout/v3/payment endpoint with the threeDSecure object included in the request body. The issuer uses this data to authorize the transaction with liability shift applied.

  1. Make a POST request to /checkout/v3/payment with the following parameters:
ParameterRequiredDescription
amountAmount to charge (in USD currency).
tenderTypeSet to CARD for card transactions.
merchantIdThe merchant's unique identifier used to process the payment.
cardAccountValid card details or a vaulted token. Refer to Card Vaulting for steps to generate a token for future use.
threeDSecureObject containing the 3DS authentication result. Required to achieve liability shift. See the threeDSecure parameter reference below.
posDataAn object containing Point of Sale data. While optional, we highly recommend including this for all card-not-present transactions to improve approval rates and lower processing fees. View the recommended configuration here.

threeDSecure Parameter Reference

ParameterRequiredDescription
threeDSecure.eciElectronic Commerce Indicator returned by the authentication session. See ECI Codes for the full reference by card network.
threeDSecure.cavvCardholder Authentication Verification Value returned by the issuer's ACS. Cryptographic proof of authentication.
threeDSecure.xidUnique transaction identifier assigned by the 3DS Server. Links the payment to the authentication record.
threeDSecure.authenticationStatusAuthentication outcome returned by the ACS. Accepted values: Y, A, N, U, R. See Authentication Status.
threeDSecure.version3DS protocol version used during authentication — 1.0.2 or 2.x. Defaults to 2.x if not specified.

{
  "amount": "125.00",
  "tenderType": "CARD",
  "merchantId": "4007497",
  "cardAccount": {
    "number": "4111111111111111",
    "expiryMonth": "12",
    "expiryYear": "2027",
    "cvv": "123",
    "avsStreet": "123 Main St",
    "avsZip": "78701"
  },
  "threeDSecure": {
    "eci": "05",
    "cavv": "AAABBJg0VhI0VniQEjRWAAAAAAA=",
    "xid": "MDAwMDAwMDAwMDAwMDAwMDAwMDE=",
    "authenticationStatus": "Y",
    "version": "2.2.0"
  },
  "posData": {
    "cardholderPresence": "Ecom",
    "panCaptureMethod": "Manual",
    "deviceAttendance": "HomePc",
    "deviceLocation": "HomePc",
    "deviceInputCapability": "KeyedOnly",
    "partialApprovalSupport": "NotSupported",
    "transactionStatus": "Normal"
  },
  "cardPresent": false,
  "authorizationIndicator": "Final"
}
  1. Once the payment request is submitted, our system performs a series of system-level validations before sending the transaction to the card network. These validations check for:
    1. Missing or invalid required fields
    2. Incorrect or mismatched threeDSecure values
    3. Merchant configuration or permission issues.

    If any validation fails, the request is rejected immediately and an error response is returned. You must correct the issue and resubmit the request. For a complete list of validation errors and how to resolve them, refer to the System Error Codes guide.
  2. If all system-level validations pass, our system processes the payment and returns a response. You can learn the outcome via GET /checkout/v3/payment/{id} or wait for the Payment webhook. Determine the result by checking the status and responseCode fields in the response.
    1. status: The primary outcome of the transaction, either APPROVED or DECLINED.
    2. responseCode: A detailed code explaining the reason for the status. See our comprehensive Response code guide for the full list.
  3. For every approved payment, store two identifiers:
    1. id: The unique Payment ID. Use this for retrieving or voiding the transaction before it settles.
    2. paymentToken: The secure Transaction Token. Use this for follow-up actions like refunds or adjustments after settlement.


ECI Codes

The Electronic Commerce Indicator (ECI) is returned by the card network after authentication and determines whether liability shift applies to the transaction. Pass the ECI value in threeDSecure.eci when submitting the payment.

NetworkECI CodeAuthentication ResultLiability Shift
Visa05Fully authenticated✓ Shifts to issuer
Visa06Authentication attemptedPartial — network dependent
Visa07Failed or not available✗ No shift
Mastercard02Fully authenticated✓ Shifts to issuer
Mastercard01Authentication attemptedPartial — network dependent
Mastercard00Failed or not available✗ No shift
Amex05Fully authenticated✓ Shifts to issuer
Amex06Authentication attemptedPartial — network dependent
Amex07Not available✗ No shift

ECI codes 05 (Visa / Amex) and 02 (Mastercard) are the strongest evidence of liability shift. Retain the eci and cavv values from every authenticated transaction — they are required when disputing a fraudulent chargeback.


Authentication Status

The authenticationStatus field returned by the 3DS session indicates the outcome of the exchange between the cardholder and the issuer's Access Control Server (ACS). Pass this value in threeDSecure.authenticationStatus when submitting the payment.

StatusDescriptionRecommended Action
YFully authenticated — cardholder verified successfully.Submit the payment. Full liability shift applies.
AAuthentication attempted — ACS was unavailable or could not complete.Submit the payment. Partial liability shift may apply depending on the card network.
NAuthentication failed — cardholder did not complete or denied the challenge.Do not submit the payment. Prompt the customer to retry with a different card.
UAuthentication unavailable — a technical error prevented the session from completing.Retry the authentication. If the issue persists, you may proceed without 3DS at your own risk.
RAuthentication rejected — the issuer explicitly denied the authentication request.Do not submit the payment. Ask the customer to use a different payment method.
📘

Note — Do not submit a payment when authenticationStatus is N or R. These statuses indicate that the cardholder was not verified — proceeding without authentication exposes your business to full chargeback liability with no recourse.



Best Practices

FeatureDescription
Always attempt 3DS before submitting paymentEven when authentication is optional, attempting 3DS improves issuer approval rates and protects against chargebacks. A frictionless authentication adds no friction to the customer experience.
Store ECI and CAVV on every transactionRetain eci, cavv, and xid alongside your payment records. These values are required evidence when disputing a fraudulent chargeback with your acquirer.
Never reuse authentication valuesEach cavv and xid is valid for a single transaction only. Re-running the 3DS session generates a fresh set of values. Reusing values will cause the payment to be rejected.
Handle all authentication statuses explicitlyDefine a clear policy for each authenticationStatus in your integration. Do not treat U (unavailable) the same as Y (authenticated) — each status carries a different liability implication.
Include AVS dataAlways pass Address Verification Service (AVS) data (avsZip, avsStreet) in the cardAccount object alongside the 3DS result. This further reduces fraud risk and can lower processing fees.
Use WebhooksStay informed about the payment status asynchronously by subscribing to PaymentSuccess and PaymentFail webhook events.
Test your integrationUse the provided 3DS test cards to simulate frictionless, challenge, failed, and unavailable authentication flows in the sandbox environment before going live.

See Also



.readme-logo { display: none !important; }