A 3-D Secure authentication is its own exchange, and it is not ISO 8583. The merchant's 3DS server talks to the scheme's directory server and the issuer's access control server over HTTPS, in JSON, and gets back an authentication response carrying a transStatus.
The authorization is a separate exchange, later, in ISO 8583. It carries an ECI — a two-digit e-commerce indicator saying what happened at the authentication step — plus the cryptographic evidence for that claim.
Nothing links the two automatically. Something in your stack has to take the result of the first exchange and attach it to the second. In most architectures that is a hand-off between two services, and it is where this goes wrong.
Liability does not move because 3-D Secure succeeded. It moves because the authorization arrived carrying the authentication result, so the scheme stamped it with an authenticated — or attempted — ECI. The ECI is what a dispute is judged on.
That distinction is invisible when everything works and decisive when it does not. If the authentication result never reaches the authorization, the scheme sees an ordinary unauthenticated e-commerce transaction. The ECI reflects that. Meanwhile your 3-D Secure logs still show a clean success, because the authentication genuinely did succeed. Both records are accurate; they are describing different things.
This is the usual explanation for “we passed 3DS and still got charged back”. Not a scheme error, not an issuer error — a hand-off that dropped a field.
One more thing worth knowing before you rely on it: an attempted outcome normally shifts liability too, which surprises people. Under the general rules, having tried is enough. Exemptions, regional rules and product-specific carve-outs all exist, so for a specific case the scheme's own rules are the authority, not this page.
Both schemes report the same three outcomes and number them in opposite directions.
| Outcome | Visa | Mastercard | Liability |
|---|---|---|---|
| Cardholder authenticated | 05 | 02 | Moves to the issuer |
| Attempted, not completed | 06 | 01 | Moves to the issuer |
| No authentication | 07 | 00 | Stays with the merchant |
For Visa a higher number is a worse outcome; for Mastercard a higher number is a better one. So a gateway field that flattens both schemes into one eci value will behave correctly for half your traffic and wrongly for the other half, with no error anywhere. The ECI decoder takes a value and a scheme and tells you which of these you are looking at, including the case where the value does not belong to the scheme you picked.
Mastercard's own documentation may not use the term ECI at all — it carries the e-commerce security level in its UCAF Security Level Indicator, and the 00/01/02 your payment API calls “eci” is that concept reshaped by the gateway into Visa's form.
The order matters. Each step is cheap and rules out a whole class of cause, so working down the list beats guessing.
1. Establish which scheme's table you should be reading. A 06 is “attempted, liability moved” for Visa and not a value at all for Mastercard. Check the scheme from the PAN before you interpret the digits. This one step rules out every bug of the form “we treat 05 as authenticated”, which is the most common and the easiest to miss, because it only ever breaks half the traffic.
2. Check that the ECI and the transStatus describe the same authentication. A retry, an expired session or a re-initiated checkout all produce a fresh authentication with a fresh transStatus. Two values sitting next to each other in a log are not necessarily from the same attempt.
3. If authentication succeeded but the ECI says otherwise, look at what the authorization actually carried. This is the hand-off from the previous section. The authorization is often built by a different service than the one that ran 3-D Secure; a retry path, an unmapped field or a queue that reconstructs the request will all silently drop the authentication result. Compare the authorization you sent against the one you meant to send, field by field.
4. If transStatus was C and you treated it as a decline, that is the bug. C means the issuer wants to challenge the cardholder and the flow is unfinished. A checkout that reads it as failure throws away transactions that would have completed. Read the final outcome from the result message after the challenge, not from the first response.
5. If transStatus was R, do not authorize. The issuer is explicitly asking you not to. Sending it anyway generally produces a decline you could have avoided, and it is a decline you cannot blame on anything else.
6. If the liability outcome is what does not add up, the ECI is the authority. The transStatus tells you what the authentication step believed; the ECI is what the scheme acted on. You need both to say which half broke, but only one of them settles the dispute.
7. If all of that lines up and the result is still wrong, the remaining causes are not public. Whether the cryptographic value was valid, whether it was placed in the subfield your acquirer expects — those live in the scheme's interface specification and, for validation, need the issuer's keys. That is the point to open the specification your acquirer gave you rather than search for it.
The ECI is a summary of a claim. The evidence is a cryptographic value carried with it — a CAVV for Visa, an AAV inside the UCAF for Mastercard.
This site does not publish their internal layout, or which subfield of DE48 carries them, because those are defined in each scheme's licensed interface specification rather than in a public standard. The same rule keeps other scheme-proprietary structures off this site. What is here is the part that is publicly documented, and the reasoning you can check.
→ Decode an ECI against the right scheme