3DS2 in Mexico Is Not PSD2: An Engineer's Guide to 3-D Secure Without the EU SCA Rules — Cesar Ayala
← All posts

3DS2 in Mexico Is Not PSD2: An Engineer's Guide to 3-D Secure Without the EU SCA Rules

3DS2 is EMVCo's card-authentication protocol (frictionless or challenge flow). SCA is a PSD2 mandate for the EEA and UK — Mexico is not subject to it, and the EU low-value and TRA exemptions do not exist in Mexican law, so never hardcode them. You still use 3DS2 in Mexico as a business decision: the fraud liability shifts to the issuer. Trigger it through your PSP.

What 3DS2 actually is: frictionless flow vs challenge flow

3-D Secure 2 (3DS2) is EMVCo’s card-authentication protocol — the technical handshake that lets a card issuer verify a cardholder during an online purchase. SCA (Strong Customer Authentication) is a completely different thing: it is a legal mandate under PSD2 that applies in the EEA and the UK, and Mexico is not subject to it. In Mexico you still use 3DS2, but as a business decision — authenticating a payment shifts fraud-chargeback liability to the issuer. You do not build it yourself; you trigger it through your PSP.

3DS2 has two outcomes once your PSP kicks it off:

  • Frictionless flow: the issuer risk-assesses the transaction from device and context data (device fingerprint, browser data, purchase history) and approves it with no user interaction at all. The cardholder never sees a screen.
  • Challenge flow: the issuer decides it needs a step-up and asks for proof — an OTP sent by SMS, a biometric prompt, or an approval inside the bank’s mobile app.

The important nuance for engineers: you do not choose the flow. You ask your PSP to attempt 3DS2, and the issuer decides frictionless vs challenge based on its own risk model. You control whether authentication is requested, not whether the user gets challenged.

  1. You request 3DS2Your PSP starts the authentication on the PaymentIntent / charge.
  2. Issuer risk-assessesDevice and context data go to the issuer's model.
  3. FrictionlessIssuer approves silently — no user screen, liability shift obtained.
  4. ChallengeIssuer steps up: OTP, biometric, or bank-app approval before approval.

The #1 misconception: SCA is a PSD2 mandate for the EEA and UK, not Mexico

Here is the correction that this whole post exists for: SCA is a PSD2 requirement, and PSD2 is European law. PSD2 SCA took effect on December 31, 2020 in the EEA and on September 14, 2021 in the UK. It requires strong (two-factor) authentication on most electronic card payments in those jurisdictions.

Mexico is not in the EEA and not in the UK. There is no Mexican statutory SCA mandate. No CNBV, Banxico, or DOF rule says “you must strongly authenticate this card payment.” So if your mental model is “I need SCA to be compliant in Mexico,” that model is wrong — you are importing a foreign regulation into a market it does not cover.

This matters because engineers copy checkout logic. If you lifted a Stripe or Adyen integration built for a European merchant, it very likely contains SCA-specific branching — exemption flags, challengeIndicator presets tuned for EEA rules, low-value skip logic. Ported into a Mexican checkout, that code is not just useless; it can make wrong decisions about when to authenticate, because it was optimizing against a rulebook that does not apply here.

If you also handle SPEI or CoDi rails, note that Mexican payment regulation lives in Banxico rules like the ones covered in Banxico Nivel 2 Bis for SPEI and CoDi — a genuinely Mexican framework — not in a card-scheme SCA import.

The exemptions trap: the EUR 30 low-value and TRA thresholds are EEA-only — do not hardcode them for MX

This is where teams get burned. PSD2 does not just mandate SCA — it also defines exemptions from SCA, and those exemptions come with hardcoded thresholds:

  • The low-value exemption: transactions under roughly EUR 30 can skip SCA (with cumulative counters).
  • The transaction-risk-analysis (TRA) exemption: at fraud-rate bands, transactions up to roughly EUR 100 / 250 / 500 can skip SCA.

Every one of those numbers is an EEA construct. They exist so European merchants can avoid an authentication that European law would otherwise force on them. In Mexican law there is no SCA mandate, so there is nothing to be exempted from. Hardcoding “if amount is under EUR 30, skip authentication” into a Mexican checkout is implementing an EU regulation that does not apply to your business.

The failure mode is subtle and expensive: a EUR-30 low-value branch silently suppresses the very 3DS2 request that would have given you the issuer liability shift on a fraudulent order. You did not gain compliance (there was none to gain) and you gave up your fraud protection.

EUR 30 low-valueAn EEA PSD2 exemption threshold. Not Mexican law. Do not hardcode it for MX.
EUR 100 / 250 / 500 TRAEEA transaction-risk-analysis bands. Do not hardcode them for MX.
SCA exemption flagsSuppressing 3DS2 by EEA rules can cost you the MX liability shift.

So delete the EEA thresholds. In Mexico, whether you authenticate is a risk-and-liability decision you make with your own rules — not a table of euro cutoffs.

So why use 3DS2 in Mexico at all? The liability shift and fraud reduction

If no regulator requires it, why bother? Two reasons, both commercial:

  1. The liability shift. When a card payment is authenticated with 3DS, liability for a fraud-related (“unauthorized” / fraud) chargeback shifts from the merchant to the issuer. Without authentication, you eat that fraud chargeback. With a successful 3DS authentication, the issuer generally does. That is the single biggest reason merchants in Mexico turn 3DS2 on.
  2. Fraud reduction. The challenge flow raises the bar for a fraudster using stolen card data — they now need the real cardholder’s OTP or bank-app approval, which they usually cannot get.

In Mexico this is driven by the card networks (Visa, Mastercard) and your acquirer/PSP commercially — through scheme rules and liability programs — not by a regulator. It is a business call about how much fraud loss you want to carry, not a compliance checkbox.

This ties directly into your dispute strategy. The liability shift only helps against fraud chargebacks — it does nothing for “product not received” or service disputes. For the full picture on fighting those, see win chargebacks in Mexico with Conekta and Mercado Pago and, on the Stripe side, Stripe disputes, chargebacks, and Radar.

3DS2 authenticated

  • Fraud-chargeback liability shifts to the issuer
  • Stolen-card use is harder (OTP / biometric / bank app)
  • Possible added checkout friction on challenge flow

Not authenticated

  • You carry fraud-chargeback liability
  • Zero authentication friction at checkout
  • Fraud rings target unauthenticated flows

How you actually turn it on: your PSP runs the flow

You do not implement the EMVCo protocol, the ACS handshake, or the challenge UI. Your PSP runs the flow — Stripe, Conekta, Mercado Pago, Adyen. Your job is to tell the PSP when to attempt authentication and then read the result off the resulting charge.

On Stripe, this is a per-PaymentIntent option. You set payment_method_options.card.request_three_d_secure to automatic (let Stripe/the network decide) or any (request it whenever the card supports it, to always pursue the liability shift), then inspect the authentication outcome on the charge:

import stripe

intent = stripe.PaymentIntent.create(
    amount=149900,          # MXN in centavos
    currency="mxn",
    payment_method=payment_method_id,
    confirm=True,
    payment_method_options={
        "card": {
            # "automatic" = network/Stripe decides.
            # "any" = request 3DS whenever supported (pursue liability shift).
            "request_three_d_secure": "any",
        }
    },
)

# Read the outcome off the resulting charge — do NOT assume it authenticated.
charge = stripe.Charge.retrieve(intent.latest_charge)
three_ds = charge.payment_method_details.card.three_d_secure
# three_ds may include authentication_flow ("frictionless"/"challenge")
# and the resulting liability-shift indicator.

The exact field names drift, so confirm them against your PSP’s current docs. Conekta and Mercado Pago expose their own equivalents — Mercado Pago, for example, surfaces 3DS as part of its token/charge flow rather than a Stripe-style option; the integration shape differs and is covered in how to integrate Mercado Pago. For choosing a PSP in the first place, see payment gateways in Mexico.

The load-bearing engineering rule: never assume authentication succeeded — read the outcome off the charge. Requesting 3DS2 is not the same as getting the liability shift; the issuer can still decline the authentication.

When to trigger: always-for-liability-shift vs risk/rules-based

You have two sane strategies, and they are both legitimate because you own the tradeoff — no regulator does.

  • Always-for-liability-shift: request 3DS2 on every order (or every order above a self-chosen risk floor) so you always pursue the issuer liability shift. Simplest to reason about; more challenge friction.
  • Risk/rules-based: request 3DS2 only when your own signals say the order is risky — new customer, mismatched geo, high amount, velocity spikes — and let low-risk orders through frictionlessly.

Here is rules-based selection in PSP-agnostic pseudo-code. Note the thresholds are your risk numbers, denominated in MXN, not ported EUR PSD2 cutoffs:

def should_request_3ds(order, customer) -> bool:
    # These are OUR risk rules, in MXN — not EEA PSD2 exemption thresholds.
    if order.amount_mxn >= 5000_00:          # high-value orders
        return True
    if customer.is_new or customer.card_country != "MX":
        return True
    if customer.orders_last_hour >= 3:       # velocity signal
        return True
    return False  # low-risk: let the frictionless/no-3DS path run

# Then map the boolean to your PSP's field, e.g. Stripe:
#   request_three_d_secure = "any" if should_request_3ds(...) else "automatic"

Whichever you pick, tune it with signals — never with a EUR table.

The tradeoff: false declines and cart abandonment vs carrying fraud liability

Authentication is not free. Every time the issuer picks the challenge flow, you insert an OTP or bank-app step into checkout, and some real customers drop off there — that is cart abandonment and, when a legitimate order fails the step-up, a false decline. Over-trigger and you lose good revenue to friction. Under-trigger and you carry more fraud-chargeback liability yourself.

Over-trigger 3DS275
Balanced rules40
Under-trigger 3DS280

The bars above are illustrative — the point is that both extremes cost you, in different currencies (lost conversions vs. absorbed fraud). Find the middle with risk rules, iterate on real data, and treat it like any other conversion-vs-loss optimization. If your fraud tooling also touches customer PII, keep it clean before it hits any model — see redact Mexican PII (CURP/RFC/CLABE) before the LLM.

A note on uplift numbers and confirming current rules before you ship

You will see vendors cite “3DS2 gives +X% authorization uplift.” Treat every such figure as a vendor estimate, not a Mexico-specific fact. Authorization behavior depends on your issuer mix, your PSP, your card portfolio, and your fraud profile — a number from a European case study or a PSP’s marketing page is not a prediction for your Mexican checkout. If you need a number, measure your own before/after.

And the standing caveat: card-network rules and acquirer requirements evolve. Field names, default behaviors, and liability-program specifics change over time. Before you ship:

  • Confirm the exact PSP fields and the authentication-result shape against your PSP’s current docs.
  • Confirm current Visa/Mastercard and acquirer behavior with your PSP or acquirer directly.
  • Keep the EEA PSD2 exemption thresholds out of your Mexican code entirely.

This is engineering guidance, not legal or card-scheme compliance advice. I ship payments in Mexico; I am not your lawyer or your scheme-compliance vendor. For adjacent Mexican regulatory obligations that are real law — data protection under LFPDPPP — see comply with LFPDPPP 2025 in your SaaS, and the broader LATAM payments hub for the rest of the stack.

Sources: