Skip to main content
3D Secure (3DS) adds an issuer authentication step to a card payment. A successful authentication can shift liability for fraud-related chargebacks from you to the card issuer. RadiumOne supports 3DS across the integration grid, with the depth of support varying by row and column.

Frictionless vs. challenge

Every 3DS attempt resolves in one of two ways:
  • Frictionless: the issuer authenticates the shopper using risk signals alone (device data, transaction history). No shopper interaction. This is the fastest path and the outcome you should design for by default.
  • Challenge: the issuer isn’t confident enough and asks the shopper to prove their identity — a one-time passcode, a banking app approval, or biometrics — inside a visible frame or a redirect. See Challenge presentation and redirects.
A third outcome, decoupled authentication, lets the shopper approve out-of-band (for example in their banking app) while your checkout page polls for the result.

3D Secure across the integration grid

  • Hosted checkout (redirect or embedded) — 3D Secure available, Beta.
  • Elements + Payments API — 3D Secure available.
  • Elements + your own 3DS provider — bring your own 3DS evidence, Beta, gated.
Compare these against the full 2x3 grid on Choose your integration.

Amount rules

3DS authenticates a specific amount, and the gateway enforces that the amount you authenticate is the amount you later charge:
  • Every checkout session has a gross amount (session amount, plain integer minor units).
  • If you redeem loyalty points or another deduction against the same session, pin the actual card-charged amount with PATCH /v1/sessions/{id} (net_payable_amount) before the browser calls authenticate(). 3DS then authenticates the net amount, not the gross.
  • At purchase time, the gateway checks the three_ds.ref was authenticated for a session whose (possibly net-payable) amount matches the charge. A mismatch returns 422 urn:radiumone:three-ds:amount-exceeds-authenticated.
Amounts are always integers in the currency’s minor unit. For example, 5000 for SGD means SGD 50.00.

Server policy

Charge a 3DS-required order only with a valid three_ds.ref obtained from that checkout’s own session flow — unless you deliberately accept the risk of a non-3DS payment (by omitting three_ds, or sending {mode:"non_payer_auth"}). Never branch on the client-reported 3DS status to decide whether to charge, or to decide liability. The client status only drives your UX (for example, showing a decline instead of submitting the payment) — the gateway independently validates the ref at purchase time (single-use, unexpired, authenticated, and matching token/currency/amount) and rejects the charge otherwise.

Non-3DS payments

You can omit three_ds entirely, or send {mode:"non_payer_auth"} to record that you deliberately skipped authentication. Some acquirer mandates require 3DS for a given card, region, or amount; if you omit it where required, the purchase or authorize call fails with 422 urn:radiumone:three-ds:authentication-required.
Never use a secret key (r1sk_…) in browser code, mobile apps, or anywhere a shopper can inspect it. Secret keys belong on your server only.

Next steps

3DS with Elements

Authenticate in the browser and charge with the resulting ref.

Use your own 3DS provider

Bring externally-produced 3DS evidence to a charge.

Challenge presentation and redirects

Iframe, modal, decoupled and redirect challenge flows.

Authentication results

Status meanings, ECI values and 3DS error remedies.
Last modified on September 15, 2026