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

# Customer Subscriptions

> Let customers list and manage their own subscriptions — pause, resume, skip, swap, change frequency or address, retry payment, and request cancellation.

The customer subscription endpoints expose self-service subscription management on the storefront. An authenticated customer can view their subscriptions, make lifecycle changes, and initiate a cancellation. All routes require a valid customer session or bearer token, and all subscription mutations enforce ownership — the subscription must belong to the authenticated customer. Mutations return the refreshed subscription detail payload unless noted otherwise.

<Info>All routes use `authenticate("customer", ["session", "bearer"])`. Ownership is validated against the authenticated customer's `actor_id`.</Info>

***

## GET /store/customers/me/subscriptions

Returns the authenticated customer's subscriptions with storefront summary data.

### Response

<ResponseField name="subscriptions" type="object[]" required>
  <Expandable title="subscription summary fields">
    <ResponseField name="id" type="string">Subscription ID.</ResponseField>
    <ResponseField name="reference" type="string">Human-readable reference (e.g. `SUB-001`).</ResponseField>
    <ResponseField name="status" type="string">Current subscription status.</ResponseField>
    <ResponseField name="product_title" type="string">Product name.</ResponseField>
    <ResponseField name="variant_title" type="string">Variant name.</ResponseField>
    <ResponseField name="next_renewal_at" type="string">Next scheduled renewal date.</ResponseField>
    <ResponseField name="active_cancellation_case" type="object | null">Active cancellation case summary, or `null`.</ResponseField>
  </Expandable>
</ResponseField>

***

## GET /store/customers/me/subscriptions/:id

Returns the full storefront-safe detail payload for one subscription.

### Path parameters

<ParamField path="id" type="string" required>
  Subscription ID. Must belong to the authenticated customer.
</ParamField>

### Response

<ResponseField name="subscription" type="object" required>
  <Expandable title="subscription detail fields">
    <ResponseField name="id" type="string">Subscription ID.</ResponseField>
    <ResponseField name="reference" type="string">Human-readable reference.</ResponseField>
    <ResponseField name="status" type="string">Current subscription status.</ResponseField>
    <ResponseField name="product_title" type="string">Product name.</ResponseField>
    <ResponseField name="variant_title" type="string">Variant name.</ResponseField>
    <ResponseField name="frequency_interval" type="string">Billing interval: `week`, `month`, or `year`.</ResponseField>
    <ResponseField name="frequency_value" type="number">Billing cadence as a positive integer.</ResponseField>
    <ResponseField name="next_renewal_at" type="string">Technical billing anchor date.</ResponseField>
    <ResponseField name="effective_next_renewal_at" type="string">Projected next renewal accounting for any skip.</ResponseField>
    <ResponseField name="last_renewal_at" type="string | null">Last successful renewal timestamp.</ResponseField>
    <ResponseField name="shipping_address" type="object">Current shipping address snapshot.</ResponseField>
    <ResponseField name="payment_status" type="string">Current payment status.</ResponseField>
    <ResponseField name="payment_provider_id" type="string">Payment provider identifier.</ResponseField>
    <ResponseField name="payment_recovery" type="object | null">Active dunning recovery case, or `null`.</ResponseField>
    <ResponseField name="scheduled_plan_change" type="object | null">Pending variant or cadence change, or `null`.</ResponseField>
    <ResponseField name="active_cancellation_case" type="object | null">Active cancellation case summary, or `null`.</ResponseField>
  </Expandable>
</ResponseField>

***

## POST /store/customers/me/subscriptions/:id/pause

Pauses the customer's subscription.

### Path parameters

<ParamField path="id" type="string" required>
  Subscription ID.
</ParamField>

### Body parameters

<ParamField body="reason" type="string">
  Optional reason for the pause.
</ParamField>

<ParamField body="effective_at" type="string">
  ISO datetime for when the pause takes effect. Optional.
</ParamField>

```json Request example theme={null}
{
  "reason": "Taking a short break",
  "effective_at": "2026-04-15T10:00:00.000Z"
}
```

***

## POST /store/customers/me/subscriptions/:id/resume

Resumes a paused subscription.

### Path parameters

<ParamField path="id" type="string" required>
  Subscription ID.
</ParamField>

### Body parameters

<ParamField body="resume_at" type="string">
  ISO datetime for when the subscription resumes. Optional.
</ParamField>

<ParamField body="preserve_billing_anchor" type="boolean">
  When `true`, keeps the original billing anchor date. Optional.
</ParamField>

```json Request example theme={null}
{
  "resume_at": "2026-04-20T10:00:00.000Z",
  "preserve_billing_anchor": true
}
```

***

## POST /store/customers/me/subscriptions/:id/change-frequency

Schedules a cadence change for the subscription. The current variant stays unchanged. The new cadence is validated against active Plans & Offers.

### Path parameters

<ParamField path="id" type="string" required>
  Subscription ID.
</ParamField>

### Body parameters

<ParamField body="frequency_interval" type="string" required>
  New billing interval. One of `week`, `month`, or `year`.
</ParamField>

<ParamField body="frequency_value" type="number" required>
  New billing cadence as a positive integer.
</ParamField>

<ParamField body="effective_at" type="string">
  ISO datetime when the change becomes effective. Optional.
</ParamField>

```json Request example theme={null}
{
  "frequency_interval": "month",
  "frequency_value": 2,
  "effective_at": "2026-05-01T10:00:00.000Z"
}
```

***

## POST /store/customers/me/subscriptions/:id/change-address

Updates the subscription shipping address.

### Path parameters

<ParamField path="id" type="string" required>
  Subscription ID.
</ParamField>

### Body parameters

<ParamField body="first_name" type="string" required>First name.</ParamField>
<ParamField body="last_name" type="string" required>Last name.</ParamField>
<ParamField body="address_1" type="string" required>Primary address line.</ParamField>
<ParamField body="city" type="string" required>City.</ParamField>
<ParamField body="postal_code" type="string" required>Postal or ZIP code.</ParamField>
<ParamField body="country_code" type="string" required>Two-letter ISO country code.</ParamField>

```json Request example theme={null}
{
  "first_name": "Jane",
  "last_name": "Doe",
  "address_1": "Main Street 1",
  "city": "Copenhagen",
  "postal_code": "2100",
  "country_code": "dk"
}
```

***

## POST /store/customers/me/subscriptions/:id/skip-next-delivery

Marks the next renewal cycle as skipped. No request body is required.

### Path parameters

<ParamField path="id" type="string" required>
  Subscription ID.
</ParamField>

***

## POST /store/customers/me/subscriptions/:id/swap-product

Schedules a product or variant swap. The target variant must belong to the subscription product and be allowed by active Plans & Offers.

### Path parameters

<ParamField path="id" type="string" required>
  Subscription ID.
</ParamField>

### Body parameters

<ParamField body="variant_id" type="string" required>
  Target variant ID.
</ParamField>

<ParamField body="frequency_interval" type="string" required>
  Billing interval for the new variant. One of `week`, `month`, or `year`.
</ParamField>

<ParamField body="frequency_value" type="number" required>
  Billing cadence as a positive integer.
</ParamField>

<ParamField body="effective_at" type="string">
  ISO datetime when the swap becomes effective. Optional.
</ParamField>

```json Request example theme={null}
{
  "variant_id": "variant_123",
  "frequency_interval": "month",
  "frequency_value": 1,
  "effective_at": "2026-05-01T10:00:00.000Z"
}
```

***

## POST /store/customers/me/subscriptions/:id/retry-payment

Runs a manual payment retry for a retry-eligible dunning recovery case.

### Path parameters

<ParamField path="id" type="string" required>
  Subscription ID.
</ParamField>

### Body parameters

<ParamField body="reason" type="string">
  Optional reason for the manual retry.
</ParamField>

```json Request example theme={null}
{
  "reason": "Customer requested immediate retry"
}
```

### Errors

| Code  | Error      | Meaning                                        |
| ----- | ---------- | ---------------------------------------------- |
| `409` | `conflict` | No retry-eligible payment recovery case exists |

***

## POST /store/customers/me/subscriptions/:id/cancellation

Starts a cancellation case for the subscription. Returns a minimal cancellation case payload rather than the full subscription detail.

### Path parameters

<ParamField path="id" type="string" required>
  Subscription ID. Must belong to the authenticated customer.
</ParamField>

### Body parameters

<ParamField body="reason" type="string">
  Free-text churn reason.
</ParamField>

<ParamField body="reason_category" type="string">
  Normalized reason category. One of `price`, `product_fit`, `delivery`, `billing`, `temporary_pause`, `switched_competitor`, or `other`.
</ParamField>

<ParamField body="notes" type="string">
  Optional notes from the customer.
</ParamField>

```json Request example theme={null}
{
  "reason": "Too expensive right now",
  "reason_category": "price",
  "notes": "Customer started cancellation from storefront"
}
```

### Response

<ResponseField name="cancellation_case" type="object" required>
  <Expandable title="cancellation case fields">
    <ResponseField name="id" type="string">Cancellation case ID.</ResponseField>
    <ResponseField name="status" type="string">Initial case status.</ResponseField>
    <ResponseField name="subscription_id" type="string">Linked subscription ID.</ResponseField>
    <ResponseField name="reason" type="string">Submitted churn reason.</ResponseField>
    <ResponseField name="reason_category" type="string">Submitted reason category.</ResponseField>
  </Expandable>
</ResponseField>
