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

# Subscribe to, upgrade or downgrade to a plan (products + size)

> Resolves the selection to a catalogue plan and creates a pending Shopify app subscription replacing the current one; returns the confirmation URL the merchant must open to approve it. Nothing is billed or changed until they approve, except that a downgrade to a plan without Merchandising deactivates the collections not in `keep_collection_ids`. Upgrades and lateral moves apply immediately (prorated), downgrades at the next billing cycle. See GET /settings/subscription/plans for what can be bought.



## OpenAPI

````yaml /api-reference/openapi/lite.json post /settings/subscription
openapi: 3.1.0
info:
  title: Search & Merchandising API
  version: 1.0.0
  description: >-
    REST API behind Depict: Search & Merchandising, the native Shopify app:
    onboarding, collections, boost & bury, dashboards, A/B testing and
    multi-store management. Endpoints are served under the /api/lite prefix and
    are authenticated with the Shopify session token that App Bridge issues to
    the embedded app.
servers:
  - url: /api/lite
security:
  - ShopifySessionToken: []
paths:
  /settings/subscription:
    post:
      summary: Subscribe to, upgrade or downgrade to a plan (products + size)
      description: >-
        Resolves the selection to a catalogue plan and creates a pending Shopify
        app subscription replacing the current one; returns the confirmation URL
        the merchant must open to approve it. Nothing is billed or changed until
        they approve, except that a downgrade to a plan without Merchandising
        deactivates the collections not in `keep_collection_ids`. Upgrades and
        lateral moves apply immediately (prorated), downgrades at the next
        billing cycle. See GET /settings/subscription/plans for what can be
        bought.
      operationId: subscriptionChange
      parameters:
        - schema:
            type: string
            description: Lite merchant id, e.g. `shopify-<shop id>`.
          required: true
          description: Lite merchant id, e.g. `shopify-<shop id>`.
          name: merchant_id
          in: query
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionPlanChangeRequest'
      responses:
        '200':
          description: The pending change and its confirmation URL.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionPlanChangeResponse'
        '400':
          description: >-
            The query or body failed the schema (`detail` only), no Shopify
            configuration, or a `code`: plan_not_sellable, currency_mismatch,
            too_many_collections (with active/kept/max).
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/SubscriptionPlanChangeError'
                  - $ref: '#/components/schemas/Detail'
        '401':
          description: Not authenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Detail'
        '403':
          description: Not allowed to call the API, or a merchant session sent a discount.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Detail'
        '404':
          description: >-
            Merchant not found for this caller, or `code` plan_not_found: no
            plan sells that selection.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/SubscriptionPlanChangeError'
                  - $ref: '#/components/schemas/Detail'
        '409':
          description: >-
            `code` already_subscribed: the merchant already has these exact
            terms.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionPlanChangeError'
        '415':
          description: Content-Type is not application/json.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Detail'
        '500':
          description: Internal error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Detail'
        '502':
          description: The current subscription could not be read from Shopify.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Detail'
        '503':
          description: The plan catalogue could not be read.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Detail'
components:
  schemas:
    SubscriptionPlanChangeRequest:
      type: object
      properties:
        products:
          type: array
          items:
            type: string
            enum:
              - search
              - recs
              - vm
          minItems: 1
          description: >-
            The paid products wanted (duplicates ignored). Never empty: DELETE
            /settings/subscription is the way to the free tier.
        size:
          type: string
          enum:
            - s
            - m
            - l
        interval:
          $ref: '#/components/schemas/AppPricingInterval'
        return_url:
          type: string
          format: uri
          description: >-
            Where Shopify sends the merchant after they approve or decline the
            charge.
        keep_collection_ids:
          type: array
          items:
            type: string
            minLength: 1
            pattern: ^[^,]*$
          description: >-
            Only read when the target plan lacks Merchandising: the collections
            that stay active (at most 3). Omitted = keep everything, allowed
            only when the active set already fits.
        discount:
          $ref: '#/components/schemas/SubscriptionDiscount'
      required:
        - products
        - size
        - interval
        - return_url
    SubscriptionPlanChangeResponse:
      type: object
      properties:
        confirmation_url:
          type: string
          description: Send the merchant here to approve the charge in Shopify.
        change:
          type: string
          enum:
            - subscribe
            - upgrade
            - downgrade
            - lateral
        applies:
          type: string
          enum:
            - immediately
            - next_billing_cycle
        trial_days:
          type: integer
        app_subscription_id:
          type:
            - string
            - 'null'
        plan:
          type: object
          properties:
            plan_id:
              type: string
            display_name:
              type: string
            products:
              type: array
              items:
                type: string
                enum:
                  - search
                  - recs
                  - vm
            size:
              type: string
              enum:
                - s
                - m
                - l
          required:
            - plan_id
            - display_name
            - products
            - size
      required:
        - confirmation_url
        - change
        - applies
        - trial_days
        - app_subscription_id
        - plan
    SubscriptionPlanChangeError:
      type: object
      properties:
        detail:
          type: string
        code:
          type: string
          enum:
            - plan_not_found
            - plan_not_sellable
            - already_subscribed
            - currency_mismatch
            - too_many_collections
        active:
          type: integer
          description: 'too_many_collections: collections syncing back now.'
        kept:
          type: integer
        max:
          type: integer
      required:
        - detail
        - code
    Detail:
      type: object
      properties:
        detail:
          type: string
      required:
        - detail
      description: 'Every 4xx/5xx body: `{detail}`.'
    AppPricingInterval:
      type: string
      enum:
        - EVERY_30_DAYS
        - ANNUAL
    SubscriptionDiscount:
      type:
        - object
        - 'null'
      properties:
        percentage:
          type: number
          exclusiveMinimum: 0
          maximum: 1
          description: Fraction off the price, e.g. 0.2 for 20%.
        duration_intervals:
          type: integer
          exclusiveMinimum: 0
          description: How many billing intervals the discount lasts.
      required:
        - percentage
        - duration_intervals
      description: Superuser sessions only; a merchant session sending one is 403.
  securitySchemes:
    ShopifySessionToken:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Shopify App Bridge session token of the embedded Depict: Search &
        Merchandising app. The shop in the token determines the merchant;
        merchant_id parameters must belong to that shop.

````