
import PaginationFields from "../../../src/reference/subbly-sdk/types/Pagination.mdx";
import SubscriptionFields from "../../../src/reference/subbly-sdk/types/Subscription.mdx";
import SubscriptionItemFields from "../../../src/reference/subbly-sdk/types/SubscriptionItem.mdx";

<SdkPage group="subscriptions" />

Every method here needs a signed-in customer, and reads or writes only that
customer's subscriptions.

A subscription has a plan, a quantity, and a list of **items**: the subscription
line itself plus any add-ons. Change the whole subscription with `update`,
`updateBundle` and `updatePreferences`; change one line with the `Item` methods.

Most methods take a `params.expand` list, and every method takes a final
`headers` object; see
[Expand parameters](/reference/subbly-sdk#expand-parameters) and
[Currency](/reference/subbly-sdk#currency).

<Method id="list" signature="subbly.subscriptions.list(params, headers?)">

Gets a page of the customer's subscriptions.

<Params>
  <Param name="params" required type="SubscriptionsListParams">
    Which subscriptions to return. The argument is required by position, so pass
    an empty object for the defaults.
    <Properties label="params">
      <Param name="page" optional type="number">
        Page to return, counted from 1.
      </Param>

      <Param name="perPage" optional type="number">
        How many subscriptions per page.
      </Param>

      <Param name="statuses" optional type="SubscriptionStatus[]">
        Keep only these statuses: `active`, `trial`, `pre_order`,
        `gift_waiting_to_start`, `cancelled`, `switched` or `expired`.
      </Param>

      <Param name="expand" optional type="string[]">
        Relations to include.
      </Param>
    </Properties>
  </Param>

  <Param name="headers" optional type="RequestHeaders">
    Extra request headers.
  </Param>
</Params>

<Returns type="Promise<SubscriptionsListResponse>">
One page of subscriptions.
<Properties>
  <Param name="data" type="Subscription[]">
    The subscriptions on this page.
    <Properties label="subscription" collapsed>
      <SubscriptionFields />
    </Properties>
  </Param>

  <Param name="pagination" type="Pagination">
    Where this page sits in the full list.
    <Properties label="pagination" collapsed>
      <PaginationFields />
    </Properties>
  </Param>
</Properties>
</Returns>

<Example>

```js title="List the active subscriptions"
const { data, pagination } = await subbly.subscriptions.list({
  statuses: ['active', 'trial'],
  expand: ['product.parent']
})
```

</Example>

</Method>

<Method id="load" signature="subbly.subscriptions.load(subscriptionId, params?, headers?)">

Loads one subscription.

<Params>
  <Param name="subscriptionId" required type="number">
    ID of the subscription.
  </Param>

  <Param name="params" optional type="SubscriptionsResourceParams">
    Extra data to include.
    <Properties label="params">
      <Param name="expand" optional type="string[]">
        Relations to include.
      </Param>
    </Properties>
  </Param>

  <Param name="headers" optional type="RequestHeaders">
    Extra request headers.
  </Param>
</Params>

<Returns type="Promise<Subscription>">
The subscription.
<Properties label="subscription" collapsed>
  <SubscriptionFields />
</Properties>
</Returns>

<Example>

```js title="Load a subscription"
const subscription = await subbly.subscriptions.load(123, {
  expand: ['product.parent', 'discounts']
})
```

</Example>

</Method>

<Method id="update" signature="subbly.subscriptions.update(subscriptionId, payload, params?, headers?)">

Changes the quantity or the metadata of a subscription. Quantity changes need
`shop.settings.subscriptionQuantitySelector`.

<Params>
  <Param name="subscriptionId" required type="number">
    ID of the subscription.
  </Param>

  <Param name="payload" required type="SubscriptionUpdatePayload">
    The change to make.
    <Properties label="payload">
      <Param name="quantity" required type="number">
        New quantity. Send it even when only the metadata changes.
      </Param>

      <Param name="metadata" optional type="MetadataObject[] | null">
        Metafield values to write. Each entry is `{ id, values }`, where `id` is
        a metafield ID. A value is `{ id }` for a preset field and
        `{ value }` for a free-text one.
      </Param>
    </Properties>
  </Param>

  <Param name="params" optional type="SubscriptionsResourceParams">
    Extra data to include in the response.
    <Properties label="params">
      <Param name="expand" optional type="string[]">
        Relations to include.
      </Param>
    </Properties>
  </Param>

  <Param name="headers" optional type="RequestHeaders">
    Extra request headers.
  </Param>
</Params>

<Returns type="Promise<Subscription>">
The subscription, with the change applied.
<Properties label="subscription" collapsed>
  <SubscriptionFields />
</Properties>
</Returns>

<Example>

```js title="Change the quantity"
await subbly.subscriptions.update(123, { quantity: 2 })
```

```js title="Write a metafield value"
await subbly.subscriptions.update(123, {
  quantity: subscription.quantity,
  metadata: [{ id: 45, values: [{ id: 67 }] }]
})
```

</Example>

</Method>

<Method id="update-preferences" signature="subbly.subscriptions.updatePreferences(subscriptionId, payload, headers?)">

Rewrites the survey answers of a subscription. Send every answer you want to
keep: the call replaces the whole set. This method takes no `params` argument.

<Params>
  <Param name="subscriptionId" required type="number">
    ID of the subscription.
  </Param>

  <Param name="payload" required type="SubscriptionPreferencesPayload">
    The new answers.
    <Properties label="payload">
      <Param name="preferences" required type="SubscriptionSurveyOption[] | null">
        One entry per question, as `{ questionId, answers }`. An answer is
        `{ content }` for a text or email question, `{ id }` for a select,
        multiple, offer or plan question, and `{ id, quantity }` for a quantity
        question. Pass `null` to clear the answers.
      </Param>

      <Param name="updateOrders" optional type="boolean">
        `true` also applies the answers to orders Subbly already generated.
      </Param>
    </Properties>
  </Param>

  <Param name="headers" optional type="RequestHeaders">
    Extra request headers.
  </Param>
</Params>

<Returns type="Promise<Subscription>">
The subscription, with the new answers.
<Properties label="subscription" collapsed>
  <SubscriptionFields />
</Properties>
</Returns>

<Example>

```js title="Answer the survey again"
await subbly.subscriptions.updatePreferences(123, {
  preferences: [
    { questionId: 11, answers: [{ id: 22 }] },
    { questionId: 12, answers: [{ content: 'No nuts, please' }] }
  ],
  updateOrders: true
})
```

</Example>

</Method>

<Method id="update-bundle" signature="subbly.subscriptions.updateBundle(subscriptionId, payload, headers?)">

Rewrites the bundle contents and the bundle preferences of a subscription. Send
the whole list of items: the call replaces what was there. This method takes no
`params` argument.

<Params>
  <Param name="subscriptionId" required type="number">
    ID of the subscription.
  </Param>

  <Param name="payload" required type="SubscriptionBundlePayload">
    The new bundle.
    <Properties label="payload">
      <Param name="productId" required type="number | null">
        The plan the bundle belongs to. May be `null`.
      </Param>

      <Param name="quantity" optional type="number">
        New quantity of the bundle.
      </Param>

      <Param name="bundle" optional type="object">
        What goes in the bundle.
        <Properties label="bundle">
          <Param name="items" required type="BundlePayloadItem[] | null">
            The items picked, as `{ productId, quantity }`. `productId` is a
            bundle item's `productId`.
          </Param>

          <Param name="preferences" required type="BundlePayloadPreference[] | null">
            The preferences picked, as `{ attributeId, values }`, where `values`
            holds attribute value IDs.
          </Param>
        </Properties>
      </Param>
    </Properties>
  </Param>

  <Param name="headers" optional type="RequestHeaders">
    Extra request headers.
  </Param>
</Params>

<Returns type="Promise<Subscription>">
The subscription, with the new bundle.
<Properties label="subscription" collapsed>
  <SubscriptionFields />
</Properties>
</Returns>

<Example>

```js title="Swap the bundle contents"
await subbly.subscriptions.updateBundle(123, {
  productId: subscription.productId,
  quantity: 1,
  bundle: {
    items: [
      { productId: 456, quantity: 2 },
      { productId: 789, quantity: 1 }
    ],
    preferences: [{ attributeId: 5, values: [9] }]
  }
})
```

</Example>

</Method>

<Method id="load-item" signature="subbly.subscriptions.loadItem(subscriptionId, itemId, params?, headers?)">

Loads one item of a subscription: the subscription line itself, or an add-on.

<Params>
  <Param name="subscriptionId" required type="number">
    ID of the subscription.
  </Param>

  <Param name="itemId" required type="number">
    ID of the item, from `subscription.items[].id`.
  </Param>

  <Param name="params" optional type="SubscriptionsResourceParams">
    Extra data to include.
    <Properties label="params">
      <Param name="expand" optional type="string[]">
        Relations to include.
      </Param>
    </Properties>
  </Param>

  <Param name="headers" optional type="RequestHeaders">
    Extra request headers.
  </Param>
</Params>

<Returns type="Promise<SubscriptionItem>">
The item.
<Properties label="item" collapsed>
  <SubscriptionItemFields />
</Properties>
</Returns>

<Example>

```js title="Load one item"
const item = await subbly.subscriptions.loadItem(123, 456, {
  expand: ['product.parent']
})
```

</Example>

</Method>

<Method id="update-item" signature="subbly.subscriptions.updateItem(subscriptionId, itemId, payload, params?, headers?)">

Changes the quantity or the metadata of one subscription item.

<Params>
  <Param name="subscriptionId" required type="number">
    ID of the subscription.
  </Param>

  <Param name="itemId" required type="number">
    ID of the item.
  </Param>

  <Param name="payload" required type="SubscriptionUpdatePayload">
    The change to make.
    <Properties label="payload">
      <Param name="quantity" required type="number">
        New quantity of the item.
      </Param>

      <Param name="metadata" optional type="MetadataObject[] | null">
        Metafield values to write, as `{ id, values }`.
      </Param>
    </Properties>
  </Param>

  <Param name="params" optional type="SubscriptionsResourceParams">
    Extra data to include in the response.
    <Properties label="params">
      <Param name="expand" optional type="string[]">
        Relations to include.
      </Param>
    </Properties>
  </Param>

  <Param name="headers" optional type="RequestHeaders">
    Extra request headers.
  </Param>
</Params>

<Returns type="Promise<SubscriptionItem>">
The item, with the change applied.
<Properties label="item" collapsed>
  <SubscriptionItemFields />
</Properties>
</Returns>

<Example>

```js title="Change the quantity of an add-on"
await subbly.subscriptions.updateItem(123, 456, { quantity: 3 })
```

</Example>

</Method>

<Method id="update-item-bundle" signature="subbly.subscriptions.updateItemBundle(subscriptionId, itemId, payload, params?, headers?)">

Rewrites the bundle contents of one subscription item. Unlike `updateBundle`,
this call carries no quantity, and `bundle` is required.

<Params>
  <Param name="subscriptionId" required type="number">
    ID of the subscription.
  </Param>

  <Param name="itemId" required type="number">
    ID of the item.
  </Param>

  <Param name="payload" required type="SubscriptionItemBundleUpdatePayload">
    The new bundle for the item.
    <Properties label="payload">
      <Param name="productId" required type="number | null">
        The variant or plan the bundle belongs to. May be `null`.
      </Param>

      <Param name="bundle" required type="object">
        What goes in the bundle.
        <Properties label="bundle">
          <Param name="items" required type="BundlePayloadItem[] | null">
            The items picked, as `{ productId, quantity }`.
          </Param>

          <Param name="preferences" required type="BundlePayloadPreference[] | null">
            The preferences picked, as `{ attributeId, values }`.
          </Param>
        </Properties>
      </Param>
    </Properties>
  </Param>

  <Param name="params" optional type="SubscriptionsResourceParams">
    Extra data to include in the response.
    <Properties label="params">
      <Param name="expand" optional type="string[]">
        Relations to include.
      </Param>
    </Properties>
  </Param>

  <Param name="headers" optional type="RequestHeaders">
    Extra request headers.
  </Param>
</Params>

<Returns type="Promise<SubscriptionItem>">
The item, with the new bundle.
<Properties label="item" collapsed>
  <SubscriptionItemFields />
</Properties>
</Returns>

<Example>

```js title="Swap the contents of one bundle item"
await subbly.subscriptions.updateItemBundle(123, 456, {
  productId: item.productId,
  bundle: {
    items: [{ productId: 789, quantity: 2 }],
    preferences: []
  }
})
```

</Example>

</Method>

<Method id="update-item-preferences" signature="subbly.subscriptions.updateItemPreferences(subscriptionId, itemId, payload, headers?)">

Rewrites the survey answers of one subscription item. This method takes no
`params` argument.

<Params>
  <Param name="subscriptionId" required type="number">
    ID of the subscription.
  </Param>

  <Param name="itemId" required type="number">
    ID of the item.
  </Param>

  <Param name="payload" required type="SubscriptionPreferencesPayload">
    The new answers.
    <Properties label="payload">
      <Param name="preferences" required type="SubscriptionSurveyOption[] | null">
        One entry per question, as `{ questionId, answers }`. Pass `null` to
        clear the answers.
      </Param>

      <Param name="updateOrders" optional type="boolean">
        `true` also applies the answers to orders Subbly already generated.
      </Param>
    </Properties>
  </Param>

  <Param name="headers" optional type="RequestHeaders">
    Extra request headers.
  </Param>
</Params>

<Returns type="Promise<SubscriptionItem>">
The item, with the new answers.
<Properties label="item" collapsed>
  <SubscriptionItemFields />
</Properties>
</Returns>

<Example>

```js title="Answer the survey for one item"
await subbly.subscriptions.updateItemPreferences(123, 456, {
  preferences: [{ questionId: 11, answers: [{ id: 22 }] }]
})
```

</Example>

</Method>
