Card on file
Save a card once, charge it again later. Which parameters to send for each Card on File scenario.
Card on File (CoF) means storing a customer's card credentials so you can charge them again without asking for the card details every time. This supports one-click checkout, subscriptions and usage-based billing.
With PPRO you never store the raw card number. The first successful payment (or a standalone validation) returns an instrumentId for a vaulted card (CARD_PPRO_VAULTED). You reuse that instrumentId for later payments.
Key concepts
Who starts the payment: initiator
initiator| Value | Meaning | Customer present? |
|---|---|---|
CONSUMER | Consumer-initiated transaction (CIT). The customer clicks "Pay" and may be asked to authenticate (for example 3DS). | Yes (on-session) |
MERCHANT | Merchant-initiated transaction (MIT). You trigger the charge, for example a monthly renewal. | No (off-session) |
The first payment that saves a card must be a CIT. Every MIT relies on the consent captured in that first CIT.
How the payment is scheduled: scheduleType
scheduleType| Value | Use it for |
|---|---|
UNSCHEDULED | One-click or stored-credential payments with no fixed schedule. Default when omitted. |
SCHEDULED | Payments that follow a fixed schedule or are part of a subscription or usage-based agreement. |
SCHEDULED_RETRY | A merchant-initiated retry of a failed scheduled payment (dunning). |
RECURRING | Deprecated. Use SCHEDULED in new integrations. |
Payment AgreementsFor any recurring flow we recommend creating a Payment Agreement. PPRO then stores and re-submits the scheme reference for you. If the agreement has a
frequency, later charges default toSCHEDULED. Without afrequencythey default toUNSCHEDULED.
Flow overview
sequenceDiagram
autonumber
actor C as Customer
participant M as Merchant
participant P as PPRO
rect rgb(235, 245, 255)
Note over C,P: 1. First payment (CIT): save the card
C->>M: Enters card, clicks Pay
M->>P: POST /v1/payment-charges<br/>initiator=CONSUMER, instrument=RAW_CARD
P-->>M: instrumentId + authorizations[].schemeAuthorizationReference
M->>M: Store instrumentId and schemeAuthorizationReference
end
rect rgb(240, 255, 240)
Note over C,P: 2a. Later, customer present (CIT): one-click
C->>M: Clicks Pay with saved card, enters CVV
M->>P: POST /v1/payment-charges<br/>initiator=CONSUMER, scheduleType=UNSCHEDULED<br/>instrumentId + instrumentUpdateDetails.cvv
P-->>M: Charge result
end
rect rgb(255, 248, 235)
Note over M,P: 2b. Later, customer absent (MIT): subscription renewal
M->>P: POST /v1/payment-charges<br/>initiator=MERCHANT, scheduleType=SCHEDULED<br/>instrumentId + initialSchemeAuthorizationReference
P-->>M: Charge result
alt Declined
M->>M: Read failure.additionalData.merchantAdviceCode
M->>P: Retry later: initiator=MERCHANT, scheduleType=SCHEDULED_RETRY
end
end
Parameters by scenario
All scenarios use POST /v1/payment-charges with paymentMethod: CARD. The table shows only the Card on File-specific fields. amount and consumer are always required.
| # | Scenario | initiator | scheduleType | Instrument fields | Other fields |
|---|---|---|---|---|---|
| 1 | First payment, save card for one-click | CONSUMER | UNSCHEDULED | instrument with type: RAW_CARD | authenticationSettings (for example EXTERNAL_3DS) if required |
| 2 | First payment, save card for subscription or usage-based billing | CONSUMER | SCHEDULED | instrument with type: RAW_CARD | authenticationSettings if required. Keep the NTI from the response. |
| 3 | Save a card without charging | CONSUMER | UNSCHEDULED | POST /v1/payment-instruments with validate.currency | Zero-value authorization. See Card Validation. |
| 4 | Returning customer, one-click (CIT) | CONSUMER | UNSCHEDULED | instrumentId + instrumentUpdateDetails (type: RAW_CARD, details.cvv) | authenticationSettings if required |
| 5 | Subscription renewal (MIT) | MERCHANT | SCHEDULED | instrumentId only. No CVV. | initialSchemeAuthorizationReference (NTI of the first CIT) |
| 6 | Usage-based charge (MIT) | MERCHANT | SCHEDULED | instrumentId only | initialSchemeAuthorizationReference |
| 7 | Ad hoc merchant charge with stored card (MIT, no schedule) | MERCHANT | UNSCHEDULED | instrumentId only | initialSchemeAuthorizationReference |
| 8 | Retry of a failed scheduled charge (dunning) | MERCHANT | SCHEDULED_RETRY | instrumentId only | initialSchemeAuthorizationReference. Respect the Merchant Advice Code. |
UseSCHEDULED_RETRYonly for billing retriesDo not use it when the customer returns to fix a failed payment. That is a new CIT on-session (scenario 4).
Linking MITs to the first CIT
Card schemes require MITs to reference the original consumer-authorized transaction.
| Field | Where it comes from | Where to send it |
|---|---|---|
schemeAuthorizationReference (NTI) | authorizations[] in the response to the first CIT | initialSchemeAuthorizationReference on every later MIT |
| Mastercard TLID | Returned for Mastercard transactions | initialTransactionLinkReference on later MITs (optional) |
If you use Payment Agreements, PPRO stores and re-sends these references for you. If you used another PSP for the first CIT, you can seed initialSchemeAuthorizationReference when you create the agreement.
Request examples
1. First payment, save the card for a subscription
POST /v1/payment-charges
{
"paymentMethod": "CARD",
"initiator": "CONSUMER",
"scheduleType": "SCHEDULED",
"amount": { "value": 1000, "currency": "BRL" },
"consumer": { "name": "John Smith", "country": "BR" },
"instrument": {
"type": "RAW_CARD",
"details": {
"number": "{CARD_NUMBER}",
"cvv": "{CVV}",
"holderName": "John Smith",
"expiryMonth": 2,
"expiryYear": 2030
}
}
}Store from the response:
{
"id": "charge_aPWseusjHRt144BTwXdU2",
"instrumentId": "instr_yGeGPffd4Ch56wZENvDbi",
"authorizations": [
{
"id": "authz_xi3UsqCIHbEirF6l7taXP",
"status": "AUTHORIZED",
"schemeAuthorizationReference": "MC1234567890ABCDE"
}
]
}4. One-click payment with a saved card (CIT)
The CVV is a trust signal for consumer-initiated payments. Send it in instrumentUpdateDetails.
POST /v1/payment-charges
{
"paymentMethod": "CARD",
"initiator": "CONSUMER",
"scheduleType": "UNSCHEDULED",
"instrumentId": "instr_yGeGPffd4Ch56wZENvDbi",
"instrumentUpdateDetails": {
"type": "RAW_CARD",
"details": { "cvv": "123" }
},
"amount": { "value": 2500, "currency": "BRL" },
"consumer": { "name": "John Smith", "country": "BR" }
}5. Subscription renewal (MIT)
POST /v1/payment-charges
{
"paymentMethod": "CARD",
"initiator": "MERCHANT",
"scheduleType": "SCHEDULED",
"instrumentId": "instr_yGeGPffd4Ch56wZENvDbi",
"initialSchemeAuthorizationReference": "MC1234567890ABCDE",
"amount": { "value": 1000, "currency": "BRL" },
"consumer": { "name": "John Smith", "country": "BR" }
}8. Retry after a decline (dunning)
Same as scenario 5, with "scheduleType": "SCHEDULED_RETRY".
Best practices
- Always send
initiatorandscheduleTypeon stored-card payments. Issuers use them to treat the payment correctly, which improves approval rates. - Store the
instrumentIdand the NTI (schemeAuthorizationReference) from the first CIT. - Validate the card when you save it without a payment (scenario 3), so you find invalid cards before the first renewal.
- On a decline, read the Merchant Advice Code before retrying.
- Keep stored cards current with Account Updater.
Updated about 2 hours ago