# Subscriptions (/docs/guides/subscriptions)

This guide shows you how to sell a product as a subscription and run it after the sale. You create a plan, sell it in a cart, follow each renewal, change what the customer pays for, and cancel. It also covers what happens when a renewal payment fails.

## How subscriptions work [#how-subscriptions-work]

- A **subscription plan** says how often to bill (`billing_interval` and `billing_interval_unit`), an optional free trial and an optional number of billings.
- A **product** with a `subscription_plan_id` starts a subscription each time it is bought.
- Paying for that product makes the **subscription**. Each period, Comecero makes a renewal **invoice** and charges the customer's saved payment method. Each paid renewal makes an **order**.

## Create a plan [#create-a-plan]

Call [Create a subscription plan](/api/subscription-plans/create-subscription-plan), or go to **Store > Subscription Plans** in the dashboard.

```bash title="Request"
curl https://api.comecero.com/api/v1/subscription_plans \
  -H "Authorization: Bearer $COMECERO_TEST_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Monthly, 14-day trial",
    "billing_interval": 1,
    "billing_interval_unit": "month",
    "trial_interval": 14,
    "trial_interval_unit": "day"
  }'
```

Leave out `end_at_billing_count` to bill until the customer cancels. With a test token you can also use `hour` as the unit, so renewals come quickly while you test.

Then set the plan's `subscription_plan_id` on the product with [Update a product](/api/products/update-product). The product's price is the price per period.

## Sell a subscription in a cart [#sell-a-subscription-in-a-cart]

A subscription product goes in a cart like any other product. See [Accept payments](/docs/guides/accept-payments) for the whole checkout.

1. [Create a cart](/api/carts/create-cart) with the subscription product.
2. Show the shopper what they sign up for: [get the item's subscription terms](/api/carts/get-cart-item-subscription-terms) for the price per period, how often, and any trial or discount.
3. [Pay for the cart](/api/carts/create-cart-payment). The payment method is always saved on the customer when the cart holds a subscription, because renewals charge it later. For PayPal, send `use_billing_agreement: true`.

When the payment succeeds, the order is made and so is the subscription: [`subscription:created`](/api/webhooks/subscription-created) fires. During a trial its `status` is `trial`, then `active`.

You can also start a subscription without a cart for a customer who already has a saved payment method, with [Create a customer subscription](/api/customers/create-customer-subscription) and a secret token. A custom item on an invoice becomes a subscription when you give it a `subscription_plan_id` (see [Invoices](/docs/guides/invoices)).

## Renewals [#renewals]

At the end of each period, Comecero makes a renewal invoice and charges it. It uses the customer's store credit first, then their saved payment method. Your subscription settings (**Settings > Subscription Settings**, or [Update subscription settings](/api/settings/update-subscription-settings)) control the details:

- `subscription_renewal_notification_days`: how many days before a renewal the customer gets a reminder email (default 3, `0` for none).
- `subscription_invoice_payment_delay`: hours between making the renewal invoice and charging it, so you can change the invoice first (default 0).
- `receipt_on_renewal` and `digital_delivery_on_renewal`: send a receipt, and the downloads and license keys again, on each renewal.

On a renewal that succeeds, these events fire:

- [`invoice:created`](/api/webhooks/invoice-created) for the renewal invoice.
- [`invoice:paid`](/api/webhooks/invoice-paid) and [`order:created`](/api/webhooks/order-created) for the renewal order.
- [`subscription:renewal_success`](/api/webhooks/subscription-renewal-success). It does not fire for the first payment.
- [`subscription:converted`](/api/webhooks/subscription-converted) on the first paid renewal after a trial.
- [`subscription:completed`](/api/webhooks/subscription-completed) when the last billing set by `end_at_billing_count` is done.

To see the subscription's renewals, [list its invoices](/api/subscriptions/list-subscription-invoices) or [get its history](/api/subscriptions/get-subscription-history).

## Failed renewals and the grace period [#failed-renewals-and-the-grace-period]

When a renewal payment fails, [`subscription:renewal_failure`](/api/webhooks/subscription-renewal-failure) fires and the subscription enters its grace period: `in_grace_period` is `true` and the subscription stays active. The customer is emailed after the first failure. The renewal invoice's `payment_status` is `retry`.

Comecero then tries again on a schedule from your subscription settings:

- `payment_retry_delay`: days between tries (default 3).
- `max_payment_attempts`: the most automatic tries (default 4).
- `payment_retry_friday_bias`: move a try that falls a day either side of a Friday to the Friday.

When a try succeeds, the grace period ends. When the last try fails, the invoice is closed as `failed` and the subscription is cancelled.

To charge the customer now, for example after they update their card, call [Retry a subscription payment](/api/subscriptions/retry-subscription-payment). It pays the newest open invoice in `retry` status and does not change the automatic schedule. It is refused (`422`) when a manual retry was declined in the last 12 hours, or when another payment for the invoice ran in the last 10 minutes.

<Callout>
Do not build your own loop that retries failed renewals. Comecero already retries on the schedule above, and an extra charge attempt can bill the customer twice or get your account flagged by the card networks.
</Callout>

## Change what the customer pays for [#change-what-the-customer-pays-for]

You can add an item, swap one item for another (an upgrade or downgrade), or change an item's quantity or price.

- **Add or swap an item**: [Create a subscription item](/api/subscriptions/create-subscription-item). Send `remove_item_id` to replace an item. An item's `item_id` is its product id, which is stored in lowercase and ends in `.test` in test mode.
- **Change quantity, price or discount**: [Update a subscription item](/api/subscriptions/update-subscription-item).

A change applies now or at the end of the current period. Your `immediate_upgrade_product_types` and `immediate_downgrade_product_types` settings decide, unless you send `apply_immediately` when you add an item.

Money can move. A change that applies now is prorated: the customer pays for the rest of the current period at once (from store credit first, then the saved payment method), and an invoice is made. A cheaper item or lower quantity is refunded prorated. A scheduled change charges nothing now and shows in the subscription's `add_at_current_period_end` or the item's `change_at_current_period_end`.

### Preview first [#preview-first]

Always preview a change and show the customer the amount before you make it. [Preview a new item](/api/subscriptions/preview-subscription-item) takes the same body as adding one, and [Preview an item update](/api/subscriptions/preview-subscription-item-update) the same body as an update. Neither charges anything.

```bash title="Request"
curl "https://api.comecero.com/api/v1/subscriptions/0093799318129SuLByRPW8/items/preview?remove_item_id=basic.test" \
  -H "Authorization: Bearer $COMECERO_TEST_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "product_id": "pro.test", "quantity": 1 }'
```

```json title="Response"
{
  "object": "subscription_change_summary",
  "payment_total": 13.3,
  "refund_total": 0,
  "net_total": 13.3,
  "currency": "USD",
  "date_effective": "2026-11-12T10:00:00Z",
  "apply_at_period_end": false
}
```

To make the change with exactly the previewed amounts, send the same body with `apply_immediately: true` and the preview's `date_effective`. On a live subscription, only one change that moves money is allowed every 10 minutes.

To drop a scheduled change, call [Delete an item's scheduled change](/api/subscriptions/delete-subscription-item-scheduled-change) or [Delete scheduled additions](/api/subscriptions/delete-subscription-scheduled-additions).

## Cancel [#cancel]

[Cancel a subscription](/api/subscriptions/cancel-subscription) has two modes. Neither refunds anything: use [Refunds](/docs/guides/refunds) for that.

| Body | What happens | Event |
|---|---|---|
| none, or `cancel_at_current_period_end: true` | The subscription keeps billing until the end of the current period, then ends. | [`subscription:cancellation_scheduled`](/api/webhooks/subscription-cancellation-scheduled) now |
| `cancel_at_current_period_end: false` | Cancelled now. Every item is cancelled, open invoices are closed, no more renewals are billed, and the customer is emailed. | [`subscription:cancelled`](/api/webhooks/subscription-cancelled) |

```bash title="Request"
curl https://api.comecero.com/api/v1/subscriptions/0093799318129SuLByRPW8/cancel \
  -H "Authorization: Bearer $COMECERO_TEST_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "cancel_at_current_period_end": false, "cancellation_reason": "Too expensive" }'
```

A scheduled cancellation can be taken back before the period ends with [Uncancel a subscription](/api/subscriptions/uncancel-subscription). A subscription that is already cancelled cannot be uncancelled.

To cancel one item, use [Cancel a subscription item](/api/subscriptions/cancel-subscription-item), with the same two modes. Cancelling the last active item now cancels the whole subscription.

A shopper signed in with a limited token can cancel, upgrade or downgrade their own subscription only when your subscription settings allow it (`allow_customer_subscription_cancel`, `allow_customer_subscription_upgrade`, `allow_customer_subscription_downgrade`).

<Cards>
  <Card title="Webhooks" href="/docs/guides/webhooks" />
  <Card title="Invoices" href="/docs/guides/invoices" />
</Cards>
