How 3DS Appears in Transactions & Orders
Every standalone 3DS journey now creates an Order and a Transaction the moment you call the Initialisation API. This makes the whole 3DS journey visible in the Merchant Portal and over webhooks — including journeys that fail or are abandoned before any payment is attempted.
This page explains what these records are, how their status changes during the 3DS flow, and how to interpret them.
This applies to the standalone 3DS APIs (/3ds/v2/initialization and related calls). Hosted Payment Page (HPP) transactions create their own order and transaction through the HPP flow and are not affected.
Why you see an Authorization you didn't make
When the Initialisation API is called, NetValve does not yet know whether the journey will end in a Sale, an Authorization, or nothing at all — the payment call comes later, if it comes at all. So the record is created as:
| Field | Value at 3DS initialisation |
|---|---|
| Transaction type | Authorization (provisional — see below) |
| Transaction status | Pending |
| Order status | Pending |
| Amount / currency | From the initialisation request |
| Card details | Masked card number and card type |
The type is Authorization because nothing has been charged at 3DS time. It is a provisional type:
- If you follow up with a Sale or Authorization call carrying the 3DS values, the same transaction record is reused and updated — the type is overwritten with the real one, and the record continues its life as a normal payment transaction under the same transaction ID and order ID.
- If the journey fails at a 3DS step, the record is declined with a
3DS_response code, so the failure is visible even though no payment was ever attempted. - If the journey is abandoned, the record simply stays Pending.
Status lifecycle
3DS Initialisation called
→ Order: Pending, Transaction: Pending (type Authorization)
Challenge required / device data collection / authentication in progress
→ stays Pending
3DS authentication successful
→ stays Pending (nothing is charged until you call /sale or /authorize)
3DS step fails (initialisation, authentication, challenge, or result)
→ Transaction: Declined, Order: Declined
→ Response code: 3DS_2xxx, response message: the actual failure reason
→ Webhook: AUTHORISATION_FAILED
Sale/Authorization called with the 3DS values
→ same transaction is reused and processed as a normal payment
→ type, status and response codes now reflect the actual payment
Customer abandons / journey never completes
→ stays Pending (never charged, never declined)
Only terminal 3DS failures decline the record. All intermediate and successful 3DS states keep it Pending, because a successful authentication still needs your Sale or Authorization call before any money moves.
New response fields on the 3DS APIs
The 3DS API responses now return the linked payment record so you can correlate the 3DS journey with the transaction and order:
{
"responseCode": "3DS_1000",
"responseMessage": "Three DS Transaction Successful.",
"transactionID": 1048291,
"orderId": 993412,
"orderState": "PENDING",
"threeDSProviderResponse": {
"transID": "c19d5b5b-0dd6-47f4-98ad-096f319cd8c6",
"...": "..."
}
}
| Parameter | Type | Description |
|---|---|---|
| transactionID | Long | The payment transaction created for this 3DS journey. When you later call Sale/Authorization with the 3DS values, the payment is recorded under this same transaction ID. |
| orderId | Long | The order created for this 3DS journey. The follow-up sale is recorded under this same order. |
| orderState | String | PENDING (journey in progress / awaiting payment), DECLINED (3DS failed or payment declined), PAID (payment completed). |
Do not confuse transactionID (the payment transaction) with threeDSProviderResponse.transID (the 3DS transaction used in the 3DS API calls). They are different identifiers.
Interpreting these records
| What you see | What it means |
|---|---|
| Type Authorization, status Pending, no response code | 3DS journey in progress, or the customer abandoned it, or 3DS succeeded but no Sale/Authorization call followed. No payment was attempted. |
Type Authorization, status Declined, response code 3DS_2xxx | The journey ended at a 3DS step. The response code tells you which step and why (see below). This is not a bank decline — the card was never sent to the bank. |
| Type Sale or Authorization, bank/processor response codes | 3DS completed and a real payment was attempted. Interpret as any normal transaction. |
Key takeaway for reconciliation: a Pending or 3DS-declined record means the cardholder was never charged. The 3DS_2xxx codes describe authentication outcomes, not payment outcomes.
Impact on approval rates and reporting
Since this feature was released, your transaction data contains records that did not exist before: journeys that failed or stopped at 3DS. Your real approval rate at the bank has not changed — declines that were previously invisible are now recorded. If your reports suddenly show more transactions and more declines, this is why.
What this means in practice:
- NetValve portal approval-rate charts are not affected. They only count transactions that received a bank response, and they count per order. Transactions declined at 3DS never reached a bank, carry no bank response code, and are excluded automatically.
- Transaction listings, exports, and webhooks now include 3DS-only declines. If you calculate approval rates yourself from these feeds, your denominator has grown, and your computed rate will appear to drop — without any change in bank behaviour.
To keep your own reporting consistent:
| Metric you want | How to compute it |
|---|---|
| Bank approval rate (comparable to before this feature) | Exclude transactions whose response code starts with 3DS_ (equivalently: transactions with no bank response code). These never reached the bank. |
| Full checkout conversion (new — previously not measurable) | Include everything. 3DS_2xxx declines show where customers fail authentication; Pending records show abandonment. |
| 3DS pass rate | 3DS-completed journeys ÷ started journeys, using the 3DS_ records alone. |
The new records are additional signal, not extra failures: a spike in 3DS_2017 (authentication failed) or a high abandonment count points at checkout friction that used to be invisible.
3DS decline codes
When a journey fails at a 3DS step, the transaction's response code is the 3DS_ code below and the response message carries the actual failure reason from the 3DS provider.
| Code | Meaning |
|---|---|
| 3DS_2000 | Authentication declined without a specific reason code. Despite the generic name, this is almost always a real decline by the cardholder's issuer or their Access Control Server (the card was not authenticated, or the authentication was rejected) where the 3DS provider did not supply a more specific reason. It is not, in the vast majority of cases, a NetValve technical error. Rarely, this code is also used as a fallback for provider connection failures. |
| 3DS_2008 | 3DS processing error from the gateway. |
| 3DS_2010 | Device data was not collected by the browser — the authentication call was made before/without device data collection. |
| 3DS_2011 | The ACS challenge was not completed by the cardholder — the result call was made before/without challenge completion. |
| 3DS_2012 | Authentication rejected by the provider. |
| 3DS_2013 | Authentication unavailable — the payer could not be authenticated due to a technical or other issue. |
| 3DS_2014 | Authentication required but was not provided. |
| 3DS_2015 | No authentication information associated with this transaction. |
| 3DS_2016 | The requested authentication method is not supported for this payment method. |
| 3DS_2017 | Authentication failed — the payer was not authenticated. Do not proceed with the payment. |
| 3DS_2018 | Invalid 3DS transaction ID. |
| 3DS_2019 | Required 3DS field missing — dsTransactionId, eci and cavv must be provided. |
| 3DS_2020 | Invalid 3DS field — xid and cavv must be Base64 encoded when provided. |
Request-validation codes (3DS_2001–3DS_2009) are returned on the API response only; see API Status Codes.
3DS_21xx — provider reason codes
When the 3DS provider returns a specific reason for the failure, the transaction carries a 3DS_21xx code instead of the generic 3DS_2000, and the response message states the exact reason. Most of these map directly to the EMV 3DS transStatusReason values, e.g.:
| Code | Meaning |
|---|---|
| 3DS_2101 | Card authentication failed. |
| 3DS_2105 | Expired card. |
| 3DS_2106 | Invalid card number. |
| 3DS_2108 | No card record. |
| 3DS_2111 | Suspected fraud. |
| 3DS_2112 | Transaction not permitted for cardholder. |
| 3DS_2114 | Transaction timed out at the ACS. |
| 3DS_2119 | Exceeds ACS maximum challenges. |
| 3DS_2126 | Authentication attempted but not performed by the cardholder. |
| 3DS_2187 | Transaction excluded from attempts processing (e.g. non-reloadable prepaid cards, non-payment authentications). |
| 3DS_2189 | Card not enrolled in EMV 3DS, or issuer rejecting authentication. |
All 3DS_21xx codes are declines originating from the card scheme, issuer, or the issuer's Access Control Server — not NetValve errors. The response message on the transaction always carries the precise reason text.
Webhooks
When a 3DS step fails and the record is declined, an AUTHORISATION_FAILED webhook is sent with the transaction ID, order ID, the 3DS_2xxx response code and the failure reason. Previously, a payment that died at 3DS produced no notification at all — now you can react to it (e.g. prompt the customer to retry) without polling.
Once a real Sale/Authorization is processed on the record, webhooks behave as for any normal payment.
FAQ
Was my customer charged?
Not unless the record shows a completed Sale/Authorization with bank response codes. Records that are Pending, or Declined with a 3DS_2xxx code, never reached the bank.
Why did my approval rate drop after this release?
It didn't — see Impact on approval rates and reporting. Declines that used to be invisible (customer failed or abandoned 3DS) are now recorded. Exclude 3DS_-coded transactions to reproduce your previous bank approval rate.
Why do Pending records accumulate? Every started 3DS journey creates one. Journeys the customer abandons stay Pending — this is expected and reflects real drop-off in your checkout. Use the portal filters to include or exclude pending records.
Do I need to change my integration?
No. This is a visibility feature. Optionally, you can start using transactionID / orderId from the 3DS responses to correlate records, and consume the AUTHORISATION_FAILED webhook to detect failed authentications in real time.
Why does my sale show up under a transaction/order that existed before the sale? Because the sale reuses the record created at 3DS initialisation, so the whole journey — authentication and payment — lives under one transaction and one order instead of disconnected records.