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

# Cargos bajo demanda

> Recolecta un método de pago y realiza cargos automáticos sin crear facturas.

Esta guía explica cómo recolectar un método de pago de tu cliente para luego mandar cargos automáticos que se realicen sin su intervención.

<Note>
  Si cada cargo corresponde a un adeudo que quieres sincronizar con Quentli, usar recordatorios y gestionar reintentos
  automáticos, sigue [Sincroniza facturas en Quentli](/api/guias/sincroniza-facturas-en-quentli).
</Note>

Los cargos automáticos te permiten cobrar a tus clientes de forma recurrente o puntual sin que ellos tengan que autorizar cada transacción individualmente. Una vez que tienes un método de pago enlazado a un cliente, puedes hacer cargos sin intervención del usuario.

<Tip>
  Obtén y conserva el consentimiento del cliente antes de iniciar cargos automáticos. El endpoint valida que el método
  de pago pertenezca al cliente; para cuentas bancarias también valida su verificación.
</Tip>

## 1. Crea un cliente

El primer paso es crear un cliente en tu sistema. Este cliente será quien proporcionará el método de pago para los cargos automáticos.

```json POST /v1/customers theme={null}
{
  "input": {
    "name": "María González",
    "username": "12345",
    "email": "maria@ejemplo.com",
    "phoneNumber": "+525555123456"
  }
}
```

## 2. Recolecta un método de pago

Antes de realizar cargos automáticos, el cliente debe proporcionar un método de pago válido (tarjeta de crédito/débito o cuenta bancaria). Este paso se realiza a través del Portal de Clientes, donde se le solicita al usuario que guarde su método de pago para cargos futuros.

Tienes 2 opciones para recolectar un método de pago:

1. En una sesión de pago (`PaymentSession`)
2. En una sesión de inscripción

### Opción 1: En una sesión de pago (`PaymentSession`)

```json POST /v1/payment-sessions theme={null}
{
  "input": {
    "returnUrl": "https://miapp.com/success",
    "cancelUrl": "https://miapp.com/declined",
    "customer": {
      "name": "Mariana López",
      "externalId": "1337"
    },
    "expiresAt": "2025-04-22T15:47:15.250Z",
    "description": "Mensualidad",
    "amount": 239000,
    "currency": "MXN"
  }
}
```

### Opción 2: En una sesión de inscripción

Las [sesiones de inscripción](/api/guias/sesiones-de-inscripcion) te permiten recolectar métodos de pago sin realizar un cobro inmediato. Esta opción es ideal para configurar suscripciones o periodos de prueba.

<Warning>Las sesiones de inscripción son una característica experimental y pueden estar sujetas a cambios.</Warning>

```json POST /v1/setup-sessions theme={null}
{
  "input": {
    "customer": {
      "name": "María González",
      "externalId": "12345",
      "email": "maria@ejemplo.com",
      "phoneNumber": "+525555123456"
    },
    "displayMode": "CUSTOMER_PORTAL",
    "returnUrl": "https://miapp.com/exito",
    "cancelUrl": "https://miapp.com/cancelado"
  }
}
```

<Tip>
  Consulta la [guía completa de sesiones de inscripción](/api/guias/sesiones-de-inscripcion) para aprender cómo
  implementar esta funcionalidad paso a paso.
</Tip>

## 3. Obtén los métodos de pago del cliente

Una vez que el cliente ha guardado un método de pago, puedes consultarlos para obtener el `paymentMethodId` que necesitarás para realizar cargos automáticos.

```
GET /v1/customers/{customerId}/payment_methods
```

### Ejemplo de respuesta

```json Respuesta theme={null}
[
  {
    "id": "pm_clvqmr51j000408jyhcth2rjy",
    "createdAt": "2025-01-15T20:30:00.000Z",
    "updatedAt": "2025-01-15T20:30:00.000Z",
    "customerId": "cus_1234567890",
    "type": "CARD",
    "confirmed": true,
    "default": true,
    "expired": false,
    "cardDetail": {
      "id": "crd_1234567890",
      "createdAt": "2025-01-15T20:30:00.000Z",
      "updatedAt": "2025-01-15T20:30:00.000Z",
      "expiryMonth": 12,
      "expiryYear": 2028,
      "cardholder": "MARIA GONZALEZ",
      "bin": "424242",
      "last4": "4242",
      "brand": "visa",
      "issuer": "BANCOMER",
      "isCorporate": false,
      "country": "MX",
      "funding": "credit"
    },
    "bankAccount": null
  },
  {
    "id": "pm_clvqmr51j000408jyhcth2abc",
    "createdAt": "2025-01-10T15:20:00.000Z",
    "updatedAt": "2025-01-10T15:20:00.000Z",
    "customerId": "cus_1234567890",
    "type": "MEXICAN_BANK_ACCOUNT",
    "confirmed": true,
    "default": false,
    "expired": false,
    "cardDetail": null,
    "bankAccount": {
      "id": "ba_1234567890",
      "createdAt": "2025-01-10T15:20:00.000Z",
      "updatedAt": "2025-01-10T15:20:00.000Z",
      "bankCode": "012",
      "bankName": "BBVA México",
      "customerId": "cus_1234567890",
      "country": "MX",
      "verified": true,
      "clabeLast": "5678",
      "clabeFirst": "0123"
    }
  }
]
```

### Campos importantes

* `id`: El identificador del método de pago que usarás en el campo `paymentMethodId` al realizar cargos.
* `type`: El tipo de método de pago (`CARD` para tarjetas o `MEXICAN_BANK_ACCOUNT` para cuentas bancarias).
* `default`: Indica si es el método de pago predeterminado del cliente.
* `confirmed`: Indica si el método de pago ha sido confirmado con al menos un pago exitoso.
* `expired`: Indica si el método de pago ha expirado (solo aplica para tarjetas).
* `cardDetail`: Detalles de la tarjeta (cuando `type` es `CARD`).
* `bankAccount`: Detalles de la cuenta bancaria (cuando `type` es `MEXICAN_BANK_ACCOUNT`).

<Tip>
  El método de pago con `default: true` será el que se use automáticamente en las suscripciones si no se especifica uno
  diferente.
</Tip>

## 4. Realiza un cargo automático

Una vez que tienes un cliente con un método de pago válido, puedes realizar cargos automáticos usando el endpoint de pagos.

### Ejemplo de solicitud

```json POST /v1/payments highlight={11-11} theme={null}
{
  "input": {
    "amount": 399900,
    "currency": "MXN",
    "description": "Mensualidad",
    "paymentMethodId": "pm_1234567890",
    "customerId": "cus_1234567890",
    "makeAttempt": true,
    "meta": {
      "orderId": "order_1234567890",
      "serviceType": "subscription"
    }
  }
}
```

### Campos relevantes

* `amount`: El monto a cobrar en unidades menores de la moneda. Por ejemplo, \$3,999.00 MXN = 399900.
* `paymentMethodId`: El identificador del método de pago previamente recolectado del cliente.
* `customerId`: El identificador del cliente al que se le realizará el cargo.
* `description`: Una descripción clara del concepto que se está cobrando.
* `makeAttempt`: Si es `true`, se hará el intento de cargo al enviar la petición. Si es `false`, se creará el pago pero no se hará el intento de cargo.
* `meta` (opcional): Información adicional que quieras asociar con el pago para tu referencia.

### Posibles respuestas

#### Intento exitoso

Cuando el cargo es exitoso, verás la propiedad `attempt.success` como `true`.

```JSON Respuesta (intento exitoso) highlight={20-20} theme={null}
{
    "payment": {
        "id": "p_1234567890",
        "createdAt": "2025-01-15T21:00:00.000Z",
        "amount": 399900,
        "currency": "MXN",
        "type": "CARD",
        "status": "COMPLETE",
        "description": "Mensualidad",
        "paymentMethodId": "pm_1234567890",
        "customerId": "cus_1234567890",
        "meta": {
            "orderId": "order_1234567890",
            "serviceType": "subscription"
        }
    },
    "attempt": {
      "id": "pa_1234567890",
      "createdAt": "2025-01-15T21:00:00.000Z",
      "type": "CARD",
      "success": true,
      "scheduled": false,
      "automatic": true,
      "errorType": null
    },
    "customer": {
      "id": "cus_1234567890",
      "name": "Alicia Ríos",
      "email": "aliciarr@ejemplos.com",
      "phoneNumber": "<número_de_celular>",
      "username": "12345",
      "meta": {}
    }
}
```

#### Intento fallido

Para identificar un cargo fallido, debes revisar el campo `success`. Puedes obtener el motivo del rechazo usando el campo `errorType` del objeto `attempt`.

<Warning>Toma en cuenta que cuando un intento es fallido, el código HTTP de la respuesta será `200`</Warning>

```json Respuesta (intento fallido) highlight={20-20,23-23} theme={null}
{
  "payment": {
    "id": "p_1234567890",
    "createdAt": "2025-01-15T21:00:00.000Z",
    "amount": 399900,
    "currency": "MXN",
    "type": "CARD",
    "status": "INCOMPLETE",
    "description": "Mensualidad",
    "paymentMethodId": "pm_1234567890",
    "customerId": "cus_1234567890",
    "meta": {
      "orderId": "order_1234567890",
      "serviceType": "subscription"
    }
  },
  "attempt": {
    "id": "pa_1234567890",
    "createdAt": "2025-01-15T21:00:00.000Z",
    "type": "CARD",
    "success": false,
    "scheduled": false,
    "automatic": true,
    "errorType": "INSUFFICIENT_FUNDS"
  },
  "customer": {
    "id": "cus_1234567890",
    "name": "Alicia Ríos",
    "email": "aliciarr@ejemplos.com",
    "phoneNumber": "<número_de_celular>",
    "username": "12345",
    "meta": {}
  }
}
```

#### Intento iniciado

Cuando el método de pago que se usa es de tipo `DIRECT_DEBIT`, el pago se creará con estado `INITIATED` y la propiedad `attempt` será `null`.

En estos casos, para monitorear el resultado, debes usar un [webhook](/api/webhooks) de tipo `PAYMENT_ATTEMPT_SUCCEEDED` o `PAYMENT_ATTEMPT_FAILED`.

<Warning>
  Esto solo aplica para pagos con domiciliación bancaria (tipo `DIRECT_DEBIT`). Los pagos con tarjeta de crédito o
  débito se procesan de forma inmediata.
</Warning>

```json Respuesta (intento iniciado) highlight={18-18} theme={null}
{
  "payment": {
    "id": "p_1234567890",
    "createdAt": "2025-01-15T21:00:00.000Z",
    "amount": 399900,
    "currency": "MXN",
    "type": "DIRECT_DEBIT",
    "status": "INITIATED",
    "description": "Mensualidad",
    "paymentMethodId": "pm_1234567890",
    "customerId": "cus_1234567890",
    "meta": {
      "orderId": "order_1234567890",
      "serviceType": "subscription"
    }
  },
  "attempt": null,
  "customer": {
    "id": "cus_1234567890",
    "name": "Alicia Ríos",
    "email": "aliciarr@ejemplos.com",
    "phoneNumber": "<número_de_celular>",
    "username": "12345",
    "meta": {}
  }
}
```

## Formas de pago soportadas

Este endpoint soporta dos formas de pago, cada una con diferentes tiempos de procesamiento:

<Note>
  Lo que determina qué forma de pago se usa es el tipo del método de pago (`PaymentMethod.type`) que proporcionas en el
  campo `paymentMethodId` al mandar el pago.
</Note>

### Tarjetas de crédito/débito (`CARD`)

Los pagos con tarjeta de crédito o débito se procesan de forma **inmediata**. Obtienes la confirmación del resultado del pago en tiempo real a través de la respuesta de la petición a `POST /v1/payments`.

### Domiciliación bancaria (`DIRECT_DEBIT`)

Los pagos mediante domiciliación bancaria (cuentas CLABE) **no se confirman inmediatamente**. El proceso funciona así:

1. **Al crear el pago**: Recibes una respuesta con estado `INITIATED`
2. **Procesamiento**: El cargo se envía al sistema bancario
3. **Confirmación**: Debes esperar hasta el **siguiente día hábil** para obtener la respuesta definitiva (mediante webhooks)

#### Ejemplo de respuesta

```json theme={null}
{
  "payment": {
    "id": "p_1234567890",
    "createdAt": "2025-01-15T21:00:00.000Z",
    "amount": 399900,
    "currency": "MXN",
    "type": "DIRECT_DEBIT",
    "status": "INITIATED",
    "description": "Mensualidad",
    "paymentMethodId": "pm_1234567890",
    "customerId": "cus_1234567890",
    "meta": {
      "orderId": "order_1234567890",
      "serviceType": "subscription"
    }
  }
}
```

<Warning>
  Para pagos con domiciliación bancaria, los webhooks son esenciales ya que no obtienes confirmación inmediata. Debes
  monitorear los eventos `PAYMENT_ATTEMPT_SUCCEEDED` y `PAYMENT_ATTEMPT_FAILED` para conocer el resultado final del
  cargo.
</Warning>

## Estados del pago

Después de crear un cargo automático, el pago pasará por diferentes estados:

* **INCOMPLETE**: El pago está siendo procesado por el sistema bancario.
* **COMPLETE**: El pago se completó exitosamente.
* **INITIATED**: El pago ha sido programado y está pendiente de procesamiento.
* **CANCELED**: El pago fue cancelado; no se admitirá.

## Monitoreo con webhooks

Para mantener tu integración sincronizada con el estado de los pagos, puedes suscribirte a los siguientes webhooks:

### Eventos de intentos de pago

* **`PAYMENT_ATTEMPT_SUCCEEDED`**: Se envía cuando un intento de cobro automático es exitoso.
* **`PAYMENT_ATTEMPT_FAILED`**: Se envía cuando un intento de cobro automático falla, incluyendo el código de error correspondiente.

### Eventos de métodos de pago

* **`PAYMENT_METHOD_CREATED`**: Se envía cuando un cliente guarda un nuevo método de pago (tarjeta o cuenta bancaria) que podrás usar para cargos automáticos.

<Tip>
  Consulta la [documentación completa de webhooks](/api/webhooks) para ver todos los eventos disponibles y sus
  estructuras.
</Tip>

<Note>
  Para casos de uso más complejos con pagos recurrentes programados, considera usar [suscripciones con pagos
  definidos](/api/guias/suscripciones-con-pagos-definidos) que ofrecen mayor flexibilidad y control.
</Note>
