> ## Documentation Index
> Fetch the complete documentation index at: https://commet.co/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.

```bash theme={null}
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:

| 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 |
| `paused` | Acceso y renovaciones pausados hasta reanudar |
| `canceled` | Finalizaron la facturación y el acceso |

## Crear

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Commet } from "@commet/node";

  const commet = new Commet({ apiKey: "ck_xxx" });

  const createdSubscription = await commet.subscriptions.create({
    customerId: "user_123",
    planId: "pln_xxx",
  });
  ```

  ```python Python theme={null}
  from commet import Commet

  commet = Commet("ck_xxx")

  created_subscription = commet.subscriptions.create(
      customer_id="user_123",
      plan_id="pln_xxx",
  )
  ```

  ```go Go theme={null}
  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)
  }
  ```

  ```java Java theme={null}
  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()
  );
  ```

  ```php PHP theme={null}
  use Commet\Commet;

  $commet = new Commet('ck_xxx');

  $createdSubscription = $commet->subscriptions->create(
      customerId: 'user_123',
      planId: 'pln_xxx',
  );
  ```
</CodeGroup>

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.

Si omitís un `promoCode` u `offerId` que tiene el checkout pendiente, incluida una Offer asignada con `PUT /subscriptions/{id}/offer`, se reemplaza por una suscripción y un checkout nuevos sin ese beneficio. Redirigí al `checkoutUrl` devuelto; el link anterior deja de funcionar. Para conservar la Offer, enviala de nuevo o asignala al ID de la suscripción devuelta.

## Consultar estado actual o histórico

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Commet } from "@commet/node";

  const commet = new Commet({ apiKey: "ck_xxx" });

  const subscription = await commet.subscriptions.getActive({ customerId: "user_123" });
  ```

  ```python Python theme={null}
  from commet import Commet

  commet = Commet("ck_xxx")

  subscription = commet.subscriptions.get_active(customer_id="user_123")
  ```

  ```go Go theme={null}
  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)
  }
  ```

  ```java Java theme={null}
  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()
  );
  ```

  ```php PHP theme={null}
  use Commet\Commet;

  $commet = new Commet('ck_xxx');

  $subscription = $commet->subscriptions->getActive(customerId: 'user_123');
  ```
</CodeGroup>

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Commet } from "@commet/node";

  const commet = new Commet({ apiKey: "ck_xxx" });

  const subscription = await commet.subscriptions.get({ id: "sub_xxx" });
  ```

  ```python Python theme={null}
  from commet import Commet

  commet = Commet("ck_xxx")

  subscription = commet.subscriptions.get("sub_xxx")
  ```

  ```go Go theme={null}
  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)
  }
  ```

  ```java Java theme={null}
  import co.commet.Commet;

  var commet = Commet.builder().apiKey("ck_xxx").build();

  var subscription = commet.subscriptions().get("sub_xxx");
  ```

  ```php PHP theme={null}
  use Commet\Commet;

  $commet = new Commet('ck_xxx');

  $subscription = $commet->subscriptions->get(id: 'sub_xxx');
  ```
</CodeGroup>

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

| Modo | Acceso y facturación | Qué pasa al reanudar |
| - | - | - |
| `immediate` | El 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_end` | El 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](/docs/es/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:

```bash theme={null}
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:

```bash theme={null}
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:

```bash theme={null}
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.

```bash theme={null}
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`.

| Respuesta | Significado |
| - | - |
| `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_failed` | El pago fue rechazado. La suscripción sigue pausada. |
| `422`, `no_payment_method` | Para reanudar una pausa de fin de período hace falta un medio de pago guardado. |
| `500`, `internal_error` | Una 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](/docs/es/api-reference/subscriptions/pause-subscription) y [Resume](/docs/es/api-reference/subscriptions/resume-subscription) para ver los esquemas completos.

### Sincronizar el acceso

Usá [Feature Access](/docs/es/api-reference/features/get-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`](/docs/es/webhooks/subscription-pause-scheduled): se programó una pausa futura; el acceso todavía continúa.
* [`subscription.pause_updated`](/docs/es/webhooks/subscription-pause-updated): cambió la duración de la pausa.
* [`subscription.pause_revoked`](/docs/es/webhooks/subscription-pause-revoked): se quitó la pausa programada.
* [`subscription.paused`](/docs/es/webhooks/subscription-paused): la pausa se hizo efectiva y se cortó el acceso de la suscripción.
* [`subscription.resumed`](/docs/es/webhooks/subscription-resumed): terminó la reanudación y volvió el acceso.
* [`subscription.resume_failed`](/docs/es/webhooks/subscription-resume-failed): falló el pago de reanudación y la suscripción sigue pausada.

## Cancelar

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Commet } from "@commet/node";

  const commet = new Commet({ apiKey: "ck_xxx" });

  const subscription = await commet.subscriptions.cancel({ id: "sub_xxx" });
  ```

  ```python Python theme={null}
  from commet import Commet

  commet = Commet("ck_xxx")

  subscription = commet.subscriptions.cancel("sub_xxx")
  ```

  ```go Go theme={null}
  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)
  }
  ```

  ```java Java theme={null}
  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()
  );
  ```

  ```php PHP theme={null}
  use Commet\Commet;

  $commet = new Commet('ck_xxx');

  $subscription = $commet->subscriptions->cancel(id: 'sub_xxx');
  ```
</CodeGroup>

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Commet } from "@commet/node";

  const commet = new Commet({ apiKey: "ck_xxx" });

  const subscription = await commet.subscriptions.uncancel({ id: "sub_xxx" });
  ```

  ```python Python theme={null}
  from commet import Commet

  commet = Commet("ck_xxx")

  subscription = commet.subscriptions.uncancel("sub_xxx")
  ```

  ```go Go theme={null}
  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)
  }
  ```

  ```java Java theme={null}
  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()
  );
  ```

  ```php PHP theme={null}
  use Commet\Commet;

  $commet = new Commet('ck_xxx');

  $subscription = $commet->subscriptions->uncancel(id: 'sub_xxx');
  ```
</CodeGroup>

`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:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Commet } from "@commet/node";

  const commet = new Commet({ apiKey: "ck_xxx" });

  const reactivatedSubscription = await commet.subscriptions.reactivate({ id: "sub_xxx" });
  ```

  ```python Python theme={null}
  from commet import Commet

  commet = Commet("ck_xxx")

  reactivated_subscription = commet.subscriptions.reactivate("sub_xxx")
  ```

  ```go Go theme={null}
  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)
  }
  ```

  ```java Java theme={null}
  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()
  );
  ```

  ```php PHP theme={null}
  use Commet\Commet;

  $commet = new Commet('ck_xxx');

  $reactivatedSubscription = $commet->subscriptions->reactivate(id: 'sub_xxx');
  ```
</CodeGroup>

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Commet } from "@commet/node";

  const commet = new Commet({ apiKey: "ck_xxx" });

  const recoveryLink = await commet.subscriptions.createRecoveryLink({ id: "sub_xxx" });
  ```

  ```python Python theme={null}
  from commet import Commet

  commet = Commet("ck_xxx")

  recovery_link = commet.subscriptions.create_recovery_link("sub_xxx")
  ```

  ```go Go theme={null}
  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)
  }
  ```

  ```java Java theme={null}
  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()
  );
  ```

  ```php PHP theme={null}
  use Commet\Commet;

  $commet = new Commet('ck_xxx');

  $recoveryLink = $commet->subscriptions->createRecoveryLink(id: 'sub_xxx');
  ```
</CodeGroup>

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](/docs/es/plan-grants)
* [Cambiar de plan](/docs/es/upgrade-and-downgrade-plans)
* [Manejar pagos fallidos](/docs/es/handle-failed-payments)
* [Precios regionales y por Market](/docs/es/regional-prices)
* [Introductory Offers](/docs/es/introductory-offers)
* [Customer Portal](/docs/es/customer-portal)


## Related topics

- [Administrar clientes](/docs/es/manage-customers.md)
- [Administrar planes](/docs/es/create-plans.md)
- [Otorgar Acceso Temporal a un Plan](/docs/es/plan-grants.md)
- [Manejar pagos fallidos](/docs/es/handle-failed-payments.md)
- [Promo Codes](/docs/es/promo-codes.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.