> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fintoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update the payment method on a subscription

> Change the payment method a Fintoc subscription charges, with a re-enrollment link for your customer or directly through the API.

When a customer's payment method fails, or when the customer wants to switch payment methods, you can update the payment method associated with a subscription. The update affects future billing cycles only. It does not charge open invoices. Collect open invoices separately using each invoice's `hosted_invoice_url`, one per invoice.

Two flows let you update a subscription's payment method:

* **Case A (user-initiated):** Send the customer a new enrollment link. Use this when the customer must authorize a new Chilean automatic debit (PAC) mandate or enter new card details.
* **Case B (merchant-initiated):** Associate an already-active payment method directly through the API, with no customer interaction.

## Case A: Send a re-enrollment link

Create a `CheckoutSession` with `flow: "setup"` and pass the existing subscription ID in `subscription`. The customer opens the link and enrolls a new payment method. For cards, Fintoc associates the payment method with the subscription when enrollment completes. For PAC, Fintoc associates the payment method once the mandate activates.

**Server**

```bash theme={null}
curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \
  --header "Authorization: YOUR_TEST_SECRET_API_KEY" \
  --header "Content-Type: application/json" \
  --data-raw '{
    "flow": "setup",
    "currency": "CLP",
    "subscription": "sub_456789abcdef",
    "success_url": "https://merchant.com/success",
    "cancel_url": "https://merchant.com/cancel",
    "customer": "cus_01234567",
    "payment_method_types": ["pac"]
  }'
```

```javascript Node theme={null}
const { Fintoc } = require('fintoc');

const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY');

const checkoutSession = await fintoc.v2.checkoutSessions.create({
  flow: 'setup',
  currency: 'CLP',
  subscription: 'sub_456789abcdef',
  success_url: 'https://merchant.com/success',
  cancel_url: 'https://merchant.com/cancel',
  customer: 'cus_01234567',
  payment_method_types: ['pac']
});
```

```python theme={null}
from fintoc import Fintoc

client = Fintoc('YOUR_TEST_SECRET_API_KEY')

checkout_session = client.v2.checkout_sessions.create(
    flow='setup',
    currency='CLP',
    subscription='sub_456789abcdef',
    success_url='https://merchant.com/success',
    cancel_url='https://merchant.com/cancel',
    customer='cus_01234567',
    payment_method_types=['pac'],
)
```

Fintoc responds with the `CheckoutSession` object:

```json theme={null}
{
  "id": "cs_li5531onlFDi235",
  "object": "checkout_session",
  "flow": "setup",
  "status": "created",
  "currency": "CLP",
  "mode": "test",
  "subscription": "sub_456789abcdef",
  "customer": {
    "id": "cus_01234567",
    "object": "customer",
    "name": "Test Customer 1",
    "email": "jon@snow.com",
    "metadata": {},
    "tax_id": {
      "type": "cl_rut",
      "value": "11.111.111-1"
    }
  },
  "payment_method_types": ["pac"],
  "success_url": "https://merchant.com/success",
  "cancel_url": "https://merchant.com/cancel",
  "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235"
}
```

Redirect the customer to `redirect_url` so the customer completes the enrollment.

### PAC activation window

For PAC, bank confirmation takes approximately 5 business days. The new payment method stays in `pending` status during this window, and Fintoc has not yet executed the swap.

`checkout_session.finished` signals that the customer completed the enrollment flow, not that the swap occurred. Wait for `subscription.payment_method_updated` before you treat the new payment method as active.

To check the activation state while the mandate is pending, call `GET /v2/payment_methods/{id}` and read `pac.status`:

```json theme={null}
{
  "id": "pm_000000000001",
  "object": "payment_method",
  "customer": "cus_01234567",
  "type": "pac",
  "pac": {
    "account_holder_id": "11.111.111-1",
    "account_number": "000000000000",
    "account_type": "checking_account",
    "institution": {
      "id": "cl_banco_de_chile",
      "country": "cl",
      "name": "Banco de Chile"
    },
    "status": "pending"
  }
}
```

### Handle re-enrollment events

Subscribe to the following events when you update a subscription's payment method through a re-enrollment link:

| Event                                       | Description                                                                                      | Action                                                                                                                           |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| `checkout_session.finished`                 | The customer completed the enrollment flow.                                                      | Store the new `payment_method` ID. For cards the swap already occurred; for PAC, wait for `subscription.payment_method_updated`. |
| `checkout_session.expired`                  | The session expired before the customer completed enrollment.                                    | Create a new session and send the customer the updated link.                                                                     |
| `subscription.payment_method_updated`       | The bank confirmed the new mandate. The subscription now charges against the new payment method. | Resume normal billing. Collect any open invoices using each invoice's `hosted_invoice_url`.                                      |
| `subscription.payment_method_update_failed` | The bank rejected the mandate activation. The subscription keeps its previous payment method.    | Create a new session so the customer can re-enroll. Collect open invoices using each invoice's `hosted_invoice_url`.             |

## Case B: Associate an existing payment method

If the customer already has an active payment method on file, associate the payment method with a subscription directly, without a new enrollment link.

### Swap the payment method on an existing subscription

Call `PATCH /v2/subscriptions/{id}` with the ID of the active payment method. The payment method must belong to the same customer as the subscription.

**Server**

```bash theme={null}
curl --request PATCH "https://api.fintoc.com/v2/subscriptions/sub_456789abcdef" \
  --header "Authorization: YOUR_TEST_SECRET_API_KEY" \
  --header "Content-Type: application/json" \
  --data-raw '{
    "payment_method": "pm_000000000001"
  }'
```

```javascript Node theme={null}
const { Fintoc } = require('fintoc');

const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY');

const subscription = await fintoc.v2.subscriptions.update('sub_456789abcdef', {
  payment_method: 'pm_000000000001'
});
```

```python theme={null}
from fintoc import Fintoc

client = Fintoc('YOUR_TEST_SECRET_API_KEY')

subscription = client.v2.subscriptions.update(
    'sub_456789abcdef',
    payment_method='pm_000000000001',
)
```

Fintoc returns the updated `Subscription`:

```json theme={null}
{
  "id": "sub_456789abcdef",
  "object": "subscription",
  "billing_cycle_anchor": "2025-08-01T00:00:00Z",
  "collection_method": "charge_automatically",
  "created_at": "2025-08-01T12:00:00Z",
  "customer": "cus_01234567",
  "items": [
    {
      "id": "si_89abcdef0123",
      "object": "subscription_item",
      "price": {
        "currency": "CLP",
        "product": { "name": "Pro Plan" },
        "recurring": { "interval": "month", "interval_count": 1 },
        "unit_amount": 15000
      },
      "quantity": 1
    }
  ],
  "metadata": {},
  "mode": "test",
  "payment_method": "pm_000000000001",
  "status": "active",
  "trial_end": null
}
```

The payment method's mandate is already active, so the swap is immediate. The `payment_method` value in the response points to the new payment method. Fintoc also emits `subscription.payment_method_updated`.

### Create a new subscription with an existing payment method

Creating a subscription against a payment method the customer already has is not an update, so it lives with the rest of subscription creation. Pass the `payment_method` to [Create a subscription](/api/payments-api/subscriptions/subscriptions-create), as described in [Charge automatically against a payment method](/guides/payments/accept-recurring-payments#charge-automatically-against-a-payment-method).

## Updating the payment method on a subscription does not pay open invoices

Updating the payment method changes which method Fintoc charges for future billing cycles. It does not pay open invoices from previous cycles. If the subscription has open invoices when the swap occurs, collect them separately using each invoice's `hosted_invoice_url`, one per invoice.

## Edge cases

**One update at a time:** Only one payment method update can be in progress per subscription. A second attempt while a PAC mandate is `pending` returns a `payment_method_update_in_progress` error (`409 Conflict`).

**Billing cycle during the activation window:** If a billing cycle anchor falls while a new PAC mandate is still `pending`, Fintoc creates the invoice in `open` status without an automatic charge. Collect the invoice using its `hosted_invoice_url`.

**Cancellation during activation:** If you cancel the subscription while a PAC mandate awaits bank confirmation, the swap does not execute. Fintoc creates and stores the new payment method on the customer's record, but does not associate the payment method with any subscription.

## Test your integration

Using your [test mode Secret Key](/guides/resources/test-mode), run both flows against a test subscription without moving money.

### 1) Test the re-enrollment link

Create the setup `Checkout Session` with the `subscription` of an existing test subscription, then complete the enrollment on the Fintoc-hosted page with the test credentials listed in [Save a payment method for future charges](/guides/payments/accept-recurring-payments/setup-a-payment-method-for-future-charges). Verify that:

* You receive `checkout_session.finished`, carrying the new `payment_method` ID.
* You receive `subscription.payment_method_updated`, and your integration treats the new payment method as active only after this event.
* [Get a subscription](/api/payments-api/subscriptions/subscriptions-get) reports the new `payment_method`.

Do not treat the swap as done on `checkout_session.finished` alone. That is the failure the [PAC activation window](#pac-activation-window) describes.

### 2) Test the API swap

Enroll a second payment method for the same test customer, then swap it in with [Update a subscription](/api/payments-api/subscriptions/subscriptions-update). Verify that:

* The response reports the new `payment_method` and keeps the subscription `active`.
* You receive `subscription.payment_method_updated`.
* A second update while another one is still in progress returns `payment_method_update_in_progress` with `409 Conflict`.
