Creá, consultá, cancelá, revertí y reactivá suscripciones con el SDK v9.
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 commetLas suscripciones conectan un customer con un plan y controlan checkout, invoices, acceso a features, uso y renovaciones.
Los estados persistidos son:
| Estado | Significado |
|---|---|
draft | Creada pero todavía no lista para facturar |
pending_payment | Esperando checkout |
trialing | El acceso de prueba está activo |
active | Facturación normal |
past_due | Falló la renovación y dunning está activo |
canceled | Finalizaron la facturación y el acceso |
Commet no expone estados de suscripción paused ni expired.
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:
| Campo | Cuándo enviarlo |
|---|---|
billingInterval | El customer eligió un intervalo que no es el default |
priceId | El customer eligió una variante concreta de precio |
offerId | Tu aplicación seleccionó una Offer directamente; reemplaza la selección introductoria automática |
promoCode | El customer ingresó un Promo Code |
initialSeats | Conocés las cantidades iniciales de seats |
skipTrial o customTrialDays | Queré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.
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.
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.
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.
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.
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.
¿Cómo está esta guía?