Ciclo de vida

Períodos y prorrateo, prueba, renovación, reintentos y morosidad, pausa y cancelación — y cuándo se mueve el dinero.

Ciclo de vida de una suscripción

El mapa de estados

                        ┌── trial_days > 0 ──→  trialing ──(fin de prueba)──┐
incomplete ──(cliente autoriza)                                             ├─→ active ⇄ suspended
                        └────── sin prueba: primer cobro ───────────────────┘      │
                                                                                   │ cobro falla
                                                                                   ▼
                                                              past_due ──(reintentos agotados)──→ unpaid | canceled

canceled puede alcanzarse desde cualquier estado no terminal: por el cliente, por el comercio, por fecha programada (cancel_at), por completar sus ciclos (duration) o por falta de pago. unpaid y canceled son terminales.

Períodos: deterministas y anclados

El próximo período de una suscripción depende solo de su estado guardado — intervalo, período vigente, prueba y billing_cycle_anchor — nunca de la hora en que corre el proceso de renovación. Ejecutar la renovación dos veces, o tarde, produce exactamente el mismo período y nunca un cobro doble (la nota de venta de cada período es única).

  • Los períodos son contiguos: cada uno termina en el instante exacto en que empieza el siguiente (current_period_ends_at = inicio del próximo).
  • Ciclos mensuales (1month): el período termina en la próxima ocurrencia del día ancla. Una suscripción anclada al 31 cobra el 31 de enero, el 28 de febrero y vuelve al 31 de marzo — el ancla no se pierde en los meses cortos.
  • El primer período puede ser corto: si la suscripción parte el 15 con ancla el 1, el primer período va del 15 al 1. Qué se cobra por ese período parcial lo decide proration_behavior:
proration_behaviorPrimer período parcial
create_prorations (por defecto)Se cobra el proporcional (factor = fracción del ciclo).
fullSe cobra el ciclo completo.
noneNo se cobra; el primer cobro real es el del primer ciclo completo.
  • Los demás intervalos (semanas, multi-mes, anual) avanzan por su largo fijo desde el día del propio período e ignoran el ancla.
  • Las renovaciones siguientes siempre cobran el ciclo completo: el prorrateo solo existe en el primer ciclo.

Prueba e inicio diferido

  • trial_days: al autorizarse, la suscripción pasa a trialing sin cobro. El primer cobro ocurre al terminar la prueba (trial_ends_at). En una suscripción creada desde un plan con prueba, la prueba corre desde la creación.
  • start_at futuro: la suscripción se activa con un período de espera por $0 hasta la fecha de inicio; el primer cobro real ocurre en start_at. En estado trialing, el comercio puede mover el inicio de la prueba actualizando start_at.

La renovación

Cuando termina el período vigente (o la prueba), el motor de renovación de Venti:

  1. Calcula el próximo período (determinista, como arriba).
  2. Genera la nota de venta del período con los productos vigentes: los recurrent siempre, los one_time solo si es el primer cobro. Los precios se leen al momento de renovar — si cambiaste el precio de un producto, el cambio se aplica desde el siguiente ciclo.
  3. Aplica descuentos: cupones asociados a la suscripción según su duración (once solo el primer ciclo, repeating los primeros N, forever siempre) y promociones vigentes (solo el primer ciclo). Los cupones se administran con la API de cupones (ver Payments en el API Reference).
  4. Aplica los impuestos: los inclusive se desglosan; los exclusivos se suman al total.
  5. Carga el total al medio de pago inscrito. Si resulta $0 (prueba, pausa, prorrateo none), la nota de venta se marca pagada sin generar cobro.

Solo renuevan las suscripciones con collection_method: automatic, con cliente y sin cancelación vencida. Cada renovación exitosa incrementa cycles.

Cuándo se mueve el dinero

Cada nota de venta pagada genera un Payment normal de Venti, con subscription_id, invoice_id y automatic: true. Ese pago:

  • Abona a tu balance menos las comisiones estándar de procesamiento del medio de pago — no hay comisiones adicionales por ser suscripción.
  • Aparece en tus transacciones de balance como cualquier venta (abono payment, cargos fee e impuestos de la comisión) y sale en tus payouts normales.

Cobros fallidos: past_due, reintentos y desenlace

Si el cargo a la tarjeta falla:

  1. La nota de venta queda open y la suscripción pasa a past_due. El cliente recibe un email avisando que su pago está pendiente (puede regularizarlo pagando la nota de venta o cambiando su tarjeta).
  2. Venti reintenta el cobro periódicamente mientras la nota de venta esté dentro de la ventana de reintentos del comercio (subscription_retry_days, por defecto 3 días desde el inicio del período). Si el cliente actualiza su medio de pago, las notas de venta pendientes se cobran con el nuevo.
  3. Agotada la ventana, la nota de venta pasa a uncollectible y la suscripción termina según la configuración del comercio (subscription_retry_failed_action):
    • mark_unpaid (por defecto): la suscripción queda unpaid — terminal, sin más cobros.
    • cancel: la suscripción queda canceled con status_reason: canceled_due_payment.

Un reintento exitoso dentro de la ventana devuelve la suscripción a active y marca la nota de venta paid.

📘

La ventana de reintentos y la acción final son configuración de tu comercio. Si necesitas cambiarlas, contáctanos.

Pausar y reactivar

  • POST /subscriptions/{id}/suspend pausa una suscripción activesuspended.
  • Mientras está suspendida, los ciclos siguen corriendo pero cada nota de venta se emite por $0: no se cobra nada, no se acumula deuda y cycles no avanza.
  • POST /subscriptions/{id}/unsuspend la devuelve a active; el próximo ciclo se cobra normalmente.
  • El cliente puede pausar/reactivar desde su página de suscripción solo si tu comercio tiene habilitada la pausa por cliente (subscription_allow_pause, habilitada por defecto). Tú puedes hacerlo siempre.

Cancelar

POST /subscriptions/{id}/end (o DELETE /subscriptions/{id}):

  • Sin parámetros: programa la cancelación para el fin del período vigente (o de la prueba). El cliente conserva lo que ya pagó; no hay más cobros.
  • cancel_at: programa la cancelación para esa fecha. Una fecha pasada cancela de inmediato.
  • cancel_at: null: revierte una cancelación programada que aún no se ejecuta.

Reglas de precedencia (aplicadas siempre en el servidor):

  • El cliente solo puede cancelar si tu comercio lo permite (subscription_allow_unsubscription, habilitado por defecto).
  • Una cancelación hecha por el cliente no puede ser revertida ni reprogramada a futuro por el comercio (subscription_was_canceled_by_customer), y una hecha por el comercio no puede ser revertida por el cliente.
  • status_reason registra quién canceló: canceled_by_customer, canceled_by_merchant, canceled_due_payment o reached_cycles_duration.

Duración limitada: si defines duration (1-365 ciclos), la suscripción se cancela sola al completar esa cantidad de ciclos cobrados. duration y cancel_at son mutuamente excluyentes — definir uno limpia el otro.

Editar una suscripción en curso

Con PUT /subscriptions/{id} puedes, entre otros:

  • Cambiar productos e impuestos (default_products, default_tax_rates): aplica desde el próximo ciclo.
  • Cambiar el medio de pago (default_payment_method_id): debe ser un medio inscrito del cliente; también se aplica a las notas de venta pendientes.
  • Mover el período vigente (current_period_starts_at / current_period_ends_at, solo en incomplete, active, past_due o suspended): adelanta o atrasa el próximo cobro; el ancla se ajusta al nuevo fin de período.
  • Cambiar interval, billing_cycle_anchor o duration: aplican al calcular el próximo período.

Siguiente paso

Las notas de venta que genera cada ciclo — y las que puedes crear tú para cobros puntuales — están en Notas de venta.