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

ValueMeaningCustomer present?
CONSUMERConsumer-initiated transaction (CIT). The customer clicks "Pay" and may be asked to authenticate (for example 3DS).Yes (on-session)
MERCHANTMerchant-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

ValueUse it for
UNSCHEDULEDOne-click or stored-credential payments with no fixed schedule. Default when omitted.
SCHEDULEDPayments that follow a fixed schedule or are part of a subscription or usage-based agreement.
SCHEDULED_RETRYA merchant-initiated retry of a failed scheduled payment (dunning).
RECURRINGDeprecated. Use SCHEDULED in new integrations.
📘

Payment Agreements

For 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 to SCHEDULED. Without a frequency they default to UNSCHEDULED.

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.

#ScenarioinitiatorscheduleTypeInstrument fieldsOther fields
1First payment, save card for one-clickCONSUMERUNSCHEDULEDinstrument with type: RAW_CARDauthenticationSettings (for example EXTERNAL_3DS) if required
2First payment, save card for subscription or usage-based billingCONSUMERSCHEDULEDinstrument with type: RAW_CARDauthenticationSettings if required. Keep the NTI from the response.
3Save a card without chargingCONSUMERUNSCHEDULEDPOST /v1/payment-instruments with validate.currencyZero-value authorization. See Card Validation.
4Returning customer, one-click (CIT)CONSUMERUNSCHEDULEDinstrumentId + instrumentUpdateDetails (type: RAW_CARD, details.cvv)authenticationSettings if required
5Subscription renewal (MIT)MERCHANTSCHEDULEDinstrumentId only. No CVV.initialSchemeAuthorizationReference (NTI of the first CIT)
6Usage-based charge (MIT)MERCHANTSCHEDULEDinstrumentId onlyinitialSchemeAuthorizationReference
7Ad hoc merchant charge with stored card (MIT, no schedule)MERCHANTUNSCHEDULEDinstrumentId onlyinitialSchemeAuthorizationReference
8Retry of a failed scheduled charge (dunning)MERCHANTSCHEDULED_RETRYinstrumentId onlyinitialSchemeAuthorizationReference. Respect the Merchant Advice Code.
🚧

Use SCHEDULED_RETRY only for billing retries

Do 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.

FieldWhere it comes fromWhere to send it
schemeAuthorizationReference (NTI)authorizations[] in the response to the first CITinitialSchemeAuthorizationReference on every later MIT
Mastercard TLIDReturned for Mastercard transactionsinitialTransactionLinkReference 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 initiator and scheduleType on stored-card payments. Issuers use them to treat the payment correctly, which improves approval rates.
  • Store the instrumentId and 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.

Did this page help you?