# Card on File (Recurring)

Charge a previously saved payment method by Customer ID without resubmitting the card number.

Source: https://developer.inoviopay.com/api/card-on-file.html  
Markdown: https://developer.inoviopay.com/api/card-on-file.md

To charge a customer using a previously saved payment method, you do not need to submit the full credit card number again. Instead, you can make a call without the card number by using only the Customer ID (`CUST_ID`). This will use the most recent payment account or credit card that was used.

The merchant may also specify which payment method to use by sending Customer ID (`CUST_ID`) paired with either the Payment ID (`PMT_ID`) or the last 4 digits of the card (`PMT_L4`).

| Parameter | Description |
|---|---|
| `CUST_ID` (required) | The Customer ID generated from the original authorization. |
| `PMT_ID / PMT_L4` (required) | Provide *either* the unique Payment ID (`PMT_ID`) or the last 4 digits of the card (`PMT_L4`) to specify which saved account to charge. |
| `REQUEST_REBILL` (optional) | Set to `1` to explicitly flag the transaction as a rebill/renewal. Set to `2` for the first transaction in a subscription. |

All four SDKs model a saved payment method as `SavedCard` (constructed with `pmtId` and/or `pmtIdXtl`, plus `custId`) and the `REQUEST_REBILL` / `REQUEST_INITATOR` compliance flags as a `Recurring` block on the request. `PMT_L4` card selection (the cURL example below) is not modeled as an SDK constructor; use `pmtId` from a prior result's `PMT_ID` instead.

**cURL**

```bash
curl -X POST "https://api.inoviopay.com/payment/pmt_service.cfm" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "request_action=CCAUTHCAP&req_username=api_user&req_password=P%40ssw0rd%21&site_id=12345&request_api_version=4.14&request_response_format=JSON&cust_id=987654&pmt_l4=1111&li_value_1=25.00&request_rebill=1"
```

**PHP**

```php
use Inovio\Gateway\{Credentials, InovioClient};
use Inovio\Gateway\Model\{LineItem, Money, PaymentMethods, Recurring};
use Inovio\Gateway\Request\TransactionRequest;

$client = new InovioClient(new Credentials('api_user', 'P@ssw0rd!', '12345'), 'SANDBOX');

$req = new TransactionRequest(
    PaymentMethods::savedCard(pmtId: '8839213', custId: '987654'),
    [new LineItem('111205', 1, Money::of('25.00', 'USD'))]
);

$req->recurring = new Recurring();
$req->recurring->rebill = 'REBILL';   // REQUEST_REBILL=1 — a renewal, not the first charge

$result = $client->sale($req);

match ($result->status) {
    'APPROVED' => /* funds captured against the saved card */,
    'DECLINED' => /* $result->serviceClassification->stopRecurring — stop the dunning cycle? */,
    default    => /* PENDING | RUNNING | FAILED */,
};
```

**Node**

```ts
import { InovioClient, Money, PaymentMethods } from '@inovio/gateway-sdk';

const client = new InovioClient(
  { reqUsername: 'api_user', reqPassword: 'P@ssw0rd!', siteId: '12345' },
  { environment: 'SANDBOX' }
);

const result = await client.sale({
  paymentMethod: PaymentMethods.savedCard({ pmtId: '8839213', custId: '987654' }),
  lineItems: [{ productId: '111205', count: 1, value: Money.of('25.00', 'USD') }],
  recurring: { rebill: 'REBILL' },   // REQUEST_REBILL=1 — a renewal, not the first charge
});

switch (result.status) {
  case 'APPROVED': /* funds captured against the saved card */ break;
  case 'DECLINED': /* result.serviceClassification?.stopRecurring — stop the dunning cycle? */ break;
  default: /* PENDING | RUNNING | FAILED */ break;
}
```

**Python**

```python
from inovio_gateway import Credentials, InovioClient, Money, PaymentMethods, TransactionStatus
from inovio_gateway.model import LineItem, Recurring
from inovio_gateway.request import TransactionRequest

client = InovioClient(Credentials("api_user", "P@ssw0rd!", site_id="12345"), environment="SANDBOX")

result = client.sale(TransactionRequest(
    payment_method=PaymentMethods.saved_card(pmt_id="8839213", cust_id="987654"),
    line_items=[LineItem("111205", 1, Money.of("25.00", "USD"))],
    recurring=Recurring(rebill="REBILL"),   # REQUEST_REBILL=1 — a renewal, not the first charge
))

if result.status is TransactionStatus.APPROVED:
    pass  # funds captured against the saved card
elif result.status is TransactionStatus.DECLINED:
    pass  # result.service_classification.stop_recurring — stop the dunning cycle?
```

**Java**

```java
InovioClient client = new InovioClient(
    new InovioClient.Credentials("api_user", "P@ssw0rd!", "12345"));

TransactionRequest req = new TransactionRequest(
    PaymentMethods.savedCard("8839213", null, "987654"),
    new LineItem("111205", 1, Money.of("25.00", "USD")));

RequestParts.Recurring recurring = new RequestParts.Recurring();
recurring.rebill = "REBILL";   // REQUEST_REBILL=1 — a renewal, not the first charge
req.recurring = recurring;

TransactionResult result = client.sale(req);

switch (result.status()) {
    case APPROVED -> { /* funds captured against the saved card */ }
    case DECLINED -> { /* result.serviceClassification().stopRecurring() — stop the dunning cycle? */ }
    default -> { /* PENDING | RUNNING | FAILED */ }
}
```

**Response**

```json
{
  "REQUEST_ACTION": "CCAUTHCAP",
  "REQ_ID": "84729108",
  "TRANS_STATUS_NAME": "APPROVED",
  "TRANS_VALUE": 0,
  "CURR_CODE_ALPHA": "USD",
  "TRANS_VALUE_SETTLED": 0,
  "CURR_CODE_ALPHA_SETTLED": "USD",
  "TRANS_EXCH_RATE": "",
  "TRANS_ID": 3948572122,
  "CUST_ID": 9827166,
  "XTL_CUST_ID": "",
  "PO_ID": 99281741,
  "XTL_ORDER_ID": "",
  "BATCH_ID": 883928,
  "PROC_NAME": "Test Processor",
  "MERCH_ACCT_ID": 110203,
  "CARD_BRAND_NAME": "Visa",
  "CARD_TYPE": "",
  "CARD_CLASS": "",
  "CARD_PREPAID": 0,
  "CARD_BANK": "",
  "CARD_COUNTRY": "",
  "CARD_DETAIL": "",
  "CARD_BALANCE": "",
  "PMT_L4": "2345",
  "PMT_ID": 8839213,
  "PMT_ID_XTL": "",
  "PMT_AAU_UPDATE_DT": "",
  "PMT_AAU_UPDATE_DESC": "",
  "PROC_UDF01": "",
  "ANI_RESP_DECISION": "",
  "PROC_UDF02": "",
  "PROC_AUTH_RESPONSE": "TEST18263",
  "PROC_RETRIEVAL_NUM": "803EECE4-7F22-4837-841C615C7D1E59D4",
  "PROC_REFERENCE_NUM": "TEST469812895",
  "PROC_REDIRECT_URL": "",
  "AVS_RESPONSE": "M",
  "CVV_RESPONSE": "M",
  "CARD_BRAND_TRANSID": "",
  "REQUEST_API_VERSION": "4.14",
  "P3DS_VENDOR": "",
  "P3DS_RESPONSE": "",
  "PO_LI_ID_1": "9928185",
  "PO_LI_COUNT_1": 1,
  "PO_LI_AMOUNT_1": "0",
  "PO_LI_PROD_ID_1": "111205",
  "MBSHP_ID_1": "",
  "TRANS_NTOKEN_USED": 0
}
```
