---
updatedAt: 2026-10-08T22:06:01.000Z
agentTools:
  projectIndex: https://docs.ventipay.com/llms.txt
---

# Reglas y errores

Las reglas del producto y los códigos de error que puede devolver la API de suscripciones y notas de venta.

# Reglas y errores

## Reglas del producto

Estas reglas se aplican siempre en el servidor:

* **Los cobros automáticos requieren tarjeta.** Iniciar una suscripción exige un medio de pago inscrito de autorización síncrona; las transferencias bancarias no sirven para cobros recurrentes.
* **La renovación es determinista e idempotente.** El próximo período depende solo del estado guardado de la suscripción, y existe exactamente **una nota de venta por período**: reprocesos nunca duplican cobros.
* **Solo se inicia una suscripción `incomplete`.** Iniciar de nuevo una suscripción ya iniciada es un error.
* **Solo se pausa una suscripción `active` y solo se reactiva una `suspended`.** Durante la pausa se emiten notas de venta por $0 y los ciclos cobrados no avanzan.
* **La cancelación del cliente manda.** Si el cliente canceló, el comercio no puede revertirlo ni reprogramarlo a futuro — y viceversa.
* **El cliente solo puede cancelar o pausar si tu comercio lo permite** (`subscription_allow_unsubscription` y `subscription_allow_pause`, ambos habilitados por defecto).
* **`duration` y `cancel_at` son excluyentes**: definir uno limpia el otro. Al completar `duration` ciclos, la suscripción se cancela sola (`reached_cycles_duration`).
* **Un cliente no puede tener dos suscripciones vigentes del mismo plan.**
* **Un plan inactivo no acepta suscripciones nuevas.**
* **Los productos e impuestos deben ser del mismo modo (live/test) que la suscripción**, y los productos, de su misma moneda; los que no calzan se ignoran.
* **Una nota de venta solo se edita completa en `draft`, solo se finaliza desde `draft` y solo se cobra en `open`.** `void` es definitivo; `uncollectible` no aplica a notas `paid` o `void`.
* **`percentage` e `inclusive` de un impuesto son inmutables**, igual que la `currency` y el `pricing_type` de un producto. Para cambiarlos, desactiva el objeto y crea otro.
* **Los reintentos tienen ventana y desenlace configurados por comercio**: `subscription_retry_days` (por defecto 3 días desde el inicio del período) y `subscription_retry_failed_action` (`mark_unpaid` por defecto, o `cancel`).
* **Las notas de venta `paid_out_of_band` no son reembolsables por Venti** (el dinero nunca pasó por Venti).

## Códigos de error

Errores del tipo `invalid_request_error` que puede devolver esta API:

| Código                                      | Cuándo                                                                                                               |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `subscription_already_started`              | Intento de iniciar (o aplicar un cupón a) una suscripción que ya no está en un estado que lo permita.                |
| `subscription_inactive`                     | La suscripción no es renovable: cancelada, sin cliente/comercio, con cancelación vencida o con sus ciclos completos. |
| `subscription_must_be_active`               | Intento de pausar una suscripción que no está `active`.                                                              |
| `subscription_must_be_suspended`            | Intento de reactivar una suscripción que no está `suspended`.                                                        |
| `subscription_cant_be_canceled_by_customer` | El cliente intentó cancelar y tu comercio no lo permite.                                                             |
| `subscription_cant_be_paused_by_customer`   | El cliente intentó pausar/reactivar y tu comercio no lo permite.                                                     |
| `subscription_was_canceled_by_customer`     | El comercio intentó revertir o reprogramar una cancelación hecha por el cliente.                                     |
| `subscription_was_canceled_by_merchant`     | El cliente intentó revertir una cancelación hecha por el comercio.                                                   |
| `plan_inactive`                             | Intento de crear una suscripción desde un plan inactivo.                                                             |
| `already_subscribed`                        | El cliente ya tiene una suscripción vigente de ese plan.                                                             |
| `invalid_subscription`                      | El `subscription_id` de la nota de venta no existe o no es de tu comercio/modo.                                      |
| `invalid_invoice`                           | La nota de venta no es cobrable (ya pagada o con datos incompletos).                                                 |
| `invalid_invoice_status`                    | La acción no aplica al estado actual (finalizar una no-`draft`, cobrar una no-`open`, anular una `void`, etc.).      |
| `invalid_period_range`                      | `period_starts_at` es posterior a `period_ends_at`.                                                                  |
| `invalid_dates`                             | Alguna fecha enviada no es válida, o el nuevo período vigente es inconsistente.                                      |
| `customer_not_found`                        | El `customer_id` enviado no existe.                                                                                  |
| `customer_inactive`                         | El cliente está deshabilitado o la suscripción no tiene cliente al iniciarse.                                        |
| `customer_is_missing`                       | Intento de cobrar una nota de venta sin cliente asignado.                                                            |
| `email_is_missing`                          | Intento de enviar una nota de venta a un cliente sin email.                                                          |
| `merchant_inactive`                         | Tu comercio está deshabilitado.                                                                                      |
| `invalid_merchant`                          | El comercio de la solicitud no es válido.                                                                            |
| `invalid_payment_method`                    | El medio de pago no existe, no es del cliente, no está habilitado o no soporta cobro automático.                     |
| `invalid_payment`                           | La nota de venta no tiene un pago exitoso que reembolsar.                                                            |
| `already_refunded`                          | El pago de la nota de venta ya fue reembolsado.                                                                      |
| `paid_out_of_band`                          | Intento de reembolsar una nota de venta pagada fuera de Venti.                                                       |
| `invalid_coupon`                            | El código promocional no existe, expiró o no aplica a suscripciones.                                                 |
| `coupon_in_use`                             | El cupón ya está aplicado a esa suscripción.                                                                         |

Los errores siguen el formato estándar de la API:

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "subscription_must_be_active",
    "message": "La suscripción debe estar activa."
  }
}
```

## Límites actuales

* **Cobros automáticos solo con tarjeta.** Medios de autorización asíncrona (transferencia bancaria) sirven para pagar notas de venta por link, pero no para cobro recurrente.
* **Sin upgrades/downgrades prorrateados a mitad de ciclo**: los cambios de productos aplican desde el próximo ciclo. El prorrateo existe solo en el primer período.
* **`quantity` de productos**: se define por suscripción/plan; no hay cobro por uso (metered billing).
* **La nota de venta no es un documento tributario** (boleta/factura); emítelos con tu propio flujo.