Skip to main content
Before a customer can subscribe, your product detail page needs to know which subscription frequencies are available, what discounts apply, and whether subscriptions are offered at all for that product or variant. The subscription offer endpoint gives you all of this in a single read, resolved against the plans and offers you have configured in Admin.

Fetching a subscription offer

Call GET /store/products/:id/subscription-offer to retrieve the effective offer for a product. Pass an optional variant_id query parameter to resolve the offer for a specific variant instead.
GET /store/products/:id/subscription-offer
GET /store/products/:id/subscription-offer?variant_id=variant_123
When variant_id is provided and that variant has its own offer configured, the variant-level offer takes precedence over the product-level offer. If no offer is found at either level, or if the offer is disabled, the response returns is_subscription_available: false.

Response shape

{
  "subscription_offer": {
    "is_subscription_available": true,
    "product_id": "prod_123",
    "variant_id": "variant_456",
    "source_offer_id": "offer_789",
    "source_scope": "variant",
    "allowed_frequencies": [
      {
        "frequency_interval": "month",
        "frequency_value": 1,
        "label": "Monthly",
        "discount": {
          "type": "percentage",
          "value": 10
        }
      },
      {
        "frequency_interval": "month",
        "frequency_value": 3,
        "label": "Every 3 months",
        "discount": {
          "type": "percentage",
          "value": 15
        }
      }
    ],
    "discount_semantics": "per_order",
    "minimum_cycles": 2,
    "trial": null
  }
}

Response fields

FieldDescription
is_subscription_availabletrue if subscriptions are available for this product or variant
product_idThe product the offer applies to
variant_idThe resolved variant, if variant_id was passed
source_offer_idThe internal ID of the offer that was resolved
source_scopeWhether the offer came from "variant" or "product" level
allowed_frequenciesArray of available subscription cadences (see below)
discount_semanticsHow the discount is applied — for example "per_order"
minimum_cyclesThe minimum number of billing cycles before cancellation is allowed, or null
trialTrial configuration object, or null if no trial is configured

Frequency items

Each object in allowed_frequencies describes one selectable cadence:
FieldDescription
frequency_intervalTime unit: "week", "month", or "year"
frequency_valueNumber of intervals between billings
labelHuman-readable label you can display directly in your UI
discount.typeDiscount type — for example "percentage" or "fixed"
discount.valueThe discount amount in the given type’s unit

Powering a PDP subscription selector

Use this endpoint to drive the subscription UI on your product detail page. A typical implementation fetches the offer on page load and uses the response to:
  1. Show or hide the subscription option — render the subscription selector only when is_subscription_available is true.
  2. Populate the frequency selector — render one option per item in allowed_frequencies, using label as the display text.
  3. Display the discount — show the savings for each frequency using discount.type and discount.value.
  4. Set checkout metadata — when the customer confirms a frequency, use the selected frequency_interval and frequency_value to set the line item metadata before calling the subscribe endpoint.
const { subscription_offer } = await medusa.client.fetch(
  `/store/products/${productId}/subscription-offer?variant_id=${variantId}`
);

if (!subscription_offer.is_subscription_available) {
  // Hide subscription option
  return;
}

// Render a frequency option for each allowed cadence
const options = subscription_offer.allowed_frequencies.map((freq) => ({
  label: freq.label,
  interval: freq.frequency_interval,
  value: freq.frequency_value,
  discount: freq.discount,
}));
The allowed_frequencies array only contains cadences that are active in your Plans & Offers configuration. Use this list to validate which cadences a customer can select — do not allow customers to submit cadences that are not present in the response.