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 estadoACTIVE 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 aceptantrueofalseliteral:"true",1, etc. devuelven400condetails[]. - Los campos no declarados se ignoran.
- Si la programación (
intervalUnit,intervalCount,startDate,totalCycles,endDate,billingDay) es inválida, la API responde400y no se crea nada: ni la suscripción, ni el producto, ni el contacto en línea.
Idempotencia
La creación de suscripciones no usa el headerIdempotency-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.
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íastotalCycles 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 objetoscheduling.
description,additionalDataypaymentMethodssolo vienen si tienen valor.scheduling.totalCyclesyscheduling.endDatesiempre vienen, connullsi no aplican.paymentUrles 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 elpaymentUrlde cada deuda enGET /subscriptions/{id}/debts.contact.contactIdsiempre trae el prefijocon_, también cuando el contacto se creó en línea concontactData.createdInlinedecontactyproductindica 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
amountse aplica también a las deudas ya generadas, conservando sus pagos parciales y suallowPartialPayments. Las deudas canceladas no se modifican. El resto de los campos solo cambia la suscripción. additionalDataes 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 (amountno numérico, booleanos no literales,paymentMethodsfuera del enum,autopay: truejunto conpaymentMethods) devuelven400condetails[]. companyCodeen el body se toma como contexto y no como campo a modificar.- Una suscripción
CANCELLEDoENDEDno 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
207con el envelope de error:error.codeesPARTIAL_UPDATEyerror.messageindica cuántas deudas no se sincronizaron (sindetails). 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
externalRequestIdde cada deuda es<externalSubscriptionId>-cycle-<n>(conndesde0), o<externalSubscriptionId>-resume-<n>-cycle-<m>para las generadas al reanudar. - No incluye deudas canceladas (igual que
GET /debts) ymeta.totalcuenta solo las listadas. - El
paymentUrlde 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.

