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

# Aceptar pagos recurrentes

> >-

Crea un flujo de suscripción que registre un método de pago y cobre al cliente automáticamente con una periodicidad fija.

Para aceptar pagos recurrentes con Fintoc, completas tres pasos:

1. En tu backend, crea un `Checkout Session` con `flow: subscription`.
2. Redirige al cliente para completar el registro en la página de checkout alojada por Fintoc.
3. Maneja los eventos posteriores al registro y de pagos recurrentes (webhooks).

El siguiente diagrama muestra cómo Fintoc interactúa tanto con tu backend como con tu frontend:

<Frame>
  <img src="https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/7c83e6d024806e4bb3f97b72e61e66f4256a045722cd1d0007dc700b9b0210aa-subscription-flow.png?fit=max&auto=format&n=YQmOnq8Zegydl6oL&q=85&s=a00e0ea28ea70b494d1943be86d94a7c" alt="fintoc-recurring-payment-diagram" width="1824" height="1159" data-path="images/7c83e6d024806e4bb3f97b72e61e66f4256a045722cd1d0007dc700b9b0210aa-subscription-flow.png" />
</Frame>

## Crea una Checkout Session

El objeto [Checkout Session](/es/reference/payments-api/checkout-sessions/checkout-session-object) representa tu intención de registrar un método de pago para cobros recurrentes y de crear una suscripción con un monto y periodicidad fijos.

Usando tu [Secret Key](/es/docs/home/api-keys), crea un `Checkout Session` en tu backend con `flow` en `subscription`.

**Servidor**

```curl 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": "subscription",
    "amount": 350000,
    "currency": "CLP",
    "success_url": "https://merchant.com/success",
    "cancel_url": "https://merchant.com/cancel",
    "payment_method_types": [
      "pac"
    ],
    "customer_data": {
      "tax_id": {
        "type": "cl_rut",
        "value": "11.111.111-1"
      },
      "name": "Felipe Castro",
      "email": "jon@snow.com",
      "metadata": {}
    },
    "line_items": [
      {
        "price_data": {
          "currency": "CLP",
          "unit_amount": 350000,
          "product_data": {
            "name": "Plan 1"
          },
          "recurring": {
            "interval": "month",
            "interval_count": 1
          }
        },
        "quantity": 1
      }
    ],
    "metadata": {
      "subscription_external_id": "sub_987654321"
    }
  }'
```

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

const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY');

const checkoutSession = await fintoc.checkoutSessions.create({
  flow: 'subscription',
  amount: 350000,
  currency: 'CLP',
  success_url: 'https://merchant.com/success',
  cancel_url: 'https://merchant.com/cancel',
  payment_method_types: ['pac'],
  customer_data: {
    tax_id: {
      type: 'cl_rut',
      value: '11.111.111-1'
    },
    name: 'Felipe Castro',
    email: 'jon@snow.com',
    metadata: {}
  },
  line_items: [
    {
      price_data: {
        currency: 'CLP',
        unit_amount: 350000,
        product_data: {
          name: 'Plan 1'
        },
        recurring: {
          interval: 'month',
          interval_count: 1
        }
      },
      quantity: 1
    }
  ],
  metadata: {
    subscription_external_id: 'sub_987654321'
  }
});
```

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

client = Fintoc('YOUR_TEST_SECRET_API_KEY')

checkout_session = client.checkout_sessions.create(
    flow='subscription',
    amount=350000,
    currency='CLP',
    success_url='https://merchant.com/success',
    cancel_url='https://merchant.com/cancel',
    payment_method_types=['pac'],
    customer_data={
        'tax_id': {
            'type': 'cl_rut',
            'value': '11.111.111-1',
        },
        'name': 'Felipe Castro',
        'email': 'jon@snow.com',
        'metadata': {},
    },
    line_items=[
        {
            'price_data': {
                'currency': 'CLP',
                'unit_amount': 350000,
                'product_data': {
                    'name': 'Plan 1',
                },
                'recurring': {
                    'interval': 'month',
                    'interval_count': 1,
                },
            },
            'quantity': 1,
        }
    ],
    metadata={
        'subscription_external_id': 'sub_987654321',
    },
)
```

Fintoc responde con el objeto [Checkout Session](/es/reference/payments-api/checkout-sessions/checkout-session-object). Guarda su `id` y `redirect_url` para continuar el flujo:

```json theme={null}
{
  "id": "cs_li5531onlFDi235",
  "object": "checkout_session",
  "mode": "test",
  "flow": "subscription",
  "status": "created",
  "amount": 350000,
  "currency": "CLP",
  "payment_method_types": ["pac"],
  "customer": {
    "id": "cus_NffrFeUfNV2Hib",
    "object": "customer",
    "name": "Felipe Castro",
    "email": "jon@snow.com",
    "metadata": {},
    "tax_id": {
      "type": "cl_rut",
      "value": "11.111.111-1"
    }
  },
  "line_items": [
    {
      "price": {
        "product": {
          "name": "Plan 1",
          "description": "Fixed-amount monthly plan"
        },
        "currency": "CLP",
        "unit_amount": 350000,
        "recurring": {
          "interval": "month",
          "interval_count": 1
        }
      },
      "quantity": 1
    }
  ],
  "metadata": {
    "subscription_external_id": "sub_987654321"
  },
  "success_url": "https://merchant.com/success",
  "cancel_url": "https://merchant.com/cancel",
  "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235"
}
```

La respuesta incluye un atributo `redirect_url`. En el siguiente paso, redirige al cliente a esta ubicación para completar la suscripción.

La siguiente tabla describe los parámetros que envías al crear un `Checkout Session`:

| Parámetro              | Ejemplo                                         | Descripción                                                                                                                                                                                                                                                                                                           |
| ---------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `amount`               | 350000                                          | **Requerido.** Un entero positivo que representa el valor a cobrar, en la unidad menor de la moneda (por ejemplo, `1000` para `$1000 CLP`, ya que CLP no tiene unidad menor, o `2476` para `$24.76 MXN`, ya que MXN tiene unidad menor). Consulta la página de [monedas](/es/docs/home/currencies) para más detalles. |
| `currency`             | CLP                                             | **Requerido.** Código ISO 4217 de tres letras de la moneda para los pagos recurrentes. Uno de `CLP` o `MXN`.                                                                                                                                                                                                          |
| `flow`                 | `subscription`                                  | **Requerido.** Tipo de flujo para la sesión. Uno de `payment`, `setup` o `subscription`.                                                                                                                                                                                                                              |
| `success_url`          | `https://merchant.com/success`                  | **Requerido.** URL a la que redirigir al cliente después de un registro exitoso.                                                                                                                                                                                                                                      |
| `cancel_url`           | `https://merchant.com/cancel`                   | **Requerido.** URL a la que redirigir al cliente si cancela el registro y vuelve a tu sitio.                                                                                                                                                                                                                          |
| `customer`             | `cus_3B2bODrQFje7ZVkT69xyaTSDwXQ`               | **Requerido si no hay `customer_data`.** ID de un `Customer` existente.                                                                                                                                                                                                                                               |
| `customer_data`        | `(object)`                                      | **Requerido si no hay `customer`.** Datos para crear un customer en línea.<br />Si ya existe un `Customer` con el mismo `tax_id`, la solicitud devuelve un error `409 Conflict`. Para reutilizar un `Customer` existente, envía su `id` en `customer` en lugar de `customer_data`.                                    |
| `payment_method_types` | `["pac"]`                                       | Lista de métodos de pago permitidos durante el registro. Uno o más de `pac` (cargos en cuentas bancarias en Chile), `direct_debit` (cargos en cuentas bancarias en México) y `card`.                                                                                                                                  |
| `line_items`           | `(array)`                                       | **Requerido.** Arreglo de ítems a los que se suscribe el cliente. Cada ítem contiene `quantity` y ya sea `price` o `price_data`.                                                                                                                                                                                      |
| `metadata`             | `{"subscription_external_id": "sub_987654321"}` | Conjunto de pares clave-valor que puedes adjuntar a un objeto. Útil para almacenar información adicional sobre el objeto en un formato estructurado.                                                                                                                                                                  |

### Incluir datos del cliente (requerido para suscripciones)

Al crear un `Checkout Session` con `flow: subscription`, debes incluir información del cliente. Puedes hacerlo ya sea referenciando un ID de customer existente (`customer`) o enviando `customer_data` para crear uno en línea:

| Atributo   | Tipo     | Descripción                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tax_id`   | `object` | **Requerido si no hay `email`.** Objeto que identifica al cliente a nivel fiscal o regulatorio. El `type` es `cl_rut` para un tax ID chileno (RUT) o `mx_rfc` para un tax ID mexicano (RFC), y `value` es el identificador fiscal como string. Consulta el [objeto Customer](/es/reference/payments-api/checkout-sessions/checkout-session-object#customer-object).<br />Si ya existe un `Customer` con el mismo `tax_id`, la solicitud devuelve un error `409 Conflict`. Para reutilizar un `Customer` existente, envía su `id` en `customer` en lugar de `customer_data`. |
| `name`     | `string` | Nombre completo del cliente.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `email`    | `string` | **Requerido si no hay `tax_id`.** Dirección de email del cliente.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `metadata` | `object` | Datos personalizados que almacenan información adicional sobre el cliente, por ejemplo IDs internos, referencias de CRM o etiquetas.                                                                                                                                                                                                                                                                                                                                                                                                                                        |

### Incluir una lista de ítems (requerido para suscripciones)

Al crear un `Checkout Session` con `flow: subscription`, debes incluir los ítems a los que se suscribe el cliente. Esta información permite a Fintoc mostrar los ítems en la página de checkout y mostrar solo los métodos de pago disponibles para productos específicos.

| Atributo     | Tipo      | Descripción                                                                   |
| :----------- | :-------- | :---------------------------------------------------------------------------- |
| `quantity`   | `integer` | **Requerido.** Número de unidades de este ítem que se compra.                 |
| `price_data` | `object`  | **Requerido.** Datos usados para generar un nuevo precio recurrente en línea. |

Cada ítem en `line_items` debe incluir `price_data`.

#### Objeto `price_data`

| Atributo       | Tipo      | Descripción                                                                                                                                                                                                                                 |
| :------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `product_data` | `object`  | **Requerido.** Datos usados para generar un nuevo objeto `Product` en línea.                                                                                                                                                                |
| `currency`     | `string`  | Código ISO 4217 de tres letras de la moneda para la suscripción. Uno de `CLP` o `MXN`.                                                                                                                                                      |
| `unit_amount`  | `integer` | **Requerido.** Un entero positivo que representa el precio por unidad, en la unidad menor de la moneda (por ejemplo, `1000` para `$1000 CLP`, ya que CLP no tiene unidad menor, o `2476` para `$24.76 MXN`, ya que MXN tiene unidad menor). |
| `recurring`    | `object`  | **Requerido.** Configuración recurrente. `interval` es uno de `day`, `week`, `month` o `year`, y `interval_count` es el número de intervalos entre cobros (por ejemplo, `1` para mensual cuando `interval` es `month`).                     |

#### Objeto `product_data`

| Atributo    | Tipo     | Descripción                                                                               |
| :---------- | :------- | :---------------------------------------------------------------------------------------- |
| `name`      | `string` | **Requerido.** Nombre del producto o servicio que se compra.                              |
| `image_url` | `string` | URL de imagen del producto. Debe ser una URL HTTPS. Relación de aspecto recomendada: 9:4. |

## Redirige al cliente para completar el registro

A continuación, redirige al cliente a la página de checkout alojada por Fintoc usando el `redirect_url`. Después de que el cliente complete el registro, Fintoc lo redirige de vuelta a tu sitio: al `success_url` en caso de éxito, o al `cancel_url` si cancela.

**Cliente**

```javascript theme={null}
window.location.assign(REDIRECT_URL_FROM_YOUR_BACKEND);
```

## Maneja los eventos posteriores a la sesión

Una vez que un `Checkout Session` finaliza, manejas el resultado en tu frontend y completas la suscripción en tu backend. Para tu backend, usas los eventos que Fintoc envía a través de webhooks.

### Completa la suscripción en tu backend

Fintoc envía un evento `checkout_session.finished` cuando la sesión se completa.

En un flujo de suscripción, este evento incluye información sobre la sesión y referencias a la `subscription` y al `payment_method` creados durante el registro.

```json theme={null}
{
  "id": "evt_a4xK32BanKWYn",
  "object": "event",
  "type": "checkout_session.finished",
  "data": {
    "id": "cs_li5531onlFDi235",
    "flow": "subscription",
    "customer": {
      "id": "cus_NffrFeUfNV2Hib",
      "object": "customer",
      "name": "Felipe Castro",
      "email": "jon@snow.com",
      "metadata": {},
      "tax_id": {
        "type": "cl_rut",
        "value": "11.111.111-1"
      }
    },
    "payment_method_types": ["pac"],
    "status": "finished",
    "payment_status": "succeeded",
    "subscription": "sub_NffrFeUfNV2Hib",
    "payment_method": "pm_NffrFeUfNV2Hib"
  }
}
```

Debes manejar los siguientes eventos posteriores a la sesión:

| Evento                      | Descripción                                                                                  | Acción                                                                                                                          |
| :-------------------------- | :------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ |
| `checkout_session.finished` | Enviado cuando un `Checkout Session` de suscripción alcanza un estado final.                 | Activa la suscripción en tu lado según el estado final y guarda los ids creados (`subscription`, `payment_method`, `customer`). |
| `checkout_session.expired`  | Enviado cuando una sesión expira.                                                            | Ofrece al cliente otro intento de suscribirse.                                                                                  |
| `payment_intent.succeeded`  | Enviado cuando un payment intent es exitoso, como un cargo en una cuenta bancaria o tarjeta. | Confirma a tu cliente que el cargo de la suscripción fue exitoso.                                                               |
| `payment_intent.failed`     | Enviado cuando un payment intent falla.                                                      | Ofrece al cliente otro intento de pagar la suscripción.                                                                         |

## Prueba tu integración

Para confirmar que tu integración funciona correctamente, puedes simular suscripciones y pagos recurrentes programados sin mover dinero.

### 1) Crea una Checkout Session de suscripción usando credenciales de usuario de prueba

Usando tu Secret Key de modo de prueba, crea un `Checkout Session` con `flow: subscription` en tu backend. Luego completa el registro en la página de checkout alojada por Fintoc con las siguientes credenciales:

**Credenciales de prueba**

* Usuario (RUT): `11.111.111-1`
* Contraseña: `jonsnow`

### 2) Maneja pagos programados simulados de la suscripción

En modo de prueba, los pagos programados de la suscripción son simulados para que puedas verificar cómo maneja tu integración el éxito y la falla sin mover dinero. Los manejas a través de los mismos eventos `invoice.*` y `payment_intent.*` descritos en la sección Manage invoices a continuación: un cargo exitoso emite `invoice.payment_succeeded` y `payment_intent.succeeded`, y uno fallido emite `invoice.payment_failed` y `payment_intent.failed`.

<Info>
  El modo de prueba aún no está disponible para pagos recurrentes en México.
</Info>

## Gestionar invoices

Cuando se crea una suscripción después de un registro exitoso en checkout, Fintoc genera automáticamente un `Invoice` para cada ciclo de facturación. Una invoice representa el monto que el cliente debe por un período dado. Fintoc intenta cobrar el pago de la invoice usando el método de pago registrado.

Para detalles completos sobre invoices, consulta el [Invoice Object](/es/reference/payments-api/invoices/invoice-object).

### Invoices en el flujo de suscripción

Después del evento `checkout_session.finished`, la suscripción pasa a `active` y Fintoc crea la primera invoice. A partir de ese momento, debes manejar los siguientes eventos relacionados a invoices junto con los eventos posteriores a la sesión descritos arriba:

| Evento                      | Descripción                                                                                                                        | Acción                                                                                                      |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `invoice.created`           | Enviado cuando Fintoc genera una nueva invoice para un ciclo de facturación.                                                       | Registra la invoice y actualiza tus registros.                                                              |
| `invoice.finalized`         | Enviado cuando Fintoc finaliza la invoice y queda lista para el pago.                                                              | Guarda el `hosted_invoice_url`, pero envíaselo a tu cliente solo si el cobro automático falla más adelante. |
| `invoice.payment_created`   | Enviado cuando comienza un pago de la invoice, ya sea desde un cobro automático o desde tu cliente usando el `hosted_invoice_url`. | Trata el evento como informativo. No envíes el `hosted_invoice_url` mientras un pago está en curso.         |
| `invoice.payment_succeeded` | Enviado cuando Fintoc cobra el pago de la invoice.                                                                                 | Confirma el pago a tu cliente y extiende el acceso.                                                         |
| `invoice.payment_failed`    | Enviado cuando un intento de pago para la invoice falla.                                                                           | Envía el `hosted_invoice_url` para que tu cliente pueda pagar la invoice.                                   |
| `invoice.voided`            | Enviado cuando una invoice se anula y Fintoc deshabilita su `hosted_invoice_url`.                                                  | Actualiza tus registros.                                                                                    |

**Mes 1:** Justo después de que se crea la suscripción, Fintoc genera la primera invoice e intenta el pago inmediatamente. Recibirás `invoice.created`, seguido de `invoice.finalized`, luego `invoice.payment_succeeded` y `payment_intent.succeeded` en caso de éxito.

**Mes 2 en adelante:** En cada renovación de ciclo de facturación (basado en el `billing_cycle_anchor` de la suscripción), Fintoc crea una nueva invoice en estado `draft`. Después de 1 hora, Fintoc intenta el pago automáticamente. En éxito recibes `invoice.payment_succeeded`. En falla, `invoice.payment_failed`.

### Recuperar un pago fallido

Cuando un cobro automático falla, Fintoc emite `invoice.payment_failed`. Para recuperar el pago, envía el `hosted_invoice_url` de la invoice a tu cliente por tu propio canal, como email o WhatsApp. La página alojada permite que tu cliente pague usando los métodos de pago habilitados en la cuenta de tu organización. Un pago exitoso crea un `payment_intent` en la invoice y salda la deuda. El método de pago inscrito de la suscripción sigue siendo válido, y Fintoc cobra el siguiente ciclo automáticamente.

El `hosted_invoice_url` queda disponible en el objeto `Invoice` una vez que la invoice alcanza el estado `open`. Para más detalles, consulta el [Invoice object](/es/reference/payments-api/invoices/invoice-object).

<Info>
  Una invoice acepta solo un pago a la vez. Si abres el `hosted_invoice_url` mientras un cobro automático está en curso, la página muestra que hay un pago de invoice en progreso y el enlace de pago queda deshabilitado. Fintoc vuelve a habilitar el enlace de pago si el cobro automático falla.
</Info>

### Probar la creación de invoice con estado `draft`

Para probar una invoice que se crea en estado `draft`, crea una suscripción con un line item usando el nombre de producto `sandbox_draft`:

**Servidor**

```curl 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": "subscription",
    "amount": 350000,
    "currency": "CLP",
    "success_url": "https://merchant.com/success",
    "cancel_url": "https://merchant.com/cancel",
    "payment_method_types": ["pac"],
    "customer_data": {
      "tax_id": {
        "type": "cl_rut",
        "value": "11.111.111-1"
      },
      "name": "Felipe Castro",
      "email": "jon@snow.com"
    },
    "line_items": [
      {
        "price_data": {
          "currency": "CLP",
          "unit_amount": 350000,
          "product_data": {
            "name": "sandbox_draft"
          },
          "recurring": {
            "interval": "month",
            "interval_count": 1
          }
        },
        "quantity": 1
      }
    ]
  }'
```

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

const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY');

const checkoutSession = await fintoc.checkoutSessions.create({
  flow: 'subscription',
  amount: 350000,
  currency: 'CLP',
  success_url: 'https://merchant.com/success',
  cancel_url: 'https://merchant.com/cancel',
  payment_method_types: ['pac'],
  customer_data: {
    tax_id: {
      type: 'cl_rut',
      value: '11.111.111-1'
    },
    name: 'Felipe Castro',
    email: 'jon@snow.com'
  },
  line_items: [
    {
      price_data: {
        currency: 'CLP',
        unit_amount: 350000,
        product_data: {
          name: 'sandbox_draft'
        },
        recurring: {
          interval: 'month',
          interval_count: 1
        }
      },
      quantity: 1
    }
  ]
});
```

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

client = Fintoc('YOUR_TEST_SECRET_API_KEY')

checkout_session = client.checkout_sessions.create(
    flow='subscription',
    amount=350000,
    currency='CLP',
    success_url='https://merchant.com/success',
    cancel_url='https://merchant.com/cancel',
    payment_method_types=['pac'],
    customer_data={
        'tax_id': {
            'type': 'cl_rut',
            'value': '11.111.111-1',
        },
        'name': 'Felipe Castro',
        'email': 'jon@snow.com',
    },
    line_items=[
        {
            'price_data': {
                'currency': 'CLP',
                'unit_amount': 350000,
                'product_data': {
                    'name': 'sandbox_draft',
                },
                'recurring': {
                    'interval': 'month',
                    'interval_count': 1,
                },
            },
            'quantity': 1,
        }
    ],
)
```

Fintoc crea el `Checkout Session`:

```json theme={null}
{
  "id": "cs_li5531onlFDi235",
  "object": "checkout_session",
  "mode": "test",
  "flow": "subscription",
  "status": "created",
  "amount": 350000,
  "currency": "CLP",
  "payment_method_types": ["pac"],
  "customer": {
    "id": "cus_NffrFeUfNV2Hib",
    "object": "customer",
    "name": "Felipe Castro",
    "email": "jon@snow.com",
    "metadata": {},
    "tax_id": {
      "type": "cl_rut",
      "value": "11.111.111-1"
    }
  },
  "line_items": [
    {
      "price": {
        "product": {
          "name": "sandbox_draft",
          "description": "Fixed-amount monthly plan"
        },
        "currency": "CLP",
        "unit_amount": 350000,
        "recurring": {
          "interval": "month",
          "interval_count": 1
        }
      },
      "quantity": 1
    }
  ],
  "success_url": "https://merchant.com/success",
  "cancel_url": "https://merchant.com/cancel",
  "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235"
}
```

Fintoc crea la invoice en estado `draft`, de modo que puedas editar sus ítems con el endpoint [Add Lines](/es/reference/payments-api/invoices/invoices-add-lines) antes de que la invoice transicione al siguiente estado.
