Skip to main content
This feature is in Beta. Behavior may change before general availability, and production access depends on your RadiumOne rollout. Contact support to confirm availability for your account.
If you already run 3D Secure through your own MPI (merchant plug-in) or a third-party authentication provider, you can bring the resulting evidence to a RadiumOne charge instead of using RadiumOne’s built-in 3DS. Elements is only used to tokenize the card for the charge — your provider runs 3DS independently. When you use your own 3DS provider, your 3DS provider handles card data outside Elements. Confirm your provider’s PCI DSS scope and how card data flows between your provider and RadiumOne before you go live.

How it works

  1. The shopper’s card is tokenized with Elements as usual (elements.submit(), without calling threeDS()).
  2. Your 3DS provider authenticates the shopper using its own access to the card — it doesn’t receive anything from Elements.
  3. Your server charges with the card token plus the evidence your provider returned.

Before you begin

This path requires per-outlet enablement. Without it, the charge is rejected with 422 urn:radiumone:three-ds:external-auth-not-permitted.

Steps

1

Create a session and tokenize the card

Create a tokenization session and mount Elements as usual. Don’t call radiumone.threeDS() on this path — you’re not using RadiumOne’s 3DS.
2

Authenticate with your own 3DS provider

Run your own 3DS integration (AReq/ARes/CReq) however you already do today. This happens entirely outside RadiumOne. Collect at minimum the scheme’s ECI, the CAVV (or AAV), and the directory server transaction ID.
3

Charge with the provider's evidence

Send the card token and your provider’s evidence to your server, then purchase or authorize with the three_ds evidence arm. API reference: purchase · API reference: authorize.
If the charge is rejected, see Handle 3DS failures with your own provider.

Handle the result

Any 2xx response is a result you must branch on status — never on response_code (that’s the verbatim host/acquirer code; useful for support tickets, not for your app logic).
Balance inquiry also takes a request_id field, but it isn’t an idempotency key — there’s no dedup or replay store. Every call re-queries the rewards host, even with the same request_id.
Keys are 8–64 characters, [a-zA-Z0-9-] only, unique per merchant account. Generate one key per order attempt and persist it to your database before you send the first request — never mint a new key just to retry the same attempt. See Prevent duplicate payments.
PENDING means the outcome isn’t known yet — most often after a processor timeout. Don’t assume success or failure. Recover it one of two ways:
  1. Wait for a webhook (payment.*, authorization.*, refund.* — see Webhook event types).
  2. Call GET /v1/transactions/{id}/status for a live inquiry against the acquirer.
If you don’t have the transaction id yet — a client-side timeout before the first response arrived — replay the same request with the same request_id and body. The replay returns the stored transaction and its id, whatever status it’s reached. Never re-submit with a new idempotency key just because the first attempt is slow — that risks a second charge for the same order.

Errors specific to this path

The two errors you’re most likely to hit on this path are three-ds:external-auth-not-permitted (your outlet isn’t enabled — see Before you begin) and gateway:validation-error (a three_ds field is missing, too long, or an unrecognized key was sent — the evidence arm rejects unknown keys). For the full 3DS error reference with HTTP codes and remedies, see Authentication results.

ECI values

The electronic commerce indicator (ECI) your provider returns determines whether liability shifts to the issuer:

Limitations

  • No 3DS1. Only 3DS2 evidence is accepted — there’s no xid field, so a provider that only supports 3DS1 can’t use this path.
  • Fields: cavv (≤64 chars), eci (≤2 chars), ds_transaction_id (≤64 chars), version (≤10 chars). Unknown keys in the same object are rejected.
  • Merchant-asserted evidence. RadiumOne doesn’t independently verify the CAVV or ECI you submit — it trusts your provider’s result. Make sure your own integration validates the ARes/RReq signature before you submit its fields here.

Server policy

Charge only after your own 3DS provider has returned a verified result for this checkout attempt — never submit placeholder or reused evidence, and never charge based on a client-reported outcome your server hasn’t independently confirmed came from your provider.
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.

Test your integration

See Test your integration for scenario coverage.

Go-live notes

  • Confirm enablement for this outlet before relying on this path in production.
  • Keep your provider’s evidence validation server-side; never trust values that could originate from the browser.
  • Review the go-live checklist before launch.

Next steps

3D Secure overview

Compare this path against RadiumOne’s built-in 3DS.

Security and PCI scope

PCI scope per integration path.
Last modified on September 15, 2026