CommetCommet
GitHubDiscordStatus
Introducción

Inicio rápido

Creá una API keyQuickstart

Aprender

Administrar suscripcionesOtorgar Acceso Temporal a un PlanUpgrade y Downgrade de Planes

Recursos

Referencia del SDKVersionado de APIManejo de erroresTestingCLIEjemplos

Plugins

Better Auth
DocumentaciónRecursosConstruir con AIAPI ReferenceWebhooks

Administrar suscripciones

Creá, consultá, pausá, reanudá, cancelá y reactivá suscripciones.

Instalá la Skill de Commet para que tu agente implemente el ciclo de vida actual de suscripciones y verifique el resultado.

npx skills add commet-labs/skills --skill commet

Las suscripciones conectan un customer con un plan y controlan checkout, invoices, acceso a features, uso y renovaciones.

Ciclo de vida

Los estados persistidos son:

EstadoSignificado
draftCreada pero todavía no lista para facturar
pending_paymentEsperando checkout
trialingEl acceso de prueba está activo
activeFacturación normal
past_dueFalló la renovación y dunning está activo
pausedAcceso y renovaciones pausados hasta reanudar
canceledFinalizaron la facturación y el acceso

Crear

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const createdSubscription = await commet.subscriptions.create({  customerId: "user_123",  planId: "pln_xxx",});
from commet import Commetcommet = Commet("ck_xxx")created_subscription = commet.subscriptions.create(    customer_id="user_123",    plan_id="pln_xxx",)
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()createdSubscription, err := client.Subscriptions.Create(ctx, &commet.CreateSubscriptionParams{	CustomerID: "user_123",	PlanID: func(value string) *string { return &value }("pln_xxx"),})if err != nil {	log.Fatal(err)}
import co.commet.Commet;import co.commet.params.CreateSubscriptionParams;var commet = Commet.builder().apiKey("ck_xxx").build();var createdSubscription = commet.subscriptions().create(    CreateSubscriptionParams.builder("user_123").planId("pln_xxx").build());
use Commet\Commet;$commet = new Commet('ck_xxx');$createdSubscription = $commet->subscriptions->create(    customerId: 'user_123',    planId: 'pln_xxx',);

Para un plan pago, redirigí al customer a checkoutUrl. Los planes gratuitos pueden activarse sin checkout y devolver checkoutUrl: null.

El flujo normal solo necesita customerId y planCode o planId. Los campos opcionales de selección son:

CampoCuándo enviarlo
billingIntervalEl customer eligió un intervalo que no es el default
priceIdEl customer eligió una variante concreta de precio
offerIdTu aplicación seleccionó una Offer directamente; reemplaza la selección introductoria automática
promoCodeEl customer ingresó un Promo Code
initialSeatsConocés las cantidades iniciales de seats
skipTrial o customTrialDaysQuerés reemplazar intencionalmente la prueba configurada

Omitir priceId conserva la resolución por defecto de precio y Market. Omitir offerId conserva la selección automática de la Introductory Offer.

Un checkout pending_payment compatible puede reutilizarse. Una selección pendiente incompatible puede reemplazarse sin duplicar una suscripción pagada.

Consultar estado actual o histórico

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const subscription = await commet.subscriptions.getActive({ customerId: "user_123" });
from commet import Commetcommet = Commet("ck_xxx")subscription = commet.subscriptions.get_active(customer_id="user_123")
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()subscription, err := client.Subscriptions.GetActive(ctx, &commet.GetActiveSubscriptionParams{	CustomerID: "user_123",})if err != nil {	log.Fatal(err)}
import co.commet.Commet;import co.commet.params.GetActiveSubscriptionParams;var commet = Commet.builder().apiKey("ck_xxx").build();var subscription = commet.subscriptions().getActive(    GetActiveSubscriptionParams.builder("user_123").build());
use Commet\Commet;$commet = new Commet('ck_xxx');$subscription = $commet->subscriptions->getActive(customerId: 'user_123');

getActive devuelve la relación de suscripción actual del customer o null.

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const subscription = await commet.subscriptions.get({ id: "sub_xxx" });
from commet import Commetcommet = Commet("ck_xxx")subscription = commet.subscriptions.get("sub_xxx")
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()subscription, err := client.Subscriptions.Get(ctx, "sub_xxx")if err != nil {	log.Fatal(err)}
import co.commet.Commet;var commet = Commet.builder().apiKey("ck_xxx").build();var subscription = commet.subscriptions().get("sub_xxx");
use Commet\Commet;$commet = new Commet('ck_xxx');$subscription = $commet->subscriptions->get(id: 'sub_xxx');

Usá get con el ID público para obtener cualquier estado persistido, incluidos pending_payment, past_due y canceled.

Pausar y reanudar

Una pausa detiene temporalmente el acceso y las renovaciones sin cancelar la suscripción. Podés pausar una suscripción de un plan pago recurrente en estado active o trialing. No aplica a planes gratuitos, pagos únicos ni suscripciones pendientes de pago, past-due o canceladas. Antes de crear una pausa, resolvé cualquier cancelación programada, cambio de plan programado o checkout pendiente de cambio de plan.

Elegir cuándo pausar

ModoAcceso y facturaciónQué pasa al reanudar
immediateEl acceso se corta en el momento. Se conserva el tiempo restante del período pago o de prueba.Recupera el tiempo restante sin un cobro nuevo. La renovación pasa al final de ese tiempo.
period_endEl acceso continúa hasta el final del período de facturación o de prueba. Se evita la renovación siguiente.Cobra un período nuevo con el medio de pago guardado. El acceso vuelve cuando se completa el pago.

Por ejemplo, si pausás inmediatamente cuando quedan 10 días pagos, esos 10 días se conservan. Si reanudás una semana después, todavía quedan 10 días antes de renovar.

Mientras está pausada, la suscripción no genera facturas de renovación. Una pausa al final del período puede generar una factura final por consumo, excedentes o ajustes pendientes de seats/quota del período terminado. No cobra capacidad por adelantado para el período siguiente.

Definir la duración

Usá un entero positivo en durationDays para programar un intento de reanudación automática, o null para una pausa indefinida que requiere reanudación manual. La duración cuenta desde que la pausa se hace efectiva, no desde que se programa una pausa futura.

En Dashboard, abrí el detalle de la suscripción y elegí Pause. Seleccioná el modo y la duración y confirmá. El cliente puede editar una pausa existente, cancelar una pausa programada y reanudar una suscripción pausada desde el Customer Portal, pero no crear pausas; Commet Admin los muestra en el detalle de la suscripción. Para modificar pausas desde Dashboard necesitás permiso para editar suscripciones.

La pausa muestra su fecha de inicio y de reanudación. Sus acciones permiten editar la duración, revocar una pausa programada o reanudar una pausa efectiva.

En el Dashboard y el Customer Portal, elegí una duración sugerida o ingresá un número de días, semanas o meses calendario. El diálogo muestra cuándo empieza la pausa y cuándo se intentará reanudar. Dejá la duración vacía para una pausa indefinida. Al editar se reconstruye una duración equivalente desde las fechas guardadas, contando desde el inicio original de la pausa. Las suscripciones semanales priorizan semanas completas; las demás, meses calendario completos y luego semanas o días. Si el mes de destino es más corto, se usa su último día.

Crear una pausa

Este pedido programa una pausa de siete días al final del período:

curl -X POST https://commet.co/api/v1/subscriptions/sub_xxx/pause \
  -H "x-api-key: $COMMET_API_KEY" \
  -H "commet-version: 2026-08-27" \
  -H "Content-Type: application/json" \
  -d '{"mode":"period_end","durationDays":7}'

Usá "mode":"immediate" para pausar ahora, o "durationDays":null para dejar abierta la fecha de reanudación.

La creación devuelve la suscripción actualizada. Una pausa futura tiene pause.status: "scheduled" y la suscripción sigue active o trialing. Cuando se hace efectiva, la suscripción pasa a paused y pause.status vale "active". El objeto pause incluye mode, effectiveAt y resumeAt; vale null cuando no hay una pausa actual ni programada.

Editar o revocar una pausa

Cambiá la duración de una pausa programada o efectiva:

curl -X PATCH https://commet.co/api/v1/subscriptions/sub_xxx/pause \
  -H "x-api-key: $COMMET_API_KEY" \
  -H "commet-version: 2026-08-27" \
  -H "Content-Type: application/json" \
  -d '{"durationDays":14}'

Esto fija una duración total de 14 días desde la fecha de inicio original; no suma 14 días desde hoy. Enviá null para hacerla indefinida. Esta operación no cambia el modo de pausa.

Revocá una pausa antes de que se haga efectiva:

curl -X DELETE https://commet.co/api/v1/subscriptions/sub_xxx/pause \
  -H "x-api-key: $COMMET_API_KEY" \
  -H "commet-version: 2026-08-27"

La suscripción conserva su período y acceso actuales. Si la pausa ya está efectiva, usá la reanudación.

Reanudar y manejar el resultado del pago

Usá resume para una suscripción pausada; reactivate es otra operación para suscripciones canceladas o past-due.

curl -X POST https://commet.co/api/v1/subscriptions/sub_xxx/resume \
  -H "x-api-key: $COMMET_API_KEY" \
  -H "commet-version: 2026-08-27"

La respuesta incluye subscriptionId, invoiceId y status. Al reanudar una pausa inmediata no hay una factura nueva, por lo que invoiceId vale null.

RespuestaSignificado
200, status: "succeeded"La reanudación terminó y el acceso se restauró.
200, status: "processing"El pago o su confirmación todavía están pendientes. No restaures acceso sólo por recibir esta respuesta.
402, charge_failedEl pago fue rechazado. La suscripción sigue pausada.
422, no_payment_methodPara reanudar una pausa de fin de período hace falta un medio de pago guardado.
500, internal_errorUna falla interna impidió completar la operación; es distinta de un rechazo del pago.

Un pago de reanudación rechazado deja la factura pendiente. Los reintentos automáticos ocurren en los días 1, 3, 5 y 7 desde el rechazo original y reutilizan esa factura. Durante los reintentos, la suscripción sigue pausada. Si todos fallan, se cancela y la factura de reanudación pasa a incobrable. Los intentos manuales de reanudación no consumen intentos automáticos.

La reanudación de una pausa de fin de período usa el precio base vigente al crear la factura nueva. Si esa factura queda pendiente, sus reintentos conservan el monto y los créditos o balance incluidos aunque el catálogo vuelva a cambiar. Las Introductory Offers y los descuentos aceptados conservan los términos que todavía no se consumieron; reanudar no otorga una Introductory Offer nueva ni vuelve a canjear un promo code.

Consultá las referencias de Pause y Resume para ver los esquemas completos.

Sincronizar el acceso

Usá Feature Access para autorizar pedidos según el estado actual de la suscripción. Suscribite a estos webhooks para procesar actualizaciones asincrónicas en tu aplicación:

  • subscription.pause_scheduled: se programó una pausa futura; el acceso todavía continúa.
  • subscription.pause_updated: cambió la duración de la pausa.
  • subscription.pause_revoked: se quitó la pausa programada.
  • subscription.paused: la pausa se hizo efectiva y se cortó el acceso de la suscripción.
  • subscription.resumed: terminó la reanudación y volvió el acceso.
  • subscription.resume_failed: falló el pago de reanudación y la suscripción sigue pausada.

Cancelar

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const subscription = await commet.subscriptions.cancel({ id: "sub_xxx" });
from commet import Commetcommet = Commet("ck_xxx")subscription = commet.subscriptions.cancel("sub_xxx")
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()subscription, err := client.Subscriptions.Cancel(ctx, "sub_xxx", nil)if err != nil {	log.Fatal(err)}
import co.commet.Commet;import co.commet.params.CancelSubscriptionParams;var commet = Commet.builder().apiKey("ck_xxx").build();var subscription = commet.subscriptions().cancel(    "sub_xxx",    CancelSubscriptionParams.builder().build());
use Commet\Commet;$commet = new Commet('ck_xxx');$subscription = $commet->subscriptions->cancel(id: 'sub_xxx');

Una suscripción paga y activa programa la cancelación al final del período salvo que envíes immediate: true. Las relaciones gratuitas, pendientes y past-due se cancelan inmediatamente. La cancelación no borra el balance almacenado.

Cancelar una suscripción pausada es inmediato y descarta el tiempo conservado. El consumo, los excedentes o los ajustes de seats pendientes todavía pueden generar una factura final. Para cancelar cuando hay una pausa futura programada, revocá esa pausa primero.

Revertir una cancelación programada

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const subscription = await commet.subscriptions.uncancel({ id: "sub_xxx" });
from commet import Commetcommet = Commet("ck_xxx")subscription = commet.subscriptions.uncancel("sub_xxx")
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()subscription, err := client.Subscriptions.Uncancel(ctx, "sub_xxx", nil)if err != nil {	log.Fatal(err)}
import co.commet.Commet;import co.commet.params.UncancelSubscriptionParams;var commet = Commet.builder().apiKey("ck_xxx").build();var subscription = commet.subscriptions().uncancel(    "sub_xxx",    UncancelSubscriptionParams.builder().build());
use Commet\Commet;$commet = new Commet('ck_xxx');$subscription = $commet->subscriptions->uncancel(id: 'sub_xxx');

uncancel funciona solamente antes de que una cancelación al final del período se haga efectiva. Conserva la misma suscripción y período actual.

Recuperar una suscripción past-due

Reactivate reintenta el cobro de renovación pendiente y conserva la relación original:

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const reactivatedSubscription = await commet.subscriptions.reactivate({ id: "sub_xxx" });
from commet import Commetcommet = Commet("ck_xxx")reactivated_subscription = commet.subscriptions.reactivate("sub_xxx")
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()reactivatedSubscription, err := client.Subscriptions.Reactivate(ctx, "sub_xxx", nil)if err != nil {	log.Fatal(err)}
import co.commet.Commet;import co.commet.params.ReactivateSubscriptionParams;var commet = Commet.builder().apiKey("ck_xxx").build();var reactivatedSubscription = commet.subscriptions().reactivate(    "sub_xxx",    ReactivateSubscriptionParams.builder().build());
use Commet\Commet;$commet = new Commet('ck_xxx');$reactivatedSubscription = $commet->subscriptions->reactivate(id: 'sub_xxx');

Si el customer debe actualizar su medio de pago, creá un link de recuperación:

import { Commet } from "@commet/node";const commet = new Commet({ apiKey: "ck_xxx" });const recoveryLink = await commet.subscriptions.createRecoveryLink({ id: "sub_xxx" });
from commet import Commetcommet = Commet("ck_xxx")recovery_link = commet.subscriptions.create_recovery_link("sub_xxx")
client, err := commet.New("ck_xxx")if err != nil {	log.Fatal(err)}ctx := context.Background()recoveryLink, err := client.Subscriptions.CreateRecoveryLink(ctx, "sub_xxx", nil)if err != nil {	log.Fatal(err)}
import co.commet.Commet;import co.commet.params.CreateSubscriptionRecoveryLinkParams;var commet = Commet.builder().apiKey("ck_xxx").build();var recoveryLink = commet.subscriptions().createRecoveryLink(    "sub_xxx",    CreateSubscriptionRecoveryLinkParams.builder().build());
use Commet\Commet;$commet = new Commet('ck_xxx');$recoveryLink = $commet->subscriptions->createRecoveryLink(id: 'sub_xxx');

Los reintentos automáticos de dunning se anclan al rechazo original en los días 1, 3, 5 y 7. Un cobro exitoso devuelve la suscripción a active.

Reactivar una suscripción cancelada

La misma operación reactivate cobra el medio de pago guardado, reutiliza el registro de suscripción y comienza un período nuevo anclado a la fecha de reactivación. Podés enviar un offerId; las fases aceptadas se persisten como una Offer Application inmutable.

El precio seleccionado no se guarda como snapshot. Las renovaciones futuras usan su valor actual de catálogo. Archivar ese precio impide nuevas selecciones, pero no rompe la suscripción existente.

Relacionado

  • Otorgar acceso temporal a un plan
  • Cambiar de plan
  • Manejar pagos fallidos
  • Precios regionales y por Market
  • Introductory Offers
  • Customer Portal

¿Cómo está esta guía?

Períodos de prueba

Usa fases de prueba gratuita en Offers para onboarding automático o campañas explícitas.

Otorgar Acceso Temporal a un Plan

Amplía temporalmente las features y los límites de una suscripción sin cambiar su plan, precio, invoice ni ciclo de facturación.

On this page

Ciclo de vida
Crear
Consultar estado actual o histórico
Pausar y reanudar
Elegir cuándo pausar
Definir la duración
Crear una pausa
Editar o revocar una pausa
Reanudar y manejar el resultado del pago
Sincronizar el acceso
Cancelar
Revertir una cancelación programada
Recuperar una suscripción past-due
Reactivar una suscripción cancelada
Relacionado