The first time you store a card and charge it later, you are not just saving a token. You are entering a scheme framework with its own flags, identifiers and decline behaviour, and most teams discover this only when an issuer starts bouncing their renewal run in the EEA. Charge a saved card without telling the network it is a stored credential, and you are one authentication_required away from a subscription book that quietly stops billing.
This guide sits underneath several others on this site. The card authorisation expiry windows differ for merchant-initiated transactions; the decline-code retry rules change when the cardholder is not present. Both assume you already know what makes a transaction a stored credential. Here is the framework itself: what Visa and Mastercard require, how the three major PSPs express it, and the identifier you have to thread through every charge or lose.
What Is a Stored Credential in Card Payments?
A stored credential is a card number (or its network token) that a merchant keeps on file to charge again without the cardholder re-entering it. The card schemes treat the act of storing and the act of reusing as two separate, regulated events. The transaction that establishes the credential must be a cardholder-initiated transaction, a CIT, where the customer is actively in the flow and consents to storage. Every later charge the merchant triggers on its own is a merchant-initiated transaction, an MIT.
That split is the whole game. An MIT can only exist legitimately if a CIT came first and captured consent. Get the order or the flags wrong and the issuer sees an MIT with no mandate behind it, which is exactly the shape of card-testing fraud. It is also why a saved card is not the same thing as a network token: the token is how the PAN is stored safely, the stored-credential framework is the rules about when you are allowed to use it.
Cardholder-Initiated vs Merchant-Initiated Transactions
The practical test for CIT versus MIT is presence. If the cardholder is in session and could complete a challenge, it is a CIT. If the charge fires on a schedule, after a trigger, or at a time only the merchant chooses, it is an MIT.
That boundary decides authentication liability. A CIT in the UK or EEA is in scope for Strong Customer Authentication and may need a 3-D Secure challenge. An MIT is out of scope, because nobody is present to authenticate. The schemes accept that trade for one thing: proof that the original CIT was authenticated and consented. Lose the proof and the exemption evaporates.
This is where a subtle production bug lives. Teams tag every saved-card charge as "recurring" because it feels right, including the ones where the customer is on the checkout page clicking pay with a stored card. That charge is a CIT, and flagging it merchant-initiated throws away an authentication you could have used.
Visa vs Mastercard Stored Credential Rules
Both schemes run the same shape of framework and name its parts differently, which is the source of most integration confusion.
Visa's Stored Credential Transaction Framework returns a unique identifier on the initial authorisation and requires you to pass it back on every subsequent MIT so the issuer can link the chain. Stripe's own documentation spells out the naming across networks: "Visa calls this the Transaction ID, Mastercard calls this the Trace ID, and American Express calls this the Acquirer Reference Data." In a PSP-neutral API it surfaces as network_transaction_id.
The Mastercard side is mid-transition, and it matters if you are building now. The legacy Trace ID was assembled by the acquirer from the Financial Network Code, the Banknet Reference Number and the Banknet settlement date. Because the acquirer generated it, the same value could collide across acquirers, which made cross-processor chains unreliable. Mastercard is replacing it with a scheme-generated Transaction Link Identifier, the TLID: a 22-character alphanumeric string assigned centrally and threaded from the first CIT through the life of the credential. The phase-in runs across 2025 to 2027, with merchants expected to store and replay the TLID before compliance assessments begin. Treat the exact milestone dates as PSP-briefing and confirm them against a Mastercard operations bulletin, but the direction is settled: the identifier is moving from the acquirer's hands into the scheme's.
The engineering consequence is identical on both networks. Capture the scheme identifier from the initial response, persist it against the stored credential, and send it on every MIT. Skip it and issuers are entitled to decline, because there is no evidence the charge belongs to a consented series.
Recurring, Instalment and Unscheduled Card-on-File
The MIT flag alone is not enough. You also have to say what kind of MIT it is, because issuers score the types differently and apply different reattempt rules.
The standing-instruction types are the three you will use most:
| Type | When it fires | Amount | Example |
|---|---|---|---|
| Recurring | Fixed schedule | Fixed or known | Monthly SaaS seat |
| Instalment | Fixed schedule | Known split of one purchase | Pay-in-4 on a single order |
| Unscheduled card-on-file | No schedule | Variable | Account top-up, usage overage |
Beyond those sit the industry-practice types for the awkward one-offs: resubmission (re-sending a failed recurring charge), delayed charges, reauthorisation, no-show, and partial shipment. These are still MITs, but not standing instructions.
Getting the type right is not pedantry. An unscheduled card-on-file charge can vary in amount and the issuer expects that; a recurring charge that suddenly changes amount looks wrong. The type is the context the issuer uses to judge whether the variable charge in front of it is legitimate.
How the Initial Network Transaction ID Chains Every MIT
Here is the single detail a pricing page will never show you, and the one that breaks the most renewal runs.
The flow is: run the CIT, read the scheme transaction identifier off the authorisation response, store it, and send it back on every MIT for the life of that credential. One identifier, captured once, replayed forever. Stripe handles this invisibly: when you charge a saved card off-session it marks the payment as an MIT and attaches the stored identifier itself, then exposes it read-only on the resulting Charge at payment_method_details.card.network_transaction_id (added in the 2024-12-18 Acacia API release). You never set it; you can only read it back.
The fragile moment is migration. When you move a card book between processors, the network transaction ID has to travel with it. Stripe's card-import process carries a "Network Transaction IDs" column and marks it mandatory for SCA-impacted merchants, because that identifier is the proof the original CIT was authenticated. Arrive without it and every imported card looks like a fresh, unauthenticated credential. The import moves over SFTP as a PGP-encrypted CSV, not through the live API, which surprises teams who assume everything is an endpoint now.
The other silent chain-breaker is the card brand changing underneath you. If an account updater swaps a saved Visa for a Mastercard, Stripe's rules say you cannot charge it as an MIT until you obtain a fresh cardholder agreement. You detect it by watching the payment_method.automatically_updated event and comparing brand against previous_attributes. Most billing systems do not, and the first sign of trouble is a cohort of renewals failing for no obvious reason.
Stripe vs Adyen vs Checkout.com: Storing Credentials in the API
The three major PSPs split cleanly on one question: do they thread the network transaction ID for you, or do you own it? That choice drives how portable your card book is.
Stripe hides the identifier. You save a card withsetup_future_usage set to on_session or off_session on the PaymentIntent, or create a SetupIntent with usage: off_session to store a card with no initial charge. Later you charge with off_session: true and confirm: true, and Stripe classifies it as an MIT and attaches the stored identifier automatically. Clean to integrate, opaque to migrate: because you never hold the identifier as an input, moving off Stripe means the CSV import dance.
// Stripe — save during the CIT
{ "amount": 5000, "currency": "gbp", "customer": "cus_...",
"payment_method": "pm_...", "confirm": true,
"setup_future_usage": "off_session" }
// Stripe — later MIT, customer offline
{ "amount": 5000, "currency": "gbp", "customer": "cus_...",
"payment_method": "pm_...", "off_session": true, "confirm": true }
Adyen makes the context explicit. shopperInteraction is Ecommerce for a CIT and ContAuth for an MIT; recurringProcessingModel is one of CardOnFile, Subscription or UnscheduledCardOnFile; storePaymentMethod: true tokenises on the initial payment. You store the scheme transaction identifier returned on the CIT and replay it on MITs in the networkTxReference field.
// Adyen — later MIT
{ "amount": {"value": 5000, "currency": "EUR"},
"paymentMethod": { "storedPaymentMethodId": "..." },
"shopperInteraction": "ContAuth",
"recurringProcessingModel": "UnscheduledCardOnFile",
"networkTxReference": "",
"shopperReference": "YOUR_SHOPPER_REF",
"merchantAccount": "YOUR_MERCHANT_ACCOUNT" }
Checkout.com is the most explicit of the three. merchant_initiated is a boolean, payment_type is Recurring, Installment or Unscheduled, source.stored: true when the card lives in a vault outside Checkout.com, and previous_payment_id points at the earlier payment in the chain, or carries the scheme transaction ID directly when the earlier charges ran on another PSP. It also hands you the Mastercard identifier back at processing.scheme_transaction_link_id.
The trade-off is the same one I drew in void vs refund vs reversal: Stripe collapses the decision into fewer fields and owns the state, which is less code and less control. Adyen and Checkout.com make you hold the identifier, which is more wiring but keeps your card book portable without a migration project. If you expect to run multi-PSP or ever leave your provider, the explicit model is cheaper in the long run even though it costs more on day one.
How SCA and 3DS2 Apply to MITs in the UK and EU
MITs sit outside Strong Customer Authentication because the payer is not present to authenticate. That exemption is not free standing: it rests entirely on the initial CIT having been authenticated. Stripe's guidance is blunt about the failure mode, warning that if the customer never authenticated up front, "their bank might decline future payments and ask for additional authentication." Checkout.com requires 3ds.enabled: true on the initial payment in SCA regions for exactly this reason.
So the correct pattern in the UK and EEA is to spend the 3-D Secure challenge once, on the CIT, and bank the result. The scheme transaction ID you store is the receipt, and every MIT afterwards leans on it to claim the exemption. That is why losing the identifier and losing SCA cover are the same event.
When an issuer wants authentication on a charge you thought was exempt, it soft-declines. Mastercard's use of code 65 to demand SCA is covered in the decline-code guide; the recovery is to step the customer back into a 3-D Secure challenge, not to blindly retry. For the full exemption map, see the SCA exemptions guide.
What Breaks When the Stored Credential Flags Are Wrong
The failures cluster into four patterns, and none show up in testing because test issuers are forgiving. No stored-credential flag at all: the charge reads as a one-off from an absent cardholder, the fraud signature issuers decline hardest. MIT flag but no network transaction ID: the chain is unprovable, the issuer cannot see the consented CIT behind it, and SCA-region declines follow. Wrong MIT type: a variable charge tagged as fixed recurring, which trips amount-change heuristics. And a broken chain from a brand swap or a botched migration, where the identifier no longer matches.
My read on where this goes: the industry is converging on scheme-generated identifiers. Visa's Transaction ID was always scheme-issued, and Mastercard's shift from the acquirer Trace ID to the central TLID closes the last gap where identifiers could collide across processors. The prediction I will stand behind is that portability gets easier at the identifier level while the pain migrates entirely to the data-transfer step. Teams that store their network transaction IDs today will move processors in an afternoon; teams that let their PSP own the identifier will keep paying for CSV-over-SFTP migrations; teams that never stored it will meet a wall of re-authentication the moment Mastercard's compliance assessments bite. Cheap to get right now, expensive to retrofit under a scheme deadline.
What This Means for Payment Engineers
Concrete steps, in order of how much pain they save:
- Persist the network transaction ID against every stored credential, as a first-class column. Even on Stripe, where you cannot set it, read it off the Charge and store it. It is your portability insurance and your SCA receipt.
- Classify presence correctly. Cardholder on the page with a saved card is a CIT; charge it as one and use the authentication. Reserve MIT flags for charges that fire without the customer.
- Pick the MIT type from the charge's actual behaviour, not from the product name. Variable amount with no schedule is unscheduled card-on-file, not recurring.
- Subscribe to card-update events (
payment_method.automatically_updatedon Stripe, the equivalent elsewhere) and freeze MITs on a brand change until you have fresh consent. - Authenticate the first CIT in SCA regions, always, even when an exemption looks available. The one challenge you run up front is what keeps the whole downstream series exempt.
- If you might ever change PSP, favour the explicit model. Holding your own identifier turns a migration project into a data export.
Key Takeaways
A stored credential is a regulated relationship, not a saved string. The first charge is a cardholder-initiated transaction that must capture consent and, in the UK and EEA, authentication. Every later merchant-initiated charge rides on a scheme identifier (Visa's Transaction ID, Mastercard's Trace ID now becoming the TLID) that you capture once and replay for the life of the card. Stripe threads it for you and keeps it; Adyen and Checkout.com make you hold it and hand back portability. Get the flag, type and identifier right and renewals just work. Get them wrong and the bill arrives as a cohort of silent declines, usually in the one region where it costs the most. More on where the card stack catches people out, from Tom Wang.