Ciclo de vida y dinero

Estados y expiración, autorización y captura, cuándo llega el dinero a tu balance y con qué comisiones, reembolsos, botones de pago y cupones.

Ciclo de vida y dinero

Expiración y cancelación

Un checkout unpaid no vive para siempre:

  • Expira automáticamente al pasar expires_at (por defecto, 2 semanas desde su creación). Un job de Venti lo marca expired y recibes el webhook checkout.expired. Puedes fijar otra fecha al crearlo o moverla con PUT /checkouts/{id}.
  • Puedes cancelarlo con POST /checkouts/{id}/cancel mientras siga unpaid. Un checkout pagado no se cancela: se reembolsa.

Cada intento de pago del cliente crea un Payment (o Loan) asociado al checkout; los intentos fallidos quedan como historial y al liquidarse el checkout apunta a exactamente un objeto exitoso (successful_object_id).

Con qué se pagó el checkout

Un checkout pagado te dice exactamente con qué medio se saldó mediante su discriminador:

{
  "status": "paid",
  "successful_object": "payment",
  "successful_object_id": "pay_hK2mR8vQpL9wN4sJhT5yBc3d",
  "payment_id": "pay_hK2mR8vQpL9wN4sJhT5yBc3d",
  "loan_id": null,
  "account_entry_id": null
}

payment_id, loan_id y account_entry_id son mutuamente excluyentes: solo se llena el del objeto que pagó, y successful_object / successful_object_id siempre apuntan a él. Léelos al recibir checkout.paid para enrutar tu lógica según el medio de pago.

Cómo se leen los montos

Todos los montos van en unidades menores de la moneda (para clp, pesos):

  • amount — el total a pagar. Se calcula en el servidor: suma de los ítems (subtotal), menos descuentos (discount), más impuestos exclusivos. No lo fijas directamente.
  • original_amount — el total al crearse, antes de cupones o promociones.
  • items[] — cada ítem lleva unit_price, quantity y su total calculado.
  • available_for_refund — cuánto queda por reembolsar (amount − refunded_amount).
  • settlement_amount / settlement_currency — lo que se liquida a tu comercio una vez pagado.
  • fee — la comisión de procesamiento del pago que lo saldó.

La lista completa de campos está en la sección Payments del API Reference.

Autorización y captura

Por defecto (authorize: true en el checkout, capture: true en el pago) el cobro es de un paso: autorización y captura ocurren juntas y el pago queda succeeded.

Para el flujo en dos pasos crea el checkout con authorize: false: cuando el cliente confirme, el pago quedará autorizado pero no capturado (requires_capture), y tú decides:

  • POST /payments/{id}/capture — hace efectivo el cobro.
  • POST /payments/{id}/cancel — libera la autorización.

La captura tiene una ventana de 10 minutos desde la autorización. Pasado ese plazo el pago deja de ser capturable (payment_not_capturable) y debes cancelarlo.

Cuándo llega el dinero a tu balance

Cuando un pago queda capturado, Venti registra las transacciones de balance de esa venta con fecha contable (accounting_at) del día hábil de la captura:

TransacciónSignoQué es
payment+El monto de liquidación de la venta (settlement_amount).
feeLa comisión de procesamiento del pago.
payout_feeEl cargo por liquidación acelerada, si tu comercio la tiene contratada.
tax_feeEl IVA sobre las comisiones.

Las ventas en cuotas BNPL abonan igual: una transacción loan por el total de la venta, con sus fee y tax_fee — tú recibes el monto completo aunque el cliente pague en cuotas. Las ventas pagadas con Cuentas Venti no generan transacciones de balance: el dinero llega recién con la cobranza del estado de cuenta.

El balance disponible se paga a tu cuenta bancaria según el payout_schedule de tu comercio: cada venta queda programada para liquidarse 1 o 3 días hábiles después de su fecha contable, y los payouts se procesan en días hábiles hacia la cuenta bancaria registrada. El detalle vive en la sección Finance del API Reference (/balance, /balance_transactions, /payouts).

Medios de pago

Los medios que ve tu cliente en la página de pago salen de la configuración de medios de pago de tu comercio: cada familia (tarjetas, transferencia, BNPL, etc.) puede estar habilitada o no, y dentro de una familia pueden deshabilitarse medios específicos. Un intento de pago con un medio no habilitado se rechaza en el servidor (invalid_payment_method_config).

La página de pago también resuelve por ti las cuotas y los sobrecargos: cuando tu comercio traspasa la comisión de cuotas al cliente, el checkout muestra el recargo antes de confirmar y este queda registrado en surcharge_amount (con su boleta de IVA emitida al cliente).

Reembolsos

Reembolsa con POST /checkouts/{id}/refund (o POST /payments/{id}/refund si manejas pagos directos). Cada reembolso crea un objeto Refund (ref_):

  • Total o parcial: si omites amount se devuelve todo lo disponible; puedes reembolsar en partes hasta agotar el monto original (available_for_refund).
  • Destino: payment_method (el medio original, por defecto) o customer_balance (la billetera Venti del cliente, útil cuando el medio original no acepta abonos).
  • Estados: pendingsucceeded o failed, con webhooks refund.created, refund.succeeded y refund.failed. El tiempo en llegar al cliente depende del medio de pago original.

El impacto en tu dinero:

  • Al quedar succeeded, se debita una transacción refund de tu balance por el monto devuelto.
  • Las comisiones de la venta no se devuelven (salvo que tu comercio tenga contratado el reembolso de comisiones, en cuyo caso se abonan proporcionalmente como fee_reimbursement y tax_fee_reimbursement).
  • Un reembolso en vivo requiere balance disponible suficiente; si no alcanza, la API responde insufficient_balance.

Casos especiales:

  • Un checkout pagado con Cuentas Venti se reembolsa instantáneamente como abono al cupo del cliente, sin movimiento de dinero ni impacto en tu balance (Cuentas Venti).
  • Un pago disputado (contracargo) no es reembolsable.
  • En modo test los reembolsos quedan succeeded de inmediato.

Botones de pago

Un PaymentButton (pb_) es un cobro reutilizable sin integración: creas el botón con título, monto y moneda, y compartes su url (https://pay.ventipay.com/pay-button/{id}). Cada cliente que lo abre obtiene su propio checkout nuevo, así que puedes cobrar lo mismo a muchas personas con un solo link o QR.

  • active: false pausa el botón: deja de generar checkouts (payment_button_inactive).
  • button_type admite pay y donate.
  • custom_fields pide datos al cliente en la página (nombre, RUT, teléfono, etc.).
  • Filtra lo cobrado con GET /checkouts?payment_button_id=pb_....

Cupones

Un Coupon (cpn_) descuenta sobre el amount de un checkout unpaid:

  • type: "amount_off" (monto fijo, requiere currency igual a la del checkout) o type: "percent_off" (porcentaje 0–100, con tope opcional por aplicación).
  • Se aplica por código con POST /checkouts/{id}/coupon (promotion_code), desde tu backend o directamente por el cliente en la página de pago si el cupón tiene reedemable_by_customer: true.
  • El descuento queda en discount_amounts y el amount se recalcula (con piso en 0).
  • Controlas su vigencia con active, expires_at, max_redemptions (contra times_redeemed) y restrictions (monto mínimo del checkout, tope por aplicación y tope acumulado de uso).
  • applies_to define si el cupón sirve para checkouts, para suscripciones, o ambos.

Siguiente paso

Sigue con Webhooks y conciliación para integrar tu backoffice y cuadrar tus ventas contra tu balance.