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

# Subscriptions

> The Subscriptions module allows you to offer products and services on a recurring basis, enabling business models like "Subscribe & Save," SaaS, content access, and custom refill schedules. Commerce Engine provides APIs to define subscription plans on products, let users initiate subscriptions, and manage the lifecycle of those subscriptions.

<Warning>
  **Key Distinction**

  Subscriptions are initiated and managed separately from the standard one-time purchase checkout flow (`POST /orders`). Creating a subscription typically involves the `POST /subscriptions` endpoint and a subsequent mandate/payment step, **bypassing the standard cart-to-order conversion for the subscription itself.**
</Warning>

<Info>
  **Prerequisites**

  * **Payment Gateway:** Juspay integration is required for managing recurring payment mandates.
  * **Product Configuration:** Products intended for subscription must have plans defined in the `subscription` array within their Catalog data.
</Info>

**Key Features:**

* Standard & Custom Plans
* Billing & Shipping Cycles
* Trial Periods (Digital)
* Lifecycle Management (Create, View, Update, Pause, Revoke via API)
* Coupon Integration (Applied during `POST /subscriptions`)
* *(Usage-Based Billing - Future)*

## Core Concepts

<AccordionGroup>
  <Accordion title="Understanding Subscription Data">
    These schemas define the structure of subscription data you'll work with when listing, viewing, or managing subscriptions.

    <AccordionGroup>
      <Accordion title="The Subscription Object">
        This object is typically returned in lists (`GET /subscriptions`) and provides a summary view.

        * `id` (string, readOnly): Unique identifier for the subscription.
        * `plan_id` (string, readOnly): Identifier of the base plan from the catalog (if standard).
        * `plan_name` (string, readOnly): Name of the subscription plan.
        * `price` (number): The base recurring price for the subscription period.
        * `status` (enum, readOnly): Current state: `created`, `active`, `paused`, `revoked`.
        * `start_date` (string, format: date): The date the subscription officially began or will begin.
        * `end_date` (string | null, format: date): The date the subscription is set to automatically revoke (if specified).
        * `trial_days` (integer): Number of free trial days (primarily for digital).
        * `trial_start_date` (string | null, format: date, readOnly): Start date of the trial period.
        * `trial_end_date` (string | null, format: date, readOnly): End date of the trial period.
        * `next_billing_date` (string, format: date, readOnly): Date the next invoice/charge is scheduled.
        * `last_payment_date` (string | null, format: date-time, readOnly): Timestamp of the last successful payment.
        * `pause_start_date` (string | null, format: date): If paused, when the pause period started or will start.
        * `pause_end_date` (string | null, format: date): If paused, when the subscription is scheduled to automatically resume. Null means indefinite pause.
        * **Scheduling:**
          * `billing_frequency` (enum): How often billing occurs (e.g., `monthly`).
          * `billing_interval` (integer): Multiplier for frequency (e.g., `1` for every month, `2` for every 2 months).
          * `billing_limit` (integer | null): Total number of billing cycles allowed (null for indefinite).
          * `shipping_frequency` (enum): How often shipping occurs (physical products).
          * `shipping_interval` (integer): Multiplier for shipping frequency.
          * `shipping_limit` (integer | null): Total number of shipments allowed (null for indefinite).
        * **Coupons:**
          * `coupon_id` (string | null): ID of the applied coupon.
          * `coupon_code` (string | null): Code of the applied coupon.
          * `coupon_discount_percent` (number): Percentage discount from coupon.
          * `coupon_discount_amount` (number): Fixed amount discount from coupon.
          * `coupon_redemption_limit` (integer | null): How many cycles the coupon applies for (null for duration of subscription).
        * **Behavior:**
          * `is_prepaid` (boolean): Is the subscription paid fully upfront?
          * `usage_based_billing` (boolean): Is billing based on usage (digital)? *(Currently not supported for initiation but placeholder exists).*
          * `usage_based_tiers` (array): Pricing tiers for usage-based billing. *(Currently not supported for initiation).*
          * `grace_period_days` (integer): Days allowed for payment retry after failure.
        * **Cancellation Rules:**
          * `is_cancellation_allowed` (boolean): Can the customer currently initiate cancellation?
          * `days_until_cancellation_allowed` (integer): How many days before the next billing date cancellation must be done.
        * `currency` (`Currency` object): Details of the subscription currency.
        * `metadata` (object): Custom key-value pairs.
        * `created_at` (string, format: date-time, readOnly): Timestamp of creation.
        * `modified_at` (string, format: date-time, readOnly): Timestamp of last modification.
      </Accordion>

      <Accordion title="SubscriptionDetail Schema">
        Returned by `GET /subscriptions/{id}` and `POST /subscriptions`, includes everything in the `Subscription` schema plus:

        * `invoice_items` (array of `SubscriptionInvoiceItem`): Details of the specific products/variants included in this subscription.
        * `billing_address` (`CustomerAddress` object | null): The billing address associated with the subscription.
        * `shipping_address` (`CustomerAddress` object | null): The shipping address (for physical products).
      </Accordion>

      <Accordion title="SubscriptionInvoiceItem Schema">
        Details about each product/variant within a subscription.

        * `product_id` (string): ID of the included product.
        * `variant_id` (string | null): ID of the included variant (if applicable).
        * `product_name` (string, readOnly): Name of the product.
        * `variant_name` (string, readOnly): Name of the variant.
        * `product_image_url` (string, readOnly): Image URL.
        * `sku` (string, readOnly): SKU of the item.
        * `quantity` (integer): Quantity of this item included per cycle.
        * `listing_price` (number, readOnly): Original price per unit.
        * `selling_price` (number, readOnly): Subscription price per unit for this item.
        * `tax_type` (string, readOnly): Type of tax (e.g., "GST").
        * `tax_rate` (number, readOnly): Tax rate percentage.
        * `price_including_tax` (boolean, readOnly): Was the selling price entered inclusive of tax?
        * `selling_price_excluding_tax` (number, readOnly): Calculated selling price before tax.
      </Accordion>

      <Accordion title="Schemas for Creating/Updating (POST/PUT /subscriptions)">
        These define the structure of the request body when creating or updating subscriptions.

        * **`CreateStandardSubscription`**: Used when initiating a subscription based on a pre-defined plan from the product catalog.
          * `plan_type`: Must be `"standard"`.
          * `plan_id`: **Required**. The ID of the `ProductSubscription` plan selected from the product.
          * `start_date`: (Optional) Defaults to current date if omitted.
          * `end_date`: (Optional) Date to automatically revoke.
          * `coupon_code`: (Optional).
        * **`CreateCustomSubscription`**: Used when creating a subscription with a custom schedule (often for multi-item subscriptions).
          * `plan_type`: Must be `"custom"`.
          * `start_date`: (Optional).
          * `end_date`: (Optional).
          * `billing_frequency`: **Required**. e.g., `"monthly"`.
          * `billing_interval`: **Required**. e.g., `1`.
          * `billing_limit`: (Optional).
          * `shipping_frequency`: (Optional, for physical).
          * `shipping_interval`: (Optional, for physical).
          * `shipping_limit`: (Optional, for physical).
          * `coupon_code`: (Optional).
        * **`SubscriptionBehaviour`**: Defines billing rules, often included alongside Create/Update schemas.
          * `is_prepaid`: (Optional, default `false`).
          * `grace_period_days`: (Optional, default `0`).
          * `is_cancellation_allowed`: (Optional, default `true`).
          * `days_until_cancellation_allowed`: (Optional, default `3`).
          * *(Usage-based fields omitted as not currently supported for initiation)*
        * **`UpdatePhysicalProductSubscription` / `UpdateDigitalProductSubscription`**: Used with `command: "update"` in `PUT /subscriptions/{id}`. Allows changing schedule fields (`billing_frequency`, etc.), behavior fields (`grace_period_days`, etc.), and potentially `invoice_items` (subject to mandate rules).
        * **`PauseSubscription`**: Used with `command: "pause"` in `PUT /subscriptions/{id}`.
          * `command`: Must be `"pause"`.
          * `pause_start_date`: (Optional) Schedule pause start.
          * `pause_end_date`: (Optional) Schedule automatic resume.
        * **`RevokeSubscription`**: Used with `command: "revoke"` in `PUT /subscriptions/{id}`.
          * `command`: Must be `"revoke"`.
          * `reason`: **Required**. Text reason for cancellation.
      </Accordion>
    </AccordionGroup>
  </Accordion>
</AccordionGroup>

## Subscription Initiation Flows

There are two primary ways a user initiates a subscription:

<AccordionGroup>
  <Accordion title="Flow 1: Standard Single-Product Subscription ('Subscribe & Save')">
    1. **Discovery:** User browses a Product Detail Page (PDP). The `subscription` array within the `Product`/`Variant` data shows available plans (e.g., "Monthly Delivery - Save 10%").
    2. **Selection:** User selects a specific `ProductSubscription` plan ID and quantity.
    3. **Initiation:** User clicks a "Subscribe Now" (or similar) button.
    4. **Data Collection (Frontend):** Your application collects necessary details not already available:
       * Billing Address
       * Shipping Address (if physical product)
       * User details (if anonymous and needs registration)
    5. **API Call:** Your application calls `POST /subscriptions`.
       * **Body:** Includes `plan_type: "standard"`, the selected `plan_id` from the product, the `invoice_items` array (containing just this one product/variant and quantity), user details, addresses, and potentially a `coupon_code`.
    6. **Mandate/Payment Step (Conceptual):** The successful response from `POST /subscriptions` (or a related, subsequent call - *API endpoint TBC*) will provide details (like a Juspay redirect URL or SDK payload) to:
       * Collect initial payment (if applicable, e.g., not a free trial).
       * Obtain user authorization for the recurring payment mandate via Juspay.
    7. **Activation:** Upon successful payment/mandate authorization, Commerce Engine activates the subscription (status becomes `active`).

    **Standard Single-Product Subscription Flow Diagram**

    <Frame caption="Standard Single-Product Subscription Flow">
      <iframe title="Standard Single-Product Subscription Flow" allowfullscreen width="100%" height="600" src="https://mermaid.tarkai.dev/embed?definition=sequenceDiagram%0A%20%20%20%20participant%20User%0A%20%20%20%20participant%20ClientApp%20as%20Client%20Application%0A%20%20%20%20participant%20CE_API%20as%20CE%20API%0A%20%20%20%20participant%20Juspay%0A%0A%20%20%20%20User-%3E%3EClientApp%3A%20Cliks%20on%20%22Subscribe%20Now%22%0A%20%20%20%20User-%3E%3EClientApp%3A%20Selects%20Plan%20SUB123%2C%20Quantity%201%0A%20%20%20%20ClientApp-%3E%3EClientApp%3A%20Collect%2FConfirm%20Address%0A%20%20%20%20ClientApp-%3E%3ECE_API%3A%20POST%20%2Fsubscriptions%20(Create%20Subscription)%0A%20%20%20%20activate%20CE_API%0A%20%20%20%20CE_API--%3E%3EClientApp%3A%20200%20OK%20(Res%3A%20%7BSubscriptionDetail%2C%20payment_mandate_info%7D)%0A%20%20%20%20deactivate%20CE_API%0A%0A%20%20%20%20ClientApp-%3E%3EUser%3A%20Use%20payment_mandate_info%20to%20redirect%0A%20%20%20%20User-%3E%3EJuspay%3A%20Authorizes%20Mandate%20%26%20Initial%20Payment%20(if%20any)%0A%20%20%20%20Juspay--%3E%3EUser%3A%20Redirects%20back%20to%20ClientApp%20(via%20return_url)%0A%20%20%20%20Juspay--%3E%3ECE_API%3A%20Webhook%3A%20Mandate%20Success%2C%20Payment%20Success%0A%20%20%20%20activate%20CE_API%0A%20%20%20%20CE_API-%3E%3ECE_API%3A%20Update%20Subscription%20status%20to%20'active'%0A%20%20%20%20deactivate%20CE_API%0A%0A%20%20%20%20ClientApp-%3E%3EUser%3A%20Display%20Subscription%20Confirmation" />
    </Frame>
  </Accordion>

  <Accordion title="Flow 2: Custom Multi-Product Subscription (Advanced)">
    1. **Discovery & Cart Building:** User adds multiple *subscription-eligible* products/variants to the standard cart (`POST /carts`, `POST /carts/{id}/items`). The frontend must track which items are intended for subscription.
    2. **Subscription Checkout Trigger:** User proceeds to a checkout flow *specifically designated for creating a custom subscription* from the cart contents (distinct from the one-time purchase checkout).
    3. **Schedule Selection:** Your application prompts the user to select **one common billing frequency and interval** for *all* items being subscribed to in this batch. Shipping frequency might also be unified or handled based on item defaults.
    4. **Data Collection (Frontend):** Confirm/collect billing and shipping addresses.
    5. **API Call:** Your application calls `POST /subscriptions`.
       * **Body:** Includes `plan_type: "custom"`, the selected `billing_frequency`, `billing_interval`, `billing_limit`, the `invoice_items` array (listing *all* products/variants from the cart intended for this subscription), user details, addresses, and potentially a `coupon_code`.
    6. **Mandate/Payment Step (Conceptual):** Similar to Flow 1, trigger the Juspay mandate/payment process based on the API response. The mandate `maxAmount` should cover the combined cost of all items in the custom subscription bundle.
    7. **Activation:** Upon success, Commerce Engine activates the single custom subscription covering all included items.

    **Custom Multi-Product Subscription Flow Diagram**

    <Frame caption="Custom Multi-Product Subscription Flow">
      <iframe title="Custom Multi-Product Subscription Flow" allowfullscreen width="100%" height="600" src="https://mermaid.tarkai.dev/embed?definition=sequenceDiagram%0A%20%20%20%20participant%20User%0A%20%20%20%20participant%20ClientApp%20as%20Client%20Application%0A%20%20%20%20participant%20CE_API%20as%20CE%20API%0A%20%20%20%20participant%20Juspay%0A%0A%20%20%20%20User-%3E%3EClientApp%3A%20Adds%20eligible%20items%20to%20Cart%0A%20%20%20%20User-%3E%3EClientApp%3A%20Proceeds%20to%20%22Subscription%20Checkout%22%0A%20%20%20%20User-%3E%3EClientApp%3A%20Selects%20Billing%20Frequency%0A%20%20%20%20ClientApp-%3E%3EClientApp%3A%20Collect%2FConfirm%20Address%0A%20%20%20%20ClientApp-%3E%3ECE_API%3A%20POST%20%2Fsubscriptions%20(Create%20Subscription)%0A%20%20%20%20activate%20CE_API%0A%20%20%20%20CE_API--%3E%3EClientApp%3A%20200%20OK%20(Res%3A%20%7BSubscriptionDetail%20%5Bstatus%3Acreated%5D%2C%20payment_mandate_info%7D%0A%20%20%20%20deactivate%20CE_API%0A%0A%20%20%20%20ClientApp-%3E%3EUser%3A%20Use%20payment_mandate_info%20to%20Redirect%20to%20Juspay%20URL%0A%20%20%20%20User-%3E%3EJuspay%3A%20Authorizes%20Mandate%20%26%20Initial%20Payment%0A%20%20%20%20Juspay--%3E%3EUser%3A%20Redirects%20back%20to%20ClientApp%0A%20%20%20%20Juspay--%3E%3ECE_API%3A%20Webhook%3A%20Mandate%20Success%2C%20Payment%20Success%0A%20%20%20%20activate%20CE_API%0A%20%20%20%20CE_API-%3E%3ECE_API%3A%20Update%20Subscription%20status%20to%20'active'%0A%20%20%20%20deactivate%20CE_API%0A%0A%20%20%20%20ClientApp-%3E%3EUser%3A%20Display%20Subscription%20Confirmation" />
    </Frame>
  </Accordion>
</AccordionGroup>

## Subscription API Endpoints

<AccordionGroup>
  <Accordion title="POST /subscriptions">
    **Primary endpoint for initiating both standard (single-item) and custom (multi-item) subscriptions.** This call gathers all necessary subscription details *before* triggering the payment/mandate process.

    * **Authentication:** Bearer Token (Typically Logged-in, but anonymous might be possible if registration occurs implicitly during mandate/payment).
    * **Request Body:** Combines:
      * Plan Details: `CreateStandardSubscription` (using `plan_id` from product) OR `CreateCustomSubscription` (defining schedule).
      * Items: `invoice_items` array (one item for standard, multiple for custom).
      * Behavior: `SubscriptionBehaviour` (prepaid, grace period etc.).
      * User Context: Implicitly via token, but might need explicit user details if creating for anonymous user needing registration.
      * Addresses: Billing and Shipping address objects.
      * `coupon_code`: (Optional).
    * **Response:** `200 OK` containing the newly created `SubscriptionDetail` object (likely with `status: 'created'`). <Warning>The mechanism for providing payment/mandate details (e.g., Juspay URL/payload) in the response or via a subsequent call is **To Be Confirmed (TBC)**.</Warning>
  </Accordion>

  <Accordion title="GET /subscriptions">
    Retrieves a list of the customer's subscriptions (active, paused, past) for display in "My Account".

    * **Authentication:** Bearer Token (Logged-in user)
    * **Response:** Paginated list of `Subscription` summary objects.
  </Accordion>

  <Accordion title="GET /subscriptions/{id}">
    Fetches complete details (`SubscriptionDetail` object) for managing a specific subscription.

    * **Authentication:** Bearer Token (User must own the subscription)
    * **Path Parameter:** `id` (Subscription ID)
    * **Response:** `SubscriptionDetail` object.
  </Accordion>

  <Accordion title="PUT /subscriptions/{id}">
    Manage the lifecycle and configuration of an *existing* subscription (pause, revoke, update schedule/items - subject to mandate rules).

    * **Authentication:** Bearer Token (User must own the subscription)
    * **Path Parameter:** `id` (Subscription ID)
    * **Request Body:** Uses `command: "update"`, `command: "pause"`, or `command: "revoke"` with relevant schema (`Update...Subscription`, `PauseSubscription`, `RevokeSubscription`).
    * **Response:** Updated `SubscriptionDetail` object.
  </Accordion>
</AccordionGroup>
