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, orxidvalues across multiple payments — each transaction requires a fresh authentication.
How to Authenticate
- Call
ThreeDSSDK.create()on your frontend using theclientSecretgenerated 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);
}
});- Call
threeDSSession.authenticate()when the customer submits their card details. Pass the card details and billing information required for the issuer lookup.
| Parameter | Required | Description |
|---|---|---|
cardNumber | ✓ | Full card number passed in memory only — never stored or logged. |
expiryMonth | ✓ | Card expiry month (e.g., 12). |
expiryYear | ✓ | Card expiry year (e.g., 2027). |
billingAddress | ✓ | Cardholder billing address including firstName, lastName, line1, city, state, postalCode, and country. |
email | Cardholder email address. Recommended — improves frictionless authentication rates. |
- Once authentication completes, the
onSuccesscallback returns the authentication result. Store the following values — they are required to submit the payment in Step 2.eci: The Electronic Commerce Indicator. Indicates the authentication outcome and determines whether liability shift applies. See ECI Codes for the full reference.cavv: Cardholder Authentication Verification Value. Cryptographic proof issued by the ACS that the cardholder was authenticated.xid: Unique transaction identifier assigned by the 3DS Server. Links the payment to the authentication record.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
onSuccesscallback 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.
- Make a
POSTrequest to/checkout/v3/paymentwith the following parameters:
| Parameter | Required | Description |
|---|---|---|
amount | ✓ | Amount to charge (in USD currency). |
tenderType | ✓ | Set to CARD for card transactions. |
merchantId | ✓ | The merchant's unique identifier used to process the payment. |
cardAccount | ✓ | Valid card details or a vaulted token. Refer to Card Vaulting for steps to generate a token for future use. |
threeDSecure | ✓ | Object containing the 3DS authentication result. Required to achieve liability shift. See the threeDSecure parameter reference below. |
posData | An 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
| Parameter | Required | Description |
|---|---|---|
threeDSecure.eci | ✓ | Electronic Commerce Indicator returned by the authentication session. See ECI Codes for the full reference by card network. |
threeDSecure.cavv | ✓ | Cardholder Authentication Verification Value returned by the issuer's ACS. Cryptographic proof of authentication. |
threeDSecure.xid | ✓ | Unique transaction identifier assigned by the 3DS Server. Links the payment to the authentication record. |
threeDSecure.authenticationStatus | ✓ | Authentication outcome returned by the ACS. Accepted values: Y, A, N, U, R. See Authentication Status. |
threeDSecure.version | 3DS 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"
}- 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:
- Missing or invalid required fields
- Incorrect or mismatched
threeDSecurevalues - 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. - 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 thestatusandresponseCodefields in the response.status: The primary outcome of the transaction, either APPROVED or DECLINED.responseCode: A detailed code explaining the reason for the status. See our comprehensive Response code guide for the full list.
- For every approved payment, store two identifiers:
id: The unique Payment ID. Use this for retrieving or voiding the transaction before it settles.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.
| Network | ECI Code | Authentication Result | Liability Shift |
|---|---|---|---|
| Visa | 05 | Fully authenticated | ✓ Shifts to issuer |
| Visa | 06 | Authentication attempted | Partial — network dependent |
| Visa | 07 | Failed or not available | ✗ No shift |
| Mastercard | 02 | Fully authenticated | ✓ Shifts to issuer |
| Mastercard | 01 | Authentication attempted | Partial — network dependent |
| Mastercard | 00 | Failed or not available | ✗ No shift |
| Amex | 05 | Fully authenticated | ✓ Shifts to issuer |
| Amex | 06 | Authentication attempted | Partial — network dependent |
| Amex | 07 | Not available | ✗ No shift |
ECI codes
05(Visa / Amex) and02(Mastercard) are the strongest evidence of liability shift. Retain theeciandcavvvalues 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.
| Status | Description | Recommended Action |
|---|---|---|
Y | Fully authenticated — cardholder verified successfully. | Submit the payment. Full liability shift applies. |
A | Authentication attempted — ACS was unavailable or could not complete. | Submit the payment. Partial liability shift may apply depending on the card network. |
N | Authentication failed — cardholder did not complete or denied the challenge. | Do not submit the payment. Prompt the customer to retry with a different card. |
U | Authentication 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. |
R | Authentication 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
authenticationStatusisNorR. These statuses indicate that the cardholder was not verified — proceeding without authentication exposes your business to full chargeback liability with no recourse.
Best Practices
| Feature | Description |
|---|---|
| Always attempt 3DS before submitting payment | Even 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 transaction | Retain eci, cavv, and xid alongside your payment records. These values are required evidence when disputing a fraudulent chargeback with your acquirer. |
| Never reuse authentication values | Each 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 explicitly | Define 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 data | Always 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 Webhooks | Stay informed about the payment status asynchronously by subscribing to PaymentSuccess and PaymentFail webhook events. |
| Test your integration | Use the provided 3DS test cards to simulate frictionless, challenge, failed, and unavailable authentication flows in the sandbox environment before going live. |
See Also
- Sale (Automatic Capture)
- Authorize Now, Capture Later
- Card Vaulting
- Transaction Context (CNP)
- Enabling 3DS for Payments (Priority Checkout)
- Enabling 3DS for Card Vaulting (Priority Vault)
- Payment Response Codes
- API Error Handling
- Card Test Data
- Payment Webhooks
Updated about 9 hours ago