Skip to main content
Una suscripción (Subscription) es un cobro recurrente que genera automáticamente una serie de deudas, una por ciclo. Tú defines qué cobrar (monto, frecuencia, deudor y duración) y TapiPay genera las cuotas y resuelve toda la complejidad interna por ti. Cuándo usarla: cobros que se repiten en el tiempo (mensualidades, cuotas de crédito, planes periódicos). Para un cargo único usa una deuda; para cobrar sin deudor conocido, una liga de pago.

Generación de cuotas por adelantado

Al crear la suscripción, TapiPay calcula las fechas de todos los ciclos y genera las deudas por adelantado (no hay un proceso que cree una cuota por mes). La generación de esas deudas ocurre de forma asíncrona: la suscripción se devuelve en estado ACTIVE apenas el cálculo y el encolado terminan correctamente.
Si la generación de las deudas falla, la suscripción se revierte automáticamente para que puedas reintentar con el mismo externalSubscriptionId sin duplicar cobros.

Crear una suscripción

Campos principales

string
requerido
Llave natural de la suscripción. Única por organización. Si la repites, la API responde 409 RESOURCE_CONFLICT. Ver Idempotencia.
string | object
requerido
El deudor. Uno de los dos es obligatorio y son excluyentes (no envíes ambos), igual que en una deuda. En v1 cada suscripción tiene exactamente un deudor.
number
requerido
Monto por ciclo en pesos, con hasta 2 decimales (mínimo 0.01).
string
requerido
Unidad del intervalo: day, week, month o year, en minúsculas exactas. Es case-sensitive: MONTH devuelve 400.
integer
requerido
Cantidad de unidades por ciclo, entero mayor o igual a 1. Por ejemplo, intervalUnit: "month" + intervalCount: 3 es trimestral.
string
requerido
Fecha de inicio en formato YYYY-MM-DD (fecha de calendario válida).
string
requerido
Nombre del producto que se cobra. Si el nombre ya existe en tu organización, se reutiliza; si no, el producto se crea en línea. Ver Creación en línea.
integer
Cantidad de ciclos a generar, de 1 a 520. Excluyente con endDate.
string
Fecha de fin (YYYY-MM-DD), posterior a startDate. Excluyente con totalCycles.
object
Override del día de cobro: { day, month? }. Solo es válido con intervalos month o year, y month (de 1 a 12) solo con year. Ver más abajo.
boolean
predeterminado:"false"
Si es true, el deudor debe pagar las cuotas en orden cronológico.
boolean
predeterminado:"true"
Si es false, las cuotas no se pueden pagar después de su vencimiento.
boolean
predeterminado:"true"
Habilita pagos parciales en las deudas generadas.
boolean
predeterminado:"false"
Solicita la domiciliación de las cuotas. autopay: true y paymentMethods son excluyentes: enviar ambos devuelve 400.
string[]
Medios de pago habilitados para las cuotas. Excluyente con autopay: true. Ver Medios de pago.
string
Descripción de la suscripción. Debe ser string (si no, 400).
object
Datos propios de tu sistema. Debe ser un objeto plano (un escalar devuelve 400) y no puede usar claves reservadas (description, paymentMethods, productName, externalProductId, debtExpirationDate, overduePayment, allowPartialPayments, recurringDebt, debtReference); si no, 400. Se guarda en las deudas generadas.

Reglas de validación

  • Los booleanos (autopay, allowOverduePayment, allowPartialPayments, enforcePaymentOrder) solo aceptan true o false literal: "true", 1, etc. devuelven 400 con details[].
  • Los campos no declarados se ignoran.
  • Si la programación (intervalUnit, intervalCount, startDate, totalCycles, endDate, billingDay) es inválida, la API responde 400 y no se crea nada: ni la suscripción, ni el producto, ni el contacto en línea.
Ver Convenciones de la API para las reglas comunes a todos los endpoints.

Idempotencia

La creación de suscripciones no usa el header Idempotency-Key. La llave de idempotencia es externalSubscriptionId: repetirla devuelve 409 RESOURCE_CONFLICT y no se crea una suscripción nueva. Las deudas generadas usan externalRequestId = <externalSubscriptionId>-cycle-<n>, con n desde 0 (la deuda del primer ciclo es -cycle-0).

Frecuencias con intervalUnit + intervalCount

Día de cobro (billingDay)

Por defecto, el día de cobro se infiere del startDate (modelo aniversario): si la suscripción inicia el día 15, todos los cobros caen el 15. El override billingDay desacopla el día de cobro del startDate. En la respuesta, scheduling.billingDay siempre muestra el día de cobro efectivo: si no lo enviaste, se infiere del startDate como { day } para month y { day, month } para year. Para day y week es null.
billingDay solo es válido para intervalos month o year. El subcampo month solo aplica a intervalos year.
Fin de mes: si el día configurado supera el último día del mes (por ejemplo, 31 en febrero), el cobro se realiza el último día del mes; el mes siguiente vuelve al día original.

Duración indefinida

Si no envías totalCycles ni endDate, la suscripción queda ACTIVE y se genera solo la deuda del primer ciclo (para no generar cobros sin límite). Define totalCycles o endDate cuando quieras generar todas las cuotas por adelantado.

La respuesta

Los datos de programación viajan anidados en el objeto scheduling.
  • description, additionalData y paymentMethods solo vienen si tienen valor.
  • scheduling.totalCycles y scheduling.endDate siempre vienen, con null si no aplican.
  • paymentUrl es la URL del portal compartida por todas las cuotas. Es una URL opaca: no la parsees ni la construyas a mano. Para abrir una cuota específica usa el paymentUrl de cada deuda en GET /subscriptions/{id}/debts.
  • contact.contactId siempre trae el prefijo con_, también cuando el contacto se creó en línea con contactData.
  • createdInline de contact y product indica si se crearon en línea al crear la suscripción, y se conserva en las lecturas posteriores.

Ciclo de vida

Cada deuda generada por la suscripción tiene su propio ciclo de vida (PENDING, PAID, etc.). Pausar o cancelar la suscripción cancela sus deudas pendientes. Ver Pausar, reanudar y cancelar y Deudas.

Pago en orden (enforcePaymentOrder)

Con enforcePaymentOrder: true, el deudor no puede pagar una cuota si hay cuotas anteriores impagas. Intentarlo devuelve 422 BUSINESS_RULE_VIOLATION. Debe saldarlas en orden cronológico.

Listar suscripciones

GET /subscriptions devuelve tus suscripciones ordenadas por externalSubscriptionId descendente, con la paginación estándar (page, limit). Filtros: Sin resultados, la respuesta es 200 con data: []. meta.total y meta.hasMore cuentan solo lo filtrado.
Con el filtro status, meta.total puede ser aproximado: el filtro se vuelve a aplicar después de calcular el estado real (por ejemplo, una suscripción ACTIVE vencida sale como ENDED).

Actualizar una suscripción

PATCH /subscriptions/{id} modifica amount, description, enforcePaymentOrder, allowOverduePayment, autopay, paymentMethods y additionalData.
  • Solo amount se aplica también a las deudas ya generadas, conservando sus pagos parciales y su allowPartialPayments. Las deudas canceladas no se modifican. El resto de los campos solo cambia la suscripción.
  • additionalData es un objeto plano con las mismas reglas que en la creación.
  • Un body vacío o un campo no modificable devuelve 400. Los tipos y valores inválidos (amount no numérico, booleanos no literales, paymentMethods fuera del enum, autopay: true junto con paymentMethods) devuelven 400 con details[].
  • companyCode en el body se toma como contexto y no como campo a modificar.
  • Una suscripción CANCELLED o ENDED no se puede modificar: 422 BUSINESS_RULE_VIOLATION.
  • Si la suscripción se actualiza pero falla la actualización de alguna de sus deudas ya generadas, la API responde 207 con el envelope de error: error.code es PARTIAL_UPDATE y error.message indica cuántas deudas no se sincronizaron (sin details). La suscripción sí quedó actualizada.

Pausar, reanudar y cancelar

Las deudas canceladas al pausar o cancelar dejan de listarse en GET /subscriptions/{id}/debts y en GET /debts, pero se siguen leyendo con GET /debts/{id}.

Deudas de la suscripción

GET /subscriptions/{id}/debts devuelve las deudas generadas, con la paginación estándar.
  • El externalRequestId de cada deuda es <externalSubscriptionId>-cycle-<n> (con n desde 0), o <externalSubscriptionId>-resume-<n>-cycle-<m> para las generadas al reanudar.
  • No incluye deudas canceladas (igual que GET /debts) y meta.total cuenta solo las listadas.
  • El paymentUrl de cada deuda es una URL opaca que abre directamente esa cuota.

Endpoints

Pruébalo en el API Reference

Explora cada endpoint con su playground interactivo.