Suscripciones
Suscribe a tus clientes con un plan existente o definido en la misma llamada, y consulta, actualiza, cambia de plan, cancela, reanuda o abre la página para actualizar el método de pago.
Métodos
subscriptions.createSuscribir a un clientesubscriptions.retrieveObtener una suscripciónsubscriptions.retrieveCheckoutObtener el checkout de una suscripciónsubscriptions.updateActualizar una suscripciónsubscriptions.cancelCancelar una suscripciónsubscriptions.resumeReanudar una suscripciónsubscriptions.previewPlanChangeCalcular un cambio de plan sin aplicarlosubscriptions.changePlanCambiar el plan de una suscripciónsubscriptions.cancelPlanChangeDeshacer un cambio de plan programadosubscriptions.listInvoicesListar las facturas de una suscripciónsubscriptions.createPaymentMethodSessionAbrir la página para actualizar el método de pago
Subscription
Así se ve el objeto que devuelven los métodos de este módulo.
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador, empieza por sub_ |
status | SubscriptionStatus | incomplete, trialing, active, past_due, unpaid, canceled o completed |
customer | string | Id del cliente (cus_...) |
plan | string | Id del plan (plan_...) |
currency | "COP" | "USD" | Moneda de los cobros |
interval | PlanInterval | Frecuencia de cobro |
phases | PlanPhase[] | Fases de precio copiadas del plan al suscribirse |
termCycleCount | number | null | Cobros antes de terminar |
currentPeriodStart | string | null | Inicio del periodo actual |
currentPeriodEnd | string | null | Fin del periodo actual |
nextBillingAt | string | null | Fecha del próximo cobro |
trialEndsAt | string | null | Fin de la prueba gratis |
cancelAtPeriodEnd | boolean | true si se cancelará al final del periodo |
balance | number | Saldo en centavos: positivo es a favor del cliente y se descuenta de los próximos cobros; negativo se suma al próximo |
pendingPlanChange | PendingPlanChange | null | Cambio de plan programado (scheduled) o esperando su cobro (pending_payment): toPlan, behavior, effectiveAt, charge… |
cancelReason | string | null | Motivo de la cancelación |
canceledAt | string | null | Cuándo se pidió la cancelación |
endedAt | string | null | Cuándo terminó |
paymentMethod | PaymentMethodSummary | null | type, brand y last4 del método registrado |
externalId | string | null | Id del usuario en tu sistema |
metadata | Record<string, string> | Tus datos propios |
source | "manual" | "checkout" | "api" | Origen |
livemode | boolean | true si se creó con una llave live |
startedAt | string | Inicio de la suscripción |
createdAt | string | Fecha de creación |
updatedAt | string | Fecha de la última edición |
Suscribir a un cliente
landapay.subscriptions.create(params, options?)
Devuelve la URL del checkout donde el cliente registra su método de pago. Si plan es un objeto, primero se crea el plan; si customer es un objeto, se crea el cliente o se reutiliza el que ya tiene ese email o externalId. La suscripción se crea cuando el cliente completa el checkout y te llega con el webhook subscription.created.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
planobligatorio | string | InlinePlanParams | Id de un plan (plan_...) o el plan definido aquí mismo: interval, amount, trialDays, phases, termCycleCount, currency, name… |
customer | string | CustomerCreateParams | Id del cliente (cus_...) o sus datos. Sin cliente, se piden en el checkout |
externalId | string | null | Id del usuario o la licencia en tu sistema; lo hereda la suscripción |
metadata | Record<string, string | number | boolean | null> | Hasta 50 pares llave/valor. Al actualizar se combina con la actual; null en una llave la borra |
redirectUrl | string | null | Recibe subscription_id y checkout_id en la URL al volver |
expiresAt | string | Date | null | Vencimiento del checkout. 24 horas por defecto, máximo 7 días |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<{ checkoutUrl: string; checkout: SubscriptionCheckout; plan: Plan | null; customer: string | null; subscription: null }>
const { checkoutUrl } = await landapay.subscriptions.create({ plan: { name: "Licencia Pro", interval: "monthly", amount: 4_990_000, trialDays: 14, }, customer: { name: "María Gómez", email: "[email protected]" }, externalId: "user_42", redirectUrl: "https://tuapp.com/suscripcion",}); // Envía al usuario a checkoutUrlObtener una suscripción
landapay.subscriptions.retrieve(id, options?)
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id de la suscripción (sub_...) |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<Subscription>
const subscription = await landapay.subscriptions.retrieve("sub_SUBSCRIPTION2345"); if (subscription.status === "active" || subscription.status === "trialing") { // Dar acceso}Obtener el checkout de una suscripción
landapay.subscriptions.retrieveCheckout(id, options?)
Útil al volver del checkout: el campo subscription trae el id de la suscripción cuando el cliente lo completó.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id del checkout (scs_...) |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<SubscriptionCheckout>
const checkout = await landapay.subscriptions.retrieveCheckout("scs_SESSIONCODE23456"); console.log(checkout.status, checkout.subscription);Actualizar una suscripción
landapay.subscriptions.update(id, params, options?)
Cambia la referencia externa o la metadata. El precio y la frecuencia vienen del plan.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id de la suscripción (sub_...) |
externalId | string | null | Id del usuario en tu sistema |
metadata | Record<string, string | number | boolean | null> | Hasta 50 pares llave/valor. Al actualizar se combina con la actual; null en una llave la borra |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<Subscription>
await landapay.subscriptions.update("sub_SUBSCRIPTION2345", { metadata: { seats: 10 },});Cancelar una suscripción
landapay.subscriptions.cancel(id, params?, options?)
Por defecto sigue activa hasta el final del periodo pagado (subscription.cancel_scheduled). Con atPeriodEnd: false termina de inmediato (subscription.canceled). En ambos casos el cliente recibe un correo.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id de la suscripción (sub_...) |
atPeriodEnd | boolean | true por defecto |
reason | string | Motivo opcional |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<Subscription>
await landapay.subscriptions.cancel("sub_SUBSCRIPTION2345", { atPeriodEnd: false, reason: "Pedido del usuario",});Reanudar una suscripción
landapay.subscriptions.resume(id, options?)
Quita una cancelación programada para el final del periodo.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id de la suscripción (sub_...) |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<Subscription>
await landapay.subscriptions.resume("sub_SUBSCRIPTION2345");Calcular un cambio de plan sin aplicarlo
landapay.subscriptions.previewPlanChange(id, params, options?)
Devuelve lo que se cobraría hoy, lo que quedaría a favor del cliente y cuándo entraría en vigor, para mostrarlo antes de confirmar. Recibe lo mismo que changePlan; usa un id de plan para no crear planes que no se van a usar.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id de la suscripción (sub_...) |
planobligatorio | string | InlinePlanParams | Id del plan nuevo (plan_...) o el plan definido aquí mismo |
behavior | "prorate" | "reset" | "no_prorate" | "period_end" | Por defecto el configurado en el panel para subidas o bajadas |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<PlanChangePreview>
PlanChangePreview
| Campo | Tipo | Descripción |
|---|---|---|
fromPlan | string | Plan actual (plan_...) |
toPlan | string | Plan nuevo (plan_...) |
direction | "upgrade" | "downgrade" | Según el precio por día de cada plan; un empate es upgrade |
behavior | PlanChangeBehavior | El que se aplicará. En prueba gratis es no_prorate y con otra frecuencia prorate pasa a reset |
applyNow | boolean | false si se programa al final del periodo |
effectiveAt | string | Cuándo entra en vigor el plan nuevo |
unusedRatio | number | Fracción del periodo sin usar, de 0 a 1 |
credit | number | Lo no usado del plan actual, en centavos |
charge | number | Lo que se cobra hoy, en centavos |
balanceDelta | number | Cambio en el saldo: positivo queda a favor del cliente; negativo es un monto menor al mínimo que se suma al próximo cobro |
balanceAfter | number | Saldo de la suscripción después del cambio |
currency | "COP" | "USD" | Moneda de los montos |
nextBillingAt | string | null | Próximo cobro con el plan nuevo |
nextAmount | number | null | Monto de ese cobro, ya con el saldo |
const preview = await landapay.subscriptions.previewPlanChange("sub_SUBSCRIPTION2345", { plan: "plan_PRO2345ABCDEFGH",}); if (preview.charge > 0) { console.log(`Pagarás hoy ${preview.charge / 100} ${preview.currency}`);} else if (preview.balanceDelta > 0) { console.log(`Quedarán a tu favor ${preview.balanceDelta / 100} ${preview.currency}`);}Cambiar el plan de una suscripción
landapay.subscriptions.changePlan(id, params, options?)
Aplica el cambio de inmediato, lo programa para el final del periodo o cobra la diferencia al método de pago guardado; el cambio solo se aplica si ese cobro se aprueba. Si se rechaza lanza InvalidRequestError con código payment_declined. Si el cobro queda pendiente (Nequi o Bancolombia), pendingPlanChange.status es pending_payment hasta el webhook subscription.plan_changed o subscription.plan_change_failed. Si plan es un objeto, primero se crea el plan.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id de la suscripción (sub_...) |
planobligatorio | string | InlinePlanParams | Id del plan nuevo (plan_...) o el plan definido aquí mismo. Debe tener la misma moneda |
behavior | "prorate" | "reset" | "no_prorate" | "period_end" | prorate cobra la diferencia y conserva la fecha, reset reinicia el ciclo hoy, no_prorate cambia sin cobrar y period_end espera al final del periodo. Por defecto el del panel |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<Subscription>
const subscription = await landapay.subscriptions.changePlan("sub_SUBSCRIPTION2345", { plan: "plan_PRO2345ABCDEFGH", behavior: "prorate",}); console.log(subscription.plan, subscription.pendingPlanChange);Deshacer un cambio de plan programado
landapay.subscriptions.cancelPlanChange(id, options?)
Quita el cambio programado con period_end; la suscripción sigue en su plan. Si no hay uno programado responde 409 no_plan_change_scheduled.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id de la suscripción (sub_...) |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<Subscription>
await landapay.subscriptions.cancelPlanChange("sub_SUBSCRIPTION2345");Listar las facturas de una suscripción
landapay.subscriptions.listInvoices(id, params?, options?)
Una factura por ciclo y una por cada cobro de cambio de plan, la más reciente primero, igual que el tab Cobros del panel. Con await obtienes una página con data, page, totalPages, total, hasMore y los métodos nextPage() y previousPage() (devuelven null si no hay más). Con for await recorres todas las facturas y la librería pide las páginas siguientes por ti.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id de la suscripción (sub_...) |
page | number | Página a consultar, empieza en 1 (por defecto) |
limit | number | Facturas por página: 15 por defecto, máximo 50 |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
PagePromise<Invoice> (con await: Page<Invoice>)
Invoice
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador, empieza por inv_ |
kind | "cycle" | "plan_change" | Factura de un ciclo o del cobro de un cambio de plan |
number | string | Consecutivo del proyecto, ej. FAC-00012 |
url | string | Página pública de la factura |
status | InvoiceStatus | open, paid o void |
chargeStatus | InvoiceChargeStatus | Estado del cobro del ciclo: pending, trial, charging, paid, failed, canceled o void |
subscription | string | Id de la suscripción (sub_...) |
payment | string | null | Pago con el que se cobró (pay_...) |
planChange | string | null | Cambio de plan que la originó; null en las de ciclo |
cycle | number | null | Número del ciclo; null en un cambio de plan |
phase | "trial" | "priced" | Fase del plan en ese ciclo |
amount | number | Precio en centavos de currency, antes del saldo |
creditApplied | number | Saldo a favor descontado; negativo si se sumó una deuda |
amountDue | number | Lo cobrado: amount - creditApplied |
currency | "COP" | "USD" | Moneda del cobro |
attempts | number | Intentos de cobro del ciclo |
periodStart | string | Inicio del periodo facturado |
periodEnd | string | Fin del periodo facturado |
dueAt | string | Fecha programada del cobro |
nextRetryAt | string | null | Próximo reintento si el cobro falló |
paidAt | string | null | Fecha de pago |
livemode | boolean | true si es una factura real |
createdAt | string | Fecha de emisión |
// Una página (15 por defecto, máximo 50)const page = await landapay.subscriptions.listInvoices("sub_SUBSCRIPTION2345", { page: 1, limit: 15,}); console.log(page.total, page.totalPages);const next = await page.nextPage(); // null si no hay más // Todas, sin pensar en páginasfor await (const invoice of landapay.subscriptions.listInvoices("sub_SUBSCRIPTION2345")) { console.log(invoice.number, invoice.url);}Abrir la página para actualizar el método de pago
landapay.subscriptions.createPaymentMethodSession(id, params?, options?)
Devuelve un enlace de un solo uso, válido 15 minutos, para que el cliente vea, agregue o elimine métodos. Si la suscripción está en past_due o unpaid, guardar o elegir un método cobra el ciclo que falló. Si aprueba, el cliente vuelve a returnUrl (o al redirectUrl del checkout) con subscription_id y payment_id, y recibes payment.approved y subscription.activated. Si la suscripción está al día, solo se guarda el método.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
idobligatorio | string | Id de la suscripción (sub_...) |
returnUrl | string | URL https de regreso tras un cobro aprobado. Sin ella se usa el redirect del checkout |
options | RequestOptions | Opcional. idempotencyKey, timeout (ms) y maxRetries solo para esta llamada |
Devuelve
Promise<PaymentMethodSession>
PaymentMethodSession
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador, empieza por pms_. No es el secreto del enlace |
url | string | Enlace de un solo uso al que rediriges al cliente |
expiresAt | string | Cuándo caduca el enlace, antes de abrirlo |
subscription | string | Suscripción (sub_...) |
const session = await landapay.subscriptions.createPaymentMethodSession( "sub_SUBSCRIPTION2345", { returnUrl: "https://tuapp.com/facturacion" },); console.log(session.url, session.expiresAt);