Card on File

Learn how to securely save card details for future payments.

🚧

Approval Required

This feature is available only on request. To gain access to the feature, please send an email to [email protected] requesting approval.

The Card on File (COF) feature enables merchants to securely save a reference to their customers' card details for future payments. This allows merchants to charge customers later without needing to request their card information again.

Unlike card tokenization, COF references can be used across different platforms, even if the initial transaction wasn't processed through Flutterwave.

Key Concepts

Before we dive into how to use Card on File (COF), it’s important to understand some key concepts:

  • 3D Secure (3DS): A security protocol that redirects customers to their bank’s authentication page during online payments. It adds an extra layer of protection by verifying the customer's identity to prevent fraud.
  • Customer Initiated Transaction (CIT): This happens when a customer provides their card details during an initial payment and consents to store them for future transactions. The payment request typically includes a special parameter (e.g., is_unscheduled set to true) to indicate this consent.
  • Merchant Initiated Transaction (MIT): Any subsequent payment made by the merchant based on the customer's initial consent. MITs don’t require the customer to take further action.
  • agreement_id: A unique reference generated by Flutterwave during the initial CIT, used by the merchant to manage future MITs.
  • trace_id: A reference generated by the card scheme during the initial CIT. It can be used across multiple platforms and processors that support COF (not just Flutterwave).

📘

Integration Tip

Using the trace_id also allows merchants to process recurring payments on Flutterwave without requiring customer authentication (NOAUTH), even if the initial consent was obtained on a different platform.

Handling a Customer-Initiated Transaction (CIT)

​​To set up recurring payments with COF, add is_unscheduled: true to the first customer charge request. For one-time tokenized charges, include the correct agreement_id linked to the card token.

# Set "preauthorize" to true if you want a preauthorized charge
curl -request POST \
  --url "https://api.flutterwave.com/v3/charges?type=card" \
  -header "Content-Type: application/json" \
  -header "Authorization: Bearer {{FLW_SECRET_KEY}}" \
  -data '{
    "preauthorize": true,
    "card_number": "5438898014560229",
    "expiry_month": "10",
    "expiry_year": "31",
    "cvv": "564",
    "amount": "7500",
    "currency": "NGN",
    "email": "[email protected]",
    "fullname": "Flutterwave Developers",
    "tx_ref": "UNIQUE_PAYMENT_REFERENCE",
    "redirect_url": "https://example_company.com/success",
    "is_unscheduled": true
  }'
# Include "preauthorize": true only if it's a preauthorized charge
curl -request POST \
  --url "https://api.flutterwave.com/v3/tokenized-charges" \
  -header "Content-Type: application/json" \
  -header "Authorization: Bearer {{FLW_SECRET_KEY}}" \
  -data '{
    "preauthorize": true,
    "token": "flw-t1nf-1dd5c21361bb85c64deb7ff57ec891b2-m03k",
    "currency": "NGN",
    "country": "NG",
    "amount": 7500,
    "email": "[email protected]",
    "full_name": "Flutterwave Developers",
    "tx_ref": "UNIQUE_PAYMENT_REFERENCE",
    "redirect_url": "https://example_company.com/success",
    "is_unscheduled": true,
    "agreement_id": "Agreement00w02W1"
  }'

The customer then proceeds to authorize the charge, which allows future recurring payments.

🚧

External 3DS Authentication Processing

Note that for enhanced security of COF payments, Flutterwave processes the initial CIT with External 3DS authentication.

When using test cards, be sure to use the 3DS Authentication test cards to simulate the CIT flow in test mode.

Upon a successful transaction, Flutterwave provides COF details through transaction verification, either directly in the response for tokenized charges or via webhooks.

{
    "status": "success",
    "message": "Transaction fetched successfully",
    "data": {
        "id": 2534420,
        "tx_ref": "YOUR_PAYMENT_REFERENCE",
        "flw_ref": "RWRZ00441717427218124433",
        "device_fingerprint": "N/A",
        "amount": 7500,
        "currency": "NGN",
        "charged_amount": 7500,
        "app_fee": 105,
        "merchant_fee": 0,
        "processor_response": "Approved",
        "auth_model": "VBVSECURECODE",
        "ip": "N/A",
        "narration": "CARD Transaction ",
        "status": "successful",
        "payment_type": "card",
        "created_at": "2024-09-09T09:11:55.000Z",
        "account_id": 27468,
        "card": {
            "first_6digits": "543889",
            "last_4digits": "0229",
            "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
            "country": "EG",
            "type": "MASTERCARD",
            "token": "flw-t1nf-1dd5c21361bb85c64deb7ff57ec891b2-m03k",
            "expiry": "10/31"
        },
        "meta": {
            "agreement_id": "Agreement00w02W1",
            "recurring_amount_variability": "VARIABLE",
            "trace_id": "123456789",
            "agreement_type": "UNSCHEDULED"
        },
        "amount_settled": 7395,
        "customer": {
            "id": 370672,
            "phone_number": "2349012345678",
            "name": "Flutterwave Developers",
            "email": "[email protected]",
            "created_at": "2020-04-30T20:09:56.000Z"
        }
    }
}
{
    "status": "success",
    "message": "Charge successful",
    "data": {
        "id": 2534420,
        "tx_ref": "YOUR_PAYMENT_REFERENCE",
        "flw_ref": "RWRZ00441717427218124433",
        "redirect_url": "https://example_company.com/success",
        "device_fingerprint": "N/A",
        "amount": 7500,
        "charged_amount": 7500,
        "app_fee": 105,
        "merchant_fee": 0,
        "processor_response": "APPROVED",
        "auth_model": "NOAUTH",
        "currency": "NGN",
        "ip": "N/A",
        "narration": "Flutterwave Developers",
        "status": "successful",
        "payment_type": "card",
        "created_at": "2024-09-09T09:11:55.000Z",
        "account_id": 27468,
        "cof": {
            "agreement_id": null,
            "recurring_amount_variability": "VARIABLE",
            "agreement_type": "UNSCHEDULED",
            "trace_id": "123456789"
        },
        "customer": {
            "id": 370672,
            "phone_number": "2349012345678",
            "name": "Flutterwave Developers",
            "email": "[email protected]",
            "created_at": "2020-04-30T20:09:56.000Z"
        },
        "card": {
            "first_6digits": "543889",
            "last_4digits": "0229",
            "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
            "country": "EG",
            "type": "MASTERCARD",
            "expiry": "10/31",
            "token": "flw-t1nf-1dd5c21361bb85c64deb7ff57ec891b2-m03k"
        }
    }
}
{
   "event": "charge.completed",
   "data": {
       "id": 2534420,
       "tx_ref": "YOUR_PAYMENT_REFERENCE",
       "flw_ref": "RWRZ00441717427218124433",
       "device_fingerprint": "N/A",
       "amount": 7500,
       "currency": "NGN",
       "charged_amount": 7500,
       "app_fee": 105,
       "merchant_fee": 0,
       "processor_response": "Approved",
       "auth_model": "VBVSECURECODE",
       "ip": "N/A",
       "narration": "CARD Transaction ",
       "status": "successful",
       "payment_type": "card",
       "created_at": "2024-09-09T09:11:55.000Z",
       "account_id": 27468,
       "customer": {
           "id": 370672,
           "name": "Flutterwave Developers",
           "phone_number": "+2349012345678",
           "email": "[email protected]",
           "created_at": "2020-04-30T20:09:56.000Z"
       },
       "card": {
           "first_6digits": "543889",
           "last_4digits": "0229",
           "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
           "country": "EG",
           "type": "MASTERCARD",
           "expiry": "10/31"
       }
   },
  "meta_data": {
      "agreement_id": "Agreement00w02W1",
      "recurring_amount_variability": "VARIABLE",
      "trace_id": "123456789",
      "agreement_type": "UNSCHEDULED"
  }
}
{
   "event": "charge.completed",
   "data": {
       "id": 2534420,
       "tx_ref": "YOUR_PAYMENT_REFERENCE",
       "flw_ref": "RWRZ00441717427218124433",
       "device_fingerprint": "N/A",
       "amount": 7500,
       "currency": "NGN",
       "charged_amount": 7500,
       "app_fee": 105,
       "merchant_fee": 0,
       "processor_response": "APPROVED",
       "auth_model": "noauth",
       "ip": "N/A",
       "narration": "Flutterwave Developers",
       "status": "successful",
       "payment_type": "card",
       "created_at": "2024-09-09T09:11:55.000Z",
       "account_id": 27468,
       "customer": {
           "id": 370672,
           "name": "Flutterwave Developers",
           "phone_number": "+2349012345678",
           "email": "[email protected]",
           "created_at": "2020-04-30T20:09:56.000Z"
       },
       "card": {
           "first_6digits": "543889",
           "last_4digits": "0229",
           "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
           "country": "EG",
           "type": "MASTERCARD",
           "expiry": "10/31"
       }
   },
  "meta_data": {
      "agreement_id": "Agreement00w02W1",
      "recurring_amount_variability": "VARIABLE",
      "trace_id": "123456789",
      "agreement_type": "UNSCHEDULED"
  }
}

Handling a Merchant-Initiated Transaction (MIT)

Direct Charge

To initiate an MIT using the direct charge method:

  • First, retrieve the customer’s trace_id from the initial CIT.
  • Next, initiate the charge by sending a tokenized charge request with the trace_id and the is_unscheduled flag set to true.

Here is a sample request payload:

# Include "preauthorize": true only if it's a preauthorized charge
curl -request POST \
  --url "https://api.flutterwave.com/v3/charges?type=card" \
  -header "Content-Type: application/json" \
  -header "Authorization: Bearer {{FLW_SECRET_KEY}}" \
  -data '{
    "preauthorize": true,
    "card_number": "5438898014560229",
    "expiry_month": "10",
    "expiry_year": "31",
    "cvv": "564",
    "amount": "7500",
    "currency": "NGN",
    "email": "[email protected]",
    "fullname": "Flutterwave Developers",
    "tx_ref": "UNIQUE_PAYMENT_REFERENCE",
    "redirect_url": "https://example_company.com/success",
    "trace_id": "123456789",
    "is_unscheduled": true,
  }'

Once the request is received, Flutterwave will process the transaction using the secure NOAUTH method based on the trace_id.

After processing the request, the COF information (with the trace_id) can be retrieved from the charge response, the transaction verification service, or webhooks will include the COF information. Samples can be found below:

{
    "status": "success",
    "message": "Successful",
    "data": {
        "id": 2534420,
        "tx_ref": "YOUR_PAYMENT_REFERENCE",
        "flw_ref": "RWRZ00441717427218124433",
        "device_fingerprint": "N/A",
        "amount": 7500,
        "charged_amount": 7500,
        "app_fee": 105,
        "merchant_fee": 0,
        "processor_response": "APPROVED",
        "auth_model": "NOAUTH",
        "currency": "NGN",
        "ip": "N/A",
        "narration": "CARD Transaction ",
        "status": "successful",
        "auth_url": "N/A",
        "payment_type": "card",
        "fraud_status": "ok",
        "charge_type": "normal",
        "created_at": "2024-09-09T09:11:55.000Z",
        "account_id": 27468,
        "customer": {
            "id": 370672,
            "phone_number": "2349012345678",
            "name": "Flutterwave Developers",
            "email": "[email protected]",
            "created_at": "2020-04-30T20:09:56.000Z"
        },
        "card": {
            "first_6digits": "543889",
            "last_4digits": "0229",
             "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
            "country": "EG",
            "type": "MASTERCARD",
            "expiry": "10/31"
        },
        "cof": {
            "agreement_id": null,
            "recurring_amount_variability": "VARIABLE",
            "agreement_type": "UNSCHEDULED",
            "trace_id": "123456789"
        }
    }
}
{
    "status": "success",
    "message": "Transaction fetched successfully",
    "data": {
        "id": 2534420,
        "tx_ref": "YOUR_PAYMENT_REFERENCE",
        "flw_ref": "RWRZ00441717427218124433",
        "device_fingerprint": "N/A",
        "amount": 7500,
        "currency": "NGN",
        "charged_amount": 7500,
        "app_fee": 105,
        "merchant_fee": 0,
        "processor_response": "APPROVED",
        "auth_model": "NOAUTH",
        "ip": "N/A",
        "narration": "CARD Transaction ",
        "status": "successful",
        "payment_type": "card",
        "created_at": "2024-09-09T09:11:55.000Z",
        "account_id": 27468,
        "card": {
            "first_6digits": "543889",
            "last_4digits": "0229",
            "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
            "country": "EG",
            "type": "MASTERCARD",
            "token": "flw-t1nf-1dd5c21361bb85c64deb7ff57ec891b2-m03k",
            "expiry": "10/31"
        },
        "meta": {
            "agreement_id": "N/A",
            "recurring_amount_variability": "VARIABLE",
            "trace_id": "123456789",
            "agreement_type": "UNSCHEDULED"
        },
        "amount_settled": 98.6,
        "customer": {
            "id": 370672,
            "name": "Flutterwave Developers",
            "phone_number": "2349012345678",
            "email": "[email protected]",
            "created_at": "2020-04-30T20:09:56.000Z"
        }
    }
}
{
   "event": "charge.completed",
   "data": {
       "id": 2534420,
       "tx_ref": "YOUR_PAYMENT_REFERENCE",
       "flw_ref": "RWRZ00441717427218124433",
       "device_fingerprint": "N/A",
       "amount": 7500,
       "currency": "NGN",
       "charged_amount": 7500,
       "app_fee": 105,
       "merchant_fee": 0,
       "processor_response": "APPROVED",
       "auth_model": "NOAUTH",
       "ip": "N/A",
       "narration": "CARD Transaction ",
       "status": "successful",
       "payment_type": "card",
       "created_at": "024-09-09T09:11:55.000Z",
       "account_id": 27468,
       "customer": {
           "id": 370672,
           "name": "Flutterwave Developers",
           "phone_number": "+2349012345678",
           "email": "[email protected]",
           "created_at": "2020-04-30T20:09:56.000Z"
       },
       "card": {
           "first_6digits": "543889",
           "last_4digits": "0229",
           "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
           "country": "EG",
           "type": "MASTERCARD",
           "expiry": "10/31"
       }
   },
  "meta_data": {
      "agreement_id": "N/A",
      "recurring_amount_variability": "VARIABLE",
      "trace_id": "123456789",
      "agreement_type": "UNSCHEDULED"
  }
}

Single Tokenized Charge

To initiate recurring MIT payments using the Single Tokenized Charge method:

  • First, retrieve the customer’s token and trace_id from the initial CIT step completed above.
  • Initiate the charge by sending a tokenized charge request with the token, trace_id, and the is_unscheduled flag set to true.
# Include "preauthorize": true only if it's a preauthorized charge
curl -request POST \
  --url "https://api.flutterwave.com/v3/tokenized-charges" \
  -header "Content-Type: application/json" \
  -header "Authorization: Bearer {{FLW_SECRET_KEY}}" \
  -data '{
    "preauthorize": true,
    "token": "flw-t1nf-1dd5c21361bb85c64deb7ff57ec891b2-m03k",
    "currency": "NGN",
    "country": "NG",
    "amount": 7500,
    "email": "[email protected]",
    "full_name": "Flutterwave Developers",
    "tx_ref": "UNIQUE_PAYMENT_REFERENCE",
    "redirect_url": "https://example_company.com/success",
    "trace_id": "123456789",
    "is_unscheduled": true,
  }'

Flutterwave will then process the transaction using the secure NOAUTH method based on the trace_id.

After processing, the tokenized charge response, transaction verification service, or webhooks will include the COF information with the trace_id.

{
    "status": "success",
    "message": "Charge successful",
    "data": {
        "id": 2534420,
        "tx_ref": "YOUR_PAYMENT_REFERENCE",
        "flw_ref": "RWRZ00441717427218124433",
        "redirect_url": "https://example_company.com/success",
        "device_fingerprint": "N/A",
        "amount": 7500,
        "charged_amount": 7500,
        "app_fee": 105,
        "merchant_fee": 0,
        "processor_response": "APPROVED",
         "auth_model": "NOAUTH",
        "currency": "NGN",
        "ip": "N/A",
        "narration": "Flutterwave Developers",
        "status": "successful",
        "payment_type": "card",
        "created_at": "2024-09-09T09:11:55.000Z",
        "account_id": 27468,
        "cof": {
            "agreement_id": null,
            "recurring_amount_variability": "VARIABLE",
            "agreement_type": "UNSCHEDULED",
            "trace_id": "123456789"
        },
        "customer": {
            "id": 370672,
            "phone_number": "2349012345678",
            "name": "Flutterwave Developers",
            "email": "[email protected]",
            "created_at": "2020-04-30T20:09:56.000Z"
        },
        "card": {
            "first_6digits": "543889",
            "last_4digits": "0229",
            "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
            "country": "EG",
            "type": "MASTERCARD",
            "expiry": "10/31",
            "token": "flw-t1nf-1dd5c21361bb85c64deb7ff57ec891b2-m03k"
        }
    }
}
{
    "status": "success",
    "message": "Transaction fetched successfully",
    "data": {
        "id": 2534420,
        "tx_ref": "YOUR_PAYMENT_REFERENCE",
        "flw_ref": "RWRZ00441717427218124433",
        "device_fingerprint": "N/A",
        "amount": 7500,
        "currency": "NGN",
        "charged_amount": 7500,
        "app_fee": 105,
        "merchant_fee": 0,
        "processor_response": "APPROVED",
        "auth_model": "NOAUTH",
        "ip": "N/A",
        "narration": "CARD Transaction ",
        "status": "successful",
        "payment_type": "card",
        "created_at": "2024-09-09T09:11:55.000Z",
        "account_id": 27468,
        "card": {
            "first_6digits": "543889",
            "last_4digits": "0229",
            "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
            "country": "EG",
            "type": "MASTERCARD",
            "token": "flw-t1nf-1dd5c21361bb85c64deb7ff57ec891b2-m03k",
            "expiry": "10/31"
        },
        "meta": {
            "agreement_id": "N/A",
            "recurring_amount_variability": "VARIABLE",
            "trace_id": "123456789",
            "agreement_type": "UNSCHEDULED"
        },
        "amount_settled": 98.6,
        "customer": {
            "id": 370672,
            "name": "Flutterwave Developers",
            "phone_number": "2349012345678",
            "email": "[email protected]",
            "created_at": "2020-04-30T20:09:56.000Z"
        }
    }
}
{
   "event": "charge.completed",
   "data": {
       "id": 2534420,
       "tx_ref": "YOUR_PAYMENT_REFERENCE",
       "flw_ref": "RWRZ00441717427218124433",
       "device_fingerprint": "N/A",
       "amount": 7500,
       "currency": "NGN",
       "charged_amount": 7500,
       "app_fee": 105,
       "merchant_fee": 0,
       "processor_response": "APPROVED",
       "auth_model": "NOAUTH",
       "ip": "N/A",
       "narration": "Flutterwave Developers",
       "status": "successful",
       "payment_type": "card",
       "created_at": "2024-09-09T09:11:55.000Z",
       "account_id": 27468,
       "customer": {
           "id": 370672,
           "name": "Flutterwave Developers",
           "phone_number": "+2349012345678",
           "email": "[email protected]",
           "created_at": "2020-04-30T20:09:56.000Z"
       },
       "card": {
           "first_6digits": "543889",
           "last_4digits": "0229",
           "issuer": "MASTERCARD MASHREQ BANK CREDITSTANDARD",
           "country": "EG",
           "type": "MASTERCARD",
           "expiry": "10/31"
       }
   },
  "meta_data": {
      "agreement_id": "N/A",
      "recurring_amount_variability": "VARIABLE",
      "trace_id": "123456789",
      "agreement_type": "UNSCHEDULED"
  }
}