Skip to main content

3D Secure 2 (3DS2) guide

3D Secure 2 (3DS2) is a cardholder authentication protocol used for card-not-present payments. It adds an authentication step between payment submission and issuer authorisation, which reduces fraud and, for authenticated transactions, shifts chargeback liability to the issuer.

This page is the canonical reference for how 3DS2 works with Payments AI: when it applies, how to maximise the rate of frictionless flows, the step-by-step challenge flow, and how the hosted payment form handles 3DS automatically for subscriptions.

When 3DS triggers

3DS is disabled by default for all gateway connections. Activation requirements depend on your legal corporate location and the markets where you sell:

  • EU/UK merchants: 3DS is mandatory under PSD2 Strong Customer Authentication (SCA) regulations for transactions involving regional cardholders.
  • Japan merchants: 3DS is mandatory for transactions with cards issued in Japan.
  • US and other markets: 3DS is optional. Activating it shifts chargeback liability to the issuer for authenticated transactions and is recommended where fraud rates are elevated.

For activation instructions and local compliance rules, see the Business Decision Matrix.

Frictionless vs challenge flow

When 3DS is active, every eligible transaction goes through an initial check. The cardholder's issuing bank decides which flow applies based on the transaction data profile:

  • Frictionless flow: The bank reviews the risk signals silently and authenticates the customer without displaying extra security prompts. The checkout experience remains identical to a standard card payment.
  • Challenge flow: The bank requires active confirmation — such as a one-time code, biometric verification, or a banking-app authorisation. The customer is redirected to the bank's security page and returned to your store after completing the challenge.

Providing a complete and consistent dataset increases the likelihood of a frictionless outcome. See How to Increase Approval Rate for the broader approval-rate strategy; the next section focuses specifically on the 3DS-relevant fields.

Maximising the frictionless rate

Banks grant frictionless approvals when they trust the incoming transaction metadata. Payments AI automatically forwards your checkout payload to the issuer during validation, so completeness on your side directly affects the outcome.

The most critical fields live inside riskMetadata on the transaction request:

FieldWhy it matters
riskMetadata.ipAddressCustomer IP at checkout. An IP whose geolocation is consistent with the billing country is a positive risk signal.
riskMetadata.fingerprintDevice fingerprint generated client-side. Keeping it stable across sessions for the same returning customer helps the bank recognise legitimate traffic.
riskMetadata.browserData.colorDepthScreen colour depth in bits. Required for 3DS2.
riskMetadata.browserData.isJavaEnabledWhether Java is enabled in the browser. Required for 3DS2.
riskMetadata.browserData.languageBrowser language (for example en-US). Required for 3DS2.
riskMetadata.browserData.screenWidthScreen width in pixels. Required for 3DS2.
riskMetadata.browserData.screenHeightScreen height in pixels. Required for 3DS2.
riskMetadata.browserData.timeZoneOffsetUTC offset in minutes (for example 300 for UTC-5). Required for 3DS2.
riskMetadata.browserData.isAdBlockEnabledWhether an ad blocker is active in the browser.
Returning-customer historyCustomers with a successful prior history on the issuer side are more likely to be authenticated frictionlessly.

Challenge flow: Step-by-step

When the issuing bank requires a challenge, your application must process through six stages.

1. Create the transaction with a redirectUrl

When constructing your initial transaction request, include a redirectUrl so the customer has a defined return path after authenticating:

curl --location 'https://api.payments.ai/v1/public-api/organizations/:organizationId/transactions' \
--header 'Content-Type: application/json' \
--header 'Authorization: ApiKey <keyValue>' \
--data '{
"customerId": "{{customerId}}",
"currency": "USD",
"amount": 99,
"type": "sale",
"paymentInstruction": {
"paymentInstrumentId": "{{paymentInstrumentId}}"
},
"redirectUrl": "https://yoursite.com/{id}/{result}"
}'

The {id} and {result} placeholders are automatically populated by Payments AI when routing the customer's browser back to your site.

2. Check the response for status: waiting

If the bank requires a challenge, the API response returns status: "waiting" alongside an approvalLink:

{
"data": {
"id": "txn_abc123",
"status": "waiting",
"result": "unknown",
"approvalLink": "https://3ds.example/..."
}
}

If the transaction qualifies for a frictionless flow, it skips this phase entirely and completes immediately with status: "completed" and result: "approved" or "declined" — no further action is required.

When status is waiting, redirect the customer's browser to the URL in approvalLink. This sends them to the bank's secure authentication screen.

4. Customer completes authentication on the bank's page

The customer enters the one-time code, completes the biometric check, or confirms in their banking app. Payments AI does not participate in this exchange; it occurs directly between the customer and their issuer.

5. Payments AI redirects the customer back to redirectUrl

After authentication, Payments AI redirects the customer to the redirectUrl you provided, substituting {id} and {result} with the actual values:

https://yoursite.com/txn_abc123/approved
https://yoursite.com/txn_abc123/declined
https://yoursite.com/txn_abc123/abandoned

6. Read the {result} and confirm via API or webhook

The {result} parameter communicates the outcome of the authenticated transaction:

ResultMeaning
approvedThe bank authorised the payment.
declinedThe bank declined after authentication.
abandonedThe customer exited the authentication interface without completing it.
canceledThe transaction was voided.
unknownFinal result not yet determined; poll the transaction or wait for the webhook.

For the authoritative final state, retrieve the transaction by ID or handle the incoming webhook. The transaction statuses relevant to 3DS are:

StatusMeaning
waiting3DS authentication required — redirect the customer to approvalLink.
offsiteThe transaction is actively processing on the bank's validation page.
completedTransaction finished; check result for the outcome.
timeoutAuthentication or processing timed out on the issuer side.

Hosted payment form (subscriptions)

For subscription flows, customers typically complete the first payment on the hosted payment form at secure-payments.app. Payments AI manages the entire 3DS orchestration natively on this form, removing the need for custom frontend challenge logic on your side.

The hosted form handles:

  • Collecting card details (the data never reaches your server).
  • Triggering 3DS authentication when the bank requests a challenge.
  • Setting up the recurring payment token once the first payment succeeds.
  • Redirecting the customer back to your redirectUrl with the result.

See Hosted Payment Form for the full description and Create a Subscription for the end-to-end subscription flow that uses it.

Webhook notifications

When a transaction fails 3DS authentication — whether the issuer declines, the customer abandons, or a timeout occurs — Payments AI dispatches the transaction-declined webhook. See Transaction Declined webhook. For the full event payload structure, see the Webhooks schemas.

Testing

Payments AI provides dedicated test card numbers for every 3DS scenario, including frictionless successes, forced challenges, frictionless declines, and non-3DS cards. Run these validation checks on the staging environment before switching to production credentials.

See Test Cards for the full list.