Skip to main content
Strong customer authentication for card payments.

What is 3D Secure?

3D Secure (3DS) is an authentication protocol that adds an extra layer of security for online card transactions. It shifts liability for fraudulent chargebacks from the merchant to the card issuer.

Benefits

BenefitDescription
Liability ShiftFraud chargebacks become issuer’s responsibility
Frictionless FlowLow-risk transactions authenticate silently
PSD2 CompliantRequired for European transactions

Automatic 3DS

When using the Payment Sheet or Elements SDK, 3DS is handled automatically:
<PaymentSheet
  clientSecret="cs_test_..."
  onSuccess={(payment) => {
    // 3DS was handled automatically if needed
    console.log('Payment complete:', payment.id);
  }}
/>

Manual 3DS API

For custom integrations, use the 3DS API directly.

Initiate Authentication

curl -X POST https://api.atlas.co/functions/v1/threeds-authenticate \
  -H "Authorization: Bearer cs_client_secret_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sess_abc123",
    "token_id": "tok_card_xyz",
    "amount": 4990,
    "currency": "USD",
    "challenge_preference": "no_preference"
  }'
Parameters:
ParameterTypeRequiredDescription
session_idstringYesPayment session ID
token_idstringYesCard token from tokenization
amountintegerYesTransaction amount in cents
currencystringYesThree-letter ISO currency code
challenge_preferencestringNono_preference, no_challenge, challenge_requested, challenge_mandated
Response:
{
  "id": "3ds_session_abc123",
  "status": "challenge_required",
  "challenge_required": true,
  "challenge_url": "https://acs.issuer.com/challenge/...",
  "authentication_value": null,
  "eci": null,
  "ds_transaction_id": "d8e8b...",
  "liability_shift": false
}

Handle Challenge

If challenge_required is true, display the challenge URL in an iframe:
// Create iframe for 3DS challenge
const iframe = document.createElement('iframe');
iframe.src = response.challenge_url;
iframe.style.cssText = 'width: 400px; height: 600px; border: none;';
document.getElementById('3ds-container').appendChild(iframe);

// Listen for completion
window.addEventListener('message', (event) => {
  if (event.data.type === 'ATLAS_3DS_COMPLETE') {
    // Challenge completed, fetch result
    fetch3DSResult(response.id);
  }
});

Get Authentication Result

curl https://api.atlas.co/functions/v1/threeds-authenticate/sessions/3ds_session_abc123/result \
  -H "Authorization: Bearer cs_client_secret_xxx"
Response:
{
  "status": "authenticated",
  "authentication_value": "kBx2ZWJ3Y...",
  "eci": "05",
  "ds_transaction_id": "d8e8b...",
  "liability_shift": true
}

Complete Challenge

After the customer completes the challenge:
curl -X POST https://api.atlas.co/functions/v1/threeds-authenticate/sessions/3ds_session_abc123/challenge-complete \
  -H "Authorization: Bearer cs_client_secret_xxx"

Authentication Status Values

StatusDescription
YFully authenticated - proceed with payment
AAttempted authentication - proceed with payment
NAuthentication failed - do not proceed
UUnable to authenticate - proceed at merchant risk
RRejected by issuer - do not proceed

ECI Values

ECINetworkMeaning
05VisaFully authenticated
06VisaAttempted authentication
07VisaNon-3DS transaction
02MastercardFully authenticated
01MastercardAttempted authentication
00MastercardNon-3DS transaction

Best Practices

  1. Always attempt 3DS for European cards (PSD2 requirement)
  2. Use challenge_preference wisely - “no_challenge” may result in lower approval rates
  3. Handle timeouts - 3DS challenges can take several minutes
  4. Test all scenarios - Use test cards that trigger challenges

Test Cards

Card Number3DS Behavior
40000000000032203DS required, authentication succeeds
40000000000030633DS required, authentication fails
40000000000030553DS optional, not challenged