openapi: 3.0.1
info:
  title: External APIs
  description: >-
    Comprehensive API documentation for managing subscriptions, payments, and
    related operations. These APIs allow you to programmatically manage
    subscription lifecycles, handle payments, configure products, and integrate
    subscription functionality into your applications.
  version: 0.0.1
servers:
  - url: https://subscription-admin.appstle.com
tags:
  - name: Subscription Management
    description: >-
      Core APIs for managing the complete subscription lifecycle including
      creation, updates, pausing, resuming, and cancellation of subscriptions.
  - name: Subscription Payments
    description: >-
      APIs for managing subscription payment methods, processing payments,
      handling payment retries, and updating billing information.
  - name: Subscription Contracts
    description: >-
      APIs for managing subscription contracts including delivery schedules,
      pricing, order notes, billing cycles, and shipping addresses.
  - name: Subscription Products
    description: >-
      APIs for managing products within subscriptions including adding,
      removing, updating quantities, and swapping products.
  - name: Billing & Payments
    description: >-
      APIs for handling billing operations, payment processing, and financial
      transactions related to subscriptions.
  - name: Subscription Discounts
    description: >-
      APIs for managing discounts and promotional codes applied to
      subscriptions.
  - name: Subscription One-Time Products
    description: >-
      APIs for managing one-time add-on products that can be purchased alongside
      recurring subscription items.
  - name: Subscription Plans
    description: >-
      APIs for managing subscription plans, pricing tiers, and plan
      configurations.
  - name: Build-a-Box & Bundles
    description: >-
      APIs for managing customizable product boxes and bundles where customers
      can select multiple items.
  - name: Product Catalog
    description: >-
      APIs for managing the product catalog including product information,
      variants, and inventory.
  - name: Operations & Settings
    description: >-
      APIs for managing operational settings, configurations, and administrative
      functions.
  - name: Customer Portal
    description: >-
      APIs powering the customer-facing portal where subscribers can manage
      their own subscriptions.
  - name: Customers
    description: APIs for managing customer information, profiles, and account details.
paths:
  /api/external/v2/subscription-contracts-update-delivery-price:
    put:
      tags:
        - Subscription Management
      summary: Update delivery price for a subscription contract
      description: >-
        Updates the fixed delivery price for all future orders in a subscription
        contract. This allows manual override of calculated shipping rates with
        a custom delivery fee.


        **Key Features:**

        - Sets a fixed delivery price regardless of shipping calculations

        - Overrides any dynamic shipping rates from carriers

        - Applies to all future orders immediately

        - Can set to 0 for free delivery

        - Automatically handles invalid discount codes

        - Tracks price changes in activity log


        **How Delivery Pricing Works:**

        - **Calculated Rates**: Default behavior uses carrier rates and rules

        - **Manual Override**: This endpoint sets a fixed price

        - **Precedence**: Manual price overrides all calculations

        - **Currency**: Always in shop's base currency


        **Common Use Cases:**

        - **Free Shipping Promotions**: Set to 0.00

        - **Flat Rate Shipping**: Fixed price regardless of location

        - **VIP Customer Rates**: Special shipping prices

        - **Subscription Perks**: Reduced delivery fees

        - **Price Corrections**: Fix shipping calculation errors

        - **Regional Adjustments**: Custom rates for specific areas


        **Impact on Orders:**

        - Next order uses new delivery price

        - All future recurring orders affected

        - Existing orders keep original pricing

        - Customer sees updated total immediately

        - No recalculation on address changes


        **Price Validation:**

        - Must be a valid decimal number

        - Can be 0 for free shipping

        - No maximum limit enforced

        - Negative values typically rejected by Shopify

        - Currency precision respected (e.g., 2 decimals for USD)


        **Side Effects:**

        - Invalid discount codes automatically removed

        - Activity log created with old/new prices

        - No customer email notification sent

        - Shipping tax recalculated if applicable

        - Total order value updated


        **Reverting to Calculated Rates:**

        To restore dynamic shipping calculations:

        1. Use the sync shipping price endpoint

        2. Or update delivery method

        3. Manual price remains until explicitly changed


        **Important Notes:**

        - Price includes all delivery charges (shipping + handling)

        - Does not affect delivery method or speed

        - Consider customer communication for increases

        - May affect subscription profitability

        - Some payment methods may decline on total changes


        **Authentication:** Requires valid X-API-Key header
      operationId: updateDeliveryPrice
      parameters:
        - name: contractId
          in: query
          description: The unique identifier of the subscription contract
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: deliveryPrice
          in: query
          description: >-
            New delivery price to be applied to the subscription contract. This
            is a fixed price that overrides any calculated shipping rates. Set
            to 0 for free delivery. Price must be in the shop's base currency.
          required: true
          schema:
            maximum: 99999.99
            minimum: 0
            type: number
            format: double
          example: 9.99
        - name: api_key
          in: query
          description: Deprecated API Key parameter; use the X-API-Key header instead
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
      responses:
        '200':
          description: >-
            Successfully updated delivery price and returned the updated
            subscription contract
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                      displayName: John Doe
                    deliveryPrice:
                      amount: '9.99'
                      currencyCode: USD
                    deliveryMethod:
                      __typename: SubscriptionDeliveryMethodShipping
                      shippingOption:
                        title: Standard Shipping
                        code: STANDARD
                        presentmentTitle: Standard Shipping (5-7 days)
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172011164
                            title: Monthly Subscription Box
                            currentPrice:
                              amount: '39.99'
                              currencyCode: USD
                    totalPrice:
                      amount: '49.98'
                      currencyCode: USD
        '400':
          description: >-
            Invalid contract ID, delivery price, or update failure due to
            business logic constraints
          content:
            application/json:
              examples:
                Invalid Delivery Price:
                  description: Invalid Delivery Price
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid delivery price
                    status: 400
                    detail: Delivery price must be a valid positive number
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Contract does not exist
                    status: 400
                    detail: No subscription contract found with ID 123456789
                Negative Price Error:
                  description: Negative Price Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Delivery price cannot be negative
                    status: 400
                    detail: Delivery price must be 0 or greater
                No Delivery Method:
                  description: No Delivery Method
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:No delivery method configured
                    status: 400
                    detail: >-
                      Cannot set delivery price for subscriptions without
                      delivery method
        '401':
          description: Authentication required or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to update the delivery price
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to modify delivery pricing
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: >-
            Delivery price update failed due to invalid input or system
            constraints
          content:
            application/json:
              examples:
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to update delivery price
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
                Invalid Discount Code Removed:
                  description: Invalid Discount Code Removed
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Delivery price updated with warnings
                    status: 422
                    detail: >-
                      Delivery price updated successfully, but invalid discount
                      code 'FREESHIP' was automatically removed
                Currency Precision Error:
                  description: Currency Precision Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Invalid price precision
                    status: 422
                    detail: >-
                      Price 9.999 exceeds currency precision for USD (2 decimal
                      places)
  /api/external/v2/subscription-groups:
    get:
      tags:
        - Subscription Plans
      summary: Get all subscription groups
      description: >-
        Retrieves a list of all subscription groups (selling plan groups)
        configured in the store. This endpoint provides a complete overview of
        all subscription offerings available.


        **Response includes:**

        - All subscription groups with their configurations

        - Complete selling plan details for each group

        - Product and variant assignments (as JSON strings)

        - Discount configurations and tiers

        - Member restrictions and settings


        **Use Cases:**

        - Display all subscription options in a custom interface

        - Audit subscription configurations

        - Export subscription data for analysis

        - Synchronize with external systems


        **Performance Notes:**

        - Returns all groups in a single response (no pagination)

        - Response size grows with number of groups and plans

        - Product/variant lists are JSON-encoded strings within the response


        **Authentication:** Requires valid X-API-Key header
      operationId: getAllSubscriptionGroupsV2External
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      responses:
        '200':
          description: Successfully retrieved subscription groups
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionGroupDTO'
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Unauthorized
                status: 401
                detail: Invalid or missing API key
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionGroupV2DTO'
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-server-error
                title: Internal Server Error
                status: 500
                detail: Error retrieving subscription groups from Shopify
    put:
      tags:
        - Subscription Plans
      summary: Update subscription group details and product assignments
      description: >-
        Updates an existing subscription group (selling plan group) including
        its name, selling plans configuration, and optionally manages
        product/variant assignments. This endpoint provides comprehensive update
        capabilities for both the subscription group structure and its product
        associations.


        **Key Capabilities:**

        - Update subscription group name

        - Modify existing selling plan configurations (discounts, frequencies,
        trials, etc.)

        - Add or remove products/variants through updateProducts and
        deleteProducts fields

        - Cannot add or remove selling plans - only modify existing ones

        - Automatically handles complex discount transitions for free trials and
        prepaid plans

        - Updates delivery profile associations if changed

        - Triggers asynchronous operations for metafield updates and free
        product checks


        **Important Notes:**

        - The 'id' field is required and must match an existing subscription
        group

        - For each selling plan in subscriptionPlans array, provide 'idNew' with
        the existing selling plan ID

        - Plan modifications maintain the same selling plan ID in Shopify

        - Product/variant updates are processed after group details are updated

        - Large product updates (allProduct=true) run asynchronously


        **Selling Plan Updates:**

        - Can change discount amounts, types, and cycles

        - Can modify billing/delivery frequencies

        - Can add/remove free trials

        - Can change member restrictions and tags

        - Can update specific day delivery settings

        - Can modify min/max cycles


        **Authentication:** Requires valid X-API-Key header
      operationId: updateSubscriptionGroupDetailsV2
      parameters:
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      requestBody:
        description: >-
          Complete subscription group update request including group details,
          selling plans, and optional product management
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionGroupV2DTO'
            examples:
              Update Group Name and Discount:
                description: Update Group Name and Discount
                value:
                  id: 123456789
                  groupName: Premium Coffee Club - Updated
                  subscriptionPlans:
                    - idNew: gid://shopify/SellingPlan/111111
                      frequencyName: Monthly Delivery
                      frequencyDescription: Updated description with better savings
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 15
                      afterCycle1: 0
                      minCycles: 3
              Add Free Trial to Existing Plan:
                description: Add Free Trial to Existing Plan
                value:
                  id: 123456789
                  groupName: Try Before You Subscribe
                  subscriptionPlans:
                    - idNew: gid://shopify/SellingPlan/111111
                      frequencyName: Monthly with Trial
                      frequencyDescription: Try free for 7 days
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      freeTrialEnabled: true
                      freeTrialCount: 7
                      freeTrialInterval: DAY
                      discountOffer: 100
                      discountOffer2: 10
                      minCycles: 3
              Update Multiple Plans with Product Changes:
                description: Update Multiple Plans with Product Changes
                value:
                  id: 123456789
                  groupName: Flexible Subscription Options
                  subscriptionPlans:
                    - idNew: gid://shopify/SellingPlan/111111
                      frequencyName: Weekly - Best Value
                      frequencyDescription: Maximum savings for frequent deliveries
                      frequencyCount: 1
                      frequencyInterval: WEEK
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 20
                      afterCycle1: 0
                    - idNew: gid://shopify/SellingPlan/222222
                      frequencyName: Monthly - Popular
                      frequencyDescription: Our most popular option
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 15
                      afterCycle1: 0
                  updateProducts:
                    productDetails: '[{"id":987654323},{"id":987654324}]'
                    variantDetails: '[{"id":123456790}]'
                  deleteProducts:
                    productIds:
                      - 987654321
                    variantIds:
                      - 123456789
              Convert to Prepaid Plan:
                description: Convert to Prepaid Plan
                value:
                  id: 123456789
                  groupName: Quarterly Prepaid Savings
                  subscriptionPlans:
                    - idNew: gid://shopify/SellingPlan/111111
                      frequencyName: 3-Month Prepaid Plan
                      frequencyDescription: Pay upfront for 3 months and save 25%
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO_PREPAID
                      payAsYouGoPrepaidBillingFrequencyCount: 3
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 25
                      maxCycles: 12
              Update with Complex Discount Cycles:
                description: Update with Complex Discount Cycles
                value:
                  id: 123456789
                  groupName: Loyalty Rewards Program
                  subscriptionPlans:
                    - idNew: gid://shopify/SellingPlan/111111
                      frequencyName: Monthly Loyalty Plan
                      frequencyDescription: Increasing rewards for loyal customers
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 10
                      afterCycle1: 0
                      discountEnabled2: true
                      discountType2: PERCENTAGE
                      discountOffer2: 15
                      afterCycle2: 3
                      appstleCycles:
                        - afterCycle: 6
                          discountType: PERCENTAGE
                          value: 20
                        - afterCycle: 12
                          discountType: FREE_PRODUCT
                          freeVariantId: 42549172011164
                          repeatingCycle: true
                          repeatingNumberOfCycle: 6
                      minCycles: 6
              Add All Products from Collection:
                description: Add All Products from Collection
                value:
                  id: 123456789
                  groupName: Coffee Collection Subscription
                  subscriptionPlans:
                    - idNew: gid://shopify/SellingPlan/111111
                      frequencyName: Monthly Coffee Box
                      frequencyDescription: All coffee products eligible
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 15
                      afterCycle1: 0
                  updateProducts:
                    allProduct: true
                    collectionId: '987654321'
              Update Member-Only Settings:
                description: Update Member-Only Settings
                value:
                  id: 123456789
                  groupName: VIP Member Exclusive
                  subscriptionPlans:
                    - idNew: gid://shopify/SellingPlan/111111
                      frequencyName: VIP Monthly Plan
                      frequencyDescription: Exclusive access for VIP members
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      memberOnly: true
                      memberInclusiveTags: vip,platinum,gold,silver
                      memberExclusiveTags: blocked,trial
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 30
                      afterCycle1: 0
        required: true
      responses:
        '200':
          description: Subscription group updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
        '400':
          description: Invalid request parameters or validation error
          content:
            application/json:
              examples:
                Missing ID:
                  description: Missing ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: Invalid id
                    errorKey: idnull
                Invalid Product Update:
                  description: Invalid Product Update
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: >-
                      At least one of the Product Id(s) or Variant Id(s) is
                      required
                Duplicate Group Name:
                  description: Duplicate Group Name
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: >-
                      UserGeneratedError: A selling plan group with this name
                      already exists
                Invalid Selling Plan:
                  description: Invalid Selling Plan
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: 'UserGeneratedError: Selling plan not found'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
        '403':
          description: Insufficient permissions to update subscription groups
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
        '404':
          description: Subscription group not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Not Found
                status: 404
                detail: Subscription group with ID 999999 not found
        '422':
          description: Shopify API error or business rule violation
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: Unprocessable Entity
                status: 422
                detail: >-
                  UserGeneratedError: Cannot update selling plan with active
                  subscriptions
    post:
      tags:
        - Subscription Plans
      summary: Create a new subscription group (selling plan group)
      description: >-
        Creates a new subscription group with one or more selling plans in
        Shopify. A subscription group is a container for selling plans that can
        be applied to products and variants. Each group can contain multiple
        plans with different frequencies, discounts, and delivery schedules.


        **Key Features:**

        - Create multiple subscription plans within a single group

        - Configure complex discount tiers (up to 2 levels + custom cycles)

        - Set up free trials with automatic discount transitions

        - Define prepaid plans (PAY_AS_YOU_GO_PREPAID) with custom billing
        cycles

        - Configure member-only plans with tag-based access control

        - Set specific delivery dates (e.g., 15th of every month)

        - Add all products from store or specific collection automatically


        **Discount Configuration:**

        - First discount tier: Applied from a specific cycle (afterCycle1)

        - Second discount tier: Applied from another cycle (afterCycle2)

        - Additional cycles: Configure via appstleCycles for complex scenarios

        - Free trials: Automatically configure 100% discount for trial period


        **Product Assignment:**

        - Assign specific products via productIds field in request body

        - Assign specific variants via variantIds field in request body

        - Use isAddAllProduct=true to add all store products

        - Use collectionId with isAddAllProduct=true to add all products from a
        collection


        **Authentication:** Requires valid X-API-Key header
      operationId: createSubscriptionGroupV2External
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: isAddAllProduct
          in: query
          description: >-
            Add all products from the store or collection to this subscription
            group. When true without collectionId: adds all active products in
            the store. When true with collectionId: adds all products from the
            specified collection. This operation runs asynchronously and may
            take time for large catalogs.
          required: false
          schema:
            type: boolean
            default: false
          example: false
        - name: collectionId
          in: query
          description: >-
            Shopify collection ID to limit product addition when isAddAllProduct
            is true. Format: numeric ID without gid prefix (e.g., '123456789'
            not 'gid://shopify/Collection/123456789')
          required: false
          schema:
            type: string
            default: ''
          example: 123456789
      requestBody:
        description: >-
          Complete subscription group configuration including name, plans, and
          product assignments
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionGroupV2DTO'
            examples:
              Simple Monthly Subscription:
                description: Simple Monthly Subscription
                value:
                  groupName: Monthly Coffee Subscription
                  subscriptionPlans:
                    - frequencyName: Delivered Monthly
                      frequencyDescription: Fresh coffee delivered every month
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 10
                      afterCycle1: 0
                      minCycles: 3
                  productIds: '[{"id":987654321}]'
              Multi-tier Discount Plan:
                description: Multi-tier Discount Plan
                value:
                  groupName: Premium Subscription Plans
                  subscriptionPlans:
                    - frequencyName: Weekly Delivery
                      frequencyDescription: Save more with weekly deliveries
                      frequencyCount: 1
                      frequencyInterval: WEEK
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 5
                      afterCycle1: 0
                      discountEnabled2: true
                      discountType2: PERCENTAGE
                      discountOffer2: 10
                      afterCycle2: 4
                      minCycles: 4
                      maxCycles: 52
                      upcomingOrderEmailBuffer: 3
                    - frequencyName: Monthly Delivery
                      frequencyDescription: Convenient monthly shipments
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 10
                      afterCycle1: 0
                      discountEnabled2: true
                      discountType2: PERCENTAGE
                      discountOffer2: 15
                      afterCycle2: 6
                      appstleCycles:
                        - afterCycle: 12
                          discountType: PERCENTAGE
                          value: 20
                          repeatingCycle: true
                  productIds: '[{"id":987654321},{"id":987654322}]'
                  variantIds: '[{"id":123456789}]'
              Free Trial Subscription:
                description: Free Trial Subscription
                value:
                  groupName: Try Before You Subscribe
                  subscriptionPlans:
                    - frequencyName: Monthly with 14-Day Trial
                      frequencyDescription: Try free for 14 days, then save 15%
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      freeTrialEnabled: true
                      freeTrialCount: 14
                      freeTrialInterval: DAY
                      discountOffer: 100
                      discountOffer2: 15
                      minCycles: 3
                      inventoryPolicyReserve: ON_FULFILLMENT
                  productIds: '[{"id":987654321}]'
              Prepaid Quarterly Plan:
                description: Prepaid Quarterly Plan
                value:
                  groupName: Prepaid Quarterly Plans
                  subscriptionPlans:
                    - frequencyName: 3-Month Prepaid
                      frequencyDescription: Pay for 3 months upfront and save 20%
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO_PREPAID
                      payAsYouGoPrepaidBillingFrequencyCount: 3
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 20
                      maxCycles: 12
                  productIds: '[{"id":987654321}]'
              Member-Only Subscription:
                description: Member-Only Subscription
                value:
                  groupName: VIP Member Subscriptions
                  subscriptionPlans:
                    - frequencyName: VIP Monthly Plan
                      frequencyDescription: Exclusive pricing for VIP members
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      memberOnly: true
                      memberInclusiveTags: vip,gold-member,platinum-member
                      memberExclusiveTags: blocked,suspended
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 25
                      afterCycle1: 0
                  productIds: '[{"id":987654321}]'
              Specific Day Delivery:
                description: Specific Day Delivery
                value:
                  groupName: 15th of Month Delivery
                  subscriptionPlans:
                    - frequencyName: Monthly on the 15th
                      frequencyDescription: Delivered on the 15th of every month
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      frequencyType: ON_SPECIFIC_DAY
                      specificDayEnabled: true
                      specificDayValue: 15
                      cutOff: 5
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 10
                      afterCycle1: 0
                  productIds: '[{"id":987654321}]'
              Complex Discount with Free Product:
                description: Complex Discount with Free Product
                value:
                  groupName: Loyalty Rewards Subscription
                  subscriptionPlans:
                    - frequencyName: Monthly with Rewards
                      frequencyDescription: Earn rewards with every order
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 10
                      afterCycle1: 0
                      appstleCycles:
                        - afterCycle: 6
                          discountType: FREE_PRODUCT
                          freeVariantId: 42549172011164
                          preventDuplicationFreeProduct: true
                        - afterCycle: 12
                          discountType: SHIPPING
                          value: 100
                          repeatingCycle: true
                          repeatingNumberOfCycle: 3
                  productIds: '[{"id":987654321}]'
        required: true
      responses:
        '201':
          description: Subscription group created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
        '400':
          description: Invalid request or validation error
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Validation Error
                status: 400
                detail: Group name is required
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Unauthorized
                status: 401
                detail: Invalid or missing API key
        '403':
          description: Insufficient permissions to create subscription groups
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Forbidden
                status: 403
                detail: You do not have permission to create subscription groups
        '422':
          description: Shopify API error or business rule violation
          content:
            application/json:
              examples:
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unprocessable Entity
                    status: 422
                    detail: 'Shopify API error: Product not found'
                Duplicate Plan Name:
                  description: Duplicate Plan Name
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unprocessable Entity
                    status: 422
                    detail: A selling plan group with this name already exists
  /api/external/v2/subscription-groups/{id}/remove-products:
    put:
      tags:
        - Subscription Plans
      summary: Remove products or variants from a subscription group
      description: >-
        Removes specified products and/or variants from an existing subscription
        group (selling plan group). This endpoint allows selective removal of
        products without affecting the group's configuration or other product
        assignments.


        **Key Features:**

        - Remove multiple products and variants in a single request

        - Remove all products from a specific collection

        - Silently ignores products/variants not currently in the group

        - Preserves subscription group configuration and settings

        - Updates synchronously and returns the modified group


        **Collection Removal:**

        - When collectionId is provided, fetches and removes all products from
        that collection

        - Collection processing is limited to 5000 products maximum

        - Collection removal is additive to any explicitly specified
        productIds/variantIds


        **Important Notes:**

        - Removing products does NOT affect existing active subscriptions

        - Can remove all products, leaving an empty subscription group

        - Products/variants not in the group are silently ignored

        - Use numeric IDs without gid:// prefix for products and variants


        **Authentication:** Requires valid X-API-Key header
      operationId: deleteProductsOrVariantsV2
      parameters:
        - name: id
          in: path
          description: Subscription group ID (numeric ID)
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: productIds
          in: query
          description: >-
            Comma-separated list of product IDs to remove. Use numeric IDs
            without gid:// prefix.
          required: false
          schema:
            pattern: ^\d+(,\d+)*$
            type: string
          example: 987654321,987654322
        - name: variantIds
          in: query
          description: >-
            Comma-separated list of variant IDs to remove. Use numeric IDs
            without gid:// prefix.
          required: false
          schema:
            pattern: ^\d+(,\d+)*$
            type: string
          example: 123456789,123456790
        - name: collectionId
          in: query
          description: >-
            Shopify collection ID. When provided, removes all products from this
            collection (up to 5000 products). This is in addition to any
            explicitly specified productIds/variantIds.
          required: false
          schema:
            type: integer
            format: int64
          example: 287654321
        - name: deleteAllProductsAndVariants
          in: query
          description: >-
            Set to true to delete all products and their variants. Defaults to
            false.
          required: false
          schema:
            type: boolean
          example: false
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      responses:
        '200':
          description: Products/variants successfully removed from subscription group
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: 123456789
                    groupName: Monthly Coffee Subscription
                    productCount: 5
                    productVariantCount: 15
                    productIds: >-
                      [{"id":987654322,"title":"Organic Dark
                      Roast"},{"id":987654323,"title":"Colombian Single
                      Origin"}]
                    variantIds: '[{"id":123456790,"title":"500g Bag"}]'
                    subscriptionPlans:
                      - id: gid://shopify/SellingPlan/111111
                        frequencyName: Delivered Monthly
                        frequencyDescription: Get fresh coffee delivered to your door every month
                        frequencyCount: 1
                        frequencyInterval: MONTH
                        discountEnabled: true
                        discountType: PERCENTAGE
                        discountOffer: 10
        '400':
          description: Invalid request parameters
          content:
            application/json:
              examples:
                Invalid Subscription Group ID:
                  description: Invalid Subscription Group ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: Invalid id
                    errorKey: idnull
                No Products or Variants Provided:
                  description: No Products or Variants Provided
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: >-
                      At least one of the Product Id(s) or Variant Id(s) is
                      required
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
        '403':
          description: Insufficient permissions to modify subscription groups
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
        '404':
          description: Subscription group not found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
  /api/external/v2/subscription-groups/{id}/add-products:
    put:
      tags:
        - Subscription Plans
      summary: Add products or variants to an existing subscription group
      description: >-
        Adds one or more products and/or product variants to an existing
        subscription group (selling plan group). This endpoint provides a simple
        way to expand the product catalog eligible for subscription without
        modifying the group's configuration or existing product assignments.


        **Key Features:**

        - Add multiple products and variants in a single request

        - Preserves existing product and variant assignments

        - Maintains the order of products as provided

        - Updates delivery profiles automatically if needed

        - Synchronously updates Shopify and returns the updated group

        - Optional response enhancement with added products information


        **Important Notes:**

        - Product IDs should be numeric Shopify product IDs without the gid://
        prefix

        - Variant IDs should be numeric Shopify variant IDs without the gid://
        prefix

        - Adding products also makes all their variants eligible for
        subscription

        - Adding specific variants limits subscription eligibility to those
        variants only

        - Duplicate products/variants are handled gracefully by Shopify

        - URL length limits apply to the comma-separated lists (use bulk
        endpoint for large additions)

        - Include 'x-return-short-response: true' header to get only added
        products/variants information in response


        **Use Cases:**

        - Launch new products with subscription options

        - Add seasonal items to existing subscription groups

        - Enable subscription for specific product variants

        - Expand subscription eligibility without changing plan configurations

        - Track which products were added in the current request


        **Authentication:** Requires valid X-API-Key header
      operationId: addProductsOrVariants
      parameters:
        - name: id
          in: path
          description: Subscription group ID (numeric ID)
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: productIds
          in: query
          description: >-
            Comma-separated list of Shopify product IDs to add. Adding a product
            makes all its variants eligible for subscription. Use numeric IDs
            only (e.g., '987654321,987654322,987654323')
          required: false
          schema:
            pattern: ^\d+(,\d+)*$
            type: string
          example: 987654321,987654322,987654323
        - name: variantIds
          in: query
          description: >-
            Comma-separated list of Shopify variant IDs to add. Use this to
            enable subscription for specific variants only. Use numeric IDs only
            (e.g., '123456789,123456790,123456791')
          required: false
          schema:
            pattern: ^\d+(,\d+)*$
            type: string
          example: 123456789,123456790
        - name: x-return-short-response
          in: header
          description: >-
            Header to indicate if response should return only added products ID
            information. Set to 'true' for minimal response, any other value or
            omitted for full response.
          required: false
          schema:
            type: boolean
            default: false
          example: false
      responses:
        '200':
          description: Products/variants successfully added to subscription group
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/SubscriptionGroupV2DTO'
                  - $ref: '#/components/schemas/AddedProductsResponseDTO'
              examples:
                Success Response (Standard):
                  description: Success Response (Standard)
                  value:
                    id: 123456789
                    groupName: Monthly Coffee Subscription
                    productCount: 10
                    productVariantCount: 35
                    productIds: >-
                      [{"id":987654321,"title":"Premium Coffee
                      Blend"},{"id":987654322,"title":"Organic Dark
                      Roast"},{"id":987654323,"title":"Colombian Single
                      Origin"}]
                    variantIds: >-
                      [{"id":123456789,"title":"250g
                      Bag"},{"id":123456790,"title":"500g Bag"}]
                    subscriptionPlans:
                      - id: gid://shopify/SellingPlan/111111
                        frequencyName: Delivered Monthly
                        frequencyDescription: Get fresh coffee delivered to your door every month
                        frequencyCount: 1
                        frequencyInterval: MONTH
                        discountEnabled: true
                        discountType: PERCENTAGE
                        discountOffer: 10
                        planType: PAY_AS_YOU_GO
                Success Response (with x-return-short-response header):
                  description: Success Response (with x-return-short-response header)
                  value:
                    addedProductIds:
                      - 987654321
                      - 987654322
                    addedVariantIds:
                      - 123456789
        '400':
          description: Invalid request parameters
          content:
            application/json:
              examples:
                Invalid Subscription Group ID:
                  description: Invalid Subscription Group ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: Invalid id
                    errorKey: idnull
                No Products or Variants Provided:
                  description: No Products or Variants Provided
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: >-
                      At least one of the Product Id(s) or Variant Id(s) is
                      required
                Invalid Product Format:
                  description: Invalid Product Format
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: Invalid product ID format. Use numeric IDs only.
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Unauthorized
                status: 401
                detail: Invalid or missing API key
        '403':
          description: Insufficient permissions to modify subscription groups
          content:
            '*/*':
              schema:
                type: object
        '404':
          description: Subscription group not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Not Found
                status: 404
                detail: Subscription group with ID 999999 not found
        '422':
          description: Shopify API error
          content:
            application/json:
              examples:
                Product Not Found:
                  description: Product Not Found
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unprocessable Entity
                    status: 422
                    detail: Product with ID 987654321 not found in Shopify
                Variant Not Found:
                  description: Variant Not Found
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unprocessable Entity
                    status: 422
                    detail: Product variant with ID 123456789 not found
  /api/external/v2/subscription-groups/remove-products:
    put:
      tags:
        - Subscription Plans
      summary: Remove products or variants from ALL subscription groups
      description: >-
        Removes specified products and/or variants from ALL subscription groups
        in the store. This is a powerful bulk operation that affects every
        subscription group simultaneously.


        **⚠️ WARNING:** This operation:

        - Affects ALL subscription groups in your store

        - Cannot be easily undone

        - Processes synchronously (may timeout for stores with many groups)

        - Does NOT affect existing active subscriptions


        **Use Cases:**

        - Discontinuing products from all subscription offerings

        - Removing seasonal items from all groups

        - Cleaning up deleted products from subscription groups

        - Compliance-driven product removals


        **Important Considerations:**

        - Each group is updated individually

        - If any group update fails, previous groups remain updated

        - Large operations may take significant time

        - Consider using individual group removal for better control


        **Authentication:** Requires valid X-API-Key header
      operationId: deleteProductsOrVariantsInAllSubscriptionGroupPlan
      parameters:
        - name: productIds
          in: query
          description: >-
            Comma-separated list of product IDs to remove from all groups. Use
            numeric IDs without gid:// prefix.
          required: false
          schema:
            pattern: ^\d+(,\d+)*$
            type: string
          example: 987654321,987654322
        - name: variantIds
          in: query
          description: >-
            Comma-separated list of variant IDs to remove from all groups. Use
            numeric IDs without gid:// prefix.
          required: false
          schema:
            pattern: ^\d+(,\d+)*$
            type: string
          example: 123456789,123456790
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      responses:
        '200':
          description: Products/variants successfully removed from all subscription groups
          content:
            application/json:
              schema:
                type: string
              example: Product Deleted Successfully
        '400':
          description: Invalid request parameters
          content:
            application/json:
              examples:
                No Products or Variants Provided:
                  description: No Products or Variants Provided
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bad Request
                    status: 400
                    detail: >-
                      At least one of the Product Id(s) or Variant Id(s) is
                      required
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                type: string
        '403':
          description: Insufficient permissions to modify subscription groups
          content:
            '*/*':
              schema:
                type: string
        '500':
          description: Internal server error - some groups may have been updated
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-server-error
                title: Internal Server Error
                status: 500
                detail: >-
                  Error processing some subscription groups. Partial updates may
                  have occurred.
  /api/external/v2/subscription-contracts-update-status:
    put:
      tags:
        - Subscription Management
      summary: Update subscription contract status
      description: >-
        Updates the status of a subscription contract to ACTIVE, PAUSED, or
        CANCELLED. This endpoint manages the lifecycle of subscriptions with
        automatic state tracking and notifications.


        **Status Transitions:**

        - **ACTIVE**: Resumes a paused subscription, enabling future billing and
        deliveries

        - **PAUSED**: Temporarily suspends all billing and deliveries until
        manually resumed

        - **CANCELLED**: Permanently terminates the subscription (irreversible)


        **Key Features:**

        - Validates status transitions (prevents same-status updates)

        - Tracks status change timestamps for audit trails

        - Sends automated email notifications to customers

        - Creates detailed activity logs for each status change

        - Handles concurrent modifications with automatic retry

        - Adjusts next billing date when resuming subscriptions


        **Permission Requirements (Customer Portal):**

        When called from customer portal context:

        - PAUSED status requires 'pauseResumeSub' permission

        - ACTIVE status (resuming) requires 'resumeSub' permission  

        - CANCELLED status requires 'cancelSub' permission

        - External API calls bypass these permission checks


        **Status Change Side Effects:**

        - **Activating**: Recalculates next billing date, marks activation
        timestamp

        - **Pausing**: Stops all scheduled orders, marks pause timestamp

        - **Cancelling**: Terminates subscription permanently, marks
        cancellation timestamp


        **Error Recovery:**

        The system automatically handles:

        - Invalid discount codes by removing them and retrying

        - Concurrent modifications by retrying the operation

        - This ensures reliable status updates in production environments


        **Important Notes:**

        - Status values are case-insensitive

        - Cancelled subscriptions cannot be reactivated

        - Paused subscriptions retain all settings and can be resumed

        - Email notifications are sent automatically unless internally
        suppressed


        **Authentication:** Requires valid X-API-Key header
      operationId: updateStatusV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to update. Provide the numeric ID without
            the gid:// prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: status
          in: query
          description: New status for the subscription contract. Case-insensitive.
          required: true
          schema:
            type: string
            enum:
              - ACTIVE
              - PAUSED
              - CANCELLED
              - active
              - paused
              - cancelled
          examples:
            Pause subscription:
              description: Pause subscription
              value: PAUSED
            Resume subscription:
              description: Resume subscription
              value: ACTIVE
            Cancel subscription:
              description: Cancel subscription
              value: CANCELLED
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      responses:
        '204':
          description: Status successfully updated - No content returned
          headers:
            X-Alert:
              description: Success message
              style: simple
              schema:
                type: string
                example: Subscription Updated
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Invalid Status Value:
                  description: Invalid Status Value
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Invalid subscription status
                    status: 400
                    detail: 'Status must be one of: ACTIVE, PAUSED, CANCELLED'
                Same Status Update:
                  description: Same Status Update
                  value:
                    type: https://example.com/errors/bad-request
                    title: Contract already in same status
                    status: 400
                    detail: Subscription is already ACTIVE. No update needed.
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: No contract found for status update
                    status: 400
                    detail: Subscription contract with ID 123456789 not found
                Invalid Contract ID:
                  description: Invalid Contract ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid contract ID
                    status: 400
                    detail: Contract ID must be a positive number
                Reactivate Cancelled Subscription:
                  description: Reactivate Cancelled Subscription
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Cannot reactivate cancelled
                      subscription
                    status: 400
                    detail: >-
                      Cancelled subscriptions cannot be reactivated. Please
                      create a new subscription.
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription status
          content:
            application/json:
              examples:
                API Key Permissions:
                  description: API Key Permissions
                  value:
                    type: https://example.com/errors/forbidden
                    title: Insufficient permissions
                    status: 403
                    detail: >-
                      API key does not have permission to modify subscription
                      contracts
                Customer Portal - Pause Permission:
                  description: Customer Portal - Pause Permission
                  value:
                    type: https://example.com/errors/forbidden
                    title: Customer permission denied
                    status: 403
                    detail: Customer does not have permission to pause subscriptions
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: >-
                  Subscription contract with ID 123456789 not found in the
                  system
        '422':
          description: Unable to process the status update due to Shopify API constraints
          content:
            application/json:
              examples:
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to update subscription status
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
                Invalid Discount Code:
                  description: Invalid Discount Code
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Contract draft discount with title SUMMER20 is invalid
                    status: 422
                    detail: >-
                      Invalid discount code detected. System will automatically
                      remove and retry.
  /api/external/v2/subscription-contracts-update-shipping-address:
    put:
      tags:
        - Subscription Management
      summary: Update subscription delivery address and method
      description: >-
        Updates the shipping address or delivery method for a subscription
        contract. Supports standard shipping, local delivery, and pickup options
        with comprehensive address validation.


        **Delivery Method Types:**

        - **SHIPPING**: Standard shipping to customer address (default)

        - **LOCAL**: Local delivery within specified zip codes

        - **PICK_UP**: Customer pickup at designated location


        **Key Features:**

        - Zip code restrictions for customer portal access

        - Optional ShipperHQ address validation

        - Automatic phone number handling for local delivery

        - Email notifications to customers

        - Shipping price recalculation

        - Activity log tracking with old/new addresses


        **Zip Code Validation (Customer Portal Only):**

        When called from customer portal:

        - Standard shipping: Validates against 'allowToSpecificZipCode' setting

        - Local delivery: Validates against
        'allowToSpecificZipCodeForLocalDelivery' setting

        - External API calls bypass zip code restrictions


        **Address Validation:**

        - If ShipperHQ is configured, addresses are validated for deliverability

        - Invalid addresses will return appropriate error messages

        - Helps prevent failed deliveries and shipping issues


        **Special Handling:**

        - Local delivery addresses missing phone numbers are auto-populated

        - Uses customer's phone if available, otherwise defaults to placeholder

        - Handles missing address components gracefully


        **Post-Update Actions:**

        - Sends 'SHIPPING_ADDRESS_UPDATED' email to customer

        - Creates activity log with address change details

        - Triggers asynchronous shipping price recalculation

        - May remove invalid discount codes automatically


        **Important Notes:**

        - Province codes should use ISO 3166-2 format (e.g., 'NY' for New York)

        - Country codes should use ISO 3166-1 alpha-2 format (e.g., 'US')

        - Phone numbers should include country code for international addresses

        - Pickup locations must be pre-configured in Shopify


        **Authentication:** Requires valid X-API-Key header
      operationId: updateShippingAddressV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to update. Provide the numeric ID without
            the gid:// prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      requestBody:
        description: New shipping address and delivery method details
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChangeShippingAddressVM'
            examples:
              Standard Shipping Address:
                description: Standard Shipping Address
                value:
                  methodType: SHIPPING
                  firstName: John
                  lastName: Doe
                  company: Acme Corp
                  address1: 456 New Street
                  address2: Suite 200
                  city: Los Angeles
                  provinceCode: CA
                  countryCode: US
                  zip: '90001'
                  phone: '+12135551234'
              Local Delivery Address:
                description: Local Delivery Address
                value:
                  methodType: LOCAL
                  firstName: Jane
                  lastName: Smith
                  address1: 789 Local Ave
                  city: Brooklyn
                  provinceCode: NY
                  countryCode: US
                  zip: '11201'
                  phone: '+17185551234'
              Pickup Location:
                description: Pickup Location
                value:
                  methodType: PICK_UP
                  pickupLocationId: gid://shopify/DeliveryLocationGroup/123456
              International Address:
                description: International Address
                value:
                  methodType: SHIPPING
                  firstName: Pierre
                  lastName: Dubois
                  address1: 123 Rue de la Paix
                  city: Paris
                  provinceCode: '75'
                  countryCode: FR
                  zip: '75001'
                  phone: '+33123456789'
        required: true
      responses:
        '200':
          description: Shipping address successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-03-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    deliveryMethod:
                      __typename: SubscriptionDeliveryMethodShipping
                      address:
                        address1: 456 New Street
                        address2: Suite 200
                        city: Los Angeles
                        provinceCode: CA
                        countryCode: US
                        zip: '90001'
                        firstName: John
                        lastName: Doe
                        company: Acme Corp
                        phone: '+12135551234'
                    deliveryPrice:
                      amount: '7.99'
                      currencyCode: USD
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Zip Code Not Allowed:
                  description: Zip Code Not Allowed
                  value:
                    type: https://example.com/errors/bad-request
                    title: 'UserGeneratedError: That zip code is not allowed'
                    status: 400
                    detail: >-
                      Delivery to zip code 12345 is not available for this
                      subscription
                Invalid Address (ShipperHQ):
                  description: Invalid Address (ShipperHQ)
                  value:
                    type: https://example.com/errors/bad-request
                    title: Address validation failed
                    status: 400
                    detail: >-
                      The provided address could not be validated. Please check
                      the address details.
                Missing Required Fields:
                  description: Missing Required Fields
                  value:
                    type: https://example.com/errors/bad-request
                    title: Validation error
                    status: 400
                    detail: 'Required fields missing: address1, city, countryCode'
                Invalid Method Type:
                  description: Invalid Method Type
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid delivery method
                    status: 400
                    detail: 'Method type must be one of: SHIPPING, LOCAL, PICK_UP'
                Shop Settings Not Found:
                  description: Shop Settings Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: 'Shop settings not found for shop: example-store'
                    status: 400
                    detail: Store configuration is missing or incomplete
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: Unable to process the address update due to Shopify API constraints
          content:
            application/json:
              examples:
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to update delivery address
                    status: 422
                    detail: >-
                      Shopify API error: Invalid province code for selected
                      country
                Invalid Pickup Location:
                  description: Invalid Pickup Location
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Pickup location not configured
                    status: 422
                    detail: The specified pickup location is not available
  /api/external/v2/subscription-contracts-update-payment-method:
    put:
      tags:
        - Subscription Payments
      summary: Send payment method update email to customer
      description: >-
        Triggers Shopify to send an email to the subscription customer with a
        secure link to update their payment method. This endpoint initiates
        Shopify's native payment update flow without requiring direct payment
        handling.


        **Key Features:**

        - Sends official Shopify payment update email to customer

        - Customer receives secure link to Shopify-hosted payment update page

        - No PCI compliance required - Shopify handles all payment data

        - Supports all Shopify-supported payment methods

        - Automatically updates subscription after customer completes the
        process


        **Process Flow:**

        1. API call triggers email send request to Shopify

        2. Shopify sends branded email to customer's registered email

        3. Customer clicks secure link in email

        4. Customer authenticates on Shopify-hosted page

        5. Customer adds/updates payment method

        6. Subscription automatically uses new payment method


        **Email Details:**

        - Sent from Shopify's email servers

        - Uses store's configured sender email

        - Subject line typically: "Update your payment method"

        - Contains secure, time-limited link

        - Shopify-branded with store information


        **Use Cases:**

        - Failed payment recovery

        - Expiring credit card updates

        - Customer-requested payment changes

        - Proactive payment method maintenance


        **Important Notes:**

        - Customer must have valid email address

        - Email cannot be customized (Shopify template)

        - Link expiration time set by Shopify

        - Multiple emails can be sent if needed

        - No webhook for completion - poll contract for updates


        **Rate Limiting:**

        - Subject to Shopify's email sending limits

        - Recommended: Wait 24 hours between sends to same customer

        - Excessive sends may be blocked by Shopify


        **Authentication:** Requires valid X-API-Key header
      operationId: updatePaymentMethodV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID for payment method update. Must be a valid
            contract ID that belongs to the authenticated shop.
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Payment update email sent successfully
          content:
            application/json:
              example:
                message: Payment method update email sent successfully
        '400':
          description: Invalid request or email send failed
          content:
            application/json:
              examples:
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Contract not found
                    status: 400
                    detail: 'No subscription contract found with ID: 123456789'
                    instance: >-
                      /api/external/v2/subscription-contracts-update-payment-method
                No Payment Method:
                  description: No Payment Method
                  value:
                    type: https://example.com/errors/bad-request
                    title: Payment method not found
                    status: 400
                    detail: Subscription has no associated payment method
                    instance: >-
                      /api/external/v2/subscription-contracts-update-payment-method
                Invalid Email Address:
                  description: Invalid Email Address
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Customer email is invalid
                    status: 400
                    detail: Cannot send email to invalid email address
                    instance: >-
                      /api/external/v2/subscription-contracts-update-payment-method
                Email Service Error:
                  description: Email Service Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Email could not be sent
                    status: 400
                    detail: Shopify email service temporarily unavailable
                    instance: >-
                      /api/external/v2/subscription-contracts-update-payment-method
                Customer Not Found:
                  description: Customer Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Customer not found
                    status: 400
                    detail: Customer associated with payment method not found
                    instance: >-
                      /api/external/v2/subscription-contracts-update-payment-method
                Cancelled Subscription:
                  description: Cancelled Subscription
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Cannot update cancelled subscription
                    status: 400
                    detail: >-
                      Payment method cannot be updated for cancelled
                      subscriptions
                    instance: >-
                      /api/external/v2/subscription-contracts-update-payment-method
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
                instance: /api/external/v2/subscription-contracts-update-payment-method
        '403':
          description: Insufficient permissions
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to update payment methods
                instance: /api/external/v2/subscription-contracts-update-payment-method
        '404':
          description: Subscription contract not found
        '422':
          description: Email cannot be sent due to business rules
          content:
            application/json:
              examples:
                Rate Limit Exceeded:
                  description: Rate Limit Exceeded
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Too many emails sent
                    status: 422
                    detail: >-
                      Payment update email was recently sent. Please wait before
                      sending another.
                    instance: >-
                      /api/external/v2/subscription-contracts-update-payment-method
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Shopify API error
                    status: 422
                    detail: Unable to send payment update email at this time
                    instance: >-
                      /api/external/v2/subscription-contracts-update-payment-method
  /api/external/v2/subscription-contracts-update-order-note/{contractId}:
    put:
      tags:
        - Subscription Management
      summary: Update order note for subscription
      description: >-
        Updates the order note that will be added to all future orders generated
        by this subscription. Order notes help merchants track special
        instructions, customer preferences, or internal information about the
        subscription.


        **Key Features:**

        - Note is automatically added to all future recurring orders

        - Visible in both merchant portal and customer portal

        - Appears in Shopify order details for easy reference

        - Changes apply to future orders only (existing orders unchanged)

        **Common Use Cases:**

        - Customer preferences: "No nuts - severe allergy"

        - Delivery instructions: "Leave package at side door"

        - Gift messages: "Happy Birthday from Mom!"

        - Internal notes: "VIP customer - priority handling"

        - Processing instructions: "Include sample with each order"


        **Important Notes:**

        - Empty string clears the existing note

        - No character limit imposed by API (check Shopify limits)

        - HTML is not rendered - stored as plain text

        - Updates are logged in activity history

        - Note persists until explicitly changed


        **Order Generation:**

        When Appstle creates recurring orders:

        1. Retrieves current order note from subscription

        2. Adds note to new Shopify order

        3. Note appears in order details immediately

        4. Merchants can still edit individual order notes


        **Authentication:** Requires valid X-API-Key header
      operationId: updateOrderNoteV2
      parameters:
        - name: contractId
          in: path
          description: Subscription contract ID to update
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: orderNote
          in: query
          description: >-
            Note text to be added to all future orders. Can include special
            instructions, preferences, or internal notes. Pass empty string to
            clear existing note. HTML tags are not rendered - stored as plain
            text.
          required: true
          schema:
            type: string
          examples:
            Delivery Instruction:
              description: Delivery Instruction
              value: Ring doorbell twice, leave at back door
            Internal Note:
              description: Internal Note
              value: VIP Customer - Include free sample
            Gift Message:
              description: Gift Message
              value: Happy Anniversary! Love, Sarah
            Allergy Note:
              description: Allergy Note
              value: No peanuts - severe allergy
            Clear Note:
              description: Clear Note
      responses:
        '200':
          description: Order note successfully updated
          headers:
            X-Application-Context:
              description: Application context with success message
              style: simple
              schema:
                type: string
                example: 'appname:Subscription Updated:'
          content:
            application/json:
              schema:
                type: boolean
              example: true
        '400':
          description: Invalid request or contract not found
          content:
            application/json:
              examples:
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Contract not found
                    status: 400
                    detail: 'No subscription contract found with ID: 123456789'
                    instance: >-
                      /api/external/v2/subscription-contracts-update-order-note/123456789
                Invalid Contract ID:
                  description: Invalid Contract ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: invalid id
                    status: 400
                    detail: Contract does not belong to this shop
                    instance: >-
                      /api/external/v2/subscription-contracts-update-order-note/123456789
                Missing Order Note:
                  description: Missing Order Note
                  value:
                    type: https://example.com/errors/bad-request
                    title: Missing required parameter
                    status: 400
                    detail: Required request parameter 'orderNote' is not present
                    instance: >-
                      /api/external/v2/subscription-contracts-update-order-note/123456789
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
                instance: >-
                  /api/external/v2/subscription-contracts-update-order-note/123456789
        '403':
          description: Insufficient permissions
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
                instance: >-
                  /api/external/v2/subscription-contracts-update-order-note/123456789
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
                instance: >-
                  /api/external/v2/subscription-contracts-update-order-note/123456789
  /api/external/v2/subscription-contracts-update-multiple-line-item-attributes:
    put:
      tags:
        - Subscription Contracts
      summary: Update multiple line item attributes for a subscription contract
      description: >-
        Updates custom attributes for multiple line items within a subscription
        contract. The request body must be a JSON object where each key is a
        line item identifier (as a String) and each value is a list of
        AttributeInfo objects containing attribute key/value pairs. For example:
        { "gid://shopify/SubscriptionLineItem/987654321": [ { "key": "color",
        "value": "red" }, { "key": "size", "value": "M" } ] }. The service
        validates that the contract exists and that each specified line item is
        eligible for update. Authentication is performed via the X-API-Key
        header (the 'api_key' parameter is deprecated).
      operationId: updateMultipleLineItemAttributesV2
      parameters:
        - name: contractId
          in: query
          description: The unique identifier of the subscription contract
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
      requestBody:
        description: >-
          A JSON object where each key is a line item ID (e.g.,
          "gid://shopify/SubscriptionLineItem/987654321") and each value is a
          list of AttributeInfo objects containing the attribute key and value.
          Example: { "gid://shopify/SubscriptionLineItem/987654321": [ { "key":
          "color", "value": "red" }, { "key": "size", "value": "M" } ] }
        content:
          application/json:
            schema:
              type: object
              additionalProperties:
                type: array
                items:
                  $ref: '#/components/schemas/AttributeInfo'
        required: true
      responses:
        '200':
          description: Multiple line item attributes updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '400':
          description: Invalid contract ID, line item IDs, or attribute values
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '403':
          description: Insufficient permissions to update the subscription
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '404':
          description: Subscription contract or one of the specified line items not found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '422':
          description: >-
            Unable to update one or more line item attributes due to
            subscription constraints
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
  /api/external/v2/subscription-contracts-update-min-cycles:
    put:
      tags:
        - Subscription Management
      summary: Update minimum cycles for a subscription contract
      description: >-
        Updates the minimum number of billing cycles (orders) that a customer
        must complete before they can cancel their subscription. This creates a
        commitment period that helps with customer retention and business
        predictability.


        **What are Minimum Cycles?**

        Minimum cycles represent a commitment period where:

        - Customers must complete a specified number of orders

        - Cancellation is blocked until the minimum is met

        - Often tied to special pricing or promotional offers

        - Counted from the subscription start date


        **Key Features:**

        - Updates commitment period for existing subscriptions

        - Can increase or decrease minimum cycles

        - Setting to null removes the minimum commitment

        - Preserves all other subscription settings

        - Automatically handles invalid discount codes

        - Updates future billing queue after change


        **Common Use Cases:**

        - **Promotional Offers**: '3-month minimum for 50% off'

        - **Hardware Subsidies**: '12-month commitment with free device'

        - **Loyalty Programs**: Reduce minimum after customer proves loyalty

        - **Seasonal Campaigns**: Temporary commitment requirements

        - **Contract Adjustments**: Customer service exceptions


        **Impact on Customers:**

        - Cannot cancel via portal until minimum cycles complete

        - Pause/resume typically still allowed (check settings)

        - Shows commitment status in customer portal

        - No automatic notification sent (consider sending separately)


        **Cycle Counting:**

        - Only successful billing attempts count toward minimum

        - Failed payments don't increment the cycle count

        - Skipped orders (if allowed) don't count

        - Current cycle = successful past orders + 1


        **Interaction with Max Cycles:**

        - Min cycles must be less than or equal to max cycles

        - If max cycles exist, subscription auto-cancels after maximum

        - Common pattern: 3 min cycles, 12 max cycles


        **Best Practices:**

        - Clearly communicate commitment terms upfront

        - Consider grandfathering existing customers

        - Use reasonable minimums (typically 3-12 cycles)

        - Document reason for changes in activity logs

        - Send customer notification for transparency


        **Important Notes:**

        - Changes apply immediately to cancellation logic

        - Doesn't affect past or in-progress orders

        - Customer portal respects this setting automatically

        - Activity log tracks old and new values

        - Consider legal requirements in your jurisdiction


        **Authentication:** Requires valid X-API-Key header
      operationId: updateMinCyclesV2
      parameters:
        - name: contractId
          in: query
          description: Contract ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: minCycles
          in: query
          description: >-
            Minimum Number of Orders. The minimum number of billing cycles a
            customer must complete before being allowed to cancel. Set to null
            to remove the minimum commitment. Common values:

            - 3: Three-month commitment

            - 6: Six-month commitment

            - 12: Annual commitment

            - null: No commitment
          required: false
          schema:
            maximum: 9999
            minimum: 1
            type: integer
            nullable: true
          example: 6
      responses:
        '200':
          description: Minimum cycles updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T00:00:00Z'
                    createdAt: '2024-01-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                      displayName: John Doe
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                      minCycles: 6
                      maxCycles: null
                      anchors:
                        - type: MONTHDAY
                          day: 1
                    deliveryPolicy:
                      interval: MONTH
                      intervalCount: 1
                    customerPaymentMethod:
                      id: gid://shopify/CustomerPaymentMethod/123456
                      instrument:
                        __typename: CustomerCreditCard
                        brand: VISA
                        lastDigits: '4242'
                        expiryMonth: 12
                        expiryYear: 2025
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172011164
                            title: Premium Subscription Box
                            currentPrice:
                              amount: '49.99'
                              currencyCode: USD
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Subscription contract not found
                    status: 400
                    detail: No subscription contract found with ID 123456789
                Invalid Min Cycles Value:
                  description: Invalid Min Cycles Value
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid minimum cycles value
                    status: 400
                    detail: Minimum cycles must be a positive integer or null
                Min Exceeds Max Cycles:
                  description: Min Exceeds Max Cycles
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Minimum cycles cannot exceed maximum
                      cycles
                    status: 400
                    detail: >-
                      Minimum cycles (12) cannot be greater than maximum cycles
                      (6)
                Contract Already Cancelled:
                  description: Contract Already Cancelled
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Cannot update cancelled subscription
                    status: 400
                    detail: Cannot modify minimum cycles for cancelled subscriptions
                Invalid Contract ID:
                  description: Invalid Contract ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid contract ID
                    status: 400
                    detail: Contract ID must be a positive number
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to update minimum cycles
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: >-
                  Subscription contract with ID 123456789 not found in the
                  system
        '422':
          description: Minimum cycles update failed due to Shopify constraints
          content:
            application/json:
              examples:
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to update minimum cycles
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
                Invalid Discount Code:
                  description: Invalid Discount Code
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Contract draft discount with title COMMIT3 is invalid
                    status: 422
                    detail: >-
                      Invalid discount code detected. System will automatically
                      remove and retry.
  /api/external/v2/subscription-contracts-update-max-cycles:
    put:
      tags:
        - Subscription Management
      summary: Update maximum cycles for a subscription contract
      description: >-
        Updates the maximum number of billing cycles (orders) after which a
        subscription will automatically terminate. This creates a fixed-duration
        subscription that ends after a specific number of orders.


        **What are Maximum Cycles?**

        Maximum cycles define subscription duration limits where:

        - Subscription automatically cancels after the specified number of
        orders

        - No further orders are generated once maximum is reached

        - Useful for fixed-term offers, trials, or seasonal subscriptions

        - Customer is notified before final order (if configured)


        **Key Features:**

        - Cannot set below current cycle count (prevents immediate cancellation)

        - Setting to null creates an indefinite subscription

        - Automatically reschedules order queue based on new limit

        - Preserves all other subscription settings

        - Validates against current subscription progress


        **Current Cycle Calculation:**

        - Current cycle = Successful billing attempts + 1

        - Failed payments don't count toward maximum

        - First order is cycle 1, second is cycle 2, etc.

        - System prevents setting max below current position


        **Common Use Cases:**

        - **Trial Subscriptions**: '3-box trial' that auto-ends

        - **Seasonal Programs**: '6-month summer subscription'

        - **Limited Series**: '12-issue magazine subscription'

        - **Promotional Offers**: 'First 5 boxes at special price'

        - **Gift Subscriptions**: Fixed duration gifts that don't renew


        **What Happens at Maximum:**

        When a subscription reaches its maximum cycles:

        1. Final order is processed normally

        2. Subscription status changes to CANCELLED

        3. No future orders are scheduled

        4. Customer receives cancellation notification

        5. Cannot be reactivated (new subscription required)


        **Interaction with Min Cycles:**

        - Can have both min and max (e.g., 3 min, 12 max)

        - Min cycles enforces commitment period

        - Max cycles enforces termination

        - Common pattern: Commitment with defined end


        **Queue Management:**

        After updating max cycles:

        - System recalculates future order schedule

        - Removes orders beyond the new maximum

        - Adjusts upcoming order notifications

        - Updates subscription end date projections


        **Important Notes:**

        - Validation prevents accidental immediate cancellation

        - Changes apply to future billing cycles only

        - Activity log tracks old and new values

        - Consider customer communication for changes

        - Setting null removes any duration limit


        **Authentication:** Requires valid X-API-Key header
      operationId: updateMaxCyclesV2
      parameters:
        - name: contractId
          in: query
          description: Contract ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: maxCycles
          in: query
          description: >-
            Maximum Cycles. The total number of orders after which the
            subscription will automatically terminate. Must be greater than or
            equal to the current cycle count and any configured minimum cycles.
            Common values:

            - 3: Three-order trial

            - 6: Six-month seasonal subscription

            - 12: Annual subscription

            - 24: Two-year commitment

            - null: Ongoing subscription with no end date
          required: true
          schema:
            maximum: 9999
            minimum: 1
            type: integer
            nullable: true
          example: 12
      responses:
        '200':
          description: Maximum cycles updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T00:00:00Z'
                    createdAt: '2024-01-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                      displayName: John Doe
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                      minCycles: 3
                      maxCycles: 12
                      anchors:
                        - type: MONTHDAY
                          day: 15
                    deliveryPolicy:
                      interval: MONTH
                      intervalCount: 1
                    lastBillingAttemptDate: '2024-03-01T00:00:00Z'
                    orders:
                      edges:
                        - node:
                            id: gid://shopify/Order/5678901234
                            createdAt: '2024-03-01T00:00:00Z'
                            fulfillmentStatus: FULFILLED
                            financialStatus: PAID
                        - node:
                            id: gid://shopify/Order/5678901233
                            createdAt: '2024-02-01T00:00:00Z'
                            fulfillmentStatus: FULFILLED
                            financialStatus: PAID
                        - node:
                            id: gid://shopify/Order/5678901232
                            createdAt: '2024-01-01T00:00:00Z'
                            fulfillmentStatus: FULFILLED
                            financialStatus: PAID
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172011164
                            title: 12-Month Subscription Box
                            currentPrice:
                              amount: '39.99'
                              currencyCode: USD
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Max Cycles Below Current Cycle:
                  description: Max Cycles Below Current Cycle
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Max cycles cannot be set to less than
                      current cycle
                    status: 400
                    detail: >-
                      Cannot set maximum cycles to 3 when subscription has
                      already completed 5 cycles
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Subscription contract not found
                    status: 400
                    detail: No subscription contract found with ID 123456789
                Invalid Max Cycles Value:
                  description: Invalid Max Cycles Value
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid maximum cycles value
                    status: 400
                    detail: Maximum cycles must be a positive integer
                Max Less Than Min Cycles:
                  description: Max Less Than Min Cycles
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Maximum cycles cannot be less than
                      minimum cycles
                    status: 400
                    detail: >-
                      Cannot set maximum cycles (6) to less than minimum cycles
                      (12)
                Already Cancelled:
                  description: Already Cancelled
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Cannot update cancelled subscription
                    status: 400
                    detail: Cannot modify maximum cycles for cancelled subscriptions
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to update maximum cycles
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: >-
                  Subscription contract with ID 123456789 not found in the
                  system
        '422':
          description: Maximum cycles update failed due to Shopify constraints
          content:
            application/json:
              examples:
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to update maximum cycles
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
                Queue Update Failed:
                  description: Queue Update Failed
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to update order queue
                    status: 422
                    detail: >-
                      Failed to reschedule upcoming orders based on new maximum
                      cycles
  /api/external/v2/subscription-contracts-update-line-item:
    put:
      tags:
        - Subscription Products
      summary: Update multiple properties of a subscription line item
      description: >-
        Comprehensive endpoint for updating a subscription line item's quantity,
        price, product variant, and/or selling plan in a single API call.
        Changes are applied intelligently - only modified values trigger
        updates.


        **Key Features:**

        - Update any combination of: quantity, price, variant, or selling plan

        - Intelligent change detection - only updates what's different

        - Automatic handling of prepaid subscription pricing

        - Preserves existing discount cycles when updating price

        - Partial success allowed - some updates may fail while others succeed

        - Each change creates separate activity log entries


        **Prepaid Subscription Handling:**

        For prepaid subscriptions (billing interval > delivery interval):

        - When `isPricePerUnit=true`: Price is multiplied by interval ratio

        - Example: Monthly billing, weekly delivery = price × 4

        - When `isPricePerUnit=false`: Price is used as total billing amount


        **Update Process:**

        1. Validates line item exists in the subscription

        2. Calculates interval multiplier for prepaid logic

        3. Updates in order: selling plan → price → quantity → variant

        4. Each update uses separate Shopify GraphQL mutation

        5. Failures are logged but don't block other updates


        **Selling Plan Updates:**

        - Can update by ID or name (name takes precedence)

        - Only updates if different from current plan

        - Useful for changing delivery frequency options


        **Price Updates:**

        - Preserves existing discount cycles (up to 2 cycles)

        - Recalculates cycle discounts based on new base price

        - Triggers shipping price recalculation

        - Sends price update email to customer


        **Quantity Updates:**

        - Validates against min/max quantity rules

        - Updates Build-a-Box totals if applicable

        - May trigger discount recalculations


        **Variant Updates:**

        - Changes the product itself (different SKU)

        - Validates new variant exists and is available

        - May affect pricing and discounts


        **Important Notes:**

        - All parameters except contractId and lineId are optional

        - Provide only the values you want to change

        - Price is always in shop's base currency

        - Changes apply to future orders only


        **Authentication:** Requires valid X-API-Key header
      operationId: updateLineItemV2
      parameters:
        - name: contractId
          in: query
          description: Subscription contract ID
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
        - name: quantity
          in: query
          description: >-
            New quantity for the line item. Leave unchanged if not updating
            quantity.
          required: false
          schema:
            maximum: 9999
            minimum: 1
            type: integer
          example: 3
        - name: variantId
          in: query
          description: >-
            New product variant ID in Shopify GID format (e.g.,
            gid://shopify/ProductVariant/42549172011164). This updates the
            associated product. Leave this parameter blank if you are not
            switching products.
          required: false
          schema:
            type: string
          example: gid://shopify/ProductVariant/42549172011164
        - name: lineId
          in: query
          description: >-
            Line item ID to update. Must be the full GraphQL ID including gid://
            prefix
          required: true
          schema:
            type: string
          example: gid://shopify/SubscriptionLine/111111
        - name: price
          in: query
          description: >-
            New price for the line item in shop currency. Behavior depends on
            isPricePerUnit flag.
          required: false
          schema:
            maximum: 999999.99
            minimum: 0.01
            type: number
            format: double
          example: 29.99
        - name: isPricePerUnit
          in: query
          description: >-
            Determines how price is interpreted for prepaid subscriptions:

            - true: Price is per unit (per delivery), will be multiplied by
            interval ratio

            - false: Price is total billing amount (for all deliveries in
            billing period)


            Example: Monthly billing, weekly delivery, price=$10

            - isPricePerUnit=true: Customer pays $40/month ($10 × 4 weeks)

            - isPricePerUnit=false: Customer pays $10/month total
          required: false
          schema:
            type: boolean
            default: false
          example: false
        - name: sellingPlanName
          in: query
          description: >-
            Name of the selling plan to apply. Takes precedence over current
            selling plan. Used to change delivery frequencies.
          required: false
          schema:
            maxLength: 255
            type: string
          example: Deliver every 2 weeks
      responses:
        '200':
          description: Line item successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-03-01T00:00:00Z'
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                    deliveryPolicy:
                      interval: WEEK
                      intervalCount: 1
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 3
                            variantId: gid://shopify/ProductVariant/98765432101
                            title: Premium Coffee - Medium Roast
                            currentPrice:
                              amount: '119.97'
                              currencyCode: USD
                            pricingPolicy:
                              basePrice:
                                amount: '9.99'
                                currencyCode: USD
                              cycleDiscounts:
                                - afterCycle: 3
                                  adjustmentType: PERCENTAGE
                                  adjustmentValue:
                                    percentage: 10
                                  computedPrice:
                                    amount: '107.97'
                                    currencyCode: USD
                            sellingPlanId: gid://shopify/SellingPlan/777777
                            sellingPlanName: Deliver every week
        '207':
          description: Partial success - some updates succeeded while others failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '400':
          description: Invalid request parameters or update failed
          content:
            application/json:
              examples:
                Line Item Not Found:
                  description: Line Item Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      No line item found for contract:123456789 and line
                      id:gid://shopify/SubscriptionLine/999999
                    status: 400
                    detail: >-
                      The specified line item does not exist in this
                      subscription
                Invalid Quantity:
                  description: Invalid Quantity
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Quantity must be greater than 0
                    status: 400
                    detail: Invalid quantity value provided
                Variant Not Found:
                  description: Variant Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: 'Product Variant not found for ID: 99999999999'
                    status: 400
                    detail: The specified product variant does not exist
                Invalid Selling Plan:
                  description: Invalid Selling Plan
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Selling plan not found
                    status: 400
                    detail: No selling plan found with the specified name
                Price Too Low:
                  description: Price Too Low
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Price must be greater than 0
                    status: 400
                    detail: Invalid price value provided
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
  /api/external/v2/subscription-contracts-update-line-item-selling-plan:
    put:
      tags:
        - Subscription Products
      summary: Update selling plan for a subscription line item
      description: >-
        Updates the selling plan associated with a specific product line item in
        a subscription contract. Selling plans define the delivery schedule,
        pricing rules, and billing policies for subscription products.


        **What are Selling Plans?**

        Selling plans are Shopify's way of defining subscription rules for
        products:

        - **Delivery Schedule**: How often the product is delivered (e.g.,
        'every 2 weeks', 'monthly')

        - **Pricing Policy**: Discounts and pricing tiers (e.g., '10% off',
        'first order free')

        - **Billing Policy**: When and how often customer is charged

        - **Plan Name**: Customer-facing description like 'Deliver every month'


        **Key Features:**

        - Update by selling plan ID or name (name takes precedence if both
        provided)

        - Validates line item exists before attempting update

        - Only creates activity log if plan actually changes

        - Uses Shopify's draft system for safe updates

        - Preserves existing line item attributes and customizations


        **Common Use Cases:**

        - Change delivery frequency: Weekly → Monthly

        - Switch pricing tiers: Regular → VIP pricing

        - Update from old plan to new plan with better terms

        - Migrate products to new selling plan groups

        - Apply seasonal or promotional plans


        **Update Process:**

        1. Validates subscription contract and line item exist

        2. Creates a draft of the subscription contract

        3. Updates the line item's selling plan in the draft

        4. Commits the draft to apply changes

        5. Records activity log if plan changed


        **Impact of Selling Plan Changes:**

        - **Delivery Schedule**: Next and future orders follow new schedule

        - **Pricing**: New plan's pricing applies from next billing

        - **Discounts**: Plan-specific discounts are recalculated

        - **Billing**: Billing frequency may change with the plan


        **Finding Selling Plans:**

        To find available selling plans:

        1. Check product's selling plan groups in Shopify admin

        2. Use Shopify's GraphQL API to query selling plans

        3. Plans must be active and associated with the product


        **Important Notes:**

        - Both sellingPlanId and sellingPlanName are optional, but at least one
        required

        - If both provided, both are updated (name doesn't override ID)

        - Plan must be valid for the product variant

        - Changes apply to future orders only

        - No customer notification sent (consider sending separately)


        **Authentication:** Requires valid X-API-Key header
      operationId: updateLineItemSellingPlan
      parameters:
        - name: contractId
          in: query
          description: The unique identifier of the subscription contract
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: lineId
          in: query
          description: >-
            The unique identifier of the line item in the subscription contract.
            Must be in full GraphQL ID format
          required: true
          schema:
            type: string
          example: gid://shopify/SubscriptionLine/987654321
        - name: sellingPlanId
          in: query
          description: >-
            The unique identifier of the new selling plan. Provide the numeric
            ID without gid:// prefix. Required if sellingPlanName is not
            provided. The plan must be:

            - Active in your Shopify store

            - Associated with the product variant

            - Part of an active selling plan group
          required: false
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 56789
        - name: sellingPlanName
          in: query
          description: >-
            The customer-facing name of the new selling plan. Required if
            sellingPlanId is not provided. This is the name shown to customers
            like 'Deliver every 2 weeks' or 'Monthly subscription'. Must match
            exactly as configured in Shopify
          required: false
          schema:
            maxLength: 255
            type: string
          example: Deliver every month
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      responses:
        '200':
          description: Selling plan updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/987654321
                            quantity: 2
                            variantId: gid://shopify/ProductVariant/42549172011164
                            title: Premium Coffee - Dark Roast
                            currentPrice:
                              amount: '27.99'
                              currencyCode: USD
                            sellingPlanId: gid://shopify/SellingPlan/56789
                            sellingPlanName: Deliver every month
                            pricingPolicy:
                              basePrice:
                                amount: '29.99'
                                currencyCode: USD
                              cycleDiscounts:
                                - afterCycle: 0
                                  adjustmentType: PERCENTAGE
                                  adjustmentValue:
                                    percentage: 10
                    deliveryPolicy:
                      interval: MONTH
                      intervalCount: 1
        '400':
          description: Invalid contract ID, line ID, or selling plan details
          content:
            application/json:
              examples:
                Both Parameters Missing:
                  description: Both Parameters Missing
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Both Selling Plan Id and Selling Plan
                      Name cannot be null
                    status: 400
                    detail: >-
                      At least one of sellingPlanId or sellingPlanName must be
                      provided
                Line Item Not Found:
                  description: Line Item Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Line item not found
                    status: 400
                    detail: >-
                      No line item found with ID
                      gid://shopify/SubscriptionLine/987654321 in contract
                      123456789
                Invalid Selling Plan:
                  description: Invalid Selling Plan
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Selling plan not found
                    status: 400
                    detail: >-
                      The specified selling plan does not exist or is not
                      available for this product
                Incompatible Selling Plan:
                  description: Incompatible Selling Plan
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Selling plan is not compatible with
                      variant
                    status: 400
                    detail: >-
                      The selected selling plan cannot be applied to this
                      product variant
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Subscription contract not found
                    status: 400
                    detail: No subscription contract found with ID 123456789
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to modify the subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract or line item not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: >-
                  Subscription contract with ID 123456789 not found in the
                  system
        '422':
          description: Unable to update selling plan due to Shopify constraints
          content:
            application/json:
              examples:
                Draft Creation Failed:
                  description: Draft Creation Failed
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to create subscription draft
                    status: 422
                    detail: >-
                      Shopify API error: Subscription is currently being
                      modified
                Draft Commit Failed:
                  description: Draft Commit Failed
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to commit changes
                    status: 422
                    detail: Cannot update subscription during active billing attempt
  /api/external/v2/subscription-contracts-update-line-item-quantity:
    put:
      tags:
        - Subscription Products
      summary: Update product line item quantity in subscription
      description: >-
        Updates the quantity of a specific product line item within a
        subscription contract. This comprehensive operation handles quantity
        validation, discount recalculation, and special Build-a-Box constraints.


        **Key Features:**

        - Updates quantity for future orders only

        - Validates minimum/maximum quantities for line items

        - Special handling for Build-a-Box subscriptions

        - Automatic discount recalculation

        - Shipping price updates

        - Activity log tracking with old/new values


        **Build-a-Box (BAB) Validation:**

        For Build-a-Box subscriptions:

        - Enforces total minimum/maximum item counts

        - Only counts recurring products (excludes one-time and free items)

        - Validates across all BAB items in the subscription

        - Can be bypassed with 'allowToAddProductQuantityMinMaxReached'
        permission


        **Line Item Validation:**

        Individual products may have:

        - Minimum quantity requirements (min_quantity attribute)

        - Maximum quantity limits (max_quantity attribute)

        - These are enforced separately from BAB constraints


        **Post-Update Actions:**

        1. **Activity Logging**: Records quantity change with old/new values

        2. **BAB Discount Sync**: Recalculates Build-a-Box volume discounts

        3. **Product Discount Sync**: Updates product-specific discounts

        4. **Shipping Price Update**: Recalculates shipping based on new
        quantity


        **Discount Recalculation:**

        - Build-a-Box discounts adjust based on total quantity tiers

        - May remove old discount codes and apply new ones

        - Handles 'subscription contract has changed' retry scenarios


        **Important Notes:**

        - Line ID must be the full GraphQL ID format

        - Quantity must be positive (minimum 1)

        - Changes apply to all future orders

        - Past or in-progress orders are not affected


        **Authentication:** Requires valid X-API-Key header
      operationId: updateLineItemQuantityV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to update. Provide the numeric ID without
            the gid:// prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: quantity
          in: query
          description: New quantity for the line item. Must be a positive integer
          required: true
          schema:
            maximum: 9999
            minimum: 1
            type: integer
          example: 3
        - name: lineId
          in: query
          description: >-
            Line item ID to update. Must be the full GraphQL ID including the
            gid:// prefix
          required: true
          schema:
            type: string
          example: gid://shopify/SubscriptionLine/111111
      responses:
        '200':
          description: Product line item quantity updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T12:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 3
                            variantId: gid://shopify/ProductVariant/42549172011164
                            title: Premium Coffee - Dark Roast
                            currentPrice:
                              amount: '44.97'
                              currencyCode: USD
                            customAttributes:
                              - key: _min_quantity
                                value: '1'
                              - key: _max_quantity
                                value: '5'
                    discounts:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionManualDiscount/222222
                            title: BUILD_A_BOX_DISCOUNT_ABC123
                            targetType: ALL_LINES
                            value:
                              percentage: 15
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Line Item Not Found:
                  description: Line Item Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      No line item found for contract:123456789 and line
                      id:gid://shopify/SubscriptionLine/999999
                    status: 400
                    detail: >-
                      The specified line item does not exist in this
                      subscription
                Quantity Below Minimum:
                  description: Quantity Below Minimum
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Minimum quantity 2 is required for this
                      product
                    status: 400
                    detail: The product has a minimum quantity requirement
                Quantity Exceeds Maximum:
                  description: Quantity Exceeds Maximum
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Maximum quantity 5 is allowed for this
                      product
                    status: 400
                    detail: The product has a maximum quantity limit
                Build-a-Box Minimum Not Met:
                  description: Build-a-Box Minimum Not Met
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Minimum 6 quantity is required
                    status: 400
                    detail: Build-a-Box subscriptions require a minimum total quantity
                    code: minQuantityNotReached
                Build-a-Box Maximum Exceeded:
                  description: Build-a-Box Maximum Exceeded
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Maximum 12 quantity is required
                    status: 400
                    detail: >-
                      Build-a-Box subscriptions have a maximum total quantity
                      limit
                    code: maxQuantityReached
                Invalid Quantity Value:
                  description: Invalid Quantity Value
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid quantity
                    status: 400
                    detail: Quantity must be a positive integer
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to update subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: Unable to process the quantity update due to Shopify API constraints
          content:
            application/json:
              examples:
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to update line item quantity
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
                Draft Commit Error:
                  description: Draft Commit Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to commit subscription changes
                    status: 422
                    detail: The subscription contract has changed. Please try again.
  /api/external/v2/subscription-contracts-update-line-item-pricing-policy:
    put:
      tags:
        - Subscription Products
      summary: Update line item pricing policy with cycle-based discounts
      description: >-
        Sets up advanced pricing rules for a subscription line item that change
        based on the number of successful orders (cycles). This powerful feature
        enables loyalty discounts, promotional pricing tiers, and
        subscribe-and-save models.


        **What are Pricing Policies?**

        Pricing policies define how a product's price changes over the
        subscription lifetime:

        - **Base Price**: Starting price for the product

        - **Cycle Discounts**: Price changes after specific numbers of orders

        - **Automatic Application**: System applies correct price based on order
        history


        **Supported Discount Types:**

        - **PERCENTAGE**: Percentage off base price (e.g., 10% off)

        - **FIXED**: Fixed amount off base price (e.g., $5 off)

        - **PRICE**: Override with new fixed price (e.g., $19.99)

        Note: SHIPPING and FREE_PRODUCT types are not supported by this endpoint


        **Cycle Counting:**

        - Cycles start at 1 (first order is cycle 1)

        - Only successful billing attempts count

        - Failed payments don't increment the cycle

        - Current cycle = 1 + count of successful past orders


        **Common Use Cases:**

        1. **Subscribe & Save**: 10% off starting from 3rd order

        2. **Loyalty Tiers**: 5% off after 3 orders, 10% after 6 orders

        3. **Introductory Pricing**: First 2 orders at $9.99, then $14.99

        4. **Promotional Periods**: Special price for orders 3-5


        **Important Limitations:**

        - Maximum 2 cycle discounts per line item

        - Cycles must have different afterCycle values

        - Changes apply to future orders only

        - Existing orders keep their original pricing


        **Prepaid Subscription Handling:**

        For prepaid subscriptions (e.g., pay monthly for weekly delivery):

        - Base price is per delivery

        - Current price = base price × delivery frequency

        - Discounts apply to base price, then multiply


        **Side Effects:**

        - Sends price update email to customer

        - Recalculates Build-a-Box discounts

        - Updates product discount synchronization

        - Triggers shipping price recalculation

        - Creates detailed activity log


        **Authentication:** Requires valid X-API-Key header
      operationId: updateLineItemPricingPolicyV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
        - name: contractId
          in: query
          description: Subscription contract ID
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: lineId
          in: query
          description: Line item ID to update. Must be full GraphQL ID format
          required: true
          schema:
            type: string
          example: gid://shopify/SubscriptionLine/111111
        - name: basePrice
          in: query
          description: >-
            Base price for the product (before any discounts). This is the
            starting price
          required: true
          schema:
            maximum: 999999.99
            minimum: 0.01
            type: number
            format: double
          example: 24.99
      requestBody:
        description: >-
          List of cycle-based pricing rules. Maximum 2 cycles, must have unique
          afterCycle values
        content:
          application/json:
            schema:
              type: string
            examples:
              Subscribe & Save (10% off after 3 orders):
                description: Subscribe & Save (10% off after 3 orders)
                value:
                  - afterCycle: 3
                    discountType: PERCENTAGE
                    value: 10
              Tiered Loyalty Discounts:
                description: Tiered Loyalty Discounts
                value:
                  - afterCycle: 3
                    discountType: PERCENTAGE
                    value: 5
                  - afterCycle: 6
                    discountType: PERCENTAGE
                    value: 10
              Fixed Amount Discounts:
                description: Fixed Amount Discounts
                value:
                  - afterCycle: 2
                    discountType: FIXED
                    value: 5
                  - afterCycle: 5
                    discountType: FIXED
                    value: 10
              Special Pricing After Trial:
                description: Special Pricing After Trial
                value:
                  - afterCycle: 3
                    discountType: PRICE
                    value: 19.99
              Clear All Discounts:
                description: Clear All Discounts
                value: []
      responses:
        '200':
          description: Pricing policy successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172011164
                            currentPrice:
                              amount: '24.99'
                              currencyCode: USD
                            pricingPolicy:
                              basePrice:
                                amount: '24.99'
                                currencyCode: USD
                              cycleDiscounts:
                                - afterCycle: 3
                                  adjustmentType: PERCENTAGE
                                  adjustmentValue:
                                    percentage: 10
                                  computedPrice:
                                    amount: '22.49'
                                    currencyCode: USD
                                - afterCycle: 6
                                  adjustmentType: PERCENTAGE
                                  adjustmentValue:
                                    percentage: 15
                                  computedPrice:
                                    amount: '21.24'
                                    currencyCode: USD
        '400':
          description: Invalid request parameters
          content:
            application/json:
              examples:
                Line Item Not Found:
                  description: Line Item Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Line item not found
                    status: 400
                    detail: >-
                      No line item found with ID:
                      gid://shopify/SubscriptionLine/999999
                Invalid Base Price:
                  description: Invalid Base Price
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid base price
                    status: 400
                    detail: Base price must be greater than 0
                Invalid Cycle Configuration:
                  description: Invalid Cycle Configuration
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid cycle configuration
                    status: 400
                    detail: Cycle discounts must have unique afterCycle values
                Too Many Cycles:
                  description: Too Many Cycles
                  value:
                    type: https://example.com/errors/bad-request
                    title: Too many cycle discounts
                    status: 400
                    detail: Maximum 2 cycle discounts allowed per line item
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '404':
          description: Subscription contract not found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '422':
          description: Unable to apply pricing policy
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: UserGeneratedError:Unable to update pricing policy
                status: 422
                detail: 'Shopify API error: Invalid discount configuration'
  /api/external/v2/subscription-contracts-update-line-item-price:
    put:
      tags:
        - Subscription Products
      summary: Update product line item price
      description: >-
        Updates the base price of a specific product line item within a
        subscription contract. This endpoint intelligently handles pricing
        updates while preserving existing discount structures.


        **Key Features:**

        - Updates base price while maintaining discount cycles

        - Automatically calculates prepaid subscription prices

        - Preserves existing percentage/fixed discounts

        - Validates actual price changes before updating

        - Triggers shipping and discount recalculations

        - Sends price update notifications to customers


        **Base Price vs Current Price:**

        - **Base Price**: The unit price before any multipliers

        - **Current Price**: Base price × fulfillment multiplier

        - For monthly billing/weekly delivery: Current = Base × 4

        - For pay-per-delivery: Current = Base × 1


        **Discount Preservation:**

        By default, this endpoint preserves existing discount cycles:

        - Percentage discounts adjust to new base price

        - Fixed discounts remain at same dollar amount

        - Discount schedule (after X cycles) unchanged


        **Prepaid Subscription Handling:**

        For prepaid subscriptions (billing interval > delivery interval):

        - Automatically calculates fulfillment multiplier

        - Updates current price accordingly

        - Ensures correct billing amounts


        **Post-Update Actions:**

        1. Build-a-Box discount recalculation

        2. Product discount synchronization

        3. Shipping price updates

        4. Customer email notifications

        5. Activity log creation


        **Important Notes:**

        - Price changes apply to future orders only

        - Cannot set price below $0.01

        - Maximum 2 discount cycles preserved

        - No update if price unchanged


        **Authentication:** Requires valid X-API-Key header
      operationId: updateLineItemPriceV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID. Provide the numeric ID without the gid://
            prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: basePrice
          in: query
          description: New base price for the line item (unit price before multipliers)
          required: true
          schema:
            maximum: 999999.99
            minimum: 0.01
            type: number
            format: double
          example: 24.99
        - name: lineId
          in: query
          description: >-
            Line item ID to update. Must be the full GraphQL ID including the
            gid:// prefix
          required: true
          schema:
            type: string
          example: gid://shopify/SubscriptionLine/4245-cfgfg-xcfdg
      responses:
        '200':
          description: Line item price successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T12:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                    deliveryPolicy:
                      interval: WEEK
                      intervalCount: 1
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172011164
                            title: Premium Coffee - Monthly Supply
                            currentPrice:
                              amount: '99.96'
                              currencyCode: USD
                            pricingPolicy:
                              basePrice:
                                amount: '24.99'
                                currencyCode: USD
                              cycleDiscounts:
                                - afterCycle: 3
                                  adjustmentType: PERCENTAGE
                                  adjustmentValue:
                                    percentage: 10
                                  computedPrice:
                                    amount: '89.96'
                                    currencyCode: USD
        '400':
          description: Invalid request parameters
          content:
            application/json:
              examples:
                Invalid Base Price:
                  description: Invalid Base Price
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid base price
                    status: 400
                    detail: Base price must be greater than 0
                Line Item Not Found:
                  description: Line Item Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Line item not found
                    status: 400
                    detail: >-
                      No line item found with ID:
                      gid://shopify/SubscriptionLine/999999
                Invalid Line ID Format:
                  description: Invalid Line ID Format
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid line ID format
                    status: 400
                    detail: >-
                      Line ID must be in format:
                      gid://shopify/SubscriptionLine/[numeric_id]
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: Unable to process the price update
          content:
            application/json:
              examples:
                No Price Change:
                  description: No Price Change
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: No update needed
                    status: 422
                    detail: The new base price is the same as the current base price
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to update line item price
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
  /api/external/v2/subscription-contracts-update-line-item-attributes:
    put:
      tags:
        - Subscription Contracts
      summary: Update line item attributes for a subscription contract
      description: >-
        Updates the custom attributes for a specific line item within a
        subscription contract. This endpoint accepts a contract ID, a line item
        ID, and a list of attribute objects (each containing key/value pairs) to
        update. It uses the underlying service to perform validation (such as
        contract existence, freeze status, and attribute-based cycle limits)
        before applying the update. The operation is intended for external API
        consumers, and authentication is performed via the X-API-Key header.
        Deprecated api_key parameter is supported for backward compatibility.
      operationId: updateLineItemAttributesV2
      parameters:
        - name: contractId
          in: query
          description: The unique identifier of the subscription contract
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: 'Deprecated: API key (use X-API-Key header instead)'
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
        - name: lineId
          in: query
          description: The unique identifier of the line item to update
          required: true
          schema:
            type: string
          example: gid://shopify/SubscriptionLineItem/987654321
      requestBody:
        content:
          application/json:
            schema:
              type: array
              description: A list of attribute objects containing keys and their new values
              items:
                $ref: '#/components/schemas/AttributeInfo'
        required: true
      responses:
        '200':
          description: Line item attributes updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '400':
          description: Invalid contract ID, line item ID, or attribute values
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '403':
          description: Insufficient permissions to update the subscription
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '404':
          description: Subscription contract or line item not found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '422':
          description: >-
            Unable to update the line item attributes due to subscription
            constraints
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
  /api/external/v2/subscription-contracts-update-frequency-by-selling-plan:
    put:
      tags:
        - Subscription Contracts
      summary: Update Subscription contract frequency by selling plan
      operationId: updateFrequencyBySellingPlanV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to update. Provide the numeric ID without
            the gid:// prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: sellingPlanId
          in: query
          description: >-
            The unique identifier of the new selling plan. Provide the numeric
            ID without gid:// prefix.
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 56789
      responses:
        '200':
          description: Subscription contract frequency updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2025-08-08T13:00:00Z'
                    customer:
                      id: gid://shopify/Customer/111111111111
                      email: abc@gmail.com
                      displayName: abc xyz
                      firstName: abc
                      lastName: xyz
                    billingPolicy:
                      interval: DAY
                      intervalCount: 5
                      anchors: []
                      maxCycles: 6
                      minCycles: 3
                    deliveryPolicy:
                      interval: DAY
                      intervalCount: 5
                      anchors: []
                    lines:
                      edges:
                        - node:
                            id: >-
                              gid://shopify/SubscriptionLine/49e73332-5dfc-4fba-9ee7-111111111
                            sellingPlanId: gid://shopify/SellingPlan/691881211111
                            sellingPlanName: 4 Monthly Subscription
                            productId: gid://shopify/Product/1111111111
                            title: Blub Indoor
                            variantId: gid://shopify/ProductVariant/111111111111
                            quantity: 1
                            currentPrice:
                              amount: '154.0'
                              currencyCode: USD
                            lineDiscountedPrice:
                              amount: '154.0'
                              currencyCode: USD
                            variantImage:
                              transformedSrc: >-
                                https://cdn.shopify.com/s/files/1/0933/4738/1543/files/shopping_41111111111111111111111111111111111
                            taxable: true
                    customerPaymentMethod:
                      id: gid://shopify/CustomerPaymentMethod/1111111111111111111
                      instrument:
                        brand: bogus
                        expiryMonth: 12
                        expiryYear: 2030
                        lastDigits: '1'
                        name: abc xyz
                    deliveryMethod:
                      address:
                        address1: test
                        city: Sunnyvale
                        country: United States
                        province: California
                        zip: '94087'
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Same Interval Error:
                  description: Same Interval Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Billing interval cannot be the same as
                      old billing interval
                    status: 400
                    detail: The subscription is already set to bill every 5 days
                Prepaid Validation Error:
                  description: Prepaid Validation Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Billing interval cannot be less than or
                      equal to delivery interval for prepaid contracts
                    status: 400
                    detail: >-
                      Cannot bill every 5 days for 5-day deliveries in prepaid
                      subscriptions
                Invalid Interval Count:
                  description: Invalid Interval Count
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid interval count
                    status: 400
                    detail: Interval count must be between 1 and 365
                Invalid Interval Type:
                  description: Invalid Interval Type
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid interval type
                    status: 400
                    detail: 'Interval must be one of: DAY, WEEK, MONTH, YEAR'
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Subscription contract not found
                    status: 400
                    detail: No subscription contract found with ID 32212746535
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to update subscription contract
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 32212746535 not found
        '422':
          description: Update failed due to Shopify constraints
          content:
            application/json:
              examples:
                No Matching Selling Plan:
                  description: No Matching Selling Plan
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: No selling plan available
                    status: 422
                    detail: No selling plan found for the requested billing frequency
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to update subscription contract
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
  /api/external/v2/subscription-contracts-update-existing-payment-method:
    put:
      tags:
        - Subscription Payments
      summary: Update subscription payment method
      description: >-
        Updates the payment method for an existing subscription contract to use
        a different existing payment method. The new payment method must already
        be associated with the customer in Shopify.


        **Important Notes:**

        - The payment method must already exist in the customer's Shopify
        payment methods

        - Only valid, non-revoked payment methods can be used

        - The update is processed through Shopify's subscription draft system

        - Payment method details are cached locally after successful update


        **Process Flow:**

        1. Validates subscription contract exists

        2. Creates a draft update in Shopify

        3. Updates the draft with new payment method

        4. Commits the draft to apply changes

        5. Caches payment instrument details locally

        6. Records activity log entry


        **Authentication:** Requires valid X-API-Key header
      operationId: updateExistingPaymentMethodV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to update payment method for. Must be a
            valid contract ID that belongs to the authenticated shop.
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: paymentMethodId
          in: query
          description: >-
            ID of the existing customer payment method to use. Must be a valid
            Shopify GraphQL payment method ID in the format
            'gid://shopify/CustomerPaymentMethod/{id}'. The payment method must:

            - Already exist in the customer's Shopify account

            - Be in a valid state (not expired or revoked)

            - Be authorized for subscription use


            You can retrieve available payment methods using the customer
            payment methods endpoint.
          required: true
          schema:
            pattern: ^gid://shopify/CustomerPaymentMethod/[a-zA-Z0-9]+$
            type: string
          example: gid://shopify/CustomerPaymentMethod/cdb2bbe581599b20439ebf636a380b8b
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      responses:
        '200':
          description: Payment method updated successfully
          content:
            application/json:
              example:
                message: Payment method updated successfully
        '400':
          description: Invalid request or update failed
          content:
            application/json:
              examples:
                Invalid Payment Method:
                  description: Invalid Payment Method
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Invalid payment method provided
                    status: 400
                    detail: Payment method ID is required and must be valid
                    instance: >-
                      /api/external/v2/subscription-contracts-update-existing-payment-method
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Contract does not exist
                    status: 400
                    detail: No subscription contract found with the specified ID
                    instance: >-
                      /api/external/v2/subscription-contracts-update-existing-payment-method
                Payment Method Not Found:
                  description: Payment Method Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Payment method not found
                    status: 400
                    detail: >-
                      The specified payment method does not exist or is not
                      associated with this customer
                    instance: >-
                      /api/external/v2/subscription-contracts-update-existing-payment-method
                Invalid Payment Method Status:
                  description: Invalid Payment Method Status
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Payment method is expired
                    status: 400
                    detail: >-
                      The payment method cannot be used because it is expired or
                      revoked
                    instance: >-
                      /api/external/v2/subscription-contracts-update-existing-payment-method
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Unable to update payment method at this
                      time
                    status: 400
                    detail: >-
                      Shopify returned an error when attempting to update the
                      payment method
                    instance: >-
                      /api/external/v2/subscription-contracts-update-existing-payment-method
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
                instance: >-
                  /api/external/v2/subscription-contracts-update-existing-payment-method
        '403':
          description: Insufficient permissions to update payment method
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to update payment methods
                instance: >-
                  /api/external/v2/subscription-contracts-update-existing-payment-method
        '404':
          description: Subscription contract not found
        '422':
          description: Payment method update failed due to business rules
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: Payment method update failed
                status: 422
                detail: >-
                  Cannot update payment method while subscription has pending
                  charges
                instance: >-
                  /api/external/v2/subscription-contracts-update-existing-payment-method
  /api/external/v2/subscription-contracts-update-delivery-method:
    put:
      tags:
        - Subscription Management
      summary: Update subscription delivery method
      description: >-
        Updates the delivery method for a subscription contract, supporting
        standard shipping, local delivery, and customer pickup options. The
        delivery method determines how future orders will be fulfilled.


        **Delivery Method Types:**

        The system automatically determines the type based on the subscription's
        current delivery address:

        - **SHIPPING**: Standard shipping to customer address (default)

        - **LOCAL**: Local delivery within merchant's delivery zones

        - **PICK_UP**: Customer pickup at designated location


        **Two Ways to Update:**

        1. **Manual Parameters**: Provide title, code, and presentment title
        directly

        2. **Delivery Method ID**: Provide a Shopify DeliveryMethodDefinition ID
        to auto-populate all fields


        **Using Delivery Method ID:**

        When providing a delivery-method-id:

        - System fetches the method from Shopify's delivery profiles

        - Automatically sets title, code, and presentment title

        - Applies associated delivery price if defined

        - ID can be numeric or full GraphQL ID format


        **Delivery Type Requirements:**

        - **Standard Shipping**: No additional requirements

        - **Local Delivery**: Phone number must exist in delivery address

        - **Pickup**: Pickup location must be configured in subscription


        **Price Updates:**

        - If using delivery-method-id with a fixed price, updates delivery price

        - Manual updates don't change the delivery price

        - Price changes affect all future orders


        **Side Effects:**

        - Creates activity log entry with method details

        - May remove invalid discount codes automatically

        - Updates apply to all future orders immediately

        - No customer notification sent


        **Common Use Cases:**

        - Switch from standard shipping to express shipping

        - Change pickup location for customer convenience

        - Update local delivery options based on availability

        - Apply seasonal delivery methods


        **Important Notes:**

        - Cannot change the delivery type (shipping/local/pickup) - only the
        method within that type

        - Delivery methods must be configured in Shopify's shipping settings

        - Changes don't affect orders already in fulfillment


        **Authentication:** Requires valid X-API-Key header
      operationId: updateDeliveryMethod
      parameters:
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: contractId
          in: query
          description: Subscription contract ID to update
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: delivery-method-title
          in: query
          description: >-
            Display name of the delivery method. This is what customers see.
            Ignored if delivery-method-id is provided.
          required: true
          schema:
            maxLength: 255
            type: string
          example: Express Shipping
        - name: delivery-method-code
          in: query
          description: >-
            Internal code for the delivery method. Often same as title. Used for
            system identification. Ignored if delivery-method-id is provided.
          required: true
          schema:
            maxLength: 255
            type: string
          example: EXPRESS_SHIP
        - name: delivery-method-presentment-title
          in: query
          description: >-
            Localized version of the title for multi-language stores. Often same
            as title for single-language stores. Ignored if delivery-method-id
            is provided.
          required: true
          schema:
            maxLength: 255
            type: string
          example: Express Shipping
        - name: delivery-method-id
          in: query
          description: >-
            Optional Shopify DeliveryMethodDefinition ID. When provided,
            automatically fetches and applies the delivery method's title, code,
            presentment title, and price. Can be numeric ID or full GraphQL ID
            (gid://shopify/DeliveryMethodDefinition/123).
          required: false
          schema:
            type: string
          example: 123456
      responses:
        '204':
          description: Delivery method successfully updated
          headers:
            X-Alert:
              description: Success message
              style: simple
              schema:
                type: string
                example: Subscription Updated
        '400':
          description: Invalid request or update failed
          content:
            application/json:
              examples:
                No Delivery Address:
                  description: No Delivery Address
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Delivery method not found for
                      contract:123456789
                    status: 400
                    detail: Subscription has no delivery address configured
                Invalid Delivery Method ID:
                  description: Invalid Delivery Method ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Delivery method not found for
                      deliveryMethodID:999999
                    status: 400
                    detail: >-
                      The specified delivery method does not exist in store's
                      delivery profiles
                Local Delivery Phone Required:
                  description: Local Delivery Phone Required
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Phone number is required
                    status: 400
                    detail: >-
                      Local delivery requires a phone number in the delivery
                      address
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Unable to update delivery method
                    status: 400
                    detail: Delivery method is not available for this delivery address
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to modify delivery methods
        '404':
          description: Subscription contract not found
        '422':
          description: Delivery method cannot be applied
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: Delivery method incompatible
                status: 422
                detail: >-
                  Selected delivery method cannot be used with subscription
                  products
  /api/external/v2/subscription-contracts-update-delivery-interval:
    put:
      tags:
        - Subscription Management
      summary: Update delivery interval for a subscription contract
      description: >
        Updates the delivery interval for the specified subscription contract.

        This endpoint allows external API consumers to change the delivery
        interval count

        and type (of type SellingPlanInterval) used for scheduling deliveries.


        The service validates that the contract exists, that the new delivery
        interval

        differs from the current setting, and that it meets all business rules.


        Authentication is enforced via the X-API-Key header (the 'api_key'
        parameter is deprecated).
      operationId: updateDeliveryIntervalV2
      parameters:
        - name: contractId
          in: query
          description: Contract ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: deliveryIntervalCount
          in: query
          description: Delivery Interval Count
          required: true
          schema:
            type: integer
            format: int32
        - name: deliveryInterval
          in: query
          description: Delivery Interval Type
          required: true
          schema:
            type: string
            enum:
              - DAY
              - WEEK
              - MONTH
              - YEAR
              - $UNKNOWN
      responses:
        '200':
          description: Delivery interval updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '400':
          description: Invalid contract ID or delivery interval values
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '403':
          description: Insufficient permissions to update delivery interval
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '404':
          description: Subscription contract not found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '422':
          description: Delivery interval update failed due to business rules
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
  /api/external/v2/subscription-contracts-update-billing-interval:
    put:
      tags:
        - Billing & Payments
      summary: Update billing interval for a subscription contract
      description: >-
        Updates the billing frequency (how often the customer is charged) for a
        subscription contract. This comprehensive operation recalculates billing
        dates, adjusts pricing, updates selling plans, and may also modify
        delivery intervals.


        **Key Features:**

        - Changes billing frequency while maintaining subscription continuity

        - Automatically adjusts delivery interval when linked to billing

        - Recalculates next billing date based on store settings

        - Reprices all line items for the new frequency

        - Finds and applies matching selling plans

        - Handles anchor day adjustments for consistent billing

        - Validates prepaid subscription constraints


        **Billing Interval Types:**

        - **DAY**: Daily billing (use with caution)

        - **WEEK**: Weekly billing (e.g., every 1, 2, 3 weeks)

        - **MONTH**: Monthly billing (e.g., every 1, 2, 3 months)

        - **YEAR**: Annual billing


        **Validation Rules:**

        - Cannot set the same interval as current (no-op prevention)

        - For prepaid subscriptions: billing interval must exceed delivery
        interval

        - Example: Can't bill monthly if delivering weekly (would be paying for
        1 delivery but receiving 4)


        **Next Billing Date Calculation:**

        The system uses sophisticated logic to determine the new billing date:

        1. Starts from current or last successful billing date

        2. Applies store timezone and order time preferences

        3. Ensures date is in the future

        4. Respects day-of-week preferences if configured

        5. May keep current date if 'enableChangeFromNextBillingDate' is false


        **Side Effects:**

        - **Delivery Interval**: Updated if currently equal to billing interval

        - **Line Item Pricing**: Recalculated based on new frequency multiplier

        - **Selling Plans**: Finds and applies best matching plans for products

        - **Anchor Days**: Updates billing anchor for consistent scheduling

        - **Email Notifications**: Sends 'ORDER_FREQUENCY_UPDATED' to customer

        - **Activity Logs**: Records both billing and delivery changes


        **Prepaid vs Pay-Per-Delivery:**

        - Pay-per-delivery: Billing and delivery intervals typically match

        - Prepaid: Customer pays upfront for multiple deliveries

        - This endpoint enforces prepaid logic to prevent undercharging


        **Authentication:** Requires valid X-API-Key header
      operationId: updateBillingIntervalV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to update. Provide the numeric ID without
            the gid:// prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: intervalCount
          in: query
          description: >-
            Number of intervals between billings. For example, intervalCount=2
            with interval=WEEK means 'every 2 weeks'
          required: true
          schema:
            maximum: 365
            minimum: 1
            type: integer
          example: 2
        - name: interval
          in: query
          description: Type of interval for billing frequency
          required: true
          schema:
            type: string
            enum:
              - DAY
              - WEEK
              - MONTH
              - YEAR
              - $UNKNOWN
          example: MONTH
      responses:
        '200':
          description: Billing interval updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T12:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 2
                      anchors:
                        - type: MONTHDAY
                          day: 1
                    deliveryPolicy:
                      interval: MONTH
                      intervalCount: 2
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172011164
                            currentPrice:
                              amount: '59.98'
                              currencyCode: USD
                            sellingPlanId: gid://shopify/SellingPlan/222222
                            sellingPlanName: Deliver every 2 months
                            pricingPolicy:
                              basePrice:
                                amount: '29.99'
                                currencyCode: USD
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Same Interval Error:
                  description: Same Interval Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Billing interval cannot be the same as
                      old billing interval
                    status: 400
                    detail: The subscription is already set to bill every 1 month
                Prepaid Validation Error:
                  description: Prepaid Validation Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Billing interval cannot be less than or
                      equal to delivery interval for prepaid contracts
                    status: 400
                    detail: >-
                      Cannot bill monthly for weekly deliveries in prepaid
                      subscriptions
                Invalid Interval Count:
                  description: Invalid Interval Count
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid interval count
                    status: 400
                    detail: Interval count must be between 1 and 365
                Invalid Interval Type:
                  description: Invalid Interval Type
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid interval type
                    status: 400
                    detail: 'Interval must be one of: DAY, WEEK, MONTH, YEAR'
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Subscription contract not found
                    status: 400
                    detail: No subscription contract found with ID 123456789
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to update billing interval
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: Billing interval update failed due to Shopify constraints
          content:
            application/json:
              examples:
                No Matching Selling Plan:
                  description: No Matching Selling Plan
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: No selling plan available
                    status: 422
                    detail: No selling plan found for the requested billing frequency
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to update billing interval
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
  /api/external/v2/subscription-contracts-update-billing-date:
    put:
      tags:
        - Billing & Payments
      summary: Update next billing date for a subscription contract
      description: >-
        Reschedules the next billing date for an active subscription contract.
        This endpoint allows you to change when the next order will be created
        and processed.


        **Key Features:**

        - Updates the next billing date to the specified date

        - Optionally reschedules all future orders based on the new date

        - Syncs the updated date to Shopify

        - Sends confirmation email to customer


        **The rescheduleFutureOrder Parameter:**

        - **true** (default): Updates the next billing date AND recalculates all
        future queued orders based on the new date. Use this to shift the entire
        billing schedule.

        - **false**: Only updates the next billing date. Other queued orders
        remain unchanged. Use this for one-time date adjustments.


        **Important Notes:**

        - The new date must be in the future (with 10 minute grace period)

        - Date is validated against the shop's timezone

        - If anchor days are configured, future orders may align to those
        anchors


        **Process Flow:**

        1. Validates the contract exists and belongs to the shop

        2. Validates the new date is not in the past

        3. Updates the billing attempt to the new date

        4. Syncs the updated nextBillingDate to Shopify

        5. If rescheduleFutureOrder=true, regenerates the queue from the new
        date

        6. Sends confirmation email to customer

        7. Records activity log entry


        **Date Format:**

        - Must be ISO 8601 format with timezone

        - Examples: `2024-03-15T12:00:00Z`, `2024-03-15T12:00:00+05:30`

        - URL encode the date when passing as query parameter


        **Timezone Handling:**

        - The provided date is used as-is for the billing attempt

        - Validation (past date check) uses the shop's configured timezone

        - All dates in the response are in UTC (Z suffix)


        **Date Restrictions (Customer Portal Only):**

        When called from customer portal context:

        - Minimum days from today (skipDaysFromCurrentDate setting)

        - Maximum days from today (billingDateRestrictToDays setting)

        - External API calls bypass these restrictions


        **Authentication:** Requires valid X-API-Key header
      operationId: updateNextBillingDateV2
      parameters:
        - name: contractId
          in: query
          description: Subscription contract ID to update
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: rescheduleFutureOrder
          in: query
          description: >-
            If true (or value not provided), next billing date will be changed
            and also schedule for future upcoming orders will be changed based
            on new updated billing date.

            If false, then only next billing date will be changed, but the
            schedule for future upcoming orders will not change.
          required: false
          schema:
            type: boolean
            default: true
          example: true
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: nextBillingDate
          in: query
          description: >-
            New billing date in ISO 8601 format with timezone. The date must be
            in the future and may be subject to merchant-configured
            restrictions. Common formats:

            - UTC: 2024-03-15T12:00:00Z

            - With offset: 2024-03-15T12:00:00+05:30

            - With timezone: 2024-03-15T12:00:00[America/New_York]


            The system will convert the date to the shop's timezone for
            validation.
          required: true
          schema:
            pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|[+-]\d{2}:\d{2}|\[.+\])$
            type: string
            format: date-time
          example: '2024-03-15T12:00:00Z'
      responses:
        '200':
          description: >-
            Billing date successfully updated. The response contains the updated
            subscription contract from Shopify with the new nextBillingDate.
          headers:
            X-Application-Context:
              description: Application context with alert message
              style: simple
              schema:
                type: string
                example: 'appname:Subscription Updated:'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    __typename: SubscriptionContract
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-03-15T12:00:00Z'
                    updatedAt: '2024-02-15T10:30:00Z'
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                    customer:
                      email: customer@example.com
                      displayName: John Doe
        '400':
          description: Invalid request or date validation failed
          content:
            application/json:
              examples:
                Date in Past:
                  summary: Billing date cannot be in the past
                  description: Date in Past
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      The billing date you are trying to set
                      (2024-01-01T00:00:00Z) is in the past. Billing dates
                      cannot be updated to a time that has already passed.
                      Please select a future billing date.
                    status: 400
                    detail: The billing date must be a future date
                    instance: >-
                      /api/external/v2/subscription-contracts-update-billing-date
                Date Outside Allowed Range:
                  summary: Customer portal date restrictions
                  description: Date Outside Allowed Range
                  value:
                    type: https://example.com/errors/bad-request
                    title: Can't reschedule on this 2024-12-31T00:00:00Z
                    status: 400
                    detail: >-
                      The selected date is outside the allowed range for
                      rescheduling
                    instance: >-
                      /api/external/v2/subscription-contracts-update-billing-date
                Contract Not Found:
                  summary: Invalid contract ID
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Contract does not exist
                    status: 400
                    detail: No subscription contract found with the specified ID
                    instance: >-
                      /api/external/v2/subscription-contracts-update-billing-date
                Invalid Date Format:
                  summary: Date must be ISO 8601 format
                  description: Invalid Date Format
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid date format
                    status: 400
                    detail: >-
                      Date must be in ISO 8601 format with timezone (e.g.,
                      2024-03-15T12:00:00Z or 2024-03-15T12:00:00+05:30)
                    instance: >-
                      /api/external/v2/subscription-contracts-update-billing-date
                Shopify API Error:
                  summary: Failed to sync with Shopify
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Unable to update billing date
                    status: 400
                    detail: >-
                      Shopify returned an error when attempting to update the
                      billing date
                    instance: >-
                      /api/external/v2/subscription-contracts-update-billing-date
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
                instance: /api/external/v2/subscription-contracts-update-billing-date
        '403':
          description: Insufficient permissions to update billing date
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
                instance: /api/external/v2/subscription-contracts-update-billing-date
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: >-
                  Subscription contract with the specified ID not found in the
                  system
                instance: /api/external/v2/subscription-contracts-update-billing-date
  /api/external/v2/subscription-contracts-remove-line-items:
    put:
      tags:
        - Subscription Products
      summary: Remove multiple products from subscription
      description: >-
        Removes multiple product line items from an existing subscription
        contract in a single request. Products are removed sequentially,
        allowing partial success if errors occur.


        **Key Features:**

        - Sequential processing - items removed one by one

        - Partial success allowed - previous removals persist if later ones fail

        - Validates each removal against current subscription state

        - Smart discount cleanup for line-specific discounts

        - Comprehensive validation for each product removal

        - Triggers all side effects after each successful removal


        **Processing Order Matters:**

        Items are removed in the order provided:

        1. First item validated and removed

        2. Second item validated against updated state

        3. Continue until all processed or error occurs

        4. Returns final subscription state


        **Validation Per Item:**

        - Line item must exist in subscription

        - At least one recurring product must remain

        - Build-a-Box min/max quantities maintained

        - Minimum cycle commitments honored

        - One-time and free products don't count toward minimum


        **Discount Handling:**

        When `removeDiscount=true`:

        - Removes discounts applied ONLY to the removed line

        - Preserves discounts that apply to multiple lines

        - Each removal evaluates discounts independently

        - Build-a-Box discounts auto-adjust based on quantity


        **Side Effects Per Removal:**

        Each successful removal triggers:

        - Activity log entry created

        - Customer email sent (except one-time products)

        - Shipping price recalculation

        - Build-a-Box discount resync

        - Product discount adjustments


        **Partial Success Scenarios:**

        If removing 3 items and the 2nd fails:

        - 1st item: Successfully removed

        - 2nd item: Fails, error returned

        - 3rd item: Not attempted

        - Result: Subscription with 1st item removed


        **Performance Considerations:**

        - Each removal is a separate Shopify API transaction

        - Multiple emails may be sent to customer

        - Consider using single remove for 1-2 items

        - Large batches may timeout

        - Recommended max: 5-10 items per request


        **Build-a-Box Handling:**

        For Build-a-Box subscriptions:

        - Validates total quantity after EACH removal

        - May fail mid-batch if minimum breached

        - Discounts recalculate after each item

        - Consider removal order carefully


        **Important Notes:**

        - NOT atomic - no rollback on partial failure

        - Order of line IDs affects success probability

        - Customer receives email per removed item

        - All validations apply as if removing individually

        - Response shows final state after all attempts


        **Authentication:** Requires valid X-API-Key header
      operationId: removeLineItems
      parameters:
        - name: contractId
          in: query
          description: Subscription contract ID to remove products from
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
        - name: removeDiscount
          in: query
          description: >-
            When true, removes discounts that apply only to each removed line
            item. When false, attempts to retain all discounts. Discounts that
            apply to multiple lines are always retained regardless of this
            setting.
          required: false
          schema:
            type: boolean
            default: false
          example: false
      requestBody:
        content:
          application/json:
            schema:
              type: array
              description: >-
                List of line item IDs to remove. IDs must be in full GraphQL
                format. Items are processed sequentially in the order provided.
                If any removal fails, processing stops but previous removals are
                kept.
              items:
                type: string
        required: true
      responses:
        '200':
          description: >-
            Products successfully removed from subscription (full or partial
            success)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/333333
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172076700
                            title: Essential Product - Monthly
                            currentPrice:
                              amount: '19.99'
                              currencyCode: USD
                    discounts:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionManualDiscount/444444
                            title: 10% OFF ALL ITEMS
                            targetType: ALL_LINES
        '207':
          description: Multi-Status - Some items removed successfully, others failed
          content:
            application/json:
              example:
                type: https://example.com/partial-success
                title: Partial success
                status: 207
                detail: 2 of 3 items removed successfully
                removedLineIds:
                  - gid://shopify/SubscriptionLine/111111
                  - gid://shopify/SubscriptionLine/222222
                failedLineIds:
                  - lineId: gid://shopify/SubscriptionLine/333333
                    error: Would violate minimum product requirement
        '400':
          description: Invalid contract ID or line item IDs - may indicate partial failure
          content:
            application/json:
              examples:
                Line Item Not Found (Partial Success):
                  description: Line Item Not Found (Partial Success)
                  value:
                    type: https://example.com/errors/bad-request
                    title: Couldn't find LineId=gid://shopify/SubscriptionLine/999999
                    status: 400
                    detail: >-
                      Line item not found. Previous items in batch may have been
                      removed successfully.
                Would Remove Last Product:
                  description: Would Remove Last Product
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Cannot remove line item. Atleast one
                      subscription product must be present in a subscription
                    status: 400
                    detail: >-
                      Removing these items would leave no recurring products in
                      the subscription
                Build-a-Box Minimum Violation:
                  description: Build-a-Box Minimum Violation
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Minimum 6 quantity is required
                    status: 400
                    detail: >-
                      Removing item would violate Build-a-Box minimum quantity.
                      Some items may have been removed.
                    code: minQuantityNotReached
                Minimum Cycles Not Met:
                  description: Minimum Cycles Not Met
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Subscription cannot be modified until 3
                      orders have completed.
                    status: 400
                    detail: >-
                      Product has minimum cycle requirement. Previous removals
                      in batch were successful.
                Empty Line IDs List:
                  description: Empty Line IDs List
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid request body
                    status: 400
                    detail: Line IDs list cannot be empty
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: >-
            One or more products cannot be removed due to subscription
            constraints
          content:
            application/json:
              examples:
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to remove line item
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
                Concurrent Modification:
                  description: Concurrent Modification
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: >-
                      UserGeneratedError:The subscription contract has changed.
                      Retry the operation.
                    status: 422
                    detail: >-
                      Another process modified the subscription. Some items may
                      have been removed.
  /api/external/v2/subscription-contracts-remove-line-item:
    put:
      tags:
        - Subscription Products
      summary: Remove product from subscription
      description: >-
        Removes a specific product line item from an existing subscription
        contract. Can optionally retain prorated discounts associated with the
        removed product.


        **Key Features:**

        - Validates minimum subscription requirements before removal

        - Handles discount cleanup for line-specific discounts

        - Enforces minimum cycle commitments on products

        - Supports Build-a-Box quantity validation

        - Automatic retry on concurrent modification conflicts

        - Email notifications for subscription changes


        **Validation Rules:**

        - At least one recurring subscription product must remain after removal

        - One-time products and free products don't count toward the minimum

        - Products with minimum cycle commitments cannot be removed until
        fulfilled

        - Build-a-Box subscriptions validate against minimum/maximum quantity
        rules


        **Discount Handling:**

        When `removeDiscount=true` (default):

        - Discounts applied only to the removed line item are deleted

        - Discounts applied to multiple line items are retained

        - System automatically identifies which discounts to remove


        **Retry Mechanism:**

        The endpoint automatically retries in these scenarios:

        - Concurrent modification detected (another process updated the
        subscription)

        - Invalid discount code errors (removes problematic discount and
        retries)

        - This ensures reliable operation in high-traffic environments


        **Post-Removal Actions:**

        - Activity log created for audit trail

        - Email notification sent to customer (except for one-time products)

        - Shipping price recalculated asynchronously

        - Build-a-Box discounts resynced if applicable

        - Product-specific discounts resynced


        **Authentication:** Requires valid X-API-Key header
      operationId: removeLineItemV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to remove product from. Provide the numeric
            ID without the gid:// prefix
          required: true
          schema:
            pattern: ^[0-9]+$
            type: string
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: lineId
          in: query
          description: >-
            Line item ID of the product to remove. Must be the full GraphQL ID
            including the gid:// prefix
          required: true
          schema:
            type: string
          example: gid://shopify/SubscriptionLine/123456789
        - name: removeDiscount
          in: query
          description: >-
            Controls whether to remove discounts that apply only to this line
            item. When true (default), line-specific discounts are removed. When
            false, attempts to retain discounts where possible. Note: Discounts
            that apply to multiple lines are always retained regardless of this
            setting
          required: false
          schema:
            type: boolean
            default: true
          example: true
      responses:
        '200':
          description: Product successfully removed from subscription
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-03-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                      firstName: John
                      lastName: Doe
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                    deliveryPolicy:
                      interval: MONTH
                      intervalCount: 1
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 2
                            variantId: gid://shopify/ProductVariant/42549172011164
                            currentPrice:
                              amount: '29.99'
                              currencyCode: USD
                            sellingPlanId: gid://shopify/SellingPlan/123456
                            sellingPlanName: Deliver every month
                    discounts:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionManualDiscount/999999
                            title: 10% OFF SUBSCRIPTION
                            targetType: ALL_LINES
                            value:
                              percentage: 10
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Line Item Not Found:
                  description: Line Item Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Couldn't find LineId=gid://shopify/SubscriptionLine/999999
                    status: 400
                    detail: >-
                      The specified line item does not exist in this
                      subscription
                Last Product Removal Attempt:
                  description: Last Product Removal Attempt
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Cannot remove line item. Atleast one
                      subscription product must be present in a subscription
                    status: 400
                    detail: >-
                      Cannot remove the last recurring product from the
                      subscription
                Minimum Cycles Not Met:
                  description: Minimum Cycles Not Met
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:This product requires a minimum
                      commitment of {{minCycles}} billing cycles before removal
                    status: 400
                    detail: >-
                      Product has a minimum cycle requirement that has not been
                      fulfilled
                Build-a-Box Validation Error:
                  description: Build-a-Box Validation Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Removing this item would violate the
                      minimum quantity requirement for your Build-a-Box
                      subscription
                    status: 400
                    detail: >-
                      Build-a-Box subscriptions must maintain minimum item
                      quantities
                Invalid Line ID Format:
                  description: Invalid Line ID Format
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid line item ID format
                    status: 400
                    detail: >-
                      Line ID must be in format:
                      gid://shopify/SubscriptionLine/[numeric_id]
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: Unable to process the removal due to Shopify API constraints
          content:
            application/json:
              examples:
                Draft Commit Error:
                  description: Draft Commit Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to commit subscription changes
                    status: 422
                    detail: 'Shopify API error: Billing attempt in progress'
                Concurrent Modification:
                  description: Concurrent Modification
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: >-
                      The subscription contract has changed. Retry the
                      operation.
                    status: 422
                    detail: >-
                      Another process modified the subscription. The system will
                      automatically retry.
  /api/external/v2/subscription-contracts-remove-discount:
    put:
      tags:
        - Subscription Discounts
      summary: Remove discount from subscription
      description: >-
        Removes a specific discount from a subscription contract based on the
        discount ID. This will affect the pricing of all future orders generated
        by the subscription.


        **Key Features:**

        - Removes any type of discount: automatic, manual, or code-based

        - Uses Shopify's draft system for safe removal

        - Immediate effect on future order pricing

        - Cannot be undone - discount must be re-applied if needed

        - Activity log tracks removed discounts


        **Finding Discount IDs:**

        Discount IDs can be found in the subscription contract's discount
        collection:

        - Query the subscription contract to see `discounts.edges[].node.id`

        - Format: `gid://shopify/SubscriptionManualDiscount/123456`

        - Each discount has a unique ID regardless of type


        **Types of Discounts:**

        - **Manual Discounts**: Applied via API (percentage, fixed, price)

        - **Code Discounts**: Applied using discount codes

        - **Automatic Discounts**: Applied by Shopify based on rules

        - **Build-a-Box Discounts**: Volume-based discounts

        - **Selling Plan Discounts**: Built into the subscription plan


        **Impact on Pricing:**

        When a discount is removed:

        - Future orders use full price (no discount)

        - Existing orders are not affected

        - Other discounts remain active

        - Shipping prices may be recalculated

        - Customer sees updated pricing immediately


        **Common Use Cases:**

        - End promotional period discounts

        - Remove expired or invalid discount codes

        - Clear discounts before applying new ones

        - Customer service adjustments

        - Correct pricing errors


        **Important Notes:**

        - Cannot remove selling plan built-in discounts

        - No customer notification sent (consider sending separately)

        - Cannot selectively remove - removes entire discount

        - Build-a-Box discounts may auto-reapply based on quantity

        - Some discounts may be required by business rules


        **Post-Removal Considerations:**

        - Customer may notice price increase on next order

        - May affect customer retention if unexpected

        - Consider grace periods or notifications

        - Document reason for removal in your system


        **Authentication:** Requires valid X-API-Key header
      operationId: removeDiscountV2
      parameters:
        - name: contractId
          in: query
          description: Subscription contract ID to remove discount from
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
        - name: discountId
          in: query
          description: >-
            ID of the discount to be removed. Must be the full GraphQL ID
            including the gid:// prefix. You can find discount IDs by querying
            the subscription contract and looking at the discounts collection.
            Format example: gid://shopify/SubscriptionManualDiscount/123456789
          required: true
          schema:
            type: string
          example: gid://shopify/SubscriptionManualDiscount/123456789
      responses:
        '200':
          description: Discount successfully removed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 2
                            variantId: gid://shopify/ProductVariant/42549172011164
                            title: Premium Coffee - Monthly Supply
                            currentPrice:
                              amount: '39.99'
                              currencyCode: USD
                            pricingPolicy:
                              basePrice:
                                amount: '39.99'
                                currencyCode: USD
                    discounts:
                      edges: []
                    deliveryPrice:
                      amount: '5.99'
                      currencyCode: USD
        '400':
          description: Invalid contract ID or discount ID
          content:
            application/json:
              examples:
                Discount Not Found:
                  description: Discount Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      Discount with id
                      gid://shopify/SubscriptionManualDiscount/999999 not found
                    status: 400
                    detail: The specified discount does not exist on this subscription
                Invalid Discount ID Format:
                  description: Invalid Discount ID Format
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid discount ID format
                    status: 400
                    detail: >-
                      Discount ID must be in format:
                      gid://shopify/SubscriptionManualDiscount/[numeric_id]
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Contract does not exist
                    status: 400
                    detail: No subscription contract found with ID 123456789
                Cannot Remove System Discount:
                  description: Cannot Remove System Discount
                  value:
                    type: https://example.com/errors/bad-request
                    title: Cannot remove this discount
                    status: 400
                    detail: >-
                      This discount is required by the subscription plan and
                      cannot be removed
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: Discount exists but cannot be removed
          content:
            application/json:
              examples:
                Draft Creation Failed:
                  description: Draft Creation Failed
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to create subscription draft
                    status: 422
                    detail: >-
                      Subscription is currently being modified by another
                      process
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to remove discount
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
  /api/external/v2/subscription-contracts-bulk-update-line-item-attributes:
    put:
      tags:
        - Subscription Contracts
      summary: Replace all line item attributes in bulk across subscription contracts
      description: >-
        This API replaces all existing attributes for the specified line items
        within subscription contracts. Use carefully, as any attributes not
        included in the request will be removed.
      operationId: updateMultipleContractsLineItemAttributesV2
      parameters:
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
        - name: contractIds
          in: query
          description: >-
            Optional comma-separated list of subscription contract IDs to
            update. Example: 32665403611,3266540311,326654036123. Ignored if
            allSubscriptions=true.
          required: false
          schema:
            type: string
        - name: allSubscriptions
          in: query
          description: >-
            If true, updates all active subscriptions of the shop. If false
            (default), updates only the provided contractId or contractIds.
          required: false
          schema:
            type: boolean
            default: false
      requestBody:
        description: >-
          A JSON array of attributes. ⚠️ Note: Providing this array will replace
          all existing attributes in the specified contract. Add or update
          attributes carefully, as any attributes not included in the request
          will be removed.
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/AttributeInfo'
            examples:
              Attributes Example:
                description: Attributes Example
                value:
                  - key: color
                    value: red
                  - key: size
                    value: M
      responses:
        '200':
          description: OK
          content:
            '*/*':
              schema:
                type: string
  /api/external/v2/subscription-contracts-apply-discount:
    put:
      tags:
        - Subscription Discounts
      summary: Apply discount code to subscription
      description: >-
        Applies a Shopify discount code to an existing subscription contract.
        The discount will be applied to future orders generated by this
        subscription.


        **Key Features:**

        - Validates discount code through Shopify's discount system

        - Prevents duplicate discount code applications

        - Uses database locking to prevent race conditions

        - Automatically recalculates shipping prices if needed

        - Creates audit trail through activity logs

        - Returns updated subscription with discount details


        **Discount Code Validation:**

        - Must be an active Shopify discount code in the store

        - Must be applicable to subscription orders

        - Cannot be applied if already active on the subscription

        - Subject to Shopify's discount rules and restrictions


        **Customer Portal Restrictions:**

        When called from customer portal context:

        - If 'enableAllowOnlyOneDiscountCode' is enabled, customers cannot apply
        additional codes

        - This restriction ensures single discount policy enforcement

        - External API calls bypass this restriction


        **Concurrency Protection:**

        - Uses database-level locking on the subscription contract

        - Prevents simultaneous discount applications

        - Ensures data consistency in high-traffic scenarios


        **Post-Application Effects:**

        - Discount applies to all future orders from the subscription

        - May trigger shipping price recalculation

        - Creates 'DISCOUNT_APPLIED' activity log entry

        - Updates subscription's discount collection


        **Important Notes:**

        - Discount codes are case-sensitive

        - Invalid or expired codes will return appropriate errors

        - Discounts stack according to Shopify's combination rules

        - Some discounts may not be compatible with subscriptions


        **Authentication:** Requires valid X-API-Key header
      operationId: applyDiscountCodeV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to apply discount to. Provide the numeric
            ID without the gid:// prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: discountCode
          in: query
          description: >-
            Valid Shopify discount code to apply. Case-sensitive. Must be an
            active discount code in your Shopify store.
          required: true
          schema:
            maxLength: 255
            minLength: 1
            pattern: ^[A-Za-z0-9_-]+$
            type: string
          example: SAVE10
      responses:
        '200':
          description: Discount code successfully applied
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-03-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                      firstName: John
                      lastName: Doe
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 2
                            variantId: gid://shopify/ProductVariant/42549172011164
                            currentPrice:
                              amount: '29.99'
                              currencyCode: USD
                    discounts:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionManualDiscount/888888
                            title: SAVE10
                            targetType: ALL_LINES
                            value:
                              percentage: 10
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Discount Already Applied:
                  description: Discount Already Applied
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Discount is already applied
                    status: 400
                    detail: >-
                      The discount code SAVE10 is already active on this
                      subscription
                Invalid Discount Code:
                  description: Invalid Discount Code
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Discount code is invalid
                    status: 400
                    detail: The discount code INVALID123 does not exist or has expired
                Multiple Discounts Not Allowed:
                  description: Multiple Discounts Not Allowed
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Permission denied, Subscription cannot
                      be modified
                    status: 400
                    detail: Only one discount code is allowed per subscription
                Discount Not Applicable:
                  description: Discount Not Applicable
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Discount cannot be applied to
                      subscriptions
                    status: 400
                    detail: >-
                      This discount code is not configured for subscription
                      orders
                Empty Discount Code:
                  description: Empty Discount Code
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid discount code
                    status: 400
                    detail: Discount code cannot be empty
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Subscription contract not found
                status: 404
                detail: No subscription contract found with ID 123456789
        '409':
          description: Concurrent modification conflict
          content:
            application/json:
              example:
                type: https://example.com/errors/conflict
                title: Subscription is being modified
                status: 409
                detail: >-
                  Another operation is currently modifying this subscription.
                  Please try again.
        '422':
          description: >-
            Discount code exists but cannot be applied due to Shopify
            constraints
          content:
            application/json:
              examples:
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to apply discount code
                    status: 422
                    detail: >-
                      Shopify API error: Discount code minimum purchase
                      requirement not met
                Draft Commit Error:
                  description: Draft Commit Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to commit subscription changes
                    status: 422
                    detail: Cannot modify subscription during active billing attempt
  /api/external/v2/subscription-contracts-add-line-items:
    put:
      tags:
        - Subscription Products
      summary: Add multiple products to subscription
      description: >-
        Adds multiple product line items to an existing subscription contract in
        a single request. This batch operation is more efficient than making
        multiple individual requests and ensures all products are added with
        consistent processing.


        **Key Features:**

        - Batch addition of multiple products in one API call

        - All products are added as recurring items (not one-time)

        - Automatic quantity defaulting (0 or null becomes 1)

        - Sequential processing with full validation for each item

        - Returns final subscription state after all additions

        - Same pricing and discount logic as single-item endpoint


        **Processing Behavior:**

        - Products are added sequentially, not in parallel

        - If any product fails, previous additions remain

        - Each product goes through full validation

        - Existing product handling follows store settings

        - Activity logs created for each product added


        **Duplicate Product Handling:**

        If a product already exists in the subscription:

        - With 'updateExistingQuantityOnAddProduct' enabled: Updates quantity

        - Without setting: Adds as new line item

        - Setting applies to all products in the batch


        **Pricing and Discounts:**

        Each product receives:

        - Appropriate selling plan assignment

        - Discount carry-forward based on store settings

        - Currency and country-specific pricing

        - Fulfillment frequency multiplier application


        **Build-a-Box Validation:**

        - Applied if any product has _bb_id attribute

        - Validates total quantity after all additions

        - May fail entire batch if limits exceeded


        **Post-Processing:**

        After all products are added:

        - Build-a-Box discounts recalculated once

        - Product discounts synchronized

        - Single email notification sent

        - Shipping price updated once


        **Important Notes:**

        - Maximum recommended batch size: 10-20 products

        - Larger batches may timeout

        - All products become recurring items

        - Use single-item endpoint for one-time products


        **Authentication:** Requires valid X-API-Key header
      operationId: addLineItems
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to add products to. Provide the numeric ID
            without the gid:// prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      requestBody:
        description: >-
          Map of variant IDs to quantities. Keys are variant IDs (numeric only,
          no gid:// prefix), values are quantities to add. Null or 0 quantities
          default to 1.
        content:
          application/json:
            schema:
              type: string
            examples:
              Add Three Products:
                description: Add Three Products
                value:
                  '42549172011164': 1
                  '42549172043932': 2
                  '42549172076700': 1
              Build-a-Box Bundle:
                description: Build-a-Box Bundle
                value:
                  '42549172011164': 2
                  '42549172043932': 2
                  '42549172076700': 2
                  '42549172109468': 1
                  '42549172142236': 1
              With Default Quantities:
                description: With Default Quantities
                value:
                  '42549172011164': 0
                  '42549172043932': null
                  '42549172076700': 3
        required: true
      responses:
        '200':
          description: Products successfully added to subscription
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T12:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                    deliveryPolicy:
                      interval: MONTH
                      intervalCount: 1
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 2
                            variantId: gid://shopify/ProductVariant/42549172011164
                            title: Premium Coffee - Dark Roast
                            currentPrice:
                              amount: '59.98'
                              currencyCode: USD
                            sellingPlanId: gid://shopify/SellingPlan/123456
                            sellingPlanName: Deliver every month
                        - node:
                            id: gid://shopify/SubscriptionLine/222222
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172043932
                            title: Organic Tea - Green
                            currentPrice:
                              amount: '24.99'
                              currencyCode: USD
                            sellingPlanId: gid://shopify/SellingPlan/123456
                            sellingPlanName: Deliver every month
                        - node:
                            id: gid://shopify/SubscriptionLine/333333
                            quantity: 2
                            variantId: gid://shopify/ProductVariant/42549172076700
                            title: Coffee Filters - 100 pack
                            currentPrice:
                              amount: '19.98'
                              currencyCode: USD
                            sellingPlanId: gid://shopify/SellingPlan/123456
                            sellingPlanName: Deliver every month
                    discounts:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionManualDiscount/444444
                            title: BUILD_A_BOX_DISCOUNT_ABC123
                            targetType: ALL_LINES
                            value:
                              percentage: 20
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Empty Request Body:
                  description: Empty Request Body
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid request body
                    status: 400
                    detail: >-
                      Request body must contain at least one variant ID and
                      quantity
                Invalid Variant ID:
                  description: Invalid Variant ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: 'Product Variant not found for ID: 99999999999'
                    status: 400
                    detail: One or more product variants do not exist
                Build-a-Box Maximum Exceeded:
                  description: Build-a-Box Maximum Exceeded
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Maximum 12 quantity is required
                    status: 400
                    detail: Adding these products would exceed Build-a-Box limits
                Invalid Quantity:
                  description: Invalid Quantity
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid quantity value
                    status: 400
                    detail: Quantities must be positive integers
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: One or more products cannot be added due to Shopify constraints
          content:
            application/json:
              examples:
                Product Not Available for Subscription:
                  description: Product Not Available for Subscription
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: >-
                      UserGeneratedError:Product is not available for
                      subscription
                    status: 422
                    detail: >-
                      One or more products are not configured for subscription
                      sales
                Partial Success Warning:
                  description: Partial Success Warning
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Partial success
                    status: 422
                    detail: Some products were added successfully, but others failed
                    addedVariants:
                      - '42549172011164'
                      - '42549172043932'
                    failedVariants:
                      - variantId: '42549172076700'
                        error: No selling plan available
  /api/external/v2/subscription-contracts-add-line-item:
    put:
      tags:
        - Subscription Products
      summary: Add product to subscription
      description: >-
        Adds a new product line item to an existing subscription contract. Can
        add either recurring products that will appear in each order or one-time
        products that appear only in the next order.


        **Key Features:**

        - Supports both recurring and one-time product additions

        - Automatically applies appropriate pricing policies based on discount
        carry-forward settings

        - Handles duplicate products by updating quantity (if enabled) or adding
        as new line

        - Calculates prices based on billing/delivery frequency multipliers

        - Sends email notifications to customers (unless suppressed)

        - Creates activity logs for audit trail


        **Pricing Policy Application:**

        The system applies discounts based on the store's discount carry-forward
        setting:

        - **PRODUCT_PLAN**: Uses the discount from the product's selling plan

        - **EXISTING_PLAN**: Applies the discount structure from existing
        subscription items

        - **PRODUCT_THEN_EXISTING**: First attempts product plan, falls back to
        existing if not found


        **One-Time Products:**

        Products added with `isOneTimeProduct=true` will:

        - Only appear in the next scheduled order

        - Be automatically removed after fulfillment

        - Still attempt to match with appropriate selling plans

        - Can have subscription discounts applied if store setting allows


        **Duplicate Product Handling:**

        When adding a product that already exists in the subscription:

        - If store has 'updateExistingQuantityOnAddProduct' enabled and product
        is not one-time: Updates existing quantity

        - Otherwise: Adds as a new line item


        **Price Calculation:**

        - Base price is fetched considering contract currency and delivery
        country

        - Price is multiplied by fulfillment frequency ratio (billing interval /
        delivery interval)

        - Example: Monthly billing with weekly delivery = price × 4


        **Authentication:** Requires valid X-API-Key header
      operationId: addLineItemV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to add product to. Provide the numeric ID
            without the gid:// prefix
          required: true
          schema:
            pattern: ^[0-9]+$
            type: string
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: quantity
          in: query
          description: Quantity of product to add. Must be a positive integer
          required: true
          schema:
            maximum: 999
            minimum: 1
            type: integer
          example: 2
        - name: variantId
          in: query
          description: >-
            Shopify variant ID of the product to add. Can be provided as numeric
            ID or with gid:// prefix
          required: true
          schema:
            pattern: ^([0-9]+|gid://shopify/ProductVariant/[0-9]+)$
            type: string
          example: 42549172011164
        - name: isOneTimeProduct
          in: query
          description: >-
            When true, product will only be included in the next order and
            automatically removed after fulfillment. When false, product will be
            included in all future orders until manually removed or subscription
            ends. One-time products are useful for samples, gifts, or
            limited-time additions
          required: false
          schema:
            type: boolean
            default: false
          example: false
      responses:
        '200':
          description: Product successfully added to subscription
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-03-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                      firstName: John
                      lastName: Doe
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                    deliveryPolicy:
                      interval: MONTH
                      intervalCount: 1
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 2
                            variantId: gid://shopify/ProductVariant/42549172011164
                            currentPrice:
                              amount: '29.99'
                              currencyCode: USD
                            sellingPlanId: gid://shopify/SellingPlan/123456
                            sellingPlanName: Deliver every month
                        - node:
                            id: gid://shopify/SubscriptionLine/222222
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/98765432101
                            currentPrice:
                              amount: '19.99'
                              currencyCode: USD
                            customAttributes:
                              - key: _one_time_product
                                value: 'true'
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Invalid Contract ID:
                  description: Invalid Contract ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Subscription contract not found
                    status: 400
                    detail: 'No subscription contract found with ID: 123456789'
                Product Variant Not Found:
                  description: Product Variant Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: 'Product Variant not found for ID: 99999999999'
                    status: 400
                    detail: The specified product variant does not exist in the store
                Invalid Quantity:
                  description: Invalid Quantity
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Invalid quantity
                    status: 400
                    detail: Quantity must be greater than 0
                Build-a-Box Validation Error:
                  description: Build-a-Box Validation Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Build-a-box quantity limit exceeded
                    status: 400
                    detail: >-
                      Adding this quantity would exceed the maximum allowed
                      items for this build-a-box subscription
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: Unable to process the request due to Shopify API constraints
          content:
            application/json:
              examples:
                Shopify GraphQL Error:
                  description: Shopify GraphQL Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: subscriptionDraftLineAddError
                    status: 422
                    detail: >-
                      Shopify API error: Product is not available for
                      subscription
                Draft Commit Error:
                  description: Draft Commit Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: subscriptionDraftCommitError
                    status: 422
                    detail: >-
                      Unable to commit subscription changes: Billing attempt in
                      progress
  /api/external/v2/subscription-contracts-add-discount:
    put:
      tags:
        - Subscription Discounts
      summary: Add custom discount to subscription
      description: >-
        Creates and applies a custom manual discount to an existing subscription
        contract. This powerful endpoint supports multiple discount types and
        configurations for flexible pricing strategies.


        **Discount Types:**

        - **PERCENTAGE**: Percentage off the order (e.g., 10% off)

        - **FIXED**: Fixed amount off the order (e.g., $10 off)

        - **PRICE**: Override price (sets total to specific amount)


        **Key Features:**

        - Custom discount titles for easy identification

        - Cycle limits for time-bound promotions

        - Per-item or subtotal application options

        - Stacks with other discounts per Shopify rules

        - Automatic shipping price recalculation

        - Activity logging for audit trails


        **Application Methods:**

        - **Subtotal Discount** (appliesOnEachItem=false): Applied to order
        total after line item calculations

        - **Per-Item Discount** (appliesOnEachItem=true): Applied to each line
        item individually


        **Cycle Limits:**

        - Set recurringCycleLimit to apply discount for specific number of
        orders

        - Leave null for unlimited duration

        - Useful for '3 months at 20% off' promotions


        **Retention Campaigns:**

        This endpoint integrates with cancellation retention workflows:

        - Can trigger merchant notifications

        - Tracks discount usage for retention analytics

        - Helps prevent churn with targeted offers


        **Important Notes:**

        - Discounts apply to future orders only

        - Cannot modify discounts once applied (must remove and re-add)

        - Some discount combinations may not be allowed by Shopify

        - Price overrides should be used carefully


        **Authentication:** Requires valid X-API-Key header
      operationId: addDiscountV2
      parameters:
        - name: contractId
          in: query
          description: >-
            Subscription contract ID to apply discount to. Provide the numeric
            ID without the gid:// prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: percentage
          in: query
          description: >-
            Discount percentage (1-100). Required when discountType is
            PERCENTAGE
          required: false
          schema:
            maximum: 100
            minimum: 1
            type: integer
          example: 10
        - name: discountTitle
          in: query
          description: >-
            Custom title for the discount. If not provided, a default title will
            be generated
          required: false
          schema:
            maxLength: 255
            type: string
          example: Loyalty Discount
        - name: recurringCycleLimit
          in: query
          description: >-
            Number of billing cycles the discount applies to. Leave null for
            unlimited duration
          required: false
          schema:
            maximum: 9999
            minimum: 1
            type: integer
          example: 3
        - name: appliesOnEachItem
          in: query
          description: >-
            Application method: true = apply to each line item individually,
            false = apply to order subtotal
          required: false
          schema:
            type: boolean
            default: false
          example: false
        - name: amount
          in: query
          description: >-
            Fixed discount amount in store currency. Required when discountType
            is FIXED or PRICE
          required: false
          schema:
            maximum: 999999.99
            minimum: 0.01
            type: number
            format: double
          example: 10.99
        - name: discountType
          in: query
          description: Type of discount to apply
          required: false
          schema:
            type: string
            enum:
              - PERCENTAGE
              - FIXED
              - PRICE
          example: PERCENTAGE
      responses:
        '200':
          description: Discount successfully added
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T12:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172011164
                            currentPrice:
                              amount: '29.99'
                              currencyCode: USD
                    discounts:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionManualDiscount/555555
                            title: Loyalty Discount
                            targetType: ALL_LINES
                            type: MANUAL
                            recurringCycleLimit: 3
                            value:
                              percentage: 10
        '400':
          description: Invalid parameters for discount creation
          content:
            application/json:
              examples:
                Missing Required Parameter:
                  description: Missing Required Parameter
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid discount parameters
                    status: 400
                    detail: Percentage is required when discountType is PERCENTAGE
                Invalid Discount Type:
                  description: Invalid Discount Type
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid discount type
                    status: 400
                    detail: 'Discount type must be one of: PERCENTAGE, FIXED, PRICE'
                Invalid Percentage Value:
                  description: Invalid Percentage Value
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid percentage value
                    status: 400
                    detail: Percentage must be between 1 and 100
                Invalid Cycle Limit:
                  description: Invalid Cycle Limit
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid cycle limit
                    status: 400
                    detail: Recurring cycle limit must be a positive integer
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Subscription contract with ID 123456789 not found
        '422':
          description: Discount parameters valid but cannot be applied
          content:
            application/json:
              examples:
                Conflicting Discounts:
                  description: Conflicting Discounts
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Discount conflict
                    status: 422
                    detail: >-
                      This discount cannot be combined with existing discounts
                      on the subscription
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to apply discount
                    status: 422
                    detail: >-
                      Shopify API error: Cannot modify subscription during
                      active billing attempt
  /api/external/v2/subscription-contract-one-offs-by-contractId-and-billing-attempt-id:
    put:
      tags:
        - Subscription One-Time Products
      summary: Add one-time product to subscription order
      description: >-
        Adds a one-time product (add-on) to a specific subscription order. The
        product will be included only in the specified billing attempt and will
        not recur in future orders. This endpoint is idempotent - attempting to
        add the same product to the same billing attempt will return success
        without creating duplicates.


        **Important Behaviors:**

        - If the specified billingAttemptId is not valid or not QUEUED, the
        system will automatically add the product to the next upcoming order

        - The system prevents duplicate products (same variantId) in the same
        billing attempt

        - Products are automatically removed after the associated order is
        processed

        - Activity logs are created for audit trails


        **Validation Rules:**

        - Contract must belong to the authenticated shop

        - Contract must not be frozen (minimum cycles restriction)

        - At least one QUEUED billing attempt must exist

        - Variant must be a valid Shopify product variant


        **Use Cases:**

        - Allow customers to add special items to their next delivery

        - Enable upselling opportunities in customer portals

        - Programmatically add promotional or seasonal items

        - Implement "try before you subscribe" features


        **Authentication:** Requires valid X-API-Key header that identifies the
        shop
      operationId: saveOneOffByV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: X-API-Key
          in: header
          description: >-
            API Key for authentication. This key identifies your shop and must
            be included in the X-API-Key header.
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: contractId
          in: query
          description: The unique identifier of the subscription contract
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 98765
        - name: billingAttemptId
          in: query
          description: >-
            The billing attempt ID to add the product to. If invalid or not
            QUEUED, the system will automatically use the next upcoming order.
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 54321
        - name: variantId
          in: query
          description: The Shopify product variant ID to add as a one-time purchase
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 42549172011164
        - name: variantHandle
          in: query
          description: >-
            The handle/slug of the product variant for URL-friendly
            identification
          required: true
          schema:
            pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
            type: string
          example: premium-coffee-blend-500g
        - name: quantity
          in: query
          description: The quantity of the product to add. Defaults to 1 if not specified.
          required: false
          schema:
            maximum: 999
            minimum: 1
            type: integer
            default: 1
          example: 2
      responses:
        '200':
          description: >-
            Successfully added one-time product or product already exists.
            Returns all one-time products for the contract.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionContractOneOffDTO'
              examples:
                Product Added Successfully:
                  description: >-
                    New product added to the list. Response includes all
                    one-time products for the contract.
                  value:
                    - id: 12345
                      shop: example-store.myshopify.com
                      subscriptionContractId: 98765
                      billingAttemptId: 54321
                      variantId: 42549172011164
                      variantHandle: premium-coffee-blend-500g
                      quantity: 2
                      price: 19.99
                    - id: 12350
                      shop: example-store.myshopify.com
                      subscriptionContractId: 98765
                      billingAttemptId: 54321
                      variantId: 42549172011167
                      variantHandle: coffee-sampler-pack
                      quantity: 1
                      price: 29.99
                Product Already Exists:
                  description: >-
                    Product already exists in the billing attempt. No duplicate
                    created. Returns existing list.
                  value:
                    - id: 12345
                      shop: example-store.myshopify.com
                      subscriptionContractId: 98765
                      billingAttemptId: 54321
                      variantId: 42549172011164
                      variantHandle: premium-coffee-blend-500g
                      quantity: 2
                      price: 19.99
                First Product Added:
                  description: First one-time product added to this contract
                  value:
                    - id: 12351
                      shop: example-store.myshopify.com
                      subscriptionContractId: 98765
                      billingAttemptId: 54321
                      variantId: 42549172011168
                      variantHandle: limited-edition-roast
                      quantity: 3
                      price: 34.99
        '400':
          description: Invalid request or business rule violation
          content:
            application/json:
              examples:
                No Queued Orders:
                  description: No Queued Orders
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:No queued billing attempts found
                    status: 400
                    detail: Cannot add one-time product without a scheduled order
                Contract Frozen:
                  description: Contract Frozen
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Contract is frozen
                    status: 400
                    detail: Cannot modify contract under minimum cycle restriction
                Variant Not Found:
                  description: Variant Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Product variant not found
                    status: 400
                    detail: The specified product variant does not exist
        '401':
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: https://example.com/probs/unauthorized
                title: Unauthorized
                status: 401
                detail: Full authentication is required to access this resource
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: https://example.com/probs/forbidden
                title: Forbidden
                status: 403
                detail: Access denied - contract does not belong to authenticated shop
    delete:
      tags:
        - Subscription One-Time Products
      summary: Remove one-time product from subscription order
      description: >-
        Removes a previously added one-time product from a specific subscription
        order. This permanently deletes the one-time product from the specified
        billing attempt. The operation is idempotent - attempting to delete a
        non-existent product will succeed without error.


        **Important Notes:**

        - Only removes the product from the specified billing attempt

        - Cannot remove products from billing attempts that are already
        processed

        - Activity logs are created for audit trails

        - Returns the updated list of all one-time products for the contract


        **Use Cases:**

        - Allow customers to remove unwanted add-ons before order processing

        - Clean up cart-like functionality in customer portals

        - Programmatically manage one-time product selections

        - Implement "undo" functionality for product additions


        **Business Rules:**

        - Contract must belong to the authenticated shop

        - The specific combination of contractId + billingAttemptId + variantId
        identifies the product to remove

        - No error is thrown if the product doesn't exist (idempotent operation)


        **Authentication:** Requires valid X-API-Key header that identifies the
        shop
      operationId: deleteOneOffByV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: X-API-Key
          in: header
          description: >-
            API Key for authentication. This key identifies your shop and must
            be included in the X-API-Key header.
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: contractId
          in: query
          description: The unique identifier of the subscription contract
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 98765
        - name: billingAttemptId
          in: query
          description: The billing attempt ID that contains the product to remove
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 54321
        - name: variantId
          in: query
          description: The Shopify product variant ID to remove from the one-time purchases
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 42549172011164
      responses:
        '200':
          description: >-
            Successfully removed the one-time product or product didn't exist.
            Returns all remaining one-time products for the contract.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionContractOneOffDTO'
              examples:
                Product Removed Successfully:
                  description: >-
                    Product was removed. Response shows remaining one-time
                    products.
                  value:
                    - id: 12345
                      shop: example-store.myshopify.com
                      subscriptionContractId: 98765
                      billingAttemptId: 54321
                      variantId: 42549172011164
                      variantHandle: premium-coffee-blend-500g
                      quantity: 2
                      price: 19.99
                All Products Removed:
                  description: >-
                    Last one-time product was removed. Contract now has no
                    one-time products.
                  value: []
                Product Didn't Exist:
                  description: >-
                    Attempted to remove non-existent product. Operation
                    succeeds, returns existing products.
                  value:
                    - id: 12346
                      shop: example-store.myshopify.com
                      subscriptionContractId: 98765
                      billingAttemptId: 54322
                      variantId: 42549172011165
                      variantHandle: coffee-filters-pack-100
                      quantity: 1
                      price: 8.99
                Multiple Products Remain:
                  description: >-
                    One product removed, multiple products remain across
                    different billing attempts
                  value:
                    - id: 12347
                      shop: example-store.myshopify.com
                      subscriptionContractId: 98765
                      billingAttemptId: 54321
                      variantId: 42549172011166
                      variantHandle: seasonal-blend-250g
                      quantity: 1
                      price: 14.99
                    - id: 12348
                      shop: example-store.myshopify.com
                      subscriptionContractId: 98765
                      billingAttemptId: 54322
                      variantId: 42549172011167
                      variantHandle: coffee-grinder-manual
                      quantity: 1
                      price: 39.99
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                Missing Required Parameter:
                  description: Missing Required Parameter
                  value:
                    type: https://example.com/probs/bad-request
                    title: Bad Request
                    status: 400
                    detail: >-
                      Required request parameter 'variantId' for method
                      parameter type Long is not present
                Invalid Parameter Format:
                  description: Invalid Parameter Format
                  value:
                    type: https://example.com/probs/bad-request
                    title: Bad Request
                    status: 400
                    detail: >-
                      Failed to convert value of type 'java.lang.String' to
                      required type 'java.lang.Long'; For input string:
                      'invalid'
        '401':
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: https://example.com/probs/unauthorized
                title: Unauthorized
                status: 401
                detail: Full authentication is required to access this resource
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: https://example.com/probs/forbidden
                title: Forbidden
                status: 403
                detail: Access denied - contract does not belong to authenticated shop
  /api/external/v2/subscription-contract-add-line-item:
    put:
      tags:
        - Subscription Products
      summary: Add product with custom price to subscription
      description: >-
        Adds a new product line item with a custom price override to an existing
        subscription contract. This endpoint bypasses standard pricing and
        selling plans to set an exact price.


        **Key Features:**

        - Direct price control - set any price regardless of product pricing

        - Optional automatic discount application based on shop settings

        - No selling plan assignment - pure custom pricing

        - Supports both recurring and one-time products

        - Email notifications sent to customers

        - Activity logging for audit trails


        **Custom Pricing Behavior:**

        - Price is set exactly as provided (no calculations)

        - Overrides any product-level pricing

        - Not affected by currency or country

        - No automatic discounts from selling plans

        - Price remains fixed unless manually updated


        **Shop-Level Discount Application:**

        Despite the method name, this endpoint MAY apply discounts:

        - Checks shop setting: 'applySubscriptionDiscount'

        - If enabled, applies shop's default subscription discount

        - Discount type: PERCENTAGE or FIXED (per shop config)

        - Creates manual discount: 'PRODUCT_DISCOUNT_[lineId]'

        - Discount is additional to the custom price


        **Common Use Cases:**

        - **Negotiated Pricing**: Custom rates for specific customers

        - **Price Matching**: Match competitor pricing

        - **Promotional Pricing**: Special one-off prices

        - **Bundle Pricing**: Custom prices for package deals

        - **Legacy Pricing**: Honor old pricing agreements

        - **Test Orders**: Zero or nominal pricing for testing


        **Differences from Standard Add:**

        - No selling plan association

        - No pricing policy rules

        - No automatic tier discounts

        - Price doesn't adjust with frequency changes

        - Manual price management required


        **One-Time Products:**

        When `isOneTimeProduct=true`:

        - Product appears only in next order

        - Automatically removed after fulfillment

        - Custom price applies to that single order

        - Shop discount still applies if configured


        **Price Validation:**

        - Must be a positive number

        - No maximum limit enforced

        - Can be less than product cost (loss leader)

        - Currency matches shop's base currency

        - Decimal precision per currency rules


        **Important Considerations:**

        - No automatic price updates with product changes

        - Frequency changes don't affect pricing

        - May bypass minimum order values

        - Consider margin implications

        - Document reason for custom pricing


        **Post-Addition Effects:**

        - Customer receives product addition email

        - Activity log records custom price

        - Shipping may need recalculation

        - Order total updates immediately

        - No impact on other line items


        **Authentication:** Requires valid X-API-Key header
      operationId: addLineItemV2_1
      parameters:
        - name: contractId
          in: query
          description: Subscription contract ID to add product to
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
        - name: quantity
          in: query
          description: Quantity of product to add
          required: true
          schema:
            type: integer
            format: int32
          example: 1
        - name: variantId
          in: query
          description: Shopify variant ID of the product to add
          required: true
          schema:
            type: string
          example: 42549172011164
        - name: price
          in: query
          description: >-
            Custom price for the product (in store currency). This exact price
            will be charged regardless of the product's normal price, selling
            plans, or frequency. If the shop has 'applySubscriptionDiscount'
            enabled, an additional discount may be applied on top of this price.
          required: true
          schema:
            maximum: 999999.99
            minimum: 0.01
            type: number
            format: double
          example: 19.99
        - name: isOneTimeProduct
          in: query
          description: >-
            When true, product will only be included in the next order; when
            false, in all future orders
          required: false
          schema:
            type: boolean
            default: false
          example: false
      responses:
        '200':
          description: Product successfully added to subscription with custom price
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-04-01T00:00:00Z'
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/42549172011164
                            title: Premium Coffee - Dark Roast
                            currentPrice:
                              amount: '29.99'
                              currencyCode: USD
                            sellingPlanId: null
                            sellingPlanName: null
                        - node:
                            id: gid://shopify/SubscriptionLine/222222
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/98765432101
                            title: Special Edition Box
                            currentPrice:
                              amount: '19.99'
                              currencyCode: USD
                            sellingPlanId: null
                            sellingPlanName: null
                            discountAllocations:
                              - discount:
                                  __typename: SubscriptionManualDiscount
                                  id: >-
                                    gid://shopify/SubscriptionManualDiscount/333333
                                  title: PRODUCT_DISCOUNT_222222
                                  type: MANUAL
                                  value:
                                    percentage: 10
        '400':
          description: Invalid contract ID, variant ID, quantity, or price
          content:
            application/json:
              examples:
                Invalid Price:
                  description: Invalid Price
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid price value
                    status: 400
                    detail: Price must be a positive number
                Product Not Found:
                  description: Product Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: 'Product Variant not found for ID: 99999999999'
                    status: 400
                    detail: The specified product variant does not exist
                Invalid Quantity:
                  description: Invalid Quantity
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Quantity must be greater than 0
                    status: 400
                    detail: Invalid quantity value provided
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Contract does not exist
                    status: 400
                    detail: No subscription contract found with ID 123456789
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to modify subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  contracts
        '404':
          description: Subscription contract not found
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '422':
          description: >-
            Product cannot be added to this subscription or price cannot be
            customized
          content:
            application/json:
              examples:
                Draft Creation Failed:
                  description: Draft Creation Failed
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: Unable to create subscription draft
                    status: 422
                    detail: Subscription is currently being modified
                Product Not Available:
                  description: Product Not Available
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Product is not available
                    status: 422
                    detail: The product variant is out of stock or discontinued
                Discount Application Failed:
                  description: Discount Application Failed
                  value:
                    type: https://example.com/errors/unprocessable-entity
                    title: UserGeneratedError:Unable to apply shop discount
                    status: 422
                    detail: >-
                      Shop's subscription discount could not be applied to the
                      custom-priced item
  /api/external/v2/subscription-bundlings/discount/{token}:
    put:
      tags:
        - Build-a-Box & Bundles
      summary: Generate discount code for bundle
      description: >-
        Generates a discount code for a subscription bundle. This endpoint
        creates a Shopify discount code that can be applied to bundle
        subscriptions, typically used during the checkout process.


        **Discount Code Generation:**

        - Creates a unique discount code in Shopify

        - Associates the discount with the bundle

        - Configures discount rules and limitations

        - Sets expiration dates if specified

        - Applies usage limits if configured


        **Discount Configuration Options:**

        - Discount type (percentage, fixed amount, or free shipping)

        - Discount value/amount

        - Minimum purchase requirements

        - Maximum usage count

        - Expiration date

        - Customer eligibility rules


        **Use Cases:**

        - Promotional campaigns for bundles

        - Welcome discounts for new subscribers

        - Loyalty rewards for existing customers

        - Special offers and limited-time promotions

        - Partner/affiliate discount codes


        **Important Notes:**

        - Discount codes are created in Shopify and follow Shopify's discount
        rules

        - Codes can be single-use or multi-use depending on configuration

        - Expired or depleted codes cannot be reused


        **Authentication:** Requires valid X-API-Key header
      operationId: generateDiscountV2
      parameters:
        - name: token
          in: path
          description: Token
          required: true
          schema:
            type: string
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DiscountCodeRequest'
        required: true
      responses:
        '200':
          description: Discount code successfully generated
          content:
            application/json:
              examples:
                Success Response:
                  description: Success Response
                  value:
                    discountCode: BUNDLE10
                    discountId: gid://shopify/DiscountCodeNode/123456
                    discountType: PERCENTAGE
                    discountValue: 10
                    expiresAt: '2024-12-31T23:59:59Z'
                    usageLimit: 100
                    currentUsageCount: 0
                    active: true
        '400':
          description: Invalid discount configuration or bundle token
          content:
            application/json:
              examples:
                Invalid Token:
                  description: Invalid Token
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid bundle token
                    status: 400
                    detail: No bundle found for the specified token
                Invalid Discount Config:
                  description: Invalid Discount Config
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid discount configuration
                    status: 400
                    detail: Discount value must be greater than 0
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/DiscountCodeResponse'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/DiscountCodeResponse'
        '422':
          description: Unable to create discount in Shopify
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: Shopify discount creation failed
                status: 422
                detail: Unable to create discount code in Shopify API
  /api/external/v2/subscription-bundling/update:
    put:
      tags:
        - Build-a-Box & Bundles
      summary: Update subscription bundling configuration
      description: >-
        Updates the configuration for one or more subscription bundles
        (Build-a-Box). This endpoint allows bulk updates to bundle product
        selections, quantities, and configurations.


        **Subscription Bundling/Build-a-Box:**

        Subscription bundling allows customers to create custom product bundles
        that are delivered on a recurring basis. Customers can select multiple
        products to be included in each delivery, creating a personalized
        subscription box.


        **Update Capabilities:**

        - Modify product selections within a bundle

        - Update product quantities

        - Change bundle configuration settings

        - Bulk update multiple bundles at once


        **Use Cases:**

        - Customer updates their bundle product selections

        - Swap products in an existing bundle

        - Adjust quantities for products in the bundle

        - Programmatically manage bundle configurations


        **Important Notes:**

        - Updates are identified by bundle handle (unique identifier)

        - Only active bundles can be updated

        - Product availability is validated before update


        **Authentication:** Requires valid X-API-Key header
      operationId: getUpdateSubscriptionBundling
      parameters:
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/BuildABoxUpdate'
        required: true
      responses:
        '200':
          description: Subscription bundling successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBundlingDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: 12345
                    shop: example-shop.myshopify.com
                    token: abc123xyz
                    bundleName: My Custom Coffee Bundle
                    bundleHandle: custom-coffee-bundle-123
                    products:
                      - variantId: 11111
                        productTitle: Medium Roast Coffee
                        quantity: 2
                      - variantId: 22222
                        productTitle: Dark Roast Coffee
                        quantity: 1
                    frequency: MONTH
                    frequencyCount: 1
                    active: true
        '400':
          description: Invalid bundle handle or product configuration
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid bundle configuration
                status: 400
                detail: One or more products in the bundle are not available
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBundlingDTO'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBundlingDTO'
        '404':
          description: Bundle not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Bundle not found
                status: 404
                detail: No bundle found with the specified handle
  /api/external/v2/subscription-billing-attempts:
    put:
      tags:
        - Billing & Payments
      summary: Update subscription billing attempt
      description: >-
        Updates an existing subscription billing attempt. This endpoint allows
        modification of billing attempt details such as billing date, order
        note, and other attributes.


        **Important Notes:**

        - Only QUEUED billing attempts can be updated

        - Cannot update attempts that are already processed or failed

        - Billing attempt must belong to the authenticated shop


        **Authentication:** Requires valid X-API-Key header
      operationId: updateSubscriptionBillingAttemptV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        required: true
      responses:
        '200':
          description: Billing attempt successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '400':
          description: Invalid request or billing attempt cannot be updated
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
  /api/external/v2/subscription-billing-attempts/unskip-order/{id}:
    put:
      tags:
        - Billing & Payments
      summary: Unskip a previously skipped order
      description: >-
        Reverses a skip action on a billing attempt. The order will be restored
        to QUEUED status and will be processed on its scheduled date.


        **Important Notes:**

        - Only works on billing attempts with SKIPPED status

        - Must be done before the scheduled billing date

        - Cannot unskip after the billing date has passed

        - Activity logs are created for audit trail


        **Use Cases:**

        - Customer changes their mind about skipping

        - Correct accidental skip actions

        - Restore delivery after resolving temporary issue


        **Authentication:** Requires valid X-API-Key header
      operationId: unSkipOrderV2
      parameters:
        - name: id
          in: path
          description: Billing Attempt ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: subscriptionContractId
          in: query
          description: Subscription Contract ID
          required: false
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Order successfully unskipped
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '400':
          description: Cannot unskip - not in SKIPPED status or date passed
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
  /api/external/v2/subscription-billing-attempts/skip-upcoming-order:
    put:
      tags:
        - Billing & Payments
      summary: Skip the next upcoming order for a subscription
      description: >-
        Skips the next scheduled billing attempt for a subscription contract
        without requiring the billing attempt ID. Automatically finds and skips
        the earliest QUEUED billing attempt.


        **Convenience Feature:**

        - No need to know the specific billing attempt ID

        - Automatically finds the next order

        - Ideal for "skip next order" functionality in customer portals


        **Use Cases:**

        - Simple "skip next delivery" button in customer portal

        - Quick skip without looking up billing attempt details

        - One-click skip functionality


        **Authentication:** Requires valid X-API-Key header
      operationId: skipFirstUpcomingOrderV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: subscriptionContractId
          in: query
          description: Subscription Contract ID
          required: false
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Next order successfully skipped
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '400':
          description: No queued billing attempts found
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: No upcoming orders
                status: 400
                detail: No queued billing attempts found for this subscription
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
  /api/external/v2/subscription-billing-attempts/skip-order/{id}:
    put:
      tags:
        - Billing & Payments
      summary: Skip a specific order
      description: >-
        Skips a specific billing attempt by ID. The order will not be processed
        on its scheduled date. This is useful when customers want to skip a
        particular delivery without canceling their subscription.


        **Important Behaviors:**

        - Only QUEUED billing attempts can be skipped

        - Skipped orders remain in the system with SKIPPED status

        - Future orders are not affected

        - Can be unskipped before the scheduled date if needed

        - Activity logs are created for audit trail


        **Use Cases:**

        - Customer is on vacation

        - Customer has excess inventory

        - Temporary delivery pause for one cycle


        **Authentication:** Requires valid X-API-Key header
      operationId: skipOrderV2
      parameters:
        - name: id
          in: path
          description: Billing Attempt ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: subscriptionContractId
          in: query
          description: Subscription Contract ID
          required: false
          schema:
            type: integer
            format: int64
        - name: isPrepaid
          in: query
          description: Is this contract Prepaid?
          required: false
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Order successfully skipped
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '400':
          description: Cannot skip order - already processed or invalid status
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Cannot skip order
                status: 400
                detail: Billing attempt is not in QUEUED status
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
  /api/external/v2/subscription-billing-attempts/reschedule-order/{id}:
    put:
      tags:
        - Billing & Payments
      summary: Reschedule a billing attempt to a new date
      description: >-
        Changes the scheduled billing date for a billing attempt. This allows
        customers to adjust when their next order will be processed.


        **Rescheduling Options:**

        - Move to earlier date (if allowed by shop settings)

        - Move to later date

        - Optionally reschedule all future orders by the same offset


        **Important Behaviors:**

        - Only QUEUED billing attempts can be rescheduled

        - New date must be in the future

        - Can affect future billing schedule if rescheduleFutureOrder is true

        - Activity logs are created for audit trail


        **Use Cases:**

        - Customer wants to delay next delivery

        - Customer wants to receive order earlier

        - Adjust delivery schedule to align with customer needs

        - Coordinate deliveries with customer vacation/travel


        **Authentication:** Requires valid X-API-Key header
      operationId: rescheduleOrderV2
      parameters:
        - name: id
          in: path
          description: Billing Attempt ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: rescheduleFutureOrder
          in: query
          required: false
          schema:
            type: boolean
            default: false
        - name: billingDate
          in: query
          description: New Billing Date
          required: true
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Order successfully rescheduled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '400':
          description: Invalid date or cannot reschedule
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid reschedule date
                status: 400
                detail: New billing date must be in the future
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
  /api/external/v2/subscription-billing-attempts/attempt-billing/{id}:
    put:
      tags:
        - Billing & Payments
      summary: Trigger immediate billing for an order
      description: >-
        Immediately processes a billing attempt, creating an order in Shopify.
        This bypasses the scheduled billing date and processes the order right
        away.


        **Important Notes:**

        - Requires shop permission 'enableImmediatePlaceOrder'

        - Only QUEUED billing attempts can be processed

        - Creates an actual order in Shopify

        - Charges the customer's payment method immediately

        - Cannot be undone once processed


        **Use Cases:**

        - Customer requests early delivery

        - Process order immediately after resolving payment issue

        - Manual order processing for special cases


        **Authentication:** Requires valid X-API-Key header and shop permission
      operationId: attemptBillingV2
      parameters:
        - name: id
          in: path
          description: Billing Attempt ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Billing processed successfully
        '400':
          description: Cannot process billing - invalid status
        '401':
          description: Authentication required
        '403':
          description: Shop does not have permission to place immediate orders
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Permission denied
                status: 403
                detail: Shop does not have enableImmediatePlaceOrder permission
  /api/external/v2/subscription-billing-attempts-update-order-note/{id}:
    put:
      tags:
        - Billing & Payments
      summary: Update order note for a billing attempt
      description: >-
        Updates the order note (customer note) for a billing attempt. This note
        will be included when the order is created in Shopify.


        **Use Cases:**

        - Add delivery instructions

        - Include gift messages

        - Add special handling notes

        - Store customer preferences for this order


        **Important Notes:**

        - Only works on QUEUED billing attempts

        - Note is included in the Shopify order when created

        - Can be updated multiple times before order is processed


        **Authentication:** Requires valid X-API-Key header
      operationId: updateOrderNoteV2_1
      parameters:
        - name: id
          in: path
          description: Billing Attempt ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: orderNote
          in: query
          description: Updated Order Note
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Order note successfully updated
          content:
            application/json:
              schema:
                type: boolean
        '400':
          description: Invalid billing attempt ID
          content:
            '*/*':
              schema:
                type: boolean
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                type: boolean
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                type: boolean
  /api/external/v2/product-swaps:
    get:
      tags:
        - Product Catalog
      summary: Get all product swaps for a shop
      description: >-
        Retrieves all configured product swap automations for the authenticated
        shop. Product swaps allow automatic replacement of products in
        subscription orders based on billing cycles or recurring schedules.


        **What are Product Swaps?**

        Product swaps enable merchants to automatically replace products in
        subscription orders at specific billing cycles. This is useful for
        seasonal products, progression paths (e.g., beginner → intermediate →
        advanced), or variety subscriptions.


        **Key Features:**

        - View all configured swap automations

        - See source and destination product mappings

        - Check which billing cycles trigger swaps

        - Identify recurring vs one-time swaps

        - Review discount carry-forward settings


        **Swap Configuration Types:**

        - **One-Time Swap**: Occurs at a specific billing cycle

        - **Recurring Swap**: Occurs at every order

        - **Conditional Swap**: Based on billing cycle number


        **Use Cases:**

        - Seasonal product rotations (summer → fall → winter products)

        - Subscription progression (trial → full product)

        - Variety boxes with automatic product rotation

        - Product lifecycle management in subscriptions

        - A/B testing different products in subscriptions


        **Authentication:** Requires valid X-API-Key header
      operationId: getAllProductSwaps
      parameters:
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: ruleName
          in: query
          required: false
          schema:
            type: string
        - name: sourceVariants
          in: query
          required: false
          schema:
            type: string
        - name: destinationVariants
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Successfully retrieved product swaps
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductSwapDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    - id: 10782
                      shop: example-shop.myshopify.com
                      sourceVariants: >-
                        [{"id":12345,"displayName":"Summer Blend
                        Coffee","imageSrc":"https://cdn.shopify.com/image1.jpg","quantity":2}]
                      destinationVariants: >-
                        [{"id":67890,"displayName":"Fall Blend
                        Coffee","imageSrc":"https://cdn.shopify.com/image2.jpg","quantity":2}]
                      updatedFirstOrder: false
                      checkForEveryRecurringOrder: false
                      name: Seasonal Coffee Rotation
                      forBillingCycle: 4
                      carryDiscountForward: true
                      stopSwapEmails: false
                      discountCarryForward: PERCENTAGE
                      active: true
                      createdAt: '2024-01-15T10:30:00Z'
                    - id: 10783
                      shop: example-shop.myshopify.com
                      sourceVariants: >-
                        [{"id":22222,"displayName":"Beginner
                        Kit","imageSrc":"https://cdn.shopify.com/kit1.jpg","quantity":1}]
                      destinationVariants: >-
                        [{"id":33333,"displayName":"Advanced
                        Kit","imageSrc":"https://cdn.shopify.com/kit2.jpg","quantity":1}]
                      updatedFirstOrder: false
                      checkForEveryRecurringOrder: true
                      name: Monthly Variety Swap
                      forBillingCycle: null
                      carryDiscountForward: false
                      stopSwapEmails: true
                      discountCarryForward: NONE
                      active: true
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to view product swaps
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to view product swaps
    put:
      tags:
        - product-swap-resource
      summary: Update an existing product swap automation
      description: >-
        Updates an existing product swap automation rule for the authenticated
        shop. Use this endpoint to modify swap configurations, change
        source/destination products, adjust timing, or update discount handling.


        **Required Fields:**

        - **id**: The product swap ID to update

        - **shop**: Your Shopify shop domain (must match authenticated shop)


        **Updatable Fields:**

        - **sourceVariants**: JSON string of variants to swap FROM

        - **destinationVariants**: JSON string of variants to swap TO

        - **name**: Descriptive name for this swap rule

        - **forBillingCycle**: Specific cycle number when swap occurs (null for
        recurring)

        - **checkForEveryRecurringOrder**: If true, applies swap to every order

        - **updatedFirstOrder**: If true, can affect the first subscription
        order

        - **changeNextOrderDateBy**: Days to adjust next order date after swap

        - **discountCarryForward**: How to handle discounts (NONE, PERCENTAGE,
        FIXED_AMOUNT, PRICE)

        - **carryDiscountForward**: Legacy boolean field (use
        discountCarryForward instead)

        - **stopSwapEmails**: If true, suppresses customer notification emails

        - **ruleSequence**: Priority order (lower number = higher priority)


        **Impact of Updates:**

        - Changes apply to future orders immediately

        - Past orders and already-swapped products are not affected

        - If changing forBillingCycle, recalculates which subscriptions are
        affected

        - Variant data is automatically enriched from Shopify on update


        **Authentication:** Requires valid X-API-Key header
      operationId: updateProductSwap
      parameters:
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        description: ProductSwapDTO payload
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductSwapDTO'
            examples:
              Request Example:
                description: Request Example
                value:
                  id: 10782
                  shop: example-shop
                  sourceVariants: '[{"id":12345,"quantity":2}]'
                  destinationVariants: '[{"id":67890,"quantity":2}]'
                  updatedFirstOrder: false
                  checkForEveryRecurringOrder: false
                  name: swap test
                  forBillingCycle: 2
                  carryDiscountForward: false
                  stopSwapEmails: false
                  discountCarryForward: NONE
        required: true
      responses:
        '200':
          description: Product swap updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductSwapDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: 10782
                    shop: example-shop
                    sourceVariants: >-
                      [{"id":12345,"displayName":"test-product","imageSrc":"https://test.com/image.png","quantity":2}]
                    destinationVariants: >-
                      [{"id":67890,"displayName":"test-product","imageSrc":"https://test.com/image.png","quantity":2}]
                    updatedFirstOrder: false
                    checkForEveryRecurringOrder: false
                    name: swap test
                    changeNextOrderDateBy: null
                    forBillingCycle: 2
                    carryDiscountForward: false
                    ruleSequence: 0
                    stopSwapEmails: false
                    discountCarryForward: NONE
        '400':
          description: Invalid request or product swap not found
          content:
            application/json:
              examples:
                ID Not Found:
                  description: ID Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid id
                    status: 400
                    detail: Invalid id
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to update product swap
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to update product swaps
        '404':
          description: Resource not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Resource not found
        '422':
          description: Unprocessable entity - business rule violation
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: Business rule violation
                status: 422
                detail: Cannot update product swap due to business rule violation
    post:
      tags:
        - product-swap-resource
      summary: Create a new product swap automation
      description: >-
        Creates a new product swap automation rule for the authenticated shop.
        Product swaps automatically replace products in subscription orders
        based on billing cycles or recurring schedules.


        **Required Fields:**

        - **shop**: Your Shopify shop domain

        - **sourceVariants**: JSON string of variants to swap FROM (format:
        [{"id":12345,"quantity":2}])

        - **destinationVariants**: JSON string of variants to swap TO (format:
        [{"id":67890,"quantity":2}])

        - **name**: Descriptive name for this swap rule


        **Optional Fields:**

        - **forBillingCycle**: Specific cycle number when swap occurs (e.g., 4 =
        swap at 4th order). Leave null for recurring swaps.

        - **checkForEveryRecurringOrder**: If true, applies swap to every order
        (overrides forBillingCycle)

        - **updatedFirstOrder**: If true, can affect the first subscription
        order

        - **changeNextOrderDateBy**: Days to adjust next order date after swap
        (positive or negative integer)

        - **discountCarryForward**: How to handle discounts - NONE, PERCENTAGE,
        FIXED_AMOUNT, or PRICE

        - **carryDiscountForward**: Legacy boolean field (deprecated, use
        discountCarryForward instead)

        - **stopSwapEmails**: If true, suppresses customer notification emails
        about the swap

        - **ruleSequence**: Priority order when multiple swaps apply (lower
        number = higher priority)


        **Variant JSON Format:**

        The API enriches your variant data with product details from Shopify.
        You only need to provide:

        ```json

        [{"id": 12345, "quantity": 2}]

        ```

        The response will include enriched data: displayName, imageSrc,
        productTitle, etc.


        **Authentication:** Requires valid X-API-Key header
      operationId: createProductSwap
      parameters:
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        description: ProductSwapDTO payload
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductSwapDTO'
            examples:
              Request Example:
                description: Request Example
                value:
                  shop: example-shop
                  sourceVariants: '[{"id":12345,"quantity":2}]'
                  destinationVariants: '[{"id":67890,"quantity":2}]'
                  updatedFirstOrder: false
                  checkForEveryRecurringOrder: false
                  name: swap test
                  forBillingCycle: 2
                  carryDiscountForward: false
                  stopSwapEmails: false
                  discountCarryForward: NONE
        required: true
      responses:
        '200':
          description: Product swap created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductSwapDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: 10782
                    shop: example-shop
                    sourceVariants: >-
                      [{"id":12345,"displayName":"test-product","imageSrc":"https://test.com/image.png","quantity":2}]
                    destinationVariants: >-
                      [{"id":67890,"displayName":"test-product","imageSrc":"https://test.com/image.png","quantity":2}]
                    updatedFirstOrder: false
                    checkForEveryRecurringOrder: false
                    name: swap test
                    changeNextOrderDateBy: null
                    forBillingCycle: 2
                    carryDiscountForward: false
                    ruleSequence: 0
                    stopSwapEmails: false
                    discountCarryForward: NONE
        '400':
          description: Invalid request or product swap already has an ID
          content:
            application/json:
              examples:
                ID Exists:
                  description: ID Exists
                  value:
                    type: https://example.com/errors/bad-request
                    title: A new productSwap cannot already have an ID
                    status: 400
                    detail: A new productSwap cannot already have an ID
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to create product swap
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to create product swaps
        '404':
          description: Resource not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Resource not found
        '422':
          description: Unprocessable entity - business rule violation
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: Business rule violation
                status: 422
                detail: Cannot create product swap due to business rule violation
  /api/external/v2/build-a-box:
    put:
      tags:
        - Build-a-Box & Bundles
      summary: Update an existing Build-A-Box subscription bundle
      description: >-
        Updates an existing Build-A-Box subscription bundle with new
        configuration settings, product selections, pricing rules, or other
        bundle attributes. This endpoint allows you to modify any aspect of a
        previously created bundle while maintaining its unique identifier and
        shop association.


        **What Can Be Updated:**

        - **Bundle Information**: Name, description, handle, and display
        settings

        - **Product Configuration**: Available products, product pool, and
        selection rules

        - **Quantity Limits**: Minimum and maximum product counts per box

        - **Pricing Settings**: Pricing type, discount rules, and promotional
        offers

        - **Delivery Options**: Subscription frequencies and delivery intervals

        - **Business Rules**: Product combination rules, category restrictions

        - **Status**: Active/inactive state for customer visibility

        - **Customization Options**: Allow product swaps, one-time purchases


        **Update Behavior:**

        - The bundle ID must be provided in the request body

        - Shop ownership is verified - you can only update bundles belonging to
        your shop

        - All fields in the request body will update the corresponding bundle
        properties

        - Partial updates are supported - only include fields you want to change

        - The update is atomic - either all changes succeed or none are applied

        - Existing subscriptions using this bundle are not automatically
        affected


        **Impact on Active Subscriptions:**

        - Changes to product availability affect future customer selections

        - Pricing updates apply to new subscriptions but not existing ones by
        default

        - Quantity limit changes are enforced on next customer modification

        - Frequency changes only affect new subscriptions

        - Deactivating a bundle prevents new subscriptions but maintains
        existing ones


        **Common Update Scenarios:**

        1. **Add/Remove Products**: Update the available product pool

        2. **Adjust Pricing**: Change discount percentages or pricing models

        3. **Modify Limits**: Update minimum/maximum product selection rules

        4. **Change Frequencies**: Add or remove subscription interval options

        5. **Update Content**: Modify bundle name, description, or images

        6. **Toggle Status**: Activate or deactivate bundle availability

        7. **Refine Rules**: Adjust product combination or category restrictions


        **Best Practices:**

        - Verify product availability before adding to the bundle

        - Test pricing changes with sample calculations

        - Communicate bundle changes to existing subscribers

        - Use inactive status for testing changes before making them live

        - Keep bundle handles consistent for external integrations

        - Document major changes for customer support reference

        - Consider seasonal or promotional updates to keep offerings fresh


        **Validation Rules:**

        - Bundle ID is required and must exist

        - Shop must match the authenticated shop (cannot transfer bundles)

        - All referenced products must be valid and available

        - Minimum product count cannot exceed maximum product count

        - Pricing values must be non-negative

        - Bundle handle should remain unique across all bundles


        **Authentication:** Requires valid X-API-Key header or api_key parameter
        (deprecated)
      operationId: updateSubscriptionBundling
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionBundlingDTO'
        required: true
      responses:
        '200':
          description: Build-A-Box subscription bundle successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBundlingDTO'
              examples:
                Updated Bundle:
                  description: Updated Bundle
                  value:
                    id: 45678
                    shop: example-shop.myshopify.com
                    bundleName: Premium Coffee Selection - Updated
                    bundleHandle: premium-coffee-selection
                    uniqueRef: bab_abc123xyz
                    description: >-
                      Choose from our expanded selection of artisan coffee
                      blends
                    buildABoxType: SINGLE_PRODUCT
                    buildBoxVersion: V2
                    minProductCount: 3
                    maxProductCount: 6
                    pricingType: PER_PRODUCT
                    discount: 15
                    discountType: PERCENTAGE
                    allowOneTimePurchase: true
                    active: true
                    availableProducts:
                      - productId: 111111
                        variantId: 222222
                        title: Medium Roast Coffee - 12oz
                        price: '14.99'
                      - productId: 111111
                        variantId: 333333
                        title: Dark Roast Coffee - 12oz
                        price: '15.99'
                      - productId: 111111
                        variantId: 444444
                        title: Espresso Roast Coffee - 12oz
                        price: '16.99'
                    frequencies:
                      - interval: MONTH
                        intervalCount: 1
                        displayName: Monthly
                      - interval: WEEK
                        intervalCount: 2
                        displayName: Bi-Weekly
                    createdAt: '2024-03-15T10:30:00Z'
                    updatedAt: '2024-03-20T14:45:00Z'
        '400':
          description: Invalid update request or validation failure
          content:
            application/json:
              examples:
                Missing Bundle ID:
                  description: Missing Bundle ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid bundle update
                    status: 400
                    detail: Bundle ID is required for updates
                    entityName: subscriptionBundling
                    errorKey: idnull
                Unauthorized Access:
                  description: Unauthorized Access
                  value:
                    type: https://example.com/errors/bad-request
                    title: Unauthorized access
                    status: 400
                    detail: >-
                      Unauthorized access or resource not found. Bundle does not
                      belong to your shop.
                    entityName: subscriptionBundling
                    errorKey: unauthorized
                Invalid Configuration:
                  description: Invalid Configuration
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid configuration
                    status: 400
                    detail: >-
                      Minimum product count (5) cannot exceed maximum product
                      count (3)
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header or api_key parameter is required
        '404':
          description: Bundle not found with the specified ID
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Bundle not found
                status: 404
                detail: No Build-A-Box bundle found with ID 45678
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-server-error
                title: Internal server error
                status: 500
                detail: >-
                  An unexpected error occurred while updating the Build-A-Box
                  bundle
    post:
      tags:
        - Build-a-Box & Bundles
      summary: Create a new Build-A-Box subscription bundle
      description: >-
        Creates a new subscription bundle (Build-A-Box) allowing customers to
        select and customize products for recurring deliveries. Build-A-Box
        enables a flexible subscription model where customers can create
        personalized product boxes.


        **What is Build-A-Box?**

        Build-A-Box is a subscription feature that allows customers to curate
        their own product bundles by selecting from a predefined set of
        products. This creates a highly personalized subscription experience
        where customers have full control over what they receive in each
        delivery cycle.


        **Key Features:**

        - **Product Selection**: Customers choose which products to include in
        their box

        - **Quantity Control**: Set minimum and maximum product quantities

        - **Flexible Configuration**: Define rules for product combinations

        - **Pricing Models**: Support for various pricing strategies (per-item,
        flat rate, tiered)

        - **Recurring Delivery**: Automatic fulfillment based on subscription
        frequency

        - **Customization Options**: Allow product swaps between delivery cycles


        **Configuration Options:**

        - **Bundle Settings**:
          - Bundle name and description
          - Unique handle for identification
          - Product pool (available products for selection)
          - Minimum/maximum number of products
          - Product quantity limits

        - **Pricing Configuration**:
          - Pricing type (per-product, flat rate, or tiered)
          - Discount rules
          - Promotional pricing
          - Currency settings

        - **Delivery Options**:
          - Subscription frequencies (weekly, bi-weekly, monthly, etc.)
          - Delivery intervals
          - Cut-off times for order modifications
          - Shipping methods

        - **Rules and Restrictions**:
          - Product combination rules
          - Category restrictions
          - Inventory requirements
          - Customer eligibility criteria

        **Build-A-Box Types:**

        1. **Open Selection**: Customers can choose any products from the
        available pool

        2. **Category-Based**: Products are organized into categories with
        selection rules

        3. **Single Product**: Customers select variations of a single product
        type

        4. **Tiered Boxes**: Different box sizes with varying product counts and
        pricing


        **Use Cases:**

        - **Coffee Subscription**: Customers select different coffee blends for
        monthly delivery

        - **Snack Boxes**: Build custom snack boxes from a variety of treats

        - **Beauty Boxes**: Choose skincare and makeup products based on
        preferences

        - **Meal Kits**: Select recipes and ingredients for weekly meal planning

        - **Pet Supply Boxes**: Customize toys, treats, and supplies for pets

        - **Supplement Subscriptions**: Create personalized vitamin and
        supplement regimens


        **Customer Workflow:**

        1. Customer discovers Build-A-Box offering

        2. Selects products from available options

        3. Chooses delivery frequency

        4. Reviews pricing and discounts

        5. Completes subscription signup

        6. Receives recurring deliveries

        7. Can modify selections between delivery cycles


        **Important Notes:**

        - Each bundle must have a unique handle for identification

        - Product availability is validated at creation time

        - Pricing rules are applied based on bundle configuration

        - Bundles must be associated with at least one subscription frequency

        - Inventory levels should be checked for all included products

        - Bundle status (active/inactive) controls customer visibility


        **Best Practices:**

        - Set clear minimum and maximum product limits

        - Provide detailed product descriptions and images

        - Configure appropriate pricing that encourages subscriptions

        - Offer multiple delivery frequency options

        - Set reasonable inventory thresholds

        - Enable customer portal access for subscription management

        - Test bundle configurations before making them live


        **Authentication:** Requires valid X-API-Key header or api_key parameter
        (deprecated)
      operationId: createSubscriptionBundling
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionBundlingDTO'
        required: true
      responses:
        '201':
          description: Build-A-Box subscription bundle successfully created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBundlingDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: 45678
                    shop: example-shop.myshopify.com
                    bundleName: Premium Coffee Selection
                    bundleHandle: premium-coffee-selection
                    uniqueRef: bab_abc123xyz
                    description: Choose your favorite coffee blends for monthly delivery
                    buildABoxType: SINGLE_PRODUCT
                    buildBoxVersion: V2
                    minProductCount: 2
                    maxProductCount: 5
                    pricingType: PER_PRODUCT
                    discount: 10
                    discountType: PERCENTAGE
                    allowOneTimePurchase: true
                    active: true
                    availableProducts:
                      - productId: 111111
                        variantId: 222222
                        title: Medium Roast Coffee - 12oz
                        price: '14.99'
                        imageUrl: https://cdn.shopify.com/coffee-medium.jpg
                      - productId: 111111
                        variantId: 333333
                        title: Dark Roast Coffee - 12oz
                        price: '15.99'
                        imageUrl: https://cdn.shopify.com/coffee-dark.jpg
                    frequencies:
                      - interval: MONTH
                        intervalCount: 1
                        displayName: Monthly
                      - interval: WEEK
                        intervalCount: 2
                        displayName: Bi-Weekly
                    createdAt: '2024-03-15T10:30:00Z'
                    updatedAt: '2024-03-15T10:30:00Z'
        '400':
          description: Invalid bundle configuration or validation failure
          content:
            application/json:
              examples:
                Bundle Already Has ID:
                  description: Bundle Already Has ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid bundle creation
                    status: 400
                    detail: A new Build-A-Box cannot already have an ID
                    entityName: subscriptionBundling
                    errorKey: idexists
                Invalid Product Configuration:
                  description: Invalid Product Configuration
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid product configuration
                    status: 400
                    detail: >-
                      One or more products in the bundle are not available or do
                      not exist
                Invalid Limits:
                  description: Invalid Limits
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid product limits
                    status: 400
                    detail: Minimum product count cannot exceed maximum product count
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header or api_key parameter is required
        '403':
          description: Insufficient permissions to create Build-A-Box bundles
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to create Build-A-Box bundles
        '422':
          description: Unprocessable entity - Business logic validation failure
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: Validation failure
                status: 422
                detail: >-
                  Bundle handle must be unique. A bundle with this handle
                  already exists.
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-server-error
                title: Internal server error
                status: 500
                detail: >-
                  An unexpected error occurred while creating the Build-A-Box
                  bundle
  /api/external/v2/update-custom-note-attributes:
    post:
      tags:
        - Subscription Management
      summary: Update custom attributes on a subscription contract
      description: >-
        Updates or replaces custom key-value attributes on a subscription
        contract. These attributes are stored with the subscription and can be
        used to track custom data, preferences, or metadata that's important for
        your business processes.


        **Custom Attributes Overview:**

        Custom attributes are key-value pairs that allow you to store additional
        information on subscriptions. They are:

        - Visible in the Shopify admin and accessible via API

        - Included in order data when subscription orders are created

        - Preserved across subscription lifecycle events

        - Useful for integrations and custom workflows


        **Update Modes:**

        - **Merge Mode (overwriteExistingAttributes=false)**: Adds new
        attributes and updates existing ones with matching keys. Other
        attributes remain unchanged.

        - **Replace Mode (overwriteExistingAttributes=true)**: Completely
        replaces all existing attributes with the provided list.


        **Common Use Cases:**

        - Store gift messages or special instructions

        - Track referral sources or marketing campaigns

        - Add internal reference numbers or tracking codes

        - Store customer preferences or customization options

        - Integration data for third-party systems


        **Important Notes:**

        - Attribute keys should not conflict with Shopify's reserved attributes

        - Both keys and values are stored as strings

        - Changes are logged in the activity history

        - Invalid discount codes may be automatically removed during update


        **Authentication:** Requires valid X-API-Key header
      operationId: updateOrderNoteAttributes
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key
          required: true
          schema:
            type: string
        - name: overwriteExistingAttributes
          in: query
          description: Merge or replace mode
          required: false
          schema:
            type: boolean
            default: true
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAttributesRequest'
        required: true
      responses:
        '200':
          description: Attributes successfully updated
          content:
            application/json:
              examples:
                Success Response:
                  description: Success Response
                  value:
                    message: Attributes updated successfully
        '400':
          description: Invalid request parameters
          content:
            application/json:
              examples:
                Missing Contract ID:
                  description: Missing Contract ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Validation Error
                    status: 400
                    detail: Subscription contract ID is required
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Subscription contract not found
                    status: 400
                    detail: No subscription contract found with the specified ID
        '401':
          description: Authentication required - missing or invalid API key
        '403':
          description: Insufficient permissions to update subscription contracts
  /api/external/v2/subscription-groups/{id}/bulk-add-products:
    post:
      tags:
        - Subscription Plans
      summary: Bulk add products or variants to an existing subscription group
      description: >-
        Adds multiple products and/or product variants to an existing
        subscription group (selling plan group) using a JSON request body. This
        endpoint is ideal for adding large numbers of products/variants that
        would exceed URL length limits in the query parameter version.


        **Advantages over query parameter endpoint:**

        - No URL length restrictions

        - Cleaner syntax for large lists

        - Better for programmatic integrations

        - Supports the same functionality with improved scalability


        **Behavior:**

        - Identical to the query parameter endpoint in functionality

        - Adds products/variants to existing assignments

        - Preserves product order

        - Updates synchronously and returns the updated group


        **Authentication:** Requires valid X-API-Key header
      operationId: bulkAddProductsOrVariants
      parameters:
        - name: id
          in: path
          description: Subscription group ID (numeric ID)
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      requestBody:
        description: Product and variant IDs to add to the subscription group
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkAddProductsRequest'
            examples:
              Add Multiple Products:
                description: Add Multiple Products
                value:
                  productIds:
                    - 987654321
                    - 987654322
                    - 987654323
                    - 987654324
                    - 987654325
                  variantIds: []
              Add Specific Variants:
                description: Add Specific Variants
                value:
                  productIds: []
                  variantIds:
                    - 123456789
                    - 123456790
                    - 123456791
                    - 123456792
              Add Both Products and Variants:
                description: Add Both Products and Variants
                value:
                  productIds:
                    - 987654321
                    - 987654322
                    - 987654323
                  variantIds:
                    - 123456789
                    - 123456790
                    - 123456791
              Large Bulk Addition:
                description: Large Bulk Addition
                value:
                  productIds:
                    - 987654321
                    - 987654322
                    - 987654323
                    - 987654324
                    - 987654325
                    - 987654326
                    - 987654327
                    - 987654328
                    - 987654329
                    - 987654330
                    - 987654331
                    - 987654332
                    - 987654333
                    - 987654334
                    - 987654335
                    - 987654336
                    - 987654337
                    - 987654338
                    - 987654339
                    - 987654340
                  variantIds:
                    - 123456789
                    - 123456790
                    - 123456791
                    - 123456792
                    - 123456793
                    - 123456794
                    - 123456795
                    - 123456796
                    - 123456797
                    - 123456798
        required: true
      responses:
        '200':
          description: Products/variants successfully added
          content:
            '*/*':
              schema:
                type: object
        '400':
          description: Invalid request
          content:
            '*/*':
              schema:
                type: object
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                type: object
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                type: object
        '404':
          description: Subscription group not found
          content:
            '*/*':
              schema:
                type: object
        '422':
          description: Shopify API error
          content:
            '*/*':
              schema:
                type: object
  /api/external/v2/subscription-contract-details/split-existing-contract:
    post:
      tags:
        - Subscription Management
      summary: Split or duplicate an existing subscription contract
      description: >-
        Creates a new subscription contract by either splitting (moving) or
        duplicating selected line items from an existing contract. This endpoint
        allows you to divide a subscription into multiple contracts or create a
        copy with specific products.


        **Split vs Duplicate Mode:**

        - **Split (isSplitContract=true)**: Moves the selected line items from
        the original contract to a new contract. The original contract will no
        longer contain these items.

        - **Duplicate (isSplitContract=false)**: Creates a new contract with
        copies of the selected line items while keeping them in the original
        contract.


        **Important Notes:**

        - When splitting, at least one subscription product must remain in the
        original contract

        - The new contract inherits all settings from the original: customer,
        payment method, billing/delivery policies, shipping address, and custom
        attributes

        - Billing schedule is automatically generated for the new contract

        - One-time products and free products don't count towards the minimum
        product requirement


        **Use Cases:**

        - Split a subscription when customer wants different delivery schedules
        for different products

        - Create a gift subscription from an existing subscription

        - Separate products for different shipping addresses

        - Duplicate a subscription for testing or backup purposes


        **Authentication:** Requires valid X-API-Key header
      operationId: splitExistingContract
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key
          required: true
          schema:
            type: string
        - name: contractId
          in: query
          description: Subscription contract ID
          required: true
          schema:
            type: integer
            format: int64
        - name: isSplitContract
          in: query
          description: Split or duplicate mode
          required: false
          schema:
            type: boolean
            default: false
        - name: attemptBilling
          in: query
          description: Attempt billing immediately
          required: false
          schema:
            type: boolean
            default: false
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                type: string
        required: true
      responses:
        '200':
          description: Contract successfully split/duplicated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/987654321
                    status: ACTIVE
                    nextBillingDate: '2024-02-15T00:00:00Z'
                    originOrder:
                      id: gid://shopify/Order/123456789
                    customer:
                      id: gid://shopify/Customer/111111
                      email: customer@example.com
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                    deliveryPolicy:
                      interval: MONTH
                      intervalCount: 1
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/222222
                            quantity: 2
                            variantId: gid://shopify/ProductVariant/333333
                            title: Premium Coffee - Medium Roast
                            currentPrice:
                              amount: '29.99'
                              currencyCode: USD
                    customAttributes:
                      - key: _origin_type
                        value: SPLIT_CONTRACT
                      - key: _original_contract_id
                        value: '123456789'
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                All Products Selected:
                  description: All Products Selected
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:All products cannot be selected, at
                      least one product is required in the current contract.
                    status: 400
                    detail: >-
                      When splitting a contract, you cannot move all products.
                      At least one subscription product must remain.
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Subscription contract not found for
                      given contract id
                    status: 400
                    detail: >-
                      The specified contract ID does not exist or you don't have
                      access to it
                No Payment Method:
                  description: No Payment Method
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:No Payment methods found for the
                      customer
                    status: 400
                    detail: >-
                      The original contract's customer must have a valid payment
                      method
                Invalid Line IDs:
                  description: Invalid Line IDs
                  value:
                    type: https://example.com/errors/bad-request
                    title: No valid line items found
                    status: 400
                    detail: None of the provided line IDs exist in the contract
        '401':
          description: Authentication required - missing or invalid API key
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '403':
          description: Insufficient permissions to split subscription contracts
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
  /api/external/v2/subscription-contract-details/replace-variants-v3:
    post:
      tags:
        - Subscription Management
      summary: Replace product variants in a subscription contract
      description: >-
        Replaces existing product variants with new ones in a subscription
        contract. This endpoint supports both regular subscription products and
        one-time products, allowing you to swap products, update quantities, and
        manage the product mix in a subscription.


        **Key Features:**

        - **Bulk Replace**: Replace multiple products at once by providing lists
        of old and new variants

        - **Line-Specific Replace**: Target a specific line item using oldLineId
        for precise replacement

        - **Quantity Management**: Set new quantities for replaced products

        - **One-Time Products**: Add or remove one-time purchase products
        independently

        - **Discount Preservation**: Configurable discount carry-forward logic


        **Discount Carry Forward Options:**

        - **PRODUCT_THEN_EXISTING**: First tries to apply the new product's
        selling plan discount, then falls back to existing discount

        - **PRODUCT_PLAN**: Always uses the new product's selling plan discount

        - **EXISTING_PLAN**: Maintains the existing product's discount structure


        **Important Notes:**

        - At least one regular subscription product must remain in the contract

        - One-time products and free products don't count towards the minimum
        product requirement

        - The system automatically handles pricing adjustments based on
        billing/delivery intervals

        - Shipping prices are automatically recalculated after changes


        **Use Cases:**

        - Product upgrades/downgrades (e.g., switching coffee blend or size)

        - Quantity adjustments during product swap

        - Adding limited-time or seasonal products as one-time purchases

        - Bulk product replacements for subscription migrations


        **Authentication:** Requires valid X-API-Key header
      operationId: replaceVariantsV3
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReplaceVariantsInfoV3'
        required: true
      responses:
        '200':
          description: Products successfully replaced
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-02-15T00:00:00Z'
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/999999
                            quantity: 3
                            variantId: gid://shopify/ProductVariant/888888
                            title: Premium Coffee - Dark Roast
                            variantTitle: 1kg / Whole Bean
                            currentPrice:
                              amount: '35.99'
                              currencyCode: USD
                            pricingPolicy:
                              basePrice:
                                amount: '39.99'
                                currencyCode: USD
                              cycleDiscounts:
                                - afterCycle: 1
                                  adjustmentType: PERCENTAGE
                                  adjustmentValue:
                                    percentage: 10
                        - node:
                            id: gid://shopify/SubscriptionLine/777777
                            quantity: 1
                            variantId: gid://shopify/ProductVariant/666666
                            title: Coffee Filters - Pack of 100
                            currentPrice:
                              amount: '9.99'
                              currencyCode: USD
                            customAttributes:
                              - key: _one_time_product
                                value: 'true'
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                No Variants Specified:
                  description: No Variants Specified
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:No variants to add or remove
                    status: 400
                    detail: You must specify at least one variant to add or remove
                Same Source and Destination:
                  description: Same Source and Destination
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Source and destination variants cannot
                      be same
                    status: 400
                    detail: You cannot replace a variant with itself
                Variant Not Found:
                  description: Variant Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Old variants didn't match with the
                      existing variants
                    status: 400
                    detail: >-
                      The specified old variant IDs do not exist in the
                      subscription
                Product Not Found:
                  description: Product Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      Product Variant not found for ID:
                      gid://shopify/ProductVariant/999999
                    status: 400
                    detail: The new variant ID does not exist in your store
                Last Product Removal:
                  description: Last Product Removal
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Cannot remove line item. Atleast one
                      subscription product must be present in a subscription
                    status: 400
                    detail: >-
                      This operation would remove all subscription products from
                      the contract
        '401':
          description: Authentication required - missing or invalid API key
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '403':
          description: Insufficient permissions to modify subscription contracts
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
  /api/external/v2/subscription-contract-details/create-subscription-contract:
    post:
      tags:
        - Subscription Management
      summary: Create a new subscription contract
      description: >-
        Creates a new subscription contract for a customer with specified
        products, billing frequency, and delivery details. This endpoint allows
        you to programmatically create subscriptions with custom pricing,
        delivery schedules, and multiple line items. The subscription will be
        created in Shopify and synchronized with the Appstle system.


        **Important Notes:**

        - Customer must have at least one valid payment method

        - If paymentMethodId is not provided, the default payment method will be
        used

        - If delivery interval is not specified, it defaults to the billing
        interval

        - Custom pricing policies can be applied per line item

        - All monetary values are in the store's base currency unless
        currencyCode is specified

        - CustomAttributes and line item customAttributes use Shopify's
        AttributeInput format: {"key": "string", "value": "string"}


        **Pricing Policy Types:**

        - SELLING_PLAN_PRICING_POLICY: Uses the default pricing from the selling
        plan

        - CUSTOM_PRICING_POLICY: Allows custom discount cycles defined in
        pricingPolicy array

        - NO_PRICING_POLICY: Uses the base price without any discounts


        **Authentication:** Requires valid X-API-Key header
      operationId: createSubscriptionContractV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionContractDTO'
        required: true
      responses:
        '201':
          description: Subscription contract successfully created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/SubscriptionContract/123456789
                    status: ACTIVE
                    nextBillingDate: '2024-02-01T00:00:00Z'
                    billingPolicy:
                      interval: MONTH
                      intervalCount: 1
                      minCycles: 3
                      maxCycles: 12
                    deliveryPolicy:
                      interval: MONTH
                      intervalCount: 1
                    customer:
                      id: gid://shopify/Customer/987654321
                      email: customer@example.com
                      firstName: John
                      lastName: Doe
                    deliveryPrice:
                      amount: '5.99'
                      currencyCode: USD
                    lines:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionLine/111111
                            quantity: 2
                            variantId: gid://shopify/ProductVariant/42549172011164
                            currentPrice:
                              amount: '25.99'
                              currencyCode: USD
                            pricingPolicy:
                              basePrice:
                                amount: '29.99'
                                currencyCode: USD
        '400':
          description: Invalid request parameters or business rule violation
          content:
            application/json:
              examples:
                Missing Required Field:
                  description: Missing Required Field
                  value:
                    type: https://example.com/errors/bad-request
                    title: UserGeneratedError:Customer ID is required
                    status: 400
                    detail: The customerId field must be provided
                No Payment Method:
                  description: No Payment Method
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:No Payment methods found for the
                      customer
                    status: 400
                    detail: Customer must have at least one valid payment method
                Multiple Payment Methods:
                  description: Multiple Payment Methods
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Multiple Payment methods found for the
                      customer
                    status: 400
                    detail: >-
                      When customer has multiple payment methods,
                      paymentMethodId must be specified
                Invalid Selling Plan:
                  description: Invalid Selling Plan
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:No selling plan found for id:
                      gid://shopify/SellingPlan/999999
                    status: 400
                    detail: The specified selling plan does not exist
        '401':
          description: Authentication required - missing or invalid API key
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '403':
          description: Insufficient permissions to create subscription contracts
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '422':
          description: >-
            Unable to process the subscription contract due to Shopify API
            constraints
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: createSubscriptionContractError
                status: 422
                detail: 'Shopify API error: Product variant not found'
  /api/external/v2/product-swaps-by-variant-groups/{contractId}:
    post:
      tags:
        - Product Catalog
      summary: Get product swap variant groups for a contract
      description: >-
        Retrieves product swap variant groups for the next 10 billing cycles of
        a specific subscription contract. This endpoint calculates and returns
        which products will be swapped to in future billing cycles based on
        configured swap automations.


        **Response Structure:**

        Returns a 2D array (List<List<VariantQuantity>>):

        - **Outer array**: Represents the next 10 billing cycles

        - **Inner arrays**: Contains the variant(s) that will be swapped to for
        that specific cycle

        - **Index 0**: Variants for the next (upcoming) billing cycle

        - **Index 1**: Variants for the cycle after that

        - And so on for the next 10 cycles


        **Variant Details:**

        Each variant object includes:

        - **variantId**: Shopify variant ID

        - **quantity**: Number of units to swap

        - **title**: Variant title (e.g., "Medium Roast - 12oz")

        - **image**: Product/variant image URL

        - **productTitle**: Full product name

        - **productId**: Shopify product GID

        - **variantTitle**: Full display name combining product and variant
        titles

        - **swapId**: ID of the swap automation rule that triggered this swap


        **How It Works:**

        1. Takes the current products in the subscription

        2. Applies configured swap automations for the next 10 cycles

        3. Calculates which products will be swapped based on:
           - Billing cycle number
           - Swap rule configurations (forBillingCycle, checkForEveryRecurringOrder)
           - Rule sequence/priority
        4. Returns the projected product lineup for each cycle


        **Use Cases:**

        - Preview upcoming product swaps in customer portals

        - Show customers their subscription product timeline

        - Build interactive swap calendars

        - Display "what you'll receive" for future orders

        - Debug and verify swap automation configurations


        **Important Notes:**

        - Returns 10 cycles even if no swaps are configured (returns current
        products)

        - Multiple variants in an inner array means multiple products will be in
        that order

        - Empty inner arrays indicate no products for that cycle (rare edge
        case)

        - The swapId can be used to trace which automation rule triggered the
        swap


        **Authentication:** Requires valid X-API-Key header
      operationId: getProductSwapsByVariantIdV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: contractId
          in: path
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        description: VariantQuantityInfo payload
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VariantQuantityInfo'
            examples:
              Request Example:
                description: Request Example
                value:
                  variantQuantityList:
                    - variantId: 12345
                      quantity: 2
                      swapId: 1001
                    - variantId: 67890
                      quantity: 2
                      swapId: 1002
        required: true
      responses:
        '200':
          description: >-
            Product swap variant groups returned successfully - Returns
            swappable variants for the next 10 billing cycles. Each element in
            the outer array represents the variants that will be swapped to for
            a specific billing cycle.
          content:
            application/json:
              examples:
                Success Response:
                  description: >-
                    Array of arrays - outer array represents billing cycles,
                    inner arrays contain variants for that cycle
                  value:
                    - - variantId: 12345
                        quantity: 2
                        title: Medium Roast - 12oz
                        image: >-
                          https://cdn.shopify.com/files/1/0000/0000/products/medium-roast.jpg
                        productTitle: House Blend Coffee
                        productId: gid://shopify/Product/98765
                        variantTitle: House Blend Coffee - Medium Roast - 12oz
                        swapId: 1001
                      - variantId: 12346
                        quantity: 1
                        title: Light Roast - 8oz
                        image: >-
                          https://cdn.shopify.com/files/1/0000/0000/products/light-roast.jpg
                        productTitle: Morning Blend Coffee
                        productId: gid://shopify/Product/98766
                        variantTitle: Morning Blend Coffee - Light Roast - 8oz
                        swapId: 1001
                    - - variantId: 67890
                        quantity: 2
                        title: Dark Roast - 12oz
                        image: >-
                          https://cdn.shopify.com/files/1/0000/0000/products/dark-roast.jpg
                        productTitle: Bold Blend Coffee
                        productId: gid://shopify/Product/88765
                        variantTitle: Bold Blend Coffee - Dark Roast - 12oz
                        swapId: 1002
        '400':
          description: Invalid contract ID or contract doesn't belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid contract
                status: 400
                detail: Contract does not belong to this shop
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to view product swap variant groups
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to view product swap variant
                  groups
        '404':
          description: Contract not found or no swap groups available
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: No swap groups found
                status: 404
                detail: No product swap variant groups available for this contract
  /api/external/v2/delivery-profiles/v3/create-shipping-profile:
    post:
      tags:
        - Operations & Settings
      summary: Create a new shipping/delivery profile (V3)
      description: >-
        Creates a new shipping or delivery profile for subscription orders using
        the V3 request format. This is the latest version with the most
        comprehensive delivery profile configuration capabilities.


        **Enhancements in V3:**

        - Full support for all Shopify delivery profile features

        - Advanced rate calculation options

        - Support for weight-based and price-based rates

        - Enhanced zone and country management

        - Better handling of delivery conditions and rules


        **Key Features:**

        - Define complex shipping rate structures

        - Configure multiple delivery methods per zone

        - Set up conditional rates based on weight, price, or item count

        - Manage detailed shipping zones with province-level granularity

        - Full control over delivery profile settings


        **Authentication:** Requires valid X-API-Key header
      operationId: createShippingProfileV3External
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateShippingProfileRequestV3'
        required: true
      responses:
        '200':
          description: Delivery profile created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateShippingProfileRequestV3'
        '400':
          description: Invalid request parameters or validation error
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/CreateShippingProfileRequestV3'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/CreateShippingProfileRequestV3'
        '403':
          description: Insufficient permissions to create delivery profiles
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/CreateShippingProfileRequestV3'
        '422':
          description: Unable to process delivery profile due to Shopify API constraints
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/CreateShippingProfileRequestV3'
  /api/external/v2/delivery-profiles/v2/create-shipping-profile:
    post:
      tags:
        - Operations & Settings
      summary: Create a new shipping/delivery profile (V2)
      description: >-
        Creates a new shipping or delivery profile for subscription orders using
        the V2 request format. This version provides enhanced configuration
        options for delivery methods, zones, and pricing.


        **Enhancements in V2:**

        - Improved zone configuration

        - Better support for multiple delivery methods

        - Enhanced rate definition capabilities

        - Support for conditional delivery rates


        **Key Features:**

        - Define custom shipping rates per zone

        - Configure local delivery options

        - Set up local pickup methods

        - Manage shipping zones and countries

        - Assign profiles to specific products or variants


        **Authentication:** Requires valid X-API-Key header
      operationId: createShippingProfileV2External
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateShippingProfileRequestV2'
        required: true
      responses:
        '200':
          description: Delivery profile created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeliveryProfileDTO'
        '400':
          description: Invalid request parameters or validation error
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/DeliveryProfileDTO'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/DeliveryProfileDTO'
        '403':
          description: Insufficient permissions to create delivery profiles
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/DeliveryProfileDTO'
        '422':
          description: Unable to process delivery profile due to Shopify API constraints
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/DeliveryProfileDTO'
  /api/external/v2/delivery-profiles/create-shipping-profile:
    post:
      tags:
        - Operations & Settings
      summary: Create a new shipping/delivery profile
      description: >-
        Creates a new shipping or delivery profile for subscription orders. This
        endpoint allows you to configure custom shipping rates, delivery
        methods, and shipping zones for your subscription products. Delivery
        profiles control how subscription products are shipped to customers.


        **Key Features:**

        - Define custom shipping rates per zone

        - Configure local delivery options

        - Set up local pickup methods

        - Manage shipping zones and countries

        - Assign profiles to specific products or variants


        **Delivery Method Types:**

        - **SHIPPING**: Standard shipping with carrier rates or custom rates

        - **LOCAL_DELIVERY**: Local delivery service within specific areas

        - **PICKUP**: Customer pickup from store locations


        **Important Notes:**

        - Each delivery profile must have a unique name

        - At least one delivery method is required

        - Shipping rates can be set per zone and per weight/price range

        - Profiles can be assigned to subscription products to control their
        shipping behavior


        **Authentication:** Requires valid X-API-Key header
      operationId: createShippingProfileV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateShippingProfileRequestVM'
        required: true
      responses:
        '200':
          description: Delivery profile created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeliveryProfileDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: '12345'
                    shop: example-shop.myshopify.com
                    name: Standard Subscription Shipping
                    shopifyDeliveryProfileId: gid://shopify/DeliveryProfile/67890
                    default: false
                    locationGroupsCount: 1
                    productsCount: 15
                    profileLocationGroups:
                      - locationGroupId: gid://shopify/DeliveryLocationGroup/11111
                        countries:
                          - code: US
                            name: United States
                            provinces: []
                          - code: CA
                            name: Canada
                            provinces: []
                        zones:
                          - methodDefinitions:
                              - name: Standard Shipping
                                rateDefinition:
                                  price:
                                    amount: '5.99'
                                    currencyCode: USD
        '400':
          description: Invalid request parameters or validation error
          content:
            application/json:
              examples:
                Missing Profile Name:
                  description: Missing Profile Name
                  value:
                    type: https://example.com/errors/bad-request
                    title: Validation Error
                    status: 400
                    detail: Delivery profile name is required
                Invalid Delivery Method:
                  description: Invalid Delivery Method
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid delivery method configuration
                    status: 400
                    detail: At least one delivery method must be specified
                Duplicate Profile Name:
                  description: Duplicate Profile Name
                  value:
                    type: https://example.com/errors/bad-request
                    title: Duplicate profile name
                    status: 400
                    detail: A delivery profile with this name already exists
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to create delivery profiles
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to create delivery profiles
        '422':
          description: Unable to process delivery profile due to Shopify API constraints
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: Shopify API error
                status: 422
                detail: Unable to create delivery profile in Shopify
  /api/external/v2/bulk-automations/replace-product:
    post:
      tags:
        - Operations & Settings
      summary: Replace products in subscriptions in bulk
      description: >-
        Replaces old product variants with new product variants across multiple
        subscription contracts in bulk. This powerful operation allows merchants
        to update products in active subscriptions when products are
        discontinued, reformulated, or repackaged.


        **What is Product Replacement?**

        Product replacement updates the products in active subscriptions by
        swapping out old variant IDs with new variant IDs. This is commonly
        needed when:

        - Products are discontinued and replaced with new versions

        - Product packaging changes (size, quantity)

        - Product reformulations or recipe updates

        - SKU consolidation or reorganization

        - Seasonal product variations

        - Price structure changes


        **Key Features:**

        - **Bulk Operation**: Update thousands of subscriptions simultaneously

        - **Multi-Variant Support**: Replace multiple old variants with new ones
        in single request

        - **Flexible Mapping**: One-to-one, many-to-one, or one-to-many variant
        replacements

        - **Selective or Universal**: Target specific subscriptions or all
        subscriptions

        - **Asynchronous Processing**: Large batches processed in background

        - **Price Preservation Options**: Maintain existing subscription pricing
        or update to new prices

        - **Activity Logging**: All replacements are logged for audit trail


        **Operation Modes:**

        1. **Specific Subscriptions**: Provide subscription contract IDs to
        update only those subscriptions

        2. **All Subscriptions**: Set allSubscriptions=true to replace products
        in ALL active subscriptions containing the old variants


        **How It Works:**

        1. Identify old variant IDs that need to be replaced

        2. Identify new variant IDs that will replace them

        3. Optionally specify which subscriptions to update (or use
        allSubscriptions=true)

        4. Submit the bulk replacement request

        5. System validates all variant IDs exist and are accessible

        6. Bulk automation task is created and queued

        7. Each subscription is updated with new variants

        8. Customers receive updated subscription details

        9. Next orders will include the new products


        **Variant ID Mapping:**

        The replacement supports flexible mapping between old and new variants:


        **One-to-One Replacement:**

        ```json

        {
          "oldVariantIds": [111111],
          "newVariantIds": [222222]
        }

        ```

        Old variant 111111 is replaced with new variant 222222


        **Multiple Variants Replacement:**

        ```json

        {
          "oldVariantIds": [111111, 333333, 555555],
          "newVariantIds": [222222, 444444, 666666]
        }

        ```

        Each old variant is replaced with its corresponding new variant (by
        position)


        **Request Structure:**

        ```json

        {
          "subscriptionIds": [
            "gid://shopify/SubscriptionContract/123456",
            "gid://shopify/SubscriptionContract/123457"
          ]
        }

        ```


        **Query Parameters:**

        - `api_key` (required): Your API authentication key

        - `allSubscriptions` (optional): Set to true to update all
        subscriptions, false/omit to update only specified IDs

        - `newVariantIds` (required): Comma-separated list of new variant IDs
        (e.g., 222222,444444,666666)

        - `oldVariantIds` (required): Comma-separated list of old variant IDs to
        replace (e.g., 111111,333333,555555)


        **Use Cases:**


        **1. Product Discontinuation:**

        When a product is being discontinued:

        - Identify replacement product

        - Map old variant IDs to new variant IDs

        - Update all subscriptions containing the old product

        - Notify customers of the change


        **2. Packaging Updates:**

        When product packaging changes (e.g., 10oz to 12oz):

        - Create new variant for new package size

        - Replace old variant across subscriptions

        - Adjust pricing if needed


        **3. Product Reformulation:**

        When product recipes or formulas change:

        - Create new product variant for reformulated version

        - Bulk replace old formula with new formula

        - Maintain customer subscription frequency and pricing


        **4. SKU Consolidation:**

        When consolidating multiple variants into a single SKU:

        - Map multiple old variant IDs to single new variant ID

        - Update all affected subscriptions

        - Simplify inventory management


        **5. Seasonal Product Rotation:**

        For seasonal subscription boxes:

        - Replace summer variants with fall variants

        - Update all active seasonal subscriptions

        - Maintain subscription continuity


        **Important Considerations:**

        - **Pricing Impact**: New variants may have different prices - verify
        pricing strategy

        - **Inventory Levels**: Ensure adequate inventory for new variants

        - **Customer Communication**: Consider notifying customers before
        replacement

        - **Variant Compatibility**: New variants should be appropriate
        replacements

        - **One Operation at a Time**: Only one bulk operation can run per shop
        simultaneously

        - **Irreversible**: Product replacements cannot be automatically undone
        (must be manually reversed)

        - **Subscription Contract IDs**: Must use Shopify GraphQL ID format


        **Processing Time:**

        - Small batches (<100 subscriptions): Seconds to minutes

        - Medium batches (100-1000): Minutes

        - Large batches (>1000): Minutes to hours

        - Processing time depends on number of subscriptions and line items


        **Best Practices:**

        1. **Test First**: Test with a small subset of subscriptions before bulk
        operation

        2. **Verify Variants**: Confirm all variant IDs are correct and products
        are active

        3. **Check Inventory**: Ensure sufficient stock of new variants

        4. **Customer Communication**: Notify affected customers about product
        changes

        5. **Price Review**: Review and confirm pricing for new variants

        6. **Backup Data**: Export subscription data before making bulk changes

        7. **Monitor Progress**: Track bulk operation status to completion

        8. **Audit Trail**: Document reason for replacement for future reference


        **Error Scenarios:**

        - Another bulk operation running: 400 error

        - Invalid variant IDs: Operation may fail or skip invalid variants

        - Mismatched array lengths: Ensure oldVariantIds and newVariantIds have
        same count

        - Product not found: Variants must exist in your Shopify store

        - Unauthorized access: Can only modify subscriptions belonging to your
        shop


        **Customer Impact:**

        - Next subscription order will contain new products

        - Previous orders are not affected

        - Subscription price may change if new variant has different price

        - Customer portal reflects the new product immediately

        - Subscription frequency and schedule remain unchanged


        **Authentication:** Requires valid api_key parameter (X-API-Key header
        support coming soon)
      operationId: replaceProductV2
      parameters:
        - name: api_key
          in: query
          description: Your API Key
          required: true
          schema:
            type: string
        - name: allSubscriptions
          in: query
          description: allSubscriptions
          required: false
          schema:
            type: boolean
        - name: newVariantIds
          in: query
          description: New Variant Ids
          required: true
          schema:
            type: array
            items:
              type: integer
              format: int64
        - name: oldVariantIds
          in: query
          description: Old Variant Ids
          required: true
          schema:
            type: array
            items:
              type: integer
              format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionContractIdsWrapper'
        required: true
      responses:
        '204':
          description: >-
            Bulk product replacement operation successfully queued and
            initiated. Subscriptions will be updated asynchronously.
          content:
            application/json:
              examples:
                Success Response:
                  description: Success Response
                  value: {}
        '400':
          description: >-
            Bad request - bulk operation already in progress, invalid
            parameters, or missing required fields
          content:
            application/json:
              examples:
                Operation Already Running:
                  description: Operation Already Running
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bulk operation in progress
                    status: 400
                    detail: >-
                      UserGeneratedError: Bulk request for current shop is
                      already in progress
                    entityName: bulkAutomation
                Missing Variant IDs:
                  description: Missing Variant IDs
                  value:
                    type: https://example.com/errors/bad-request
                    title: Missing required parameters
                    status: 400
                    detail: >-
                      Both oldVariantIds and newVariantIds parameters are
                      required
                Mismatched Variant Arrays:
                  description: Mismatched Variant Arrays
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid variant mapping
                    status: 400
                    detail: >-
                      oldVariantIds and newVariantIds must have the same number
                      of elements
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid api_key parameter is required
        '403':
          description: Insufficient permissions to perform bulk product replacement
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to modify subscription
                  products
        '404':
          description: One or more variant IDs not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Variant not found
                status: 404
                detail: One or more specified variant IDs do not exist in your store
        '422':
          description: >-
            Unprocessable entity - Invalid variant IDs or business logic
            validation failure
          content:
            application/json:
              example:
                type: https://example.com/errors/unprocessable-entity
                title: Invalid variant replacement
                status: 422
                detail: New variant is not compatible with subscription configuration
        '500':
          description: Internal server error during bulk operation initialization
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-server-error
                title: Internal server error
                status: 500
                detail: >-
                  An unexpected error occurred while initiating the bulk
                  replacement operation
  /api/external/v2/bulk-automations/hide-subscriptions:
    post:
      tags:
        - Operations & Settings
      summary: Hide subscriptions in bulk
      description: >-
        Hides multiple subscription contracts from customer view in bulk. This
        operation allows merchants to quickly hide subscriptions from appearing
        in the customer portal without canceling or deleting them.


        **What Does 'Hide' Mean?**

        Hiding a subscription makes it invisible to customers in their customer
        portal while keeping the subscription data intact. The subscription is
        not deleted or canceled - it's simply hidden from the customer's view.
        This is useful for:

        - Temporarily removing subscriptions from customer access

        - Managing test or dummy subscriptions

        - Handling subscription disputes or issues

        - Preparing subscriptions for migration or cleanup


        **Key Features:**

        - **Bulk Operation**: Process multiple subscriptions in a single request

        - **Non-Destructive**: Subscriptions are hidden, not deleted

        - **Reversible**: Hidden subscriptions can be unhidden later

        - **Asynchronous Processing**: Large batches are processed in the
        background

        - **Conflict Detection**: Prevents multiple simultaneous bulk operations


        **Operation Modes:**

        1. **Specific Subscriptions**: Provide a list of subscription contract
        IDs to hide

        2. **All Subscriptions**: Set allSubscriptions=true to hide all active
        subscriptions (use with caution)


        **How It Works:**

        1. Submit a request with subscription IDs or allSubscriptions flag

        2. System validates the subscription IDs belong to your shop

        3. A bulk automation task is created and queued

        4. Each subscription is marked as hidden

        5. Subscriptions disappear from customer portal immediately

        6. Subscriptions remain in merchant admin for management


        **Request Body Structure:**

        ```json

        {
          "subscriptionIds": [
            "gid://shopify/SubscriptionContract/123456",
            "gid://shopify/SubscriptionContract/123457",
            "gid://shopify/SubscriptionContract/123458"
          ]
        }

        ```


        **Use Cases:**

        - **Subscription Cleanup**: Hide test or duplicate subscriptions created
        during setup

        - **Customer Service**: Temporarily hide problematic subscriptions while
        resolving issues

        - **Migration Preparation**: Hide old subscriptions before migrating to
        new plans

        - **Dispute Management**: Hide subscriptions involved in billing
        disputes

        - **Seasonal Management**: Hide seasonal subscriptions during off-season

        - **Batch Processing**: Clean up subscriptions that meet certain
        criteria


        **Important Notes:**

        - Only one bulk operation can run at a time per shop

        - If a bulk operation is already in progress, the request will fail with
        400 error

        - Subscription IDs must be in Shopify GraphQL ID format
        (gid://shopify/SubscriptionContract/xxxxx)

        - Hidden subscriptions stop appearing in customer portal but remain
        active for billing

        - You can unhide subscriptions later through the admin interface

        - Using allSubscriptions=true will hide ALL subscriptions - use with
        extreme caution


        **Processing Time:**

        - Small batches (<100): Usually complete within seconds

        - Medium batches (100-1000): May take 1-2 minutes

        - Large batches (>1000): May take several minutes to hours

        - Progress can be tracked through the bulk automation status endpoint


        **Best Practices:**

        - Always specify exact subscription IDs rather than using
        allSubscriptions=true

        - Test with a small batch first before processing large numbers

        - Keep track of hidden subscription IDs for future reference

        - Document the reason for hiding subscriptions for audit purposes

        - Monitor bulk operation status to ensure completion

        - Consider notifying customers before hiding their subscriptions


        **Workflow Example:**

        1. Identify subscriptions to hide (e.g., test subscriptions with
        specific tags)

        2. Extract their subscription contract IDs

        3. Call this endpoint with the list of IDs

        4. Verify 204 No Content response indicating successful queue

        5. Monitor processing status through admin or status endpoint

        6. Confirm subscriptions are hidden from customer portal


        **Error Scenarios:**

        - Another bulk operation is running: 400 error with message about
        operation in progress

        - Invalid subscription IDs: Silently skips invalid IDs, processes valid
        ones

        - Unauthorized subscription access: Only subscriptions belonging to your
        shop are processed

        - Empty subscription list: Operation completes successfully with no
        action


        **Authentication:** Requires valid api_key parameter (X-API-Key header
        support coming soon)
      operationId: hideSubscriptionsV2
      parameters:
        - name: api_key
          in: query
          description: Your API Key
          required: true
          schema:
            type: string
        - name: allSubscriptions
          in: query
          description: allSubscriptions
          required: false
          schema:
            type: boolean
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionContractIdsWrapper'
        required: true
      responses:
        '204':
          description: >-
            Bulk hide operation successfully queued and initiated. Subscriptions
            will be hidden asynchronously.
          content:
            application/json:
              examples:
                Success Response:
                  description: Success Response
                  value: {}
        '400':
          description: >-
            Bad request - bulk operation already in progress or invalid
            parameters
          content:
            application/json:
              examples:
                Operation Already Running:
                  description: Operation Already Running
                  value:
                    type: https://example.com/errors/bad-request
                    title: Bulk operation in progress
                    status: 400
                    detail: >-
                      UserGeneratedError: Bulk request for current shop is
                      already in progress
                    entityName: bulkAutomation
                Invalid Request Body:
                  description: Invalid Request Body
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid subscription IDs
                    status: 400
                    detail: Request body must contain valid subscription contract IDs
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid api_key parameter is required
        '403':
          description: Insufficient permissions to perform bulk hide operations
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to hide subscriptions
        '500':
          description: Internal server error during bulk operation initialization
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-server-error
                title: Internal server error
                status: 500
                detail: >-
                  An unexpected error occurred while initiating the bulk hide
                  operation
  /api/external/v2/upcoming-subscription-contract-one-offs-by-contractId:
    get:
      tags:
        - Subscription One-Time Products
      summary: Get one-time products for next upcoming order
      description: >-
        Retrieves one-time products that will be included in the next scheduled
        order for a subscription contract. This endpoint specifically returns
        products associated with the earliest queued billing attempt, making it
        ideal for showing customers what additional items will be in their next
        delivery.


        **Key Differences from /subscription-contract-one-offs-by-contractId:**

        - Returns ONLY products for the next upcoming order (not all future
        orders)

        - Finds the earliest QUEUED billing attempt by date

        - Returns empty array if no queued billing attempts exist

        - Useful for "Your Next Order" previews in customer portals


        **Use Cases:**

        - Display a preview of the next order including one-time add-ons

        - Calculate the total cost of the upcoming delivery

        - Show customers their next delivery date with associated one-time items

        - Allow last-minute modifications before order processing


        **Business Logic:**

        1. Searches for billing attempts with status = QUEUED

        2. Selects the one with the earliest billing date

        3. Returns all one-time products for that specific billing attempt

        4. Returns empty array if no queued orders exist (e.g., subscription
        paused/cancelled)


        **Authentication:** Requires valid X-API-Key header that identifies the
        shop
      operationId: getOneOffForContractNextOrderExternal
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: X-API-Key
          in: header
          description: >-
            API Key for authentication. This key identifies your shop and must
            be included in the X-API-Key header.
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: contractId
          in: query
          description: >-
            The unique identifier of the subscription contract to retrieve
            upcoming one-time products for
          required: true
          schema:
            minimum: 1
            type: integer
            description: Must be a valid contract ID that belongs to the authenticated shop
            format: int64
          example: 98765
      responses:
        '200':
          description: Successfully retrieved next order one-time products
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionContractOneOffDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    - id: 12345
                      shop: example-shop.myshopify.com
                      contractId: 67890
                      billingAttemptId: 11111
                      variantId: 22222
                      quantity: 2
                      productTitle: Coffee Filters - Pack of 100
                      variantTitle: Standard Size
                      image: >-
                        https://cdn.shopify.com/s/files/1/0000/0000/products/filter.jpg
                      price: '9.99'
                      currencyCode: USD
        '400':
          description: Invalid contract or no upcoming orders
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
              examples:
                Missing Contract ID:
                  description: Missing Contract ID
                  value:
                    type: https://example.com/probs/bad-request
                    title: Bad Request
                    status: 400
                    detail: >-
                      Required request parameter 'contractId' for method
                      parameter type Long is not present
                    instance: >-
                      /api/external/v2/upcoming-subscription-contract-one-offs-by-contractId
                Invalid Contract ID Format:
                  description: Invalid Contract ID Format
                  value:
                    type: https://example.com/probs/bad-request
                    title: Bad Request
                    status: 400
                    detail: >-
                      Failed to convert value of type 'java.lang.String' to
                      required type 'java.lang.Long'; For input string:
                      'invalid'
                    instance: >-
                      /api/external/v2/upcoming-subscription-contract-one-offs-by-contractId
        '401':
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: https://example.com/probs/unauthorized
                title: Unauthorized
                status: 401
                detail: Full authentication is required to access this resource
                instance: >-
                  /api/external/v2/upcoming-subscription-contract-one-offs-by-contractId
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: https://example.com/probs/forbidden
                title: Forbidden
                status: 403
                detail: >-
                  Access is denied - contract does not belong to authenticated
                  shop
                instance: >-
                  /api/external/v2/upcoming-subscription-contract-one-offs-by-contractId
  /api/external/v2/theme-settings/regenerate-scripts-for-shop:
    get:
      tags:
        - Customer Portal
      summary: Regenerate subscription widget scripts
      description: >-
        Triggers regeneration and deployment of subscription widget JavaScript
        files for the authenticated shop. This endpoint rebuilds the widget
        scripts that power subscription functionality on your storefront and
        deploys them to CDN.


        **What Does This Endpoint Do?**

        This endpoint initiates an asynchronous process to regenerate and update
        the JavaScript files that enable subscription widgets on your store's
        theme. The widget scripts handle:

        - Subscription product selection and display

        - Subscription plan offerings on product pages

        - Frequency and delivery interval selectors

        - Subscription pricing display

        - Add-to-cart subscription functionality

        - Widget styling and customization


        **When to Use This Endpoint:**


        **1. After Widget Settings Changes:**

        - Modified widget appearance or styling

        - Changed subscription plan display options

        - Updated widget text or labels

        - Altered widget positioning or layout

        - Changed frequency options display


        **2. After Theme Customization:**

        - Installed a new theme

        - Updated existing theme

        - Made CSS customizations affecting widgets

        - Changed theme structure requiring widget updates


        **3. After Plan Configuration Changes:**

        - Added new subscription plans

        - Modified existing plan details

        - Changed plan pricing or discounts

        - Updated plan availability rules


        **4. Troubleshooting:**

        - Widget not displaying correctly on storefront

        - Subscription options showing outdated information

        - Widget functionality broken after theme changes

        - Script conflicts or errors on product pages

        - Cache issues preventing updates from showing


        **5. After App Updates:**

        - Appstle subscription app has been upgraded

        - New widget features have been released

        - Bug fixes requiring script updates


        **How It Works:**


        1. **Initiation**: API call triggers the script regeneration process

        2. **Compilation**: System compiles widget configuration, theme
        settings, and subscription plans into optimized JavaScript

        3. **Deployment**: Generated scripts are uploaded to CDN for fast global
        delivery

        4. **Cache Invalidation**: Old cached versions are invalidated

        5. **Completion**: Updated scripts become available to your storefront
        (typically within 1-2 minutes)


        **What Gets Regenerated:**

        - **Widget JavaScript**: Core widget functionality and UI components

        - **Configuration Data**: Embedded shop-specific settings and plan
        information

        - **Styling Rules**: Custom CSS and theme-specific styles

        - **Initialization Code**: Auto-load and widget mounting logic

        - **Event Handlers**: Customer interaction and analytics tracking


        **Process Details:**

        - **Asynchronous**: The regeneration happens in the background

        - **Non-blocking**: Endpoint returns immediately (true on success)

        - **No downtime**: Existing widgets continue working during regeneration

        - **Automatic deployment**: Scripts are automatically deployed to CDN

        - **Versioning**: New script versions don't break existing functionality


        **Expected Behavior:**

        - Endpoint returns `true` immediately to confirm process started

        - Script regeneration completes in background (typically 30-90 seconds)

        - Updated scripts propagate to CDN (1-2 minutes)

        - Browser cache may need clearing to see changes immediately

        - Changes visible to customers after cache expiration (varies by
        browser)


        **Use Cases:**

        - **Automated Deployments**: Include in CI/CD pipeline after theme
        updates

        - **Widget Troubleshooting**: Force refresh when widget issues occur

        - **Configuration Sync**: Ensure widgets reflect latest settings after
        bulk changes

        - **Theme Migration**: Update scripts after moving to new theme

        - **Testing**: Regenerate scripts after making configuration changes in
        staging

        - **Maintenance**: Periodic regeneration to ensure optimal performance


        **Important Notes:**

        - Safe to call multiple times (idempotent operation)

        - No negative impact on existing subscriptions

        - Does not modify theme files directly

        - Scripts are hosted on CDN, not in your theme

        - Changes apply to all store pages using subscription widgets

        - Browser caching may delay visibility of changes to end users


        **Best Practices:**

        - Call this endpoint after making widget setting changes

        - Wait 2-3 minutes before testing changes on storefront

        - Clear browser cache when testing to see latest version

        - Use in test/staging environment before production

        - Avoid calling excessively (once per configuration change is
        sufficient)

        - Monitor widget functionality after regeneration


        **Troubleshooting:**

        If widgets still don't reflect changes after regeneration:

        1. Wait 5 minutes for full CDN propagation

        2. Clear browser cache and hard refresh (Ctrl+Shift+R / Cmd+Shift+R)

        3. Check browser console for JavaScript errors

        4. Verify theme has widget embed code installed

        5. Confirm subscription plans are properly configured

        6. Test in incognito/private browsing mode


        **Integration Workflows:**


        **Theme Update Workflow:**

        1. Make theme changes

        2. Update widget settings if needed

        3. Call regenerate-scripts endpoint

        4. Wait 2-3 minutes

        5. Test widgets on storefront

        6. Deploy to production


        **Bulk Configuration Update:**

        1. Update multiple subscription plans

        2. Modify widget appearance settings

        3. Call regenerate-scripts once (not after each change)

        4. Verify changes propagated correctly


        **Authentication:** Requires valid API key via api_key parameter or
        X-API-Key header
      operationId: regenerateScriptForShop
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: >-
            Script regeneration initiated successfully. Returns true to confirm
            the process has started. Scripts will be regenerated asynchronously
            in the background and deployed to CDN within 1-2 minutes.
          content:
            application/json:
              schema:
                type: boolean
              examples:
                Success Response:
                  description: Success Response
                  value: true
        '400':
          description: >-
            Bad request - Invalid shop configuration or missing required
            settings
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid configuration
                status: 400
                detail: Shop theme settings are not properly configured
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: >-
                  Valid API key is required. Provide via api_key parameter or
                  X-API-Key header.
        '403':
          description: Insufficient permissions to regenerate scripts
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to regenerate theme scripts
        '429':
          description: Rate limit exceeded - Too many regeneration requests
          content:
            application/json:
              example:
                type: https://example.com/errors/rate-limit
                title: Rate limit exceeded
                status: 429
                detail: >-
                  Too many script regeneration requests. Please wait before
                  trying again.
                retryAfter: 60
        '500':
          description: Internal server error - Script regeneration failed to initiate
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-error
                title: Script regeneration failed
                status: 500
                detail: >-
                  Unable to initiate script regeneration process. Please try
                  again or contact support.
  /api/external/v2/subscription-groups/{id}:
    get:
      tags:
        - Subscription Plans
      summary: Get subscription group by ID
      description: >-
        Retrieves detailed information about a specific subscription group
        (selling plan group) by its ID. This endpoint provides complete
        configuration details for a single subscription group.


        **Response includes:**

        - Group name and configuration

        - All selling plans with complete details

        - Product and variant assignments

        - Discount tiers and configurations

        - Free trial settings

        - Member restrictions

        - Delivery and billing frequencies


        **Use Cases:**

        - Display detailed subscription options for editing

        - Verify configuration before updates

        - Debug subscription issues

        - Integration with external systems


        **Authentication:** Requires valid X-API-Key header
      operationId: getSubscriptionGroupV2External
      parameters:
        - name: id
          in: path
          description: Subscription group ID (numeric ID)
          required: true
          schema:
            type: integer
            format: int64
          example: 123456789
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      responses:
        '200':
          description: Successfully retrieved subscription group
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: 123456789
                    groupName: Monthly Coffee Subscription
                    productCount: 10
                    productVariantCount: 35
                    productIds: >-
                      [{"id":987654321,"title":"Premium Coffee
                      Blend","status":"ACTIVE","handle":"premium-coffee-blend","imageSrc":"https://cdn.shopify.com/...","vendor":"Coffee
                      Co","tags":"coffee,subscription","productType":"Coffee","price":"19.99"}]
                    variantIds: '[{"id":123456789,"title":"250g Bag","status":"ACTIVE"}]'
                    subscriptionPlans:
                      - id: gid://shopify/SellingPlan/111111
                        idNew: gid://shopify/SellingPlan/111111
                        frequencyName: Delivered Monthly
                        frequencyDescription: Get fresh coffee delivered to your door every month
                        frequencyCount: 1
                        frequencyInterval: MONTH
                        billingFrequencyCount: 1
                        billingFrequencyInterval: MONTH
                        planType: PAY_AS_YOU_GO
                        discountEnabled: true
                        discountType: PERCENTAGE
                        discountOffer: 10
                        afterCycle1: 0
                        discountEnabled2: true
                        discountType2: PERCENTAGE
                        discountOffer2: 15
                        afterCycle2: 6
                        minCycles: 3
                        maxCycles: null
                        upcomingOrderEmailBuffer: 3
                        inventoryPolicyReserve: ON_SALE
                        memberOnly: false
                        specificDayEnabled: false
                        frequencyType: ON_PURCHASE_DAY
                        freeTrialEnabled: false
                        deliveryPolicyPreAnchorBehavior: ASAP
                        frequencySequence: 0
                        groupId: 123456789
                        groupName: Monthly Coffee Subscription
                        appstleCycles: []
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionGroupV2DTO'
        '404':
          description: Subscription group not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Not Found
                status: 404
                detail: Subscription group with ID 999999 not found
  /api/external/v2/subscription-groups/all-selling-plans:
    get:
      tags:
        - Subscription Plans
      summary: Get all selling plans across all subscription groups
      description: >-
        Retrieves a flattened list of all selling plans from all subscription
        groups in the store. This endpoint provides a consolidated view of every
        subscription plan available, regardless of which group it belongs to.


        **Response includes:**

        - All selling plans with their configurations

        - Group information for each plan (groupId and groupName)

        - Complete discount and pricing details

        - Delivery and billing frequencies

        - Member restrictions and settings

        - Free trial configurations


        **Use Cases:**

        - Build a unified subscription selector

        - Compare all available subscription options

        - Analyze pricing across all plans

        - Find specific plan configurations

        - Generate reports on subscription offerings


        **Differences from /subscription-groups endpoint:**

        - Returns plans as a flat list, not grouped

        - Each plan includes its parent group information

        - Easier to search/filter across all plans

        - Does not include product/variant assignments


        **Authentication:** Requires valid X-API-Key header
      operationId: getAllSellingPlansV2External
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
      responses:
        '200':
          description: Successfully retrieved all selling plans
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FrequencyInfoDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    - id: gid://shopify/SellingPlan/111111
                      frequencyName: Delivered Monthly
                      frequencyDescription: Save 10% on monthly deliveries
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      billingFrequencyCount: 1
                      billingFrequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 10
                      afterCycle1: 0
                      minCycles: 3
                      maxCycles: null
                      groupId: 123456789
                      groupName: Monthly Coffee Subscription
                      inventoryPolicyReserve: ON_SALE
                      memberOnly: false
                      frequencyType: ON_PURCHASE_DAY
                      upcomingOrderEmailBuffer: 3
                    - id: gid://shopify/SellingPlan/222222
                      frequencyName: Weekly Tea Box
                      frequencyDescription: Fresh tea every week with 15% savings
                      frequencyCount: 1
                      frequencyInterval: WEEK
                      billingFrequencyCount: 1
                      billingFrequencyInterval: WEEK
                      planType: PAY_AS_YOU_GO
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 15
                      afterCycle1: 0
                      groupId: 123456790
                      groupName: Premium Tea Collection
                    - id: gid://shopify/SellingPlan/333333
                      frequencyName: 3-Month Prepaid Coffee
                      frequencyDescription: Pay upfront for 3 months and save 25%
                      frequencyCount: 1
                      frequencyInterval: MONTH
                      billingFrequencyCount: 3
                      billingFrequencyInterval: MONTH
                      planType: PAY_AS_YOU_GO_PREPAID
                      payAsYouGoPrepaidBillingFrequencyCount: 3
                      discountEnabled: true
                      discountType: PERCENTAGE
                      discountOffer: 25
                      afterCycle1: 0
                      maxCycles: 12
                      groupId: 123456789
                      groupName: Monthly Coffee Subscription
                      repeatingCycle: true
                      repeatingNumberOfCycle: 12
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/FrequencyInfoDTO'
        '403':
          description: Insufficient permissions to view selling plans
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/FrequencyInfoDTO'
        '500':
          description: Internal server error
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/FrequencyInfoDTO'
  /api/external/v2/subscription-customers/{id}:
    get:
      tags:
        - Customers
      summary: Get customer details with subscriptions
      description: >-
        Retrieves comprehensive customer information including their
        subscription contracts. This endpoint provides customer profile data
        along with a paginated list of their active and historical
        subscriptions.


        **Key Features:**

        - Customer profile information (name, email, phone, addresses)

        - Complete subscription history with pagination

        - Payment method details

        - Customer account state and metadata

        - Order history related to subscriptions

        - Customer tags and notes


        **Subscription Data Included:**

        - All subscription contracts (active, paused, cancelled)

        - Contract details with line items

        - Billing and delivery policies

        - Next billing dates and amounts

        - Applied discounts


        **Pagination:**

        - Subscription contracts are paginated

        - Default page size varies by Shopify plan

        - Use cursor for subsequent pages

        - Cursor-based pagination ensures consistency


        **Use Cases:**

        - Customer service representatives viewing customer details

        - Integration with CRM systems

        - Customer analytics and reporting

        - Subscription management interfaces

        - Billing reconciliation


        **Important Notes:**

        - Customer ID is numeric (without gid:// prefix)

        - Returns null if customer not found

        - Includes both active and inactive subscriptions

        - Payment methods may be masked for security


        **Authentication:** Requires valid X-API-Key header
      operationId: getSubscriptionCustomerV2
      parameters:
        - name: id
          in: path
          description: >-
            Customer ID to retrieve. Provide the numeric ID without the gid://
            prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 987654321
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: cursor
          in: query
          description: >-
            Pagination cursor for subscription contracts. Use the cursor from
            previous response's pageInfo.endCursor to get the next page
          required: false
          schema:
            type: string
          example: >-
            eyJsYXN0X2lkIjoxMjM0NTY3ODksImxhc3RfdmFsdWUiOiIyMDI0LTAxLTE1IDEwOjAwOjAwIn0=
      responses:
        '200':
          description: Customer details successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Customer'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: gid://shopify/Customer/987654321
                    displayName: John Doe
                    firstName: John
                    lastName: Doe
                    email: john.doe@example.com
                    phone: '+12125551234'
                    state: ENABLED
                    acceptsMarketing: true
                    createdAt: '2023-01-15T10:30:00Z'
                    updatedAt: '2024-03-15T14:45:00Z'
                    tags:
                      - VIP
                      - Subscription
                    note: Preferred customer - handle with care
                    verifiedEmail: true
                    validEmailAddress: true
                    defaultAddress:
                      id: gid://shopify/MailingAddress/123456789
                      address1: 123 Main St
                      address2: Apt 4B
                      city: New York
                      province: New York
                      provinceCode: NY
                      country: United States
                      countryCode: US
                      zip: '10001'
                      phone: '+12125551234'
                      firstName: John
                      lastName: Doe
                      company: Acme Corp
                    addresses:
                      - id: gid://shopify/MailingAddress/123456789
                        address1: 123 Main St
                        city: New York
                        provinceCode: NY
                        countryCode: US
                        zip: '10001'
                      - id: gid://shopify/MailingAddress/987654321
                        address1: 456 Office Blvd
                        city: Brooklyn
                        provinceCode: NY
                        countryCode: US
                        zip: '11201'
                    paymentMethods:
                      - id: gid://shopify/CustomerPaymentMethod/111111
                        instrument:
                          __typename: CustomerCreditCard
                          brand: VISA
                          lastDigits: '4242'
                          expiryMonth: 12
                          expiryYear: 2025
                          maskedNumber: •••• •••• •••• 4242
                    subscriptionContracts:
                      edges:
                        - node:
                            id: gid://shopify/SubscriptionContract/123456789
                            status: ACTIVE
                            nextBillingDate: '2024-04-01T12:00:00Z'
                            createdAt: '2024-01-15T10:00:00Z'
                            updatedAt: '2024-03-15T14:30:00Z'
                            billingPolicy:
                              interval: MONTH
                              intervalCount: 1
                            deliveryPolicy:
                              interval: MONTH
                              intervalCount: 1
                            lines:
                              edges:
                                - node:
                                    id: gid://shopify/SubscriptionLine/111111
                                    productId: gid://shopify/Product/7890123456
                                    variantId: >-
                                      gid://shopify/ProductVariant/42549172011164
                                    title: Premium Coffee Subscription
                                    quantity: 2
                                    currentPrice:
                                      amount: '59.98'
                                      currencyCode: USD
                          cursor: >-
                            eyJsYXN0X2lkIjoxMjM0NTY3ODksImxhc3RfdmFsdWUiOiIyMDI0LTAxLTE1IDEwOjAwOjAwIn0=
                      pageInfo:
                        hasNextPage: true
                        hasPreviousPage: false
                        startCursor: >-
                          eyJsYXN0X2lkIjoxMjM0NTY3ODksImxhc3RfdmFsdWUiOiIyMDI0LTAxLTE1IDEwOjAwOjAwIn0=
                        endCursor: >-
                          eyJsYXN0X2lkIjoxMjM0NTY3OTAsImxhc3RfdmFsdWUiOiIyMDI0LTAyLTAxIDEyOjAwOjAwIn0=
                    numberOfOrders: '15'
        '400':
          description: Invalid request parameters
          content:
            application/json:
              examples:
                Invalid Customer ID:
                  description: Invalid Customer ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid customer ID
                    status: 400
                    detail: Customer ID must be a positive number
                Invalid Cursor:
                  description: Invalid Cursor
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid pagination cursor
                    status: 400
                    detail: The provided cursor is malformed or expired
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to access customer data
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to read customer data
        '404':
          description: Customer not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Customer not found
                status: 404
                detail: No customer found with ID 987654321
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-error
                title: Internal server error
                status: 500
                detail: An unexpected error occurred while retrieving customer data
  /api/external/v2/subscription-customers/valid/{customerId}:
    get:
      tags:
        - Customers
      summary: Get valid subscription contract IDs for a customer
      description: >-
        Retrieves a set of all valid (active, paused, or otherwise non-deleted)
        subscription contract IDs for a specific customer. This endpoint returns
        only the contract IDs without detailed subscription information, making
        it ideal for quick lookups and validation checks.


        **What Are Valid Subscription Contracts?**

        Valid contracts are subscriptions that exist in the system and haven't
        been permanently deleted. This includes subscriptions in all states
        except those that have been hard-deleted or hidden from the system. The
        contract IDs returned represent subscriptions that can be queried,
        modified, or managed through other API endpoints.


        **Contract States Included:**


        **Active States:**

        - `ACTIVE` - Currently active and billing recurring subscriptions

        - `PAUSED` - Temporarily paused subscriptions (customer can resume)


        **Inactive States:**

        - `CANCELLED` - Cancelled subscriptions (retained for historical data)

        - `EXPIRED` - Subscriptions that reached their max cycle limit

        - `FAILED` - Subscriptions with payment failures (may be in dunning)


        **Excluded:**

        - Hard-deleted subscription records

        - Hidden subscriptions (marked for cleanup)

        - Subscriptions from test/development that were purged


        **Use Cases:**


        **1. Customer Portal:**

        - Check if customer has any subscriptions before showing portal

        - Display subscription count in dashboard

        - Validate customer access to subscription management


        **2. Integration & Automation:**

        - Pre-flight check before bulk operations

        - Verify customer has subscriptions before sending emails

        - Filter customers for targeted campaigns (has active subscriptions)


        **3. Validation & Security:**

        - Verify a specific contract ID belongs to a customer

        - Validate user permissions before showing subscription details

        - Check authorization for subscription modification requests


        **4. Analytics & Reporting:**

        - Count total subscriptions per customer

        - Identify customers with multiple subscriptions

        - Build customer segmentation based on subscription count


        **Response Format:**


        Returns a Set<Long> containing Shopify subscription contract IDs.


        ```json

        [123456789, 123456790, 123456791]

        ```


        **Set Properties:**

        - **Unique values**: No duplicate contract IDs

        - **Unordered**: IDs are not in any specific order

        - **Numeric**: IDs are Long integers (not GraphQL GIDs)


        **Common Response Scenarios:**


        **Customer with multiple subscriptions:**

        ```json

        [5234567890, 5234567891, 5234567892, 5234567893]

        ```


        **Customer with single subscription:**

        ```json

        [5234567890]

        ```


        **Customer with no subscriptions:**

        ```json

        []

        ```


        **Integration Examples:**


        **Example 1: Check if customer has subscriptions**

        ```javascript

        const contractIds = await
        fetch('/api/external/v2/subscription-customers/valid/12345', {
          headers: { 'X-API-Key': 'your-api-key' }
        }).then(r => r.json());


        if (contractIds.length > 0) {
          console.log(`Customer has ${contractIds.length} subscriptions`);
          // Show customer portal
        } else {
          console.log('Customer has no subscriptions');
          // Redirect to create subscription page
        }

        ```


        **Example 2: Validate contract ownership**

        ```javascript

        const customerId = 12345;

        const contractIdToVerify = 5234567890;


        const validContracts = await
        fetch(`/api/external/v2/subscription-customers/valid/${customerId}`, {
          headers: { 'X-API-Key': 'your-api-key' }
        }).then(r => r.json());


        if (validContracts.includes(contractIdToVerify)) {
          console.log('Customer owns this contract - allowing access');
          // Proceed with subscription modification
        } else {
          console.log('Unauthorized - contract does not belong to customer');
          // Return 403 Forbidden
        }

        ```


        **Performance Characteristics:**


        **Fast Response:**

        - Lightweight query (returns only IDs, not full subscription data)

        - Typical response time: 50-200ms

        - Suitable for real-time validation checks


        **Scalability:**

        - Efficient even for customers with 100+ subscriptions

        - Database query uses indexed customer ID field

        - Minimal network payload (just array of numbers)


        **Important Notes:**


        **Contract ID Format:**

        - Returns numeric Shopify contract IDs (e.g., `5234567890`)

        - NOT Shopify GraphQL GIDs (e.g.,
        `gid://shopify/SubscriptionContract/...`)

        - Use these IDs with other Appstle API endpoints


        **Data Freshness:**

        - Returns data from Appstle database (not real-time Shopify query)

        - Data is updated via webhooks (typically < 1 second lag)

        - If data seems stale, use sync endpoint to refresh


        **Empty Response:**

        - Empty array `[]` means customer has no valid subscriptions

        - This is NOT an error - it's a valid response

        - Returns 200 OK with empty array (not 404)


        **Security & Authorization:**

        - Customer ID is validated against authenticated shop

        - Cannot query customers from other shops

        - API key must have customer read permissions


        **Best Practices:**


        1. **Use for Validation**: Perfect for quick ownership/existence checks

        2. **Cache Locally**: Cache results briefly to reduce API calls

        3. **Check Empty Array**: Always handle empty array case gracefully

        4. **Combine with Details**: Use this for initial check, then fetch full
        details if needed

        5. **Avoid Polling**: Don't poll this endpoint repeatedly - use webhooks
        for updates


        **When to Use vs. Other Endpoints:**


        **Use this endpoint when you:**

        - Need just the contract IDs (not full subscription details)

        - Want to validate a customer has subscriptions

        - Need to verify contract ownership for authorization

        - Want fast, lightweight responses


        **Use subscription-customers-detail endpoint when you:**

        - Need full subscription details (status, products, billing dates, etc.)

        - Want to display subscription information to users

        - Need to make decisions based on subscription state


        **Related Endpoints:**

        - `GET
        /api/external/v2/subscription-customers-detail/valid/{customerId}` - Get
        full subscription details

        - `GET /api/external/v2/subscription-contract-details` - Query
        subscriptions with filters

        - `GET
        /api/external/v2/subscription-contracts/contract-external/{contractId}`
        - Get single contract details


        **Authentication:** Requires valid X-API-Key header or api_key parameter
        (deprecated)
      operationId: getValidSubscriptionCustomerV2
      parameters:
        - name: customerId
          in: path
          description: Id
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: >-
            Successfully retrieved valid subscription contract IDs. Returns a
            set of contract IDs (may be empty if customer has no subscriptions).
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
                  format: int64
              examples:
                Customer with multiple subscriptions:
                  description: Customer with multiple subscriptions
                  value:
                    - 5234567890
                    - 5234567891
                    - 5234567892
                    - 5234567893
                Customer with single subscription:
                  description: Customer with single subscription
                  value:
                    - 5234567890
                Customer with no subscriptions:
                  description: Customer with no subscriptions
                  value: []
        '400':
          description: Bad request - Invalid customer ID format
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid customer ID
                status: 400
                detail: Customer ID must be a valid positive integer
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Forbidden - Customer does not belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: Customer 12345 does not belong to your shop
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              example:
                type: https://example.com/errors/rate-limit
                title: Rate limit exceeded
                status: 429
                detail: Too many requests. Please retry after 60 seconds.
                retryAfter: 60
  /api/external/v2/subscription-customers/sync-info/{customerId}:
    get:
      tags:
        - Customers
      summary: Sync customer subscription details from Shopify
      description: >-
        Synchronizes customer subscription information from Shopify to the
        Appstle subscription system. This endpoint fetches the latest customer
        data from Shopify and updates the local database to ensure data
        consistency across platforms.


        **What Does This Endpoint Do?**

        This endpoint triggers a synchronization process that pulls customer
        subscription data from Shopify's GraphQL API and updates the Appstle
        subscription database with the latest information. It ensures that
        customer details, subscription statuses, and associated metadata are
        current and accurate.


        **Sync Process:**


        1. **Data Retrieval**: Fetches customer subscription data from Shopify
        using their GraphQL API

        2. **Validation**: Validates the retrieved data against existing records

        3. **Update**: Updates customer subscription details in Appstle database

        4. **Reconciliation**: Reconciles any discrepancies between Shopify and
        Appstle data

        5. **Logging**: Logs all sync activities for audit trail


        **What Gets Synchronized:**


        **Customer Information:**

        - Customer ID and Shopify GraphQL ID

        - Customer name and email address

        - Customer tags and metadata

        - Customer acceptance status

        - Marketing preferences


        **Subscription Details:**

        - Active subscription contracts

        - Subscription statuses (ACTIVE, PAUSED, CANCELLED, EXPIRED)

        - Next billing dates

        - Billing interval and delivery interval

        - Subscription line items (products and variants)

        - Pricing and discounts


        **Payment Information:**

        - Associated payment methods

        - Payment instrument status

        - Billing address details


        **Delivery Information:**

        - Shipping address details

        - Delivery method and profile

        - Delivery preferences


        **Use Cases:**


        **1. Data Consistency:**

        - Resolve data discrepancies between Shopify and Appstle

        - Update customer information after changes in Shopify admin

        - Sync subscription modifications made directly in Shopify


        **2. Troubleshooting:**

        - Fix sync issues for specific customers

        - Recover from webhook delivery failures

        - Debug customer portal display issues


        **3. Migration & Integration:**

        - Initial data sync after app installation

        - Re-sync after system maintenance or updates

        - Integration testing and validation


        **4. Customer Support:**

        - Refresh customer data when assisting with support tickets

        - Verify latest subscription status during customer inquiries

        - Update data after manual changes in Shopify


        **When to Use This Endpoint:**


        **Recommended Scenarios:**

        - Customer reports incorrect subscription data in portal

        - After making manual changes to subscriptions in Shopify admin

        - When troubleshooting webhook sync failures

        - Before running bulk operations on customer subscriptions

        - During migration or data reconciliation processes


        **Avoid Using For:**

        - Real-time data refresh (webhooks handle this automatically)

        - Frequent polling (use webhooks instead to avoid rate limits)

        - Bulk syncs of many customers (use batch endpoints or scheduled jobs)


        **Sync Behavior:**


        **Synchronous Operation:**

        - Endpoint blocks until sync completes

        - Returns void on success

        - Throws exception on failure


        **Data Precedence:**

        - Shopify data is always treated as source of truth

        - Local Appstle data is overwritten with Shopify values

        - Custom Appstle-specific fields are preserved


        **Error Handling:**

        - Invalid customer ID: Returns 400 Bad Request

        - Customer not found in Shopify: Returns 404 Not Found

        - Shopify API errors: Returns 502 Bad Gateway

        - Rate limit exceeded: Returns 429 Too Many Requests


        **Important Considerations:**


        **Performance:**

        - Sync duration depends on number of subscriptions (typically 1-5
        seconds)

        - May timeout for customers with 100+ active subscriptions

        - Consider using asynchronous sync for high-volume customers


        **Rate Limiting:**

        - Subject to Shopify GraphQL API rate limits

        - Frequent calls may exhaust rate limit budget

        - Use webhooks for real-time sync instead of polling this endpoint


        **Data Integrity:**

        - Always creates audit log entries for tracking

        - Preserves historical data and activity logs

        - Does not delete local-only data (e.g., custom notes)


        **Best Practices:**


        1. **Use Sparingly**: Rely on webhooks for automatic sync; use this only
        when needed

        2. **Check Logs**: Review activity logs after sync to verify changes

        3. **Validate Results**: Query customer data after sync to confirm
        updates

        4. **Handle Errors**: Implement retry logic with exponential backoff

        5. **Monitor Rate Limits**: Track Shopify API usage to avoid hitting
        limits


        **Security Notes:**

        - Requires valid API key authentication via X-API-Key header

        - Customer ID is validated against shop ownership

        - Cannot sync customers from other shops

        - All sync operations are logged for audit compliance


        **Response:**

        - Returns HTTP 204 No Content on successful sync

        - No response body returned

        - Check activity logs for detailed sync results


        **Alternative Approaches:**


        If you need to:

        - **Sync multiple customers**: Use bulk sync endpoint or scheduled job

        - **Real-time updates**: Rely on webhook subscriptions

        - **Verify data without modifying**: Use GET endpoints to retrieve
        current data


        **Integration Workflow Example:**


        ```

        1. Customer contacts support about incorrect billing date

        2. Support agent checks subscription in Appstle admin

        3. Agent makes correction in Shopify admin

        4. Agent calls sync endpoint for this customer

        5. Sync retrieves latest data from Shopify

        6. Appstle database is updated with corrected billing date

        7. Customer portal now shows correct date

        8. Support ticket resolved

        ```


        **Authentication:** Requires valid X-API-Key header or api_key parameter
        (deprecated)
      operationId: syncCustomerInfo
      parameters:
        - name: customerId
          in: path
          description: Customer Id
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '204':
          description: >-
            Customer subscription data successfully synchronized from Shopify.
            No response body returned. Check activity logs to verify sync
            completion and review changes made.
          content:
            application/json: {}
        '400':
          description: Bad request - Invalid customer ID or malformed request parameters
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid request
                status: 400
                detail: Customer ID must be a valid positive integer
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: >-
            Insufficient permissions or customer does not belong to
            authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  Customer does not belong to your shop or API key lacks
                  required permissions
        '404':
          description: Customer not found in Shopify or has no subscriptions
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Customer not found
                status: 404
                detail: No customer found with ID 12345 in Shopify
        '429':
          description: >-
            Rate limit exceeded - Too many sync requests or Shopify API rate
            limit hit
          content:
            application/json:
              example:
                type: https://example.com/errors/rate-limit
                title: Rate limit exceeded
                status: 429
                detail: >-
                  Shopify API rate limit exceeded. Please retry after 60
                  seconds.
                retryAfter: 60
        '502':
          description: Bad gateway - Shopify API error or connection failure
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-gateway
                title: Shopify API error
                status: 502
                detail: Failed to connect to Shopify API. Please try again later.
        '504':
          description: >-
            Gateway timeout - Sync operation took too long (customer has too
            many subscriptions)
          content:
            application/json:
              example:
                type: https://example.com/errors/timeout
                title: Sync timeout
                status: 504
                detail: >-
                  Sync operation timed out. Customer may have too many
                  subscriptions. Please contact support for manual sync.
  /api/external/v2/subscription-customers-detail/valid/{customerId}:
    get:
      tags:
        - Customers
      summary: Get detailed subscription information for a customer
      description: >-
        Retrieves comprehensive subscription contract details for a specific
        customer, including subscription status, products, billing information,
        delivery schedules, and more. This endpoint returns full subscription
        objects with all associated data, making it ideal for displaying
        subscription management interfaces and detailed analytics.


        **What This Endpoint Returns:**

        Unlike the contract IDs endpoint which returns only numeric IDs, this
        endpoint provides complete SubscriptionContractDetailsDTO objects for
        each of the customer's subscriptions. Each object contains all
        information needed to display and manage a subscription.


        **Data Included in Response:**


        **Subscription Identity:**

        - Subscription contract ID (Shopify numeric ID)

        - Subscription GraphQL ID (Shopify GID format)

        - Internal Appstle database ID

        - Contract creation date


        **Subscription Status & Lifecycle:**

        - Current status (ACTIVE, PAUSED, CANCELLED, EXPIRED, FAILED)

        - Status reason (why paused/cancelled)

        - Next billing date and time

        - Contract anchor date

        - Cancellation date (if applicable)

        - Current billing cycle number

        - Min/max cycle limits


        **Billing Configuration:**

        - Billing interval (WEEK, MONTH, YEAR)

        - Billing interval count (e.g., every 2 weeks)

        - Billing policy (pricing details)

        - Currency code

        - Recurring total price

        - Applied discounts and pricing policies


        **Delivery Configuration:**

        - Delivery interval (WEEK, MONTH, YEAR)

        - Delivery interval count

        - Delivery method (SHIPPING, PICK_UP, LOCAL_DELIVERY)

        - Delivery policy details

        - Delivery price


        **Products & Line Items:**

        - All subscribed products and variants

        - Product titles, SKUs, and images

        - Quantities per product

        - Individual line item prices

        - Product-specific discounts

        - Line item attributes and custom fields


        **Customer Information:**

        - Customer ID and GraphQL ID

        - Customer name and email

        - Customer acceptance status


        **Address Details:**

        - Billing address (full address object)

        - Shipping address (full address object)

        - Address validation status


        **Payment Information:**

        - Payment instrument type

        - Payment method details (card last 4, etc.)

        - Payment gateway used


        **Order & Fulfillment:**

        - Last order ID and details

        - Last order date

        - Order note

        - Fulfillment status


        **Additional Metadata:**

        - Custom note attributes

        - Tags and labels

        - Internal flags and settings

        - Selling plan ID and group ID

        - Shop domain


        **Use Cases:**


        **1. Customer Portal:**

        - Display all subscriptions on customer dashboard

        - Show subscription details page

        - Enable subscription management actions

        - Display upcoming order information


        **2. Admin Dashboard:**

        - View customer's complete subscription portfolio

        - Analyze subscription health and status

        - Identify at-risk or high-value subscriptions

        - Generate customer subscription reports


        **3. Customer Support:**

        - Quick access to all customer subscription details

        - Troubleshoot billing or delivery issues

        - Verify subscription configurations

        - Assist with subscription modifications


        **4. Analytics & Reporting:**

        - Calculate customer lifetime value

        - Analyze subscription mix per customer

        - Track subscription frequency distribution

        - Identify cross-sell/upsell opportunities


        **5. Integration & Automation:**

        - Sync subscription data to CRM/analytics platforms

        - Trigger workflows based on subscription details

        - Build custom reporting dashboards

        - Export subscription data for analysis


        **Response Format:**


        Returns an array of SubscriptionContractDetailsDTO objects:

        ```json

        [
          {
            "id": 789,
            "subscriptionContractId": 5234567890,
            "status": "ACTIVE",
            "nextBillingDate": "2024-03-15T00:00:00Z",
            "billingInterval": "MONTH",
            "billingIntervalCount": 1,
            "deliveryInterval": "MONTH",
            "deliveryIntervalCount": 1,
            "currencyCode": "USD",
            "currentTotalPrice": "49.99",
            "customerId": 12345,
            "customerEmail": "customer@example.com",
            "lineItems": [...],
            "billingAddress": {...},
            "shippingAddress": {...}
          },
          {...}
        ]

        ```


        **Response Scenarios:**


        **Customer with no subscriptions:**

        ```json

        []

        ```

        Returns empty array with 200 OK status (not an error).


        **Customer with multiple subscriptions:**

        Array contains multiple subscription objects, each representing a
        separate subscription contract.


        **Performance Considerations:**


        **Response Size:**

        - Each subscription object can be 5-50 KB depending on line items

        - Customer with 10 subscriptions: ~100-500 KB response

        - Consider pagination or filtering for customers with 20+ subscriptions


        **Query Performance:**

        - Typical response time: 200-500ms

        - Slower for customers with many subscriptions or complex products

        - Database query is optimized with indexed lookups


        **Best Practices:**


        1. **Cache Results**: Cache response data to minimize API calls

        2. **Filter Client-Side**: Filter/sort subscriptions on client after
        retrieval

        3. **Selective Display**: Don't display all fields if not needed

        4. **Handle Empty Array**: Always gracefully handle case with no
        subscriptions

        5. **Optimize Images**: Product images can be large - lazy load if
        displaying


        **Data Freshness:**

        - Data is retrieved from Appstle database (not real-time Shopify query)

        - Updated via webhooks with < 1 second lag typically

        - Use sync endpoint if data appears stale


        **Security Notes:**

        - Customer ID is validated against authenticated shop

        - Returns only subscriptions belonging to specified customer

        - Cannot access customers from other shops

        - Sensitive payment details (full card numbers) are never returned


        **Comparison with Other Endpoints:**


        **vs. GET /subscription-customers/valid/{customerId}:**

        - This endpoint: Returns complete subscription details

        - Valid contracts endpoint: Returns only contract IDs

        - Use this when you need full subscription information


        **vs. GET /subscription-contract-details:**

        - This endpoint: Filtered by single customer

        - Contract details endpoint: Query across all customers with filters

        - Use this for customer-specific views


        **vs. GET /subscription-contracts/contract-external/{contractId}:**

        - This endpoint: All contracts for a customer

        - Contract external endpoint: Single contract with Shopify raw data

        - Use this for customer overview, other for detailed single contract


        **Authentication:** Requires valid X-API-Key header or api_key parameter
        (deprecated)
      operationId: getValidSubscriptionCustomerDetailsV2
      parameters:
        - name: customerId
          in: path
          description: Customer Id
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: >-
            Successfully retrieved customer subscription details. Returns array
            of subscription objects (may be empty).
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionContractDetailsDTO'
              examples:
                Customer with active subscriptions:
                  description: Customer with active subscriptions
                  value:
                    - id: 789
                      subscriptionContractId: 5234567890
                      status: ACTIVE
                      nextBillingDate: '2024-03-15T00:00:00Z'
                      billingInterval: MONTH
                      billingIntervalCount: 1
                      deliveryInterval: MONTH
                      deliveryIntervalCount: 1
                      currencyCode: USD
                      currentTotalPrice: '49.99'
                      customerId: 12345
                      customerEmail: customer@example.com
                      shop: example-shop.myshopify.com
                      currentCycle: 3
                      deliveryMethod: SHIPPING
                    - id: 790
                      subscriptionContractId: 5234567891
                      status: PAUSED
                      billingInterval: WEEK
                      billingIntervalCount: 2
                      currencyCode: USD
                      currentTotalPrice: '24.99'
                      customerId: 12345
                      customerEmail: customer@example.com
                Customer with no subscriptions:
                  description: Customer with no subscriptions
                  value: []
        '400':
          description: Bad request - Invalid customer ID
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid customer ID
                status: 400
                detail: Customer ID must be a valid positive integer
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Forbidden - Customer does not belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: Customer 12345 does not belong to your shop
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              example:
                type: https://example.com/errors/rate-limit
                title: Rate limit exceeded
                status: 429
                detail: Too many requests. Please retry after 60 seconds.
                retryAfter: 60
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-error
                title: Server error
                status: 500
                detail: >-
                  An unexpected error occurred while retrieving subscription
                  details
  /api/external/v2/subscription-custom-csses/{id}:
    get:
      tags:
        - Customer Portal
      summary: Get custom CSS for customer portal
      description: >-
        Retrieves the custom CSS styling configuration for the customer portal.
        This endpoint returns all custom CSS rules that have been configured to
        customize the appearance, layout, and branding of the subscription
        customer portal.


        **What is Custom CSS?**

        Custom CSS allows merchants to fully customize the visual appearance of
        their customer portal beyond the basic theme settings. This enables
        complete brand alignment and creates a seamless experience that matches
        the merchant's main store design.


        **Custom CSS Capabilities:**

        - **Layout Customization**:
          - Modify page layouts and spacing
          - Adjust grid and flexbox configurations
          - Control responsive breakpoints
          - Customize navigation and sidebars

        - **Typography**:
          - Custom fonts and font families
          - Font sizes, weights, and line heights
          - Letter spacing and text transforms
          - Heading and paragraph styles

        - **Colors and Branding**:
          - Brand color palette application
          - Custom background colors and gradients
          - Button and link styling
          - Hover and focus states
          - Border colors and shadows

        - **Component Styling**:
          - Subscription card appearances
          - Form input styling
          - Button designs and interactions
          - Modal and dialog boxes
          - Navigation menus
          - Product images and thumbnails

        - **Advanced Features**:
          - CSS animations and transitions
          - Media queries for responsive design
          - Pseudo-elements and pseudo-classes
          - Custom icons using CSS
          - Transform and filter effects

        **CSS Structure:**

        The returned CSS includes:

        - Global styles for portal-wide consistency

        - Component-specific styles

        - Responsive design rules

        - Theme overrides

        - Custom animations

        - Print styles (optional)


        **Common CSS Selectors Available:**

        ```css

        /* Portal container */

        .subscription-portal { }


        /* Subscription cards */

        .subscription-card { }

        .subscription-card-header { }

        .subscription-card-body { }


        /* Buttons */

        .btn-primary { }

        .btn-secondary { }

        .btn-cancel { }


        /* Forms */

        .form-control { }

        .form-group { }

        .form-label { }


        /* Navigation */

        .portal-nav { }

        .nav-item { }


        /* Product displays */

        .product-item { }

        .product-image { }

        .product-title { }

        ```


        **Use Cases:**

        - Apply custom branding to match main store design

        - Create unique visual experiences for different customer segments

        - Implement seasonal or promotional themes

        - Enhance mobile responsiveness

        - Add accessibility improvements (high contrast, larger fonts)

        - A/B test different portal designs

        - Integrate with design systems

        - Implement dark mode or theme switching


        **Important Notes:**

        - CSS is sanitized for security (XSS prevention)

        - Certain properties may be restricted for security reasons

        - External resources (fonts, images) must use HTTPS

        - CSS is cached for performance - changes may take a few minutes to
        propagate

        - Invalid CSS syntax is automatically filtered out

        - Some core portal elements have !important styles that cannot be
        overridden


        **Best Practices:**

        - Use specific selectors to avoid conflicts

        - Test across different browsers and devices

        - Keep CSS organized with comments

        - Use CSS variables for maintainability

        - Minify CSS for production performance

        - Consider accessibility in color choices (WCAG compliance)

        - Provide fallbacks for advanced CSS features


        **Security Considerations:**

        - CSS is sanitized to prevent code injection

        - External URLs are validated

        - JavaScript in CSS is blocked (e.g., expression(), behavior())

        - Data URIs are validated for malicious content


        **Authentication:** Requires valid X-API-Key header
      operationId: getSubscriptionCustomCssV2
      parameters:
        - name: id
          in: path
          description: Id
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Custom CSS successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionCustomCssDTO'
              examples:
                Success Response:
                  description: Success Response
                  value: |-
                    {
                      "id": 12345,
                      "shop": "example-shop.myshopify.com",
                      "customCss": "/* Global Portal Styles */\n" +
                        ".subscription-portal {\n" +
                        "  font-family: 'Helvetica Neue', Arial, sans-serif;\n" +
                        "  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n" +
                        "  min-height: 100vh;\n" +
                        "}\n\n" +
                        "/* Subscription Cards */\n" +
                        ".subscription-card {\n" +
                        "  border-radius: 12px;\n" +
                        "  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n" +
                        "  background: white;\n" +
                        "  padding: 24px;\n" +
                        "  margin-bottom: 16px;\n" +
                        "  transition: transform 0.2s ease, box-shadow 0.2s ease;\n" +
                        "}\n\n" +
                        ".subscription-card:hover {\n" +
                        "  transform: translateY(-2px);\n" +
                        "  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);\n" +
                        "}\n\n" +
                        "/* Primary Button Styling */\n" +
                        ".btn-primary {\n" +
                        "  background-color: #4A90E2;\n" +
                        "  border-color: #4A90E2;\n" +
                        "  color: white;\n" +
                        "  font-weight: 600;\n" +
                        "  padding: 12px 24px;\n" +
                        "  border-radius: 6px;\n" +
                        "  transition: all 0.3s ease;\n" +
                        "}\n\n" +
                        ".btn-primary:hover {\n" +
                        "  background-color: #357ABD;\n" +
                        "  border-color: #357ABD;\n" +
                        "  transform: scale(1.02);\n" +
                        "}\n\n" +
                        "/* Form Inputs */\n" +
                        ".form-control {\n" +
                        "  border: 2px solid #E0E0E0;\n" +
                        "  border-radius: 6px;\n" +
                        "  padding: 10px 14px;\n" +
                        "  font-size: 14px;\n" +
                        "}\n\n" +
                        ".form-control:focus {\n" +
                        "  border-color: #4A90E2;\n" +
                        "  box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);\n" +
                        "  outline: none;\n" +
                        "}\n\n" +
                        "/* Responsive Design */\n" +
                        "@media (max-width: 768px) {\n" +
                        "  .subscription-card {\n" +
                        "    padding: 16px;\n" +
                        "  }\n" +
                        "  .btn-primary {\n" +
                        "    width: 100%;\n" +
                        "  }\n" +
                        "}",
                      "enabled": true,
                      "version": 2,
                      "lastModified": "2024-02-20T14:45:00Z",
                      "createdAt": "2024-01-15T10:30:00Z",
                      "updatedAt": "2024-02-20T14:45:00Z"
                    }
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to view custom CSS
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to view custom CSS settings
        '404':
          description: Custom CSS not found - No custom CSS has been configured
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: CSS not found
                status: 404
                detail: No custom CSS has been configured for this shop
  /api/external/v2/subscription-contracts/contract-external/{contractId}:
    get:
      tags:
        - Subscription Management
      summary: Get raw Shopify GraphQL contract response
      description: >-
        Retrieves the complete, unprocessed subscription contract data directly
        from Shopify's GraphQL API. This endpoint returns the full Shopify
        subscription contract object exactly as Shopify provides it, including
        all nested fields, relationships, and GraphQL metadata.


        **What This Endpoint Returns:**

        Unlike processed/transformed endpoints, this returns Shopify's raw
        SubscriptionContract GraphQL object with all available fields. This is
        the same data structure you would receive if querying Shopify's GraphQL
        API directly, making it ideal for:

        - Debugging Shopify data synchronization issues

        - Accessing fields not exposed in other endpoints

        - Understanding complete Shopify contract structure

        - Building custom integrations requiring full data

        - Comparing Shopify source data with processed data


        **Data Included:**


        **Contract Core:**

        - Full subscription contract object from Shopify

        - All GraphQL __typename fields preserved

        - Complete nested object structures

        - All available Shopify contract fields


        **Customer Information:**

        - Complete customer object with all fields

        - Default address details

        - Customer tags and metadata

        - Marketing preferences


        **Line Items:**

        - Full line item details with edges/nodes structure

        - Product and variant complete objects

        - Pricing policies with all cycle discounts

        - Line item custom attributes

        - Current and original prices


        **Billing & Delivery:**

        - Complete billing policy object

        - Full delivery policy details

        - Delivery method with all fields

        - Delivery price breakdown

        - Billing anchor details


        **Payment Information:**

        - Payment method details (if available)

        - Customer payment instrument

        - Payment gateway information


        **Orders & History:**

        - Origin order details

        - Last payment status

        - Historical billing attempts (in Appstle)


        **Use Cases:**


        **1. Debugging & Troubleshooting:**

        - Investigate data sync discrepancies

        - Verify what Shopify actually stores

        - Debug webhook payload issues

        - Compare expected vs actual data


        **2. Advanced Integrations:**

        - Access Shopify-specific fields not in standard APIs

        - Build custom analytics using raw data

        - Integrate with Shopify GraphQL directly

        - Extract fields for custom processing


        **3. Data Analysis:**

        - Analyze complete contract structure

        - Extract all available metadata

        - Build comprehensive data exports

        - Perform deep data audits


        **4. Development & Testing:**

        - Understand Shopify's data model

        - Test new feature development

        - Verify API responses

        - Documentation and examples


        **Response Structure:**


        Returns SubscriptionContractQuery.SubscriptionContract object:

        ```json

        {
          "id": "gid://shopify/SubscriptionContract/123456789",
          "status": "ACTIVE",
          "nextBillingDate": "2024-03-15T00:00:00Z",
          "customer": {
            "id": "gid://shopify/Customer/987654321",
            "email": "customer@example.com",
            "displayName": "John Doe",
            "__typename": "Customer"
          },
          "lines": {
            "edges": [
              {
                "node": {
                  "id": "gid://shopify/SubscriptionLine/111111",
                  "quantity": 2,
                  "variantId": "gid://shopify/ProductVariant/222222",
                  "title": "Monthly Coffee Box",
                  "variantTitle": "Medium Roast",
                  "currentPrice": {
                    "amount": "29.99",
                    "currencyCode": "USD"
                  },
                  "pricingPolicy": {...},
                  "__typename": "SubscriptionLine"
                }
              }
            ]
          },
          "billingPolicy": {
            "interval": "MONTH",
            "intervalCount": 1,
            "minCycles": 3,
            "maxCycles": 12
          },
          "deliveryPolicy": {...},
          "deliveryMethod": {...},
          "__typename": "SubscriptionContract"
        }

        ```


        **Important Considerations:**


        **Data Source:**

        - Queries Shopify GraphQL API in real-time

        - NOT cached in Appstle database

        - Always returns current Shopify state

        - Subject to Shopify API rate limits


        **Performance:**

        - Slower than database queries (500-1500ms typical)

        - Makes real-time call to Shopify

        - Response size can be large (10-50 KB)

        - Use sparingly to avoid rate limits


        **GraphQL Structure:**

        - Includes __typename fields throughout

        - Uses GraphQL ID format (gid://shopify/...)

        - Nested edges/nodes structure for lists

        - All fields as defined in Shopify's schema


        **Best Practices:**


        1. **Use for Debugging**: Perfect for troubleshooting data issues

        2. **Avoid Polling**: Don't call repeatedly - use cached/processed
        endpoints instead

        3. **Cache Response**: Cache the response if using for display

        4. **Parse Carefully**: Handle GraphQL structure (edges/nodes)

        5. **Monitor Rate Limits**: Each call counts against Shopify API limits


        **When to Use vs Other Endpoints:**


        **Use this endpoint when:**

        - Need complete Shopify contract data

        - Debugging synchronization issues

        - Accessing Shopify-specific fields

        - Building Shopify GraphQL integrations


        **Use /api/external/v2/subscription-contract-details when:**

        - Need processed, filtered contract data

        - Want faster response times

        - Querying multiple contracts

        - Building customer-facing UIs


        **Authentication:** Requires valid X-API-Key header
      operationId: getSubscriptionContractRawExternalV2
      parameters:
        - name: contractId
          in: path
          description: Contract ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Successfully retrieved raw Shopify contract data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionContract'
        '400':
          description: Bad request - Invalid contract ID
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid contract ID
                status: 400
                detail: Contract ID must be a valid positive integer
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Forbidden - Contract does not belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: Subscription contract does not belong to your shop
        '404':
          description: Contract not found in Shopify
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Contract not found
                status: 404
                detail: No subscription contract found with ID 12345 in Shopify
        '429':
          description: Rate limit exceeded - Shopify API rate limit hit
          content:
            application/json:
              example:
                type: https://example.com/errors/rate-limit
                title: Rate limit exceeded
                status: 429
                detail: >-
                  Shopify API rate limit exceeded. Please retry after 60
                  seconds.
                retryAfter: 60
        '502':
          description: Bad gateway - Shopify API error
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-gateway
                title: Shopify API error
                status: 502
                detail: >-
                  Failed to retrieve contract from Shopify. Please try again
                  later.
  /api/external/v2/subscription-contracts-email-magic-link:
    get:
      tags:
        - Customer Portal
      summary: Send magic link email to customer for portal access
      description: >-
        Sends an automated email to a customer containing a secure magic link
        for accessing their subscription management portal. The email is sent
        using the shop's configured email template and includes a time-limited
        authentication token.


        **What This Endpoint Does:**

        1. Validates customer exists and has subscriptions

        2. Generates secure portal access token

        3. Retrieves shop's email template configuration

        4. Sends personalized email with magic link

        5. Logs activity for audit trail


        **Magic Link Functionality:**


        **What is a Magic Link?**

        A magic link is a special URL containing an encrypted authentication
        token that allows customers to access their portal without entering a
        password. Clicking the link automatically logs them in.


        **Link Contents:**

        - Shop's portal URL

        - Encrypted customer token (2-hour expiration)

        - Direct access to subscription management

        - No password required


        **Security:**

        - Token expires in 2 hours

        - Single customer authentication

        - Cannot be used by others

        - Logged for security audit


        **Request Parameters:**


        **email (required):**

        - Customer's email address

        - Must exactly match email in Shopify

        - Customer must have at least one subscription

        - Case-sensitive in some systems


        **Email Template Configuration:**


        **Template Requirements:**

        - Email template must be configured in Appstle settings

        - Template type: SUBSCRIPTION_MANAGEMENT_LINK

        - Template must not be disabled

        - Template includes shop branding and customization


        **Email Content:**

        - Personalized greeting with customer name

        - Clickable magic link button/link

        - Expiration notice (link valid 2 hours)

        - Shop branding and footer

        - Optional custom messaging


        **Template Variables:**

        - `{customer_name}`: Customer's display name

        - `{magic_link}`: Portal URL with token

        - `{shop_name}`: Store name

        - `{expiration_time}`: Token expiry time


        **Use Cases:**


        **1. Customer Self-Service:**

        - "Forgot password" alternative

        - Quick portal access without account setup

        - Passwordless authentication flow

        - Reduce friction for customers


        **2. Subscription Management Prompts:**

        - "Manage your subscription" emails

        - Pre-billing reminders with management link

        - Post-purchase subscription setup

        - Re-engagement campaigns


        **3. Customer Support:**

        - Send portal access to customers

        - Enable self-service during support interactions

        - Provide instant portal access

        - Reduce support workload


        **4. Automated Workflows:**

        - Payment failure recovery emails

        - Subscription expiration notices

        - Pause/skip reminders

        - Renewal notifications


        **5. Marketing Campaigns:**

        - Subscription feature announcements

        - New product availability

        - Loyalty program invitations

        - Referral program links


        **Process Flow:**


        ```

        1. API receives email parameter

        2. Searches subscription database for customer email

        3. If not found → Returns 400 error

        4. If found → Retrieves customer subscriptions

        5. Sorts subscriptions by status (active first)

        6. Checks email template configuration

        7. If disabled → Returns 400 error with instructions

        8. If enabled → Generates magic link token

        9. Prepares email with template

        10. Sends email via configured provider

        11. Logs activity (source: MERCHANT_EXTERNAL_API)

        12. Returns success message

        ```


        **Response Format:**

        ```json

        "Email triggered successfully."

        ```


        **Simple string response** confirming email queued for delivery.


        **Important Considerations:**


        **Customer Validation:**

        - Email MUST exist in subscription database

        - Customer MUST have at least one subscription

        - Customers without subscriptions cannot receive link

        - Returns error if customer not found


        **Email Template Disabled:**

        - If template disabled in settings: Returns error

        - Error message guides merchant to enable template

        - Path: "More -> Email Settings"

        - Template must be explicitly enabled


        **Email Delivery:**

        - Email sent asynchronously

        - Success response doesn't guarantee delivery

        - Check email logs for delivery confirmation

        - Respects shop's email provider settings


        **Multiple Subscriptions:**

        - If customer has multiple subscriptions: Sorts by status

        - Active subscriptions shown first

        - Link provides access to ALL customer subscriptions

        - Portal displays all contracts


        **Activity Logging:**

        - All magic link emails logged

        - Source: MERCHANT_EXTERNAL_API

        - Includes timestamp and customer

        - Viewable in activity logs


        **Integration Examples:**


        **Webhook Trigger - Payment Failed:**

        ```javascript

        async function handlePaymentFailure(webhook) {
          const customerEmail = webhook.customer.email;
          
          // Send magic link to customer
          await fetch(
            `/api/external/v2/subscription-contracts-email-magic-link?email=${customerEmail}`,
            { headers: { 'X-API-Key': process.env.APPSTLE_API_KEY } }
          );
          
          console.log(`Magic link sent to ${customerEmail} for payment update`);
        }

        ```


        **Customer Support Button:**

        ```javascript

        async function sendPortalAccess(customerEmail) {
          try {
            const response = await fetch(
              `/api/external/v2/subscription-contracts-email-magic-link?email=${encodeURIComponent(customerEmail)}`,
              { 
                headers: { 'X-API-Key': apiKey },
                method: 'GET'
              }
            );
            
            if (response.ok) {
              alert('Portal access email sent to customer!');
            }
          } catch (error) {
            console.error('Failed to send magic link:', error);
          }
        }

        ```


        **Best Practices:**


        1. **Validate Email**: Check email format before calling API

        2. **Rate Limiting**: Don't spam customers - limit frequency

        3. **Error Handling**: Handle customer not found gracefully

        4. **User Feedback**: Confirm email sent to user

        5. **Test Template**: Ensure email template configured and working

        6. **Monitor Logs**: Check activity logs for delivery issues


        **Common Errors:**


        **"Customer Email does not exist":**

        - Email not found in subscription database

        - Customer has no subscriptions

        - Email may be misspelled


        **"Email template not found":**

        - SUBSCRIPTION_MANAGEMENT_LINK template not configured

        - Contact Appstle support to set up template


        **"Email is currently disabled":**

        - Template disabled in Email Settings

        - Navigate to More -> Email Settings

        - Enable "Subscription Management Link" email


        **Authentication:** Requires valid X-API-Key header
      operationId: emailMagicLinkV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: email
          in: query
          description: Customer email
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Email successfully queued for delivery
          content:
            application/json:
              schema:
                type: string
              example: Email triggered successfully.
        '400':
          description: Bad request - Customer not found or email template disabled
          content:
            application/json:
              examples:
                Customer Not Found:
                  description: Customer Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Customer not found
                    status: 400
                    detail: UserGeneratedError:Customer Email does not exist
                Email Template Not Found:
                  description: Email Template Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Email template not configured
                    status: 400
                    detail: UserGeneratedError:Email template not found
                Email Template Disabled:
                  description: Email Template Disabled
                  value:
                    type: https://example.com/errors/bad-request
                    title: Email disabled
                    status: 400
                    detail: >-
                      UserGeneratedError:The Subscription Management Link email
                      is currently disabled in Email Settings. To enable it, go
                      to More -> Email Settings.
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '500':
          description: Internal server error - Email send failure
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-error
                title: Email send failed
                status: 500
                detail: Failed to send magic link email
  /api/external/v2/subscription-contract-one-offs-by-contractId:
    get:
      tags:
        - Product Catalog
      summary: Get all one-time products for a subscription contract
      description: >-
        Retrieves all one-time products (add-ons) associated with a specific
        subscription contract across all billing attempts. One-time products are
        additional items that customers can add to their subscription orders on
        a non-recurring basis. Each one-time product is tied to a specific
        billing attempt and will only be included in that particular order.


        **Key Features:**

        - Returns ALL one-time products across all queued billing attempts

        - Each product includes the billing attempt ID to identify which order
        it belongs to

        - Includes product details: variant ID, quantity, title, image, and
        price

        - Products are automatically removed after the associated billing
        attempt is processed


        **Use Cases:**

        - Display all one-time products added to a subscription across all
        upcoming orders

        - Allow customers to review their one-time add-ons in customer portal

        - Enable merchants to see all one-time products for a contract

        - Integrate with external systems to manage subscription add-ons


        **Authentication:** Requires valid X-API-Key header
      operationId: getOneOffsForSubscriptionContractV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: X-API-Key
          in: header
          description: >-
            API Key for authentication. This key identifies your shop and must
            be included in the X-API-Key header.
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: contractId
          in: query
          description: >-
            The unique identifier of the subscription contract to retrieve
            one-time products for
          required: true
          schema:
            minimum: 1
            type: integer
            description: Must be a valid contract ID that belongs to the authenticated shop
            format: int64
          example: 98765
      responses:
        '200':
          description: Successfully retrieved one-time products
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionContractOneOffDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    - id: 12345
                      shop: example-shop.myshopify.com
                      contractId: 67890
                      billingAttemptId: 11111
                      variantId: 22222
                      quantity: 2
                      productTitle: Coffee Filters - Pack of 100
                      variantTitle: Standard Size
                      image: >-
                        https://cdn.shopify.com/s/files/1/0000/0000/products/filter.jpg
                      price: '9.99'
                      currencyCode: USD
                      createdAt: '2024-01-15T10:30:00Z'
                      updatedAt: '2024-01-15T10:30:00Z'
                    - id: 12346
                      shop: example-shop.myshopify.com
                      contractId: 67890
                      billingAttemptId: 11112
                      variantId: 33333
                      quantity: 1
                      productTitle: Coffee Scoop
                      variantTitle: Stainless Steel
                      image: >-
                        https://cdn.shopify.com/s/files/1/0000/0000/products/scoop.jpg
                      price: '14.99'
                      currencyCode: USD
                      createdAt: '2024-01-16T14:20:00Z'
                      updatedAt: '2024-01-16T14:20:00Z'
        '400':
          description: Invalid contract ID or contract doesn't belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid contract
                status: 400
                detail: Contract does not belong to this shop
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to view one-time products
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to view one-time products
  /api/external/v2/subscription-contract-details:
    get:
      tags:
        - Subscription Contracts
      summary: Retrieve subscription contracts
      description: >-
        Retrieves a paginated list of subscription contracts with powerful
        filtering capabilities. This endpoint enables complex queries to find
        specific subscriptions based on various criteria including dates,
        customer information, product details, and subscription characteristics.


        **Key Features:**

        - Comprehensive filtering across 20+ parameters

        - Full pagination support with customizable page size

        - Partial text matching for customer and order searches

        - Date range filtering for multiple date fields

        - Product and variant filtering within line items

        - Order amount range filtering

        - Plan type differentiation (prepaid vs pay-per-delivery)


        **Pagination:**

        - Uses Spring's Pageable format

        - Default page size: 20 items

        - Maximum page size: 2000 items (exceeding this limit will result in a
        400 error)

        - Returns total count in X-Total-Count header

        - Provides navigation links in Link header


        **IMPORTANT - Sorting Limitations:**

        Due to the use of native SQL queries, sort parameters MUST use database
        column names (snake_case) rather than Java field names (camelCase).


        Common sorting examples:

        - `sort=next_billing_date,asc` (NOT nextBillingDate)

        - `sort=customer_name,desc` (NOT customerName)

        - `sort=created_at,asc` (NOT createdAt)

        - `sort=subscription_contract_id,desc` (NOT subscriptionContractId)

        - `sort=order_amount,asc` (NOT orderAmount)


        **Date Format:**

        All date parameters use ISO 8601 format with timezone:

        `yyyy-MM-dd'T'HH:mm:ssXXX`

        Examples: `2024-03-15T10:30:00+00:00` or `2024-03-15T10:30:00Z`


        **Date Range Filtering:**

        - For created, updated dates: Can use either 'from', 'to', or both

        - For next billing date: Both 'from' and 'to' must be provided together
        (current limitation)


        **Text Search Behavior:**

        - Customer name searches both name and email fields

        - Order name searches current and historical orders (in
        subscription_billing_attempt table)

        - All text searches are case-insensitive

        - Partial matches are supported (contains logic)

        - Subscription contract ID search supports partial numeric matching


        **Plan Type Classification:**

        - **prepaid**: Billing interval > delivery interval

        - **non-prepaid**: Billing interval = delivery interval


        **Performance Considerations:**

        - Complex filters (especially JSON searches and order amount
        calculations) may impact response time

        - Use specific filters when possible

        - Consider smaller page sizes for complex queries

        - Product, variant, and selling plan searches use JSON_SEARCH which may
        be slow on large datasets


        **Authentication:** Requires valid X-API-Key header (the deprecated
        'api_key' query parameter is still accepted but not recommended)
      operationId: getAllSubscriptionContractDetails
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: fromCreatedDate
          in: query
          description: Filter by subscriptions created on or after this date
          required: false
          schema:
            type: string
            format: date-time
          example: '2025-10-01T00:00:00+02:00'
        - name: toCreatedDate
          in: query
          description: Filter by subscriptions created on or before this date
          required: false
          schema:
            type: string
            format: date-time
          example: '2025-10-31T23:59:59+02:00'
        - name: fromUpdatedDate
          in: query
          description: Filter by subscriptions updated on or after this date
          required: false
          schema:
            type: string
            format: date-time
          example: '2025-10-01T00:00:00+02:00'
        - name: toUpdatedDate
          in: query
          description: Filter by subscriptions updated on or before this date
          required: false
          schema:
            type: string
            format: date-time
          example: '2025-10-31T23:59:59+02:00'
        - name: fromNextDate
          in: query
          description: >-
            Filter by subscriptions with next billing date on or after this
            date. Note: Both fromNextDate and toNextDate must be provided
            together
          required: false
          schema:
            type: string
            format: date-time
          example: '2025-10-01T00:00:00+02:00'
        - name: toNextDate
          in: query
          description: >-
            Filter by subscriptions with next billing date on or before this
            date. Note: Both fromNextDate and toNextDate must be provided
            together
          required: false
          schema:
            type: string
            format: date-time
          example: '2025-10-31T23:59:59+02:00'
        - name: subscriptionContractId
          in: query
          description: >-
            Filter by subscription contract ID (partial match supported,
            case-insensitive)
          required: false
          schema:
            type: string
          example: 123456
        - name: customerName
          in: query
          description: >-
            Filter by customer name or email (partial match, case-insensitive).
            Searches both customer_name and customer_email fields
          required: false
          schema:
            type: string
          example: john
        - name: orderName
          in: query
          description: >-
            Filter by order number (searches current order_name and historical
            orders in subscription_billing_attempt table, partial match)
          required: false
          schema:
            type: string
          example: SUB-1001
        - name: status
          in: query
          description: Filter by subscription status (case-insensitive)
          required: false
          schema:
            type: string
            enum:
              - ACTIVE
              - PAUSED
              - CANCELLED
          example: ACTIVE
        - name: billingPolicyIntervalCount
          in: query
          description: >-
            Filter by delivery interval count (Note: This parameter name is
            misleading - it actually filters the delivery_policy_interval_count
            field)
          required: false
          schema:
            maximum: 365
            minimum: 1
            type: integer
          example: 1
        - name: billingPolicyInterval
          in: query
          description: >-
            Filter by delivery interval type (Note: This parameter name is
            misleading - it actually filters the delivery_policy_interval field)
          required: false
          schema:
            type: string
            enum:
              - DAY
              - WEEK
              - MONTH
              - YEAR
          example: MONTH
        - name: planType
          in: query
          description: >-
            Filter by plan type classification. 'prepaid' = billing interval
            count ≠ delivery interval count, 'non-prepaid' = billing interval
            count = delivery interval count
          required: false
          schema:
            type: string
            enum:
              - prepaid
              - non-prepaid
          example: prepaid
        - name: recordType
          in: query
          description: >-
            Filter by record type. 'imported' = has imported_id, 'nonImported' =
            no imported_id
          required: false
          schema:
            type: string
            enum:
              - imported
              - nonImported
          example: imported
        - name: productId
          in: query
          description: >-
            Filter by product ID (searches within subscription line items JSON).
            Provide numeric ID only
          required: false
          schema:
            type: integer
            format: int64
          example: 7890123456
        - name: variantId
          in: query
          description: >-
            Filter by variant ID (searches within subscription line items JSON).
            Provide numeric ID only
          required: false
          schema:
            type: integer
            format: int64
          example: 42549172011164
        - name: sellingPlanId
          in: query
          description: >-
            Filter by selling plan ID (searches within subscription line items
            JSON). Provide numeric ID only
          required: false
          schema:
            type: integer
            format: int64
          example: 123456
        - name: minOrderAmount
          in: query
          description: >-
            Filter by minimum total order amount (calculated from sum of line
            items: quantity * currentPrice)
          required: false
          schema:
            type: number
            format: double
          example: 50
        - name: maxOrderAmount
          in: query
          description: >-
            Filter by maximum total order amount (calculated from sum of line
            items: quantity * currentPrice)
          required: false
          schema:
            type: number
            format: double
          example: 500
        - name: pageable
          in: query
          description: >-
            Pagination and sorting parameters. IMPORTANT: Sort fields must use
            database column names (snake_case), not Java field names. Maximum
            page size is 2000.
          required: true
          schema:
            $ref: '#/components/schemas/Pageable'
          example: page=0&size=20&sort=next_billing_date,asc&sort=id,desc
      responses:
        '200':
          description: Successfully retrieved subscription contracts
          headers:
            X-Total-Count:
              description: Total number of matching subscription contracts
              style: simple
              schema:
                type: integer
                example: 150
            Link:
              description: Pagination navigation links (first, prev, next, last)
              style: simple
              schema:
                type: string
                example: >-
                  <http://api.example.com/subscription-contract-details?page=2&size=20>;
                  rel="next"
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionContractDetailsDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    - id: 1001
                      subscriptionContractId: 123456789
                      graphSubscriptionContractId: gid://shopify/SubscriptionContract/123456789
                      status: active
                      customerId: 987654321
                      customerName: John Doe
                      customerEmail: john.doe@example.com
                      orderName: '#SUB-1001'
                      nextBillingDate: '2024-04-01T12:00:00.000+00:00'
                      billingPolicyInterval: MONTH
                      billingPolicyIntervalCount: 1
                      deliveryPolicyInterval: MONTH
                      deliveryPolicyIntervalCount: 1
                      totalPrice: 99.99
                      currencyCode: USD
                      createdAt: '2024-01-15T08:00:00.000+00:00'
                      updatedAt: '2024-03-01T14:30:00.000+00:00'
                      contractDetailsJson:
                        - productId: gid://shopify/Product/7890123456
                          variantId: gid://shopify/ProductVariant/42549172011164
                          productTitle: Premium Subscription Box
                          variantTitle: Monthly Plan
                          quantity: 1
                          currentPrice: 99.99
                          sellingPlanId: gid://shopify/SellingPlan/123456
                          sellingPlanName: Deliver every month
                      minCycles: 3
                      maxCycles: null
                      activatedOn: '2024-01-15T08:00:00.000+00:00'
                      pausedOn: null
                      cancelledOn: null
                      importedId: null
                    - id: 1002
                      subscriptionContractId: 123456790
                      status: paused
                      customerId: 987654322
                      customerName: Jane Smith
                      customerEmail: jane.smith@example.com
                      orderName: '#SUB-1002'
                      nextBillingDate: '2024-05-01T12:00:00.000+00:00'
                      billingPolicyInterval: MONTH
                      billingPolicyIntervalCount: 3
                      deliveryPolicyInterval: MONTH
                      deliveryPolicyIntervalCount: 1
                      totalPrice: 149.97
                      currencyCode: USD
                      createdAt: '2024-02-01T10:00:00.000+00:00'
                      updatedAt: '2024-03-10T16:45:00.000+00:00'
        '400':
          description: Bad Request - Invalid parameter format or values
          content:
            application/json:
              examples:
                Invalid Date Format:
                  description: Invalid Date Format
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid date format
                    status: 400
                    detail: >-
                      Date must be in format: yyyy-MM-dd'T'HH:mm:ssXXX (e.g.,
                      2024-03-15T10:30:00+00:00 or 2024-03-15T10:30:00Z)
                Invalid Status Value:
                  description: Invalid Status Value
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid status value
                    status: 400
                    detail: >-
                      Status must be one of: ACTIVE, PAUSED, CANCELLED
                      (case-insensitive)
                Invalid Sort Field:
                  description: Invalid Sort Field
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid sort field
                    status: 400
                    detail: >-
                      Unknown column 'nextBillingDate'. Use snake_case column
                      names for sorting (e.g., 'next_billing_date')
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions to access subscription data
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to read subscription
                  contracts
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-error
                title: Internal server error
                status: 500
                detail: >-
                  An unexpected error occurred while retrieving subscription
                  contracts
  /api/external/v2/subscription-contract-details/subscription-fulfillments/{contractId}:
    get:
      tags:
        - Subscription Management
      summary: Get subscription fulfillment details for latest order
      description: >-
        Retrieves fulfillment information for the most recent successful order
        associated with a subscription contract. This includes tracking details,
        shipment status, delivery estimates, and fulfillment line items from
        Shopify.


        **What This Endpoint Returns:**

        Complete fulfillment data for the subscription's last successfully
        billed order, queried in real-time from Shopify's GraphQL API. Shows
        customers when and how their subscription items will be (or were)
        delivered.


        **Fulfillment Data Included:**


        **Shipment Tracking:**

        - Tracking numbers and URLs

        - Carrier information (USPS, FedEx, UPS, etc.)

        - Tracking company details

        - Tracking status updates


        **Delivery Status:**

        - Fulfillment status (fulfilled, in_transit, out_for_delivery,
        delivered, etc.)

        - Estimated delivery date

        - Actual delivery timestamp (if delivered)

        - Delivery method (shipping, pickup, local delivery)


        **Fulfillment Details:**

        - Fulfilled line items (which products shipped)

        - Quantities fulfilled

        - Fulfillment service (manual, automated, 3PL)

        - Fulfillment created/updated dates

        - Multiple fulfillments (if order shipped in parts)


        **Location Information:**

        - Fulfillment location/warehouse

        - Origin address details

        - Fulfillment service name


        **Order Determination Logic:**


        **Which Order is Retrieved:**

        1. Finds most recent SUCCESS billing attempt for contract

        2. If found: Uses that order's Shopify order ID

        3. If none: Falls back to subscription's origin order ID

        4. Queries Shopify for that order's fulfillments


        **Why This Matters:**

        - Shows CURRENT/LATEST fulfillment status

        - Not historical fulfillments from months ago

        - Reflects what customer is waiting for NOW

        - Updates after each new billing cycle


        **Use Cases:**


        **1. Customer Portal "Where's My Order":**

        - Display tracking information

        - Show estimated delivery date

        - Provide carrier tracking links

        - Update fulfillment status


        **2. Subscription Order Tracking:**

        - Track recurring order deliveries

        - Monitor fulfillment progress

        - Identify delayed shipments

        - Provide proactive delivery updates


        **3. Customer Support:**

        - Answer "where is my order" questions

        - Verify shipment details

        - Troubleshoot delivery issues

        - Provide accurate tracking info


        **4. Automated Notifications:**

        - Send tracking emails automatically

        - Notify customers of shipments

        - Alert on delivery completion

        - Trigger review request flows


        **5. Subscription Management:**

        - Show fulfillment in subscription history

        - Display delivery patterns

        - Track fulfillment reliability

        - Monitor shipping performance


        **Response Structure:**


        Returns Shopify Order object with fulfillments:

        ```json

        {
          "id": "gid://shopify/Order/123456789",
          "name": "#1001",
          "fulfillmentOrders": {
            "edges": [
              {
                "node": {
                  "id": "gid://shopify/FulfillmentOrder/111111",
                  "status": "SUCCESS",
                  "fulfillments": {
                    "edges": [
                      {
                        "node": {
                          "trackingInfo": [
                            {
                              "number": "1Z999AA10123456784",
                              "url": "https://wwwapps.ups.com/tracking/...",
                              "company": "UPS"
                            }
                          ],
                          "status": "IN_TRANSIT",
                          "estimatedDeliveryAt": "2024-03-20T00:00:00Z",
                          "deliveredAt": null
                        }
                      }
                    ]
                  }
                }
              }
            ]
          }
        }

        ```


        **Common Scenarios:**


        **Scenario: Order Fulfilled & Shipped**

        ```json

        {
          "trackingInfo": [{"number": "9400...", "company": "USPS"}],
          "status": "IN_TRANSIT",
          "estimatedDeliveryAt": "2024-03-18T00:00:00Z"
        }

        ```


        **Scenario: Order Delivered**

        ```json

        {
          "status": "DELIVERED",
          "deliveredAt": "2024-03-15T14:23:00Z"
        }

        ```


        **Scenario: Not Yet Fulfilled**

        ```json

        {
          "fulfillmentOrders": {
            "edges": [
              {
                "node": {
                  "status": "OPEN",
                  "fulfillments": {"edges": []}
                }
              }
            ]
          }
        }

        ```


        **Scenario: No Order Yet (New Subscription)**

        Returns `null` or empty response


        **Important Considerations:**


        **Real-Time Shopify Query:**

        - Makes live call to Shopify GraphQL API

        - NOT cached data

        - Response time: 500-1500ms

        - Subject to Shopify rate limits


        **Data Freshness:**

        - Returns current fulfillment status from Shopify

        - Tracking updates reflect Shopify's data

        - May lag behind carrier's actual status

        - Shopify updates tracking periodically


        **Null Responses:**

        - Returns null if no orders exist yet

        - Returns null if order ID not found

        - Handle gracefully in UI


        **Multiple Fulfillments:**

        - Order may have multiple fulfillments (split shipments)

        - Each fulfillment has own tracking

        - Iterate through all fulfillment nodes


        **Integration Example:**


        **Customer Portal - Track Shipment:**

        ```javascript

        const order = await fetch(
          `/api/external/v2/subscription-contract-details/subscription-fulfillments/${contractId}`,
          { headers: { 'X-API-Key': 'your-key' } }
        ).then(r => r.json());


        if (!order) {
          return '<p>No shipment information available yet.</p>';
        }


        const fulfillments = order.fulfillmentOrders?.edges || [];

        fulfillments.forEach(fo => {
          fo.node.fulfillments?.edges?.forEach(f => {
            const tracking = f.node.trackingInfo?.[0];
            if (tracking) {
              console.log(`Track with ${tracking.company}: ${tracking.number}`);
              console.log(`URL: ${tracking.url}`);
            }
          });
        });

        ```


        **Best Practices:**


        1. **Cache Response**: Cache for 30-60 minutes to reduce Shopify API
        calls

        2. **Handle Nulls**: Always check for null/empty responses

        3. **Parse GraphQL**: Navigate edges/nodes structure carefully

        4. **Show All Tracking**: Display all fulfillments if multiple shipments

        5. **Link to Carrier**: Provide clickable tracking URLs


        **Authentication:** Requires valid X-API-Key header
      operationId: getSubscriptionFulfillmentsExternalV2
      parameters:
        - name: contractId
          in: path
          description: Contract ID
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: >-
            Successfully retrieved fulfillment details (may be null if no orders
            exist)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '400':
          description: Bad request - Invalid contract ID
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid contract ID
                status: 400
                detail: Contract ID must be a valid positive integer
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Forbidden - Contract does not belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: Contract does not belong to your shop
        '502':
          description: Bad gateway - Shopify API error
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-gateway
                title: Shopify API error
                status: 502
                detail: Failed to retrieve fulfillment data from Shopify
  /api/external/v2/subscription-contract-details/shopify/customer/{customerId}/payment-methods:
    get:
      tags:
        - Customers
      summary: Get customer payment methods from Shopify
      description: >-
        Retrieves all payment methods associated with a customer directly from
        Shopify's payment API. This endpoint returns detailed information about
        stored payment instruments including credit/debit cards, digital
        wallets, and other payment methods that the customer can use for
        subscription billing.


        **What This Endpoint Does:**

        Queries Shopify's GraphQL API to fetch the customer's payment methods,
        including active instruments and optionally revoked (expired, removed,
        or failed) payment methods. This provides real-time payment method data
        directly from Shopify's payment vault.


        **Payment Method Types Supported:**


        **Credit/Debit Cards:**

        - Visa, Mastercard, American Express, Discover

        - Card last 4 digits

        - Expiry month and year

        - Card brand and type

        - Billing address associated with card


        **Digital Wallets:**

        - Shop Pay

        - Apple Pay

        - Google Pay

        - PayPal (when stored)


        **Alternative Payment Methods:**

        - Bank accounts (ACH, SEPA)

        - Buy Now Pay Later instruments

        - Store credit


        **Payment Method Information Returned:**


        **For Each Payment Method:**

        - **Payment Instrument ID**: Unique identifier (used for updates)

        - **Display Name**: Human-readable name (e.g., "Visa ending in 4242")

        - **Payment Type**: Card, wallet, bank account, etc.

        - **Status**: ACTIVE, REVOKED, EXPIRED, FAILED

        - **Is Default**: Whether this is the customer's default payment method

        - **Last 4 Digits**: For cards and bank accounts

        - **Expiry Date**: For cards (month/year)

        - **Brand**: Visa, Mastercard, Amex, etc.

        - **Billing Address**: Address associated with payment method

        - **Created Date**: When payment method was added


        **Query Parameters:**


        **allowRevokedMethod (optional, default: false):**

        - `false`: Returns only active, usable payment methods

        - `true`: Returns both active AND revoked payment methods


        **Revoked Payment Methods:**

        Include expired cards, deleted payment methods, failed instruments, and
        customer-removed methods. Useful for historical records and
        troubleshooting, but cannot be used for new billing attempts.


        **Use Cases:**


        **1. Customer Portal:**

        - Display saved payment methods

        - Allow customer to select default payment method

        - Show payment method update/delete options

        - Validate payment methods before subscription modification


        **2. Subscription Management:**

        - Verify customer has valid payment method before creating subscription

        - Check payment method expiry before next billing

        - Identify subscriptions at risk due to expiring cards

        - Prompt customer to update payment if needed


        **3. Payment Method Updates:**

        - List available payment methods for customer selection

        - Identify payment instrument ID for update operations

        - Validate payment method before switching subscription


        **4. Troubleshooting & Support:**

        - Debug payment failures

        - Verify which payment method is being used

        - Check if payment method is expired or revoked

        - Assist customer with payment issues


        **5. Analytics & Alerts:**

        - Track payment methods approaching expiry

        - Send proactive notifications to update cards

        - Analyze payment method distribution

        - Identify customers with no valid payment methods


        **Response Structure:**


        Returns CustomerPaymentMethodsQuery.PaymentMethods object from Shopify
        GraphQL:

        ```json

        {
          "nodes": [
            {
              "id": "gid://shopify/CustomerPaymentMethod/abc123",
              "instrument": {
                "__typename": "CustomerCreditCard",
                "brand": "VISA",
                "lastDigits": "4242",
                "expiryMonth": 12,
                "expiryYear": 2025,
                "name": "John Doe"
              },
              "revokedAt": null,
              "revokedReason": null,
              "subscriptionContracts": [...]
            }
          ]
        }

        ```


        **Common Scenarios:**


        **Scenario 1: Customer with multiple cards**

        Returns array with multiple payment method objects, each representing a
        stored card.


        **Scenario 2: Customer with no payment methods**

        Returns empty nodes array - customer needs to add payment method.


        **Scenario 3: Expired card included (allowRevokedMethod=true)**

        Returns both active cards and expired/revoked cards with revokedAt
        timestamp.


        **Important Considerations:**


        **Data Source:**

        - Queries Shopify API in real-time (not Appstle database)

        - Always returns current Shopify payment method state

        - Subject to Shopify API rate limits


        **Performance:**

        - Response time: 300-800ms (depends on Shopify API)

        - Slower than database queries

        - Consider caching for non-critical displays


        **Security:**

        - Never returns full card numbers (PCI compliance)

        - Returns only last 4 digits

        - CVV is never stored or returned

        - Payment instrument IDs are tokenized references


        **Privacy:**

        - Customer ID validated against shop

        - Cannot query payment methods from other shops

        - Requires appropriate API permissions


        **Best Practices:**


        1. **Default to Active Only**: Use `allowRevokedMethod=false` for
        payment selection UIs

        2. **Check Expiry Dates**: Validate card expiry before using for
        subscriptions

        3. **Cache Responsibly**: Cache for short periods (5-10 min) to reduce
        API calls

        4. **Handle Empty Response**: Always handle case where customer has no
        payment methods

        5. **Show User-Friendly Names**: Display brand and last 4 (e.g., "Visa
        •••• 4242")

        6. **Indicate Default**: Highlight the default payment method clearly


        **Integration Examples:**


        **Example 1: Display payment methods in customer portal**

        ```javascript

        const paymentMethods = await fetch(
          `/api/external/v2/subscription-contract-details/shopify/customer/${customerId}/payment-methods`,
          { headers: { 'X-API-Key': 'your-key' } }
        ).then(r => r.json());


        paymentMethods.nodes.forEach(pm => {
          if (pm.instrument.__typename === 'CustomerCreditCard') {
            console.log(`${pm.instrument.brand} ending in ${pm.instrument.lastDigits}`);
            if (pm.instrument.expiryYear < currentYear) {
              console.warn('Card expired!');
            }
          }
        });

        ```


        **Example 2: Check for valid payment before creating subscription**

        ```javascript

        const paymentMethods = await fetch(...);

        const hasValidPayment = paymentMethods.nodes.some(pm => 
          !pm.revokedAt && pm.instrument.expiryYear >= currentYear
        );


        if (!hasValidPayment) {
          alert('Please add a valid payment method before subscribing');
        }

        ```


        **Related Endpoints:**

        - `PUT /api/external/v2/subscription-contracts-update-payment-method` -
        Update subscription payment method

        - `POST
        /api/external/v2/associate-shopify-customer-to-external-payment-gateways`
        - Add external payment method


        **Authentication:** Requires valid X-API-Key header
      operationId: getShopifyCustomerPaymentDetails
      parameters:
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: customerId
          in: path
          description: Customer Id
          required: true
          schema:
            type: integer
            format: int64
        - name: allowRevokedMethod
          in: query
          description: Get revoked payment methods?
          required: false
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Successfully retrieved customer payment methods from Shopify
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentMethods'
              examples:
                Customer with payment methods:
                  description: Customer with payment methods
                  value:
                    nodes:
                      - id: gid://shopify/CustomerPaymentMethod/abc123
                        instrument:
                          __typename: CustomerCreditCard
                          brand: VISA
                          lastDigits: '4242'
                          expiryMonth: 12
                          expiryYear: 2025
                          name: John Doe
                          source: SHOPIFY
                        revokedAt: null
                        revokedReason: null
                      - id: gid://shopify/CustomerPaymentMethod/def456
                        instrument:
                          __typename: CustomerShopPayAgreement
                          lastDigits: '1234'
                          name: Shop Pay
                        revokedAt: null
                        revokedReason: null
        '400':
          description: Bad request - Invalid customer ID or parameters
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid request
                status: 400
                detail: Customer ID must be a valid positive integer
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: >-
            Forbidden - Customer does not belong to shop or insufficient
            permissions
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: >-
                  Customer does not belong to your shop or API key lacks payment
                  method read permissions
        '404':
          description: Customer not found in Shopify
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Customer not found
                status: 404
                detail: No customer found with ID 12345 in Shopify
        '429':
          description: Rate limit exceeded - Shopify API rate limit hit
          content:
            application/json:
              example:
                type: https://example.com/errors/rate-limit
                title: Rate limit exceeded
                status: 429
                detail: >-
                  Shopify API rate limit exceeded. Please retry after 60
                  seconds.
                retryAfter: 60
        '502':
          description: Bad gateway - Shopify API error
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-gateway
                title: Shopify API error
                status: 502
                detail: >-
                  Failed to retrieve payment methods from Shopify. Please try
                  again later.
  /api/external/v2/subscription-contract-details/customers:
    get:
      tags:
        - Customers
      summary: Retrieve customers with subscriptions
      description: >-
        Returns a paginated list of customers who have subscription contracts.
        Supports filtering by customer name, email, and subscription count.
      operationId: getAllSubscriptionContractDetailsByShop
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
        - name: name
          in: query
          description: Filter customers by name (partial match supported)
          required: false
          schema:
            type: string
        - name: email
          in: query
          description: Filter customers by exact email address
          required: false
          schema:
            type: string
        - name: activeMoreThanOneSubscription
          in: query
          description: >-
            When true, returns only customers who have more than one active
            subscription
          required: false
          schema:
            type: boolean
            default: false
          example: false
        - name: pageable
          in: query
          description: Pagination parameters (page number and size)
          required: true
          schema:
            $ref: '#/components/schemas/Pageable'
          example:
            page: 0
            size: 10
            sort:
              - id,desc
      responses:
        '200':
          description: Successfully retrieved customer list
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerInfo'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerInfo'
        '403':
          description: Insufficient permissions to access customer data
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerInfo'
  /api/external/v2/subscription-contract-details/current-cycle/{contractId}:
    get:
      tags:
        - Subscription Management
      summary: Get current billing cycle number for a subscription contract
      description: >-
        Retrieves the current billing cycle number for a specific subscription
        contract. The cycle number represents how many successful billing
        attempts have occurred for this subscription, starting from 1 for the
        initial order.


        **What is a Billing Cycle?**

        A billing cycle represents one completed billing period in a
        subscription's lifetime. Each successful billing attempt increments the
        cycle count. This number is crucial for:

        - Tracking subscription progress towards minimum/maximum cycle limits

        - Applying cycle-based pricing adjustments (discounts after N cycles)

        - Determining eligibility for cancellation (minimum cycles requirement)

        - Calculating customer lifetime value

        - Analyzing subscription retention metrics


        **How Cycle Counting Works:**


        **Initial Order:**

        - Cycle 1 starts when subscription is first created

        - Initial order counts as the first billing cycle

        - Includes origin order that created the subscription


        **Subsequent Orders:**

        - Each successful billing attempt increments cycle by 1

        - Only SUCCESS status billing attempts are counted

        - Failed/skipped billing attempts do NOT increment cycle

        - Paused subscriptions maintain their current cycle number


        **Calculation Formula:**

        ```

        Current Cycle = 1 + (Number of Successful Billing Attempts)

        ```


        **Example Timeline:**

        - Day 1: Subscription created, initial order → Cycle 1

        - Day 30: First recurring order successful → Cycle 2

        - Day 60: Second recurring order successful → Cycle 3

        - Day 90: Billing fails (payment declined) → Still Cycle 3

        - Day 95: Retry successful → Cycle 4


        **Use Cases:**


        **1. Cancellation Eligibility:**

        - Verify customer has met minimum cycle requirement

        - Enforce contract terms (e.g., "3 month minimum")

        - Display "Can cancel after N more orders" messaging

        - Block premature cancellations


        **2. Pricing Adjustments:**

        - Apply introductory pricing for first N cycles

        - Trigger loyalty discounts after X cycles

        - Calculate when pricing changes take effect

        - Implement "First 3 months 50% off" promotions


        **3. Customer Retention:**

        - Identify subscriptions at risky cycle counts

        - Send retention campaigns at specific milestones

        - Track average cycles before churn

        - Celebrate subscription anniversaries


        **4. Analytics & Reporting:**

        - Calculate customer lifetime value (cycle × price)

        - Analyze subscription duration distribution

        - Track retention curves by cohort

        - Measure success of lifecycle campaigns


        **5. Customer Portal Display:**

        - Show "Order #X of Y" progress indicators

        - Display remaining cycles until cancellation allowed

        - Show subscription tenure/loyalty status

        - Calculate and display subscription value earned


        **Response Format:**


        Returns a single integer representing the current cycle number:

        ```json

        3

        ```


        **Response Examples:**


        **New subscription (just created):**

        ```json

        1

        ```


        **After 5 successful billing attempts:**

        ```json

        6

        ```

        Note: Initial order (1) + 5 successful renewals = Cycle 6


        **Important Considerations:**


        **Cycle vs. Billing Attempts:**

        - Failed billing attempts don't increment cycle

        - Skipped orders don't increment cycle

        - Manual order creation may not increment cycle

        - Cycle represents successful billing events only


        **Paused Subscriptions:**

        - Cycle number remains frozen while paused

        - Resumes at same cycle when un-paused

        - Pause duration doesn't affect cycle count


        **Minimum/Maximum Cycles:**

        - `minCycles`: Minimum cycles before cancellation allowed

        - `maxCycles`: Subscription auto-expires after this many cycles

        - Use this endpoint to check progress towards these limits


        **Data Source:**

        - Queries Appstle database (not Shopify API)

        - Counts records in subscription_billing_attempt table

        - Filters by SUCCESS status only

        - Fast response time (< 100ms typically)


        **Integration Example:**


        **Check if customer can cancel:**

        ```javascript

        // Get subscription details

        const contract = await getSubscriptionContract(contractId);

        const currentCycle = await fetch(
          `/api/external/v2/subscription-contract-details/current-cycle/${contractId}`,
          { headers: { 'X-API-Key': 'your-key' } }
        ).then(r => r.json());


        const minCycles = contract.minCycles || 0;


        if (currentCycle >= minCycles) {
          console.log('Customer can cancel now');
          showCancelButton();
        } else {
          const cyclesRemaining = minCycles - currentCycle;
          console.log(`Must complete ${cyclesRemaining} more orders before canceling`);
          showMinimumCommitmentMessage(cyclesRemaining);
        }

        ```


        **Display progress to max cycles:**

        ```javascript

        const currentCycle = await getCycleNumber(contractId);

        const maxCycles = contract.maxCycles;


        if (maxCycles) {
          const progress = (currentCycle / maxCycles) * 100;
          console.log(`Subscription ${progress.toFixed(0)}% complete (${currentCycle}/${maxCycles})`);
          
          if (currentCycle === maxCycles) {
            console.log('This is the final cycle - subscription will expire after this order');
          }
        }

        ```


        **Performance Characteristics:**


        **Fast Query:**

        - Simple database count query

        - Indexed by shop and contractId

        - Typical response time: 50-150ms

        - Suitable for real-time UI updates


        **Best Practices:**


        1. **Cache Results**: Cache cycle number briefly (few minutes) to reduce
        API calls

        2. **Combine with Contract Data**: Fetch contract details simultaneously
        for min/max cycles

        3. **Handle Edge Cases**: Account for subscriptions with no successful
        billings yet

        4. **Display Progress**: Show cycle number in customer-friendly format
        ("Order 3 of 12")

        5. **Sync with Billing**: Update cycle number after each billing attempt
        completes


        **Common Misunderstandings:**


        **Myth: Cycle = Months Subscribed**

        - Reality: Cycle = Successful billing attempts, not time elapsed

        - A paused subscription stays at same cycle for months

        - Failed payments don't advance the cycle


        **Myth: First order is Cycle 0**

        - Reality: Cycles start at 1, not 0

        - Initial/origin order is Cycle 1


        **Related Fields:**

        - `minCycles`: Minimum cycles before cancellation (from contract)

        - `maxCycles`: Maximum cycles before auto-expiry (from contract)

        - `billingInterval`: Frequency between cycles (from contract)


        **Authentication:** Requires valid X-API-Key header
      operationId: getCurrentCycleOfSubscriptionContractV2
      parameters:
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: contractId
          in: path
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Successfully retrieved current billing cycle number
          content:
            application/json:
              schema:
                type: integer
                format: int32
              examples:
                New subscription:
                  description: Subscription just created, on first billing cycle
                  value: 1
                Established subscription:
                  description: >-
                    Subscription has had 5 successful billing renewals plus
                    initial order
                  value: 6
        '400':
          description: Bad request - Invalid contract ID
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid contract ID
                status: 400
                detail: Contract ID must be a valid positive integer
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Forbidden - Contract does not belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: Subscription contract does not belong to your shop
        '404':
          description: Contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Contract not found
                status: 404
                detail: No subscription contract found with ID 12345
  /api/external/v2/subscription-contract-details/billing-interval:
    get:
      tags:
        - Subscription Management
      summary: Get available billing intervals for selling plan(s)
      description: >-
        Retrieves all available billing frequency options configured for
        specific Shopify selling plan(s). Returns the complete set of billing
        intervals that customers can choose from, including frequency, interval
        type, and any associated discounts or pricing policies.


        **What This Endpoint Does:**

        Queries the subscription group plans database to find all frequency
        configurations associated with given selling plan ID(s). This is
        essential for building subscription frequency selectors in customer
        portals or during subscription modifications.


        **Key Concepts:**


        **Selling Plans:**

        - Shopify's mechanism for defining subscription options

        - Each product variant can have multiple selling plans

        - Selling plans define billing/delivery frequency

        - Plans are grouped in subscription groups


        **Frequency Info:**

        - Specific billing interval configuration

        - E.g., "Every 2 weeks", "Every month", "Every 3 months"

        - Includes pricing policies and discounts

        - Customers select from available frequencies


        **Request Parameters:**


        **sellingPlanIds (required):**

        - Comma-separated list of Shopify selling plan IDs

        - Example: `"123456,123457,123458"`

        - Can query single or multiple plans

        - Returns frequencies for ALL provided plans


        **Lookup Process:**

        1. Parse selling plan IDs from comma-separated string

        2. Find subscription groups containing these plans

        3. Extract frequency configurations from group JSON

        4. Return all matching frequency options

        5. Deduplicate if same frequency appears multiple times


        **Response Data Included:**


        **For Each Frequency Option:**

        - **id**: Selling plan ID

        - **frequencyName**: Display name (e.g., "Monthly")

        - **interval**: WEEK, MONTH, or YEAR

        - **intervalCount**: Number of intervals (e.g., 2 for bi-weekly)

        - **deliveryInterval**: Same or different from billing

        - **deliveryIntervalCount**: Delivery frequency

        - **pricingPolicy**: Discount configuration

        - **billingPolicy**: Min/max cycles, anchor settings


        **Pricing Policy Details:**

        - Discount type (percentage, fixed amount)

        - Discount value

        - After cycle discounts (e.g., "50% off first 3 months")

        - Adjustment type


        **Use Cases:**


        **1. Frequency Selection UI:**

        - Build dropdown/radio list of frequency options

        - Show available intervals to customers

        - Display pricing for each frequency

        - Enable subscription frequency changes


        **2. Subscription Modification:**

        - Show current frequency and alternatives

        - Allow customers to switch frequencies

        - Validate new frequency selection

        - Preview pricing changes


        **3. Product Page:**

        - Display subscription frequency options

        - Show "Subscribe and save" pricing

        - Calculate savings per frequency

        - Build subscription purchase selectors


        **4. Customer Portal:**

        - "Change Frequency" functionality

        - Show all available options

        - Highlight current selection

        - Display pricing differences


        **Response Format:**

        ```json

        [
          {
            "id": "123456",
            "frequencyName": "Every 2 Weeks",
            "interval": "WEEK",
            "intervalCount": 2,
            "deliveryInterval": "WEEK",
            "deliveryIntervalCount": 2,
            "pricingPolicy": {
              "adjustmentType": "PERCENTAGE",
              "adjustmentValue": "10.0"
            }
          },
          {
            "id": "123457",
            "frequencyName": "Monthly",
            "interval": "MONTH",
            "intervalCount": 1,
            "deliveryInterval": "MONTH",
            "deliveryIntervalCount": 1,
            "pricingPolicy": {
              "adjustmentType": "PERCENTAGE",
              "adjustmentValue": "15.0"
            }
          }
        ]

        ```


        **Integration Example:**


        **Customer Portal - Frequency Selector:**

        ```javascript

        // Get selling plan from current subscription

        const currentSellingPlanId = subscription.sellingPlanId;


        // Fetch available frequencies

        const frequencies = await fetch(
          `/api/external/v2/subscription-contract-details/billing-interval?sellingPlanIds=${currentSellingPlanId}`,
          { headers: { 'X-API-Key': 'your-key' } }
        ).then(r => r.json());


        // Build selector

        const selector = frequencies.map(freq => `
          <option value="${freq.id}" 
            ${freq.id === currentSellingPlanId ? 'selected' : ''}>
            ${freq.frequencyName} - Save ${freq.pricingPolicy.adjustmentValue}%
          </option>
        `).join('');


        document.querySelector('#frequency-select').innerHTML = selector;

        ```


        **Important Considerations:**


        **Data Source:**

        - Queries Appstle database (NOT Shopify API)

        - Based on subscription group configuration

        - Fast response (< 100ms typically)

        - Data synced when groups are updated


        **Multiple Selling Plans:**

        - Can query multiple plans at once

        - Returns union of all frequencies

        - Useful for products with multiple subscription options

        - Results may contain duplicates if plans share frequencies


        **Empty Results:**

        - Returns empty array `[]` if no plans found

        - Returns empty if selling plan ID invalid

        - Not an error - handle gracefully


        **Best Practices:**


        1. **Query Relevant Plans**: Only query selling plans for current
        product/variant

        2. **Display Discounts**: Show savings clearly in UI

        3. **Sort by Interval**: Order options logically (weekly → monthly →
        yearly)

        4. **Highlight Current**: Clearly mark customer's current frequency

        5. **Cache Results**: Cache frequency data per selling plan


        **Authentication:** Requires valid X-API-Key header
      operationId: getSubscriptionContractBillingInterval
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: sellingPlanIds
          in: query
          description: Selling Plan ID
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successfully retrieved billing intervals (may be empty array)
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/FrequencyInfoDTO'
        '400':
          description: Bad request - Missing or invalid selling plan IDs
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid parameters
                status: 400
                detail: sellingPlanIds parameter is required
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
  /api/external/v2/subscription-contract-details/analytics/{contractId}:
    get:
      tags:
        - Subscription Management
      summary: Get subscription contract analytics and revenue metrics
      description: >-
        Retrieves comprehensive analytics for a specific subscription contract,
        including total revenue generated, number of successful orders, and
        formatted revenue display. This endpoint provides key performance
        metrics for understanding the financial impact of individual
        subscriptions.


        **What This Endpoint Returns:**

        Financial and operational analytics for a single subscription contract,
        calculated from all successful billing attempts throughout the
        subscription's lifetime. Unlike realtime contract queries, this provides
        historical aggregated data.


        **Metrics Included:**


        **Revenue Metrics:**

        - **totalOrderAmount**: Total revenue in decimal format (e.g., 299.95)

        - **totalOrderRevenue**: Formatted currency string (e.g., "$299.95")

        - Calculated from all SUCCESS status billing attempts

        - Includes taxes, shipping, and discounts

        - Does NOT include failed or pending payments


        **Order Count:**

        - **totalOrders**: Count of successful billing attempts

        - Represents number of orders generated by subscription

        - Does NOT include failed billing attempts

        - Starts at 0 for brand new subscriptions


        **Currency Formatting:**

        - Uses shop's configured money_format

        - Respects shop's currency code (USD, EUR, GBP, etc.)

        - Handles currency symbols and decimal places correctly

        - Falls back to USD if currency unknown


        **Calculation Logic:**


        **Data Source:**

        ```sql

        SELECT 
          COUNT(*) as totalOrders,
          SUM(order_amount) as totalOrderAmount
        FROM subscription_billing_attempt

        WHERE shop = ? 
          AND contract_id = ?
          AND status = 'SUCCESS'
        ```


        **What Gets Counted:**

        - ✅ Initial subscription order

        - ✅ All successful recurring orders

        - ✅ Manual billing attempts that succeeded

        - ✅ Retry attempts that eventually succeeded

        - ❌ Failed payment attempts

        - ❌ Skipped billing cycles

        - ❌ Cancelled/voided orders

        - ❌ Pending/in-progress billing


        **Use Cases:**


        **1. Customer Lifetime Value:**

        - Calculate total revenue from specific customer

        - Measure subscription ROI

        - Identify high-value subscriptions

        - Track revenue growth over time


        **2. Subscription Performance:**

        - Analyze revenue per subscription

        - Compare subscriptions by total value

        - Identify most profitable subscription types

        - Calculate average order value


        **3. Customer Portal:**

        - Display "You've saved $XXX" messaging

        - Show "X orders delivered" stats

        - Celebrate subscription milestones

        - Build customer loyalty through transparency


        **4. Reporting & Analytics:**

        - Build subscription revenue dashboards

        - Generate customer value reports

        - Track subscription health metrics

        - Forecast future revenue


        **5. Business Intelligence:**

        - Segment customers by subscription value

        - Identify churn risk (low order count)

        - Calculate retention rates

        - Measure subscription program success


        **Response Format:**

        ```json

        {
          "totalOrders": 12,
          "totalOrderAmount": 599.88,
          "totalOrderRevenue": "$599.88"
        }

        ```


        **Response Fields:**

        - `totalOrders` (integer): Count of successful billing attempts

        - `totalOrderAmount` (decimal): Numeric revenue total

        - `totalOrderRevenue` (string): Formatted currency display


        **Example Scenarios:**


        **Brand New Subscription:**

        ```json

        {
          "totalOrders": 0,
          "totalOrderAmount": 0.00,
          "totalOrderRevenue": "$0.00"
        }

        ```


        **After First Successful Order:**

        ```json

        {
          "totalOrders": 1,
          "totalOrderAmount": 49.99,
          "totalOrderRevenue": "$49.99"
        }

        ```


        **Established Subscription (EUR):**

        ```json

        {
          "totalOrders": 24,
          "totalOrderAmount": 1199.76,
          "totalOrderRevenue": "€1.199,76"
        }

        ```


        **Integration Examples:**


        **Customer Portal - Loyalty Display:**

        ```javascript

        const analytics = await fetch(
          `/api/external/v2/subscription-contract-details/analytics/${contractId}`,
          { headers: { 'X-API-Key': 'your-key' } }
        ).then(r => r.json());


        const loyaltyMessage = `
          <div class="loyalty-badge">
            <h3>Thank you for your loyalty!</h3>
            <p>You've received ${analytics.totalOrders} orders</p>
            <p>Total value: ${analytics.totalOrderRevenue}</p>
          </div>
        `;

        ```


        **Revenue Dashboard:**

        ```javascript

        // Fetch analytics for multiple subscriptions

        const contractIds = [123, 456, 789];

        const analyticsPromises = contractIds.map(id => 
          getContractAnalytics(id)
        );


        const allAnalytics = await Promise.all(analyticsPromises);

        const totalRevenue = allAnalytics.reduce(
          (sum, a) => sum + a.totalOrderAmount, 0
        );


        console.log(`Total subscription revenue: $${totalRevenue.toFixed(2)}`);

        ```


        **Important Considerations:**


        **Data Accuracy:**

        - Based on Appstle's billing attempt records

        - May differ slightly from Shopify order totals

        - Includes only what Appstle successfully billed

        - Updated after each billing attempt completes


        **Currency Handling:**

        - Formatting uses shop's money_format setting

        - Different shops may have different decimal separators

        - Currency symbol placement varies by locale

        - Always use totalOrderAmount for calculations


        **Performance:**

        - Fast database aggregation query

        - Typical response time: 100-300ms

        - Indexed by shop and contract ID

        - Suitable for real-time display


        **Best Practices:**


        1. **Use for Display**: Use totalOrderRevenue for customer-facing
        display

        2. **Calculate with Amount**: Use totalOrderAmount for mathematical
        operations

        3. **Cache Strategically**: Cache for dashboards, fetch real-time for
        critical displays

        4. **Handle Zero**: Gracefully handle new subscriptions with 0 orders

        5. **Validate Contract**: Ensure contract exists before querying
        analytics


        **Limitations:**


        **What's NOT Included:**

        - Future projected revenue

        - Failed payment attempt counts

        - Refunds or chargebacks

        - Pending/processing orders

        - Orders from other subscriptions


        **Related Calculations:**


        **Average Order Value:**

        ```javascript

        const aov = analytics.totalOrderAmount / analytics.totalOrders;

        console.log(`Average order value: $${aov.toFixed(2)}`);

        ```


        **Customer Lifetime Value (projected):**

        ```javascript

        const monthsActive = calculateMonthsActive(contract.createdAt);

        const monthlyRevenue = analytics.totalOrderAmount / monthsActive;

        const projectedLTV = monthlyRevenue * 12; // Annual LTV

        ```


        **Authentication:** Requires valid X-API-Key header
      operationId: getSubscriptionContractAnalyticsByContractIdExternalV2
      parameters:
        - name: contractId
          in: path
          description: Contract ID
          required: true
          schema:
            type: string
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Successfully retrieved contract analytics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContractAnalytics'
              examples:
                Active subscription with history:
                  description: Active subscription with history
                  value:
                    totalOrders: 12
                    totalOrderAmount: 599.88
                    totalOrderRevenue: $599.88
                New subscription (no orders yet):
                  description: New subscription (no orders yet)
                  value:
                    totalOrders: 0
                    totalOrderAmount: 0
                    totalOrderRevenue: $0.00
        '400':
          description: Bad request - Invalid contract ID
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid contract ID
                status: 400
                detail: Contract ID must be a valid positive integer
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Forbidden - Contract does not belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: Contract does not belong to your shop
        '404':
          description: Contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Contract not found
                status: 404
                detail: No subscription contract found with ID 12345
  /api/external/v2/subscription-bundlings/external/get-bundle/{handle}:
    get:
      tags:
        - Build-a-Box & Bundles
      summary: Get bundle details by handle
      description: >-
        Retrieves complete details for a subscription bundle using its unique
        handle. This endpoint returns the bundle configuration, included
        products, pricing, and available subscription options.


        **Bundle Information Returned:**

        - Bundle name and description

        - Product selections with quantities

        - Pricing and discounts

        - Available subscription frequencies

        - Bundle status and availability

        - Product images and details


        **Use Cases:**

        - Display bundle details on product pages

        - Show bundle contents in customer portal

        - Fetch bundle configuration for cart/checkout

        - Integration with external systems

        - Build custom bundle selection interfaces


        **Bundle Handle:**

        The handle is a unique, URL-friendly identifier for the bundle. It's
        typically generated when the bundle is created and remains constant
        throughout the bundle's lifecycle.


        **Authentication:** Requires valid X-API-Key header
      operationId: getValidSubscriptionCustomerV2_1
      parameters:
        - name: handle
          in: path
          description: Customer Handle
          required: true
          schema:
            type: string
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Bundle details successfully retrieved
          content:
            application/json:
              examples:
                Success Response:
                  description: Success Response
                  value:
                    bundle:
                      id: 12345
                      name: Premium Coffee Bundle
                      handle: premium-coffee-bundle
                      description: Choose your favorite coffee blends
                      minProducts: 2
                      maxProducts: 5
                      totalPrice: '49.99'
                      currencyCode: USD
                    subscriptions:
                      - frequency: MONTH
                        frequencyCount: 1
                        frequencyName: Monthly Delivery
                        discount: 10
                        discountType: PERCENTAGE
                      - frequency: WEEK
                        frequencyCount: 2
                        frequencyName: Bi-Weekly Delivery
                        discount: 15
                        discountType: PERCENTAGE
                    products:
                      - variantId: 11111
                        productId: 99999
                        title: Medium Roast Coffee
                        price: '14.99'
                        image: https://cdn.shopify.com/image.jpg
                        available: true
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBundlingResponse'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/SubscriptionBundlingResponse'
        '404':
          description: Bundle not found or no subscriptions available
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Bundle not found
                status: 404
                detail: 'No bundle exists with handle: premium-coffee-bundle'
  /api/external/v2/subscription-bundle-settings/{id}:
    get:
      tags:
        - Build-a-Box & Bundles
      summary: Get subscription bundle settings (Build-a-Box configuration)
      description: >-
        Retrieves the configuration settings for subscription bundles (also
        known as Build-a-Box or customizable subscription boxes). This endpoint
        returns all settings that control how customers can create and manage
        their custom subscription bundles.


        **What are Subscription Bundles (Build-a-Box)?**

        Subscription bundles allow customers to create personalized subscription
        boxes by selecting multiple products from a curated collection. Instead
        of subscribing to a fixed product, customers build their own custom
        bundle that gets delivered on a recurring basis. This is perfect for
        coffee subscriptions, snack boxes, beauty boxes, supplement packs, and
        any product category where variety and personalization drive customer
        satisfaction.


        **Bundle Configuration Settings:**


        **1. Product Selection Rules:**

        - Minimum number of products required in bundle

        - Maximum number of products allowed in bundle

        - Product categories available for selection

        - Variant selection constraints

        - Quantity limits per product

        - Total bundle value constraints (min/max price)


        **2. Bundle Behavior:**

        - Allow customers to modify bundle between orders

        - Lock bundle after first order

        - Enable automatic product rotation

        - Allow quantity adjustments

        - Substitution rules when products unavailable


        **3. Pricing & Discounts:**

        - Bundle pricing model (fixed price vs. sum of products)

        - Volume discounts based on bundle size

        - Tiered pricing structures

        - Promotional pricing for bundles

        - Discount application rules


        **4. UI/UX Settings:**

        - Bundle builder interface layout

        - Product display format (grid/list)

        - Images and descriptions shown

        - Filter and search options

        - Preview and summary display

        - Mobile responsiveness settings


        **5. Fulfillment Options:**

        - Bundling method (ship together vs. separate)

        - Packaging preferences

        - Custom box selection

        - Gift message options

        - Delivery instructions


        **6. Customer Experience:**

        - Welcome flow for new bundle subscribers

        - Modification window before each order

        - Reminder notifications to update bundle

        - Recommendation engine settings

        - Save favorite bundle configurations


        **Common Bundle Types:**


        **Coffee Subscription Bundle:**

        - Select 3-5 coffee varieties per month

        - Choose roast levels, origins, or flavors

        - Option to rotate selections monthly

        - Fixed price regardless of selection


        **Snack Box Bundle:**

        - Choose 10 items from 50+ snacks

        - Category limits (e.g., max 3 sweet, 7 savory)

        - Dietary restriction filters (vegan, gluten-free)

        - Tiered pricing based on bundle size


        **Beauty Box Bundle:**

        - Select products from skincare, makeup, haircare categories

        - Minimum 5 products, maximum 8 products

        - Total value must be between $40-$100

        - Can swap 2 products each month


        **Vitamin/Supplement Bundle:**

        - Build personalized supplement pack

        - Health goal-based recommendations

        - Compatibility checking (ingredient interactions)

        - Fixed monthly price for up to 5 supplements


        **Use Cases:**

        - Configure bundle builder in customer portal

        - Validate customer bundle selections against rules

        - Display bundle configuration options during signup

        - Integrate with checkout to show bundle pricing

        - Build custom bundle management interfaces

        - Sync bundle settings with mobile apps

        - Generate bundle recommendation algorithms


        **Important Notes:**

        - Settings apply to all subscription bundles in the shop

        - Changes affect new bundles immediately

        - Existing bundles maintain their original configuration unless migrated

        - Product availability is checked in real-time during bundle creation

        - Bundle modifications may have cutoff times before order processing


        **Best Practices:**

        - Set reasonable min/max limits to balance choice and complexity

        - Provide clear guidance on bundle building process

        - Use category limits to ensure variety

        - Enable modification windows to boost engagement

        - Offer curated bundle templates as starting points

        - Implement substitution logic for out-of-stock items

        - Test bundle builder UX across devices


        **Authentication:** Requires valid X-API-Key header
      operationId: getSubscriptionBundleSettingsV2
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Bundle settings successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBundleSettingsDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: 12345
                    shop: example-shop.myshopify.com
                    enabled: true
                    minProducts: 3
                    maxProducts: 8
                    minBundleValue: 40
                    maxBundleValue: 100
                    pricingModel: FIXED_PRICE
                    fixedBundlePrice: 59.99
                    allowModifications: true
                    modificationCutoffDays: 5
                    lockAfterFirstOrder: false
                    enableProductRotation: true
                    maxSwapsPerCycle: 2
                    requireCategoryDiversity: true
                    categoryLimits:
                      coffee-light-roast:
                        min: 0
                        max: 3
                      coffee-medium-roast:
                        min: 0
                        max: 3
                      coffee-dark-roast:
                        min: 0
                        max: 3
                      coffee-decaf:
                        min: 0
                        max: 2
                      coffee-flavored:
                        min: 0
                        max: 2
                    displaySettings:
                      layoutType: GRID
                      productsPerRow: 3
                      showProductImages: true
                      showProductDescriptions: true
                      showPricing: false
                      enableFiltering: true
                      enableSearch: true
                      showBundlePreview: true
                    notifications:
                      sendBundleCreatedEmail: true
                      sendModificationReminderEmail: true
                      reminderDaysBeforeOrder: 7
                      sendBundleModifiedConfirmation: true
                    substitution:
                      allowSubstitutions: true
                      substitutionMethod: SIMILAR_PRODUCT
                      notifyCustomerOfSubstitutions: true
                      allowCustomerToApproveSubstitutions: false
                    recommendations:
                      enableRecommendations: true
                      recommendationStrategy: POPULAR_AND_PERSONALIZED
                      showBestSellers: true
                      showCuratedBundles: true
                    discounts:
                      enableVolumeDiscounts: true
                      volumeDiscountTiers:
                        - minProducts: 5
                          discountPercent: 10
                        - minProducts: 7
                          discountPercent: 15
                    createdAt: '2024-01-15T10:30:00Z'
                    updatedAt: '2024-02-20T14:45:00Z'
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to view bundle settings
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to view bundle settings
        '404':
          description: Bundle settings not found - Bundle feature may not be enabled
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Settings not found
                status: 404
                detail: >-
                  Subscription bundle settings have not been configured for this
                  shop
  /api/external/v2/subscription-billing-attempts/top-orders:
    get:
      tags:
        - Billing & Payments
      summary: Get upcoming orders (top orders)
      description: >-
        Retrieves upcoming (queued) billing attempts for a subscription contract
        or customer. Returns the next scheduled orders that have not yet been
        processed.


        **Query Options:**

        - Filter by contract ID to see upcoming orders for a specific
        subscription

        - Filter by customer ID to see all upcoming orders for a customer

        - Results are ordered by billing date (earliest first)


        **Use Cases:**

        - Display "Your Next Order" in customer portal

        - Show upcoming delivery schedule

        - Calculate upcoming charges

        - Preview next order contents


        **Authentication:** Requires valid X-API-Key header
      operationId: getTopOrdersV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: contractId
          in: query
          description: Contract ID
          required: false
          schema:
            type: integer
            format: int64
        - name: customerId
          in: query
          description: Customer ID
          required: false
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Successfully retrieved upcoming orders
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '400':
          description: Invalid contract or customer ID
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
  /api/external/v2/subscription-billing-attempts/past-orders:
    get:
      tags:
        - Billing & Payments
      summary: Get past orders
      description: >-
        Retrieves paginated list of past (processed) billing attempts for a
        subscription contract or customer. Includes successful orders, failed
        attempts, and skipped orders.


        **Filter Options:**

        - By contract ID: Get order history for specific subscription

        - By customer ID: Get all orders across all customer subscriptions

        - Pagination: Control page size and page number


        **Order Information:**

        - Billing attempt status (SUCCESS, FAILED, SKIPPED)

        - Shopify order ID for successful attempts

        - Billing date and processing date

        - Order total and line items

        - Error messages for failed attempts


        **Authentication:** Requires valid X-API-Key header
      operationId: getPastOrdersV2
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: contractId
          in: query
          description: Billing Attempt ID
          required: false
          schema:
            type: integer
            format: int64
        - name: customerId
          in: query
          description: Customer ID
          required: false
          schema:
            type: integer
            format: int64
        - name: pageable
          in: query
          description: Pagination parameters (page number and size)
          required: true
          schema:
            $ref: '#/components/schemas/Pageable'
          example:
            page: 0
            size: 5
            sort:
              - id,desc
      responses:
        '200':
          description: Successfully retrieved past orders
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '400':
          description: Invalid parameters
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDTO'
  /api/external/v2/subscription-billing-attempts/past-orders/report:
    get:
      tags:
        - Billing & Payments
      summary: Get past orders report with detailed filtering
      description: >-
        Retrieves a detailed report of past billing attempts with advanced
        filtering options. This endpoint provides comprehensive data for
        analytics, troubleshooting, and reporting purposes.


        **Filter Options:**

        - By status: SUCCESS, FAILED, SKIPPED

        - By date range: Filter by billing date range

        - By attempt count: Filter by number of retry attempts

        - By contract status: Filter by subscription contract status

        - By contract ID: Get report for specific subscription


        **Response Includes:**

        - Detailed billing attempt information

        - Shopify exception details for failed attempts (optional)

        - Retry attempt count

        - Processing timestamps

        - Order totals and line items


        **Authentication:** Requires valid X-API-Key header
      operationId: getPastOrdersReport
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: contractId
          in: query
          description: Filter by contract Id
          required: false
          schema:
            type: integer
            format: int64
        - name: status
          in: query
          description: Filter by status
          required: true
          schema:
            type: string
            enum:
              - SUCCESS
              - FAILURE
              - REQUESTING
              - PROGRESS
              - QUEUED
              - SKIPPED
              - SOCIAL_CONNECTION_NULL
              - CONTRACT_CANCELLED
              - CONTRACT_ENDED
              - CONTRACT_PAUSED
              - AUTO_CHARGE_DISABLED
              - SHOPIFY_EXCEPTION
              - SKIPPED_DUNNING_MGMT
              - SKIPPED_INVENTORY_MGMT
              - IMMEDIATE_TRIGGERED
              - SECURITY_CHALLENGE
              - CONTRACT_PAUSED_MAX_CYCLES
              - REFUNDED
              - SKIPPED_DEMO_SHOP
              - SKIPPED_SHOP_INFO_NOT_FOUND
              - SKIPPED_BILLING_DATE_STALE
              - SKIPPED_DUNNING_NOT_CONFIGURED
        - name: includeShopifyException
          in: query
          description: Include Shopify Exception in case of Failure
          required: false
          schema:
            type: boolean
            default: false
        - name: fromDay
          in: query
          description: Filter date range from
          required: false
          schema:
            type: string
            format: date-time
        - name: toDay
          in: query
          description: Filter by date range to
          required: false
          schema:
            type: string
            format: date-time
        - name: attemptCount
          in: query
          description: Filter by retry attempts
          required: false
          schema:
            type: integer
            format: int32
        - name: contractStatus
          in: query
          description: Filter by Contract Status
          required: false
          schema:
            type: string
        - name: pageable
          in: query
          description: Pagination parameters (page number and size)
          required: true
          schema:
            $ref: '#/components/schemas/Pageable'
          example:
            page: 0
            size: 5
            sort:
              - id,desc
      responses:
        '200':
          description: Successfully retrieved report
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDetails'
        '400':
          description: Invalid filter parameters
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDetails'
        '401':
          description: Authentication required
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDetails'
        '403':
          description: Insufficient permissions
          content:
            '*/*':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubscriptionBillingAttemptDetails'
  /api/external/v2/product-swaps/{id}:
    get:
      tags:
        - Product Catalog
      summary: Get a specific product swap by ID
      description: >-
        Retrieves detailed information about a specific product swap automation
        configuration. This endpoint returns complete details about the source
        products, destination products, swap triggers, and all associated
        settings.


        **Response Details:**

        - Complete swap configuration

        - Source product variants with images and quantities

        - Destination product variants with images and quantities

        - Billing cycle triggers and conditions

        - Discount carry-forward settings

        - Email notification preferences

        - Swap status and history


        **Source and Destination Variants:**

        Both source and destination variants are returned as JSON strings
        containing:

        - Variant ID

        - Display name/title

        - Product image URL

        - Quantity to swap

        - Product metadata


        **Swap Timing:**

        - **forBillingCycle**: If set, swap occurs at this specific cycle number

        - **checkForEveryRecurringOrder**: If true, swap happens on every order

        - **updatedFirstOrder**: If true, can affect the initial subscription
        order


        **Discount Handling:**

        - **NONE**: No discount carried forward

        - **PERCENTAGE**: Percentage discount is maintained

        - **FIXED_AMOUNT**: Fixed amount discount is maintained

        - **PRICE**: Specific price point is maintained


        **Authentication:** Requires valid X-API-Key header
      operationId: getProductSwap
      parameters:
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Product swap returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductSwapDTO'
        '400':
          description: Invalid product swap ID
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid id
                status: 400
                detail: Product swap does not belong to this shop
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to view product swap
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to view product swaps
        '404':
          description: Product swap not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Product swap with ID 10782 not found
    delete:
      tags:
        - Product Catalog
      summary: Delete a product swap automation
      description: >-
        Permanently deletes a product swap automation configuration. Once
        deleted, the swap will no longer be applied to any subscription orders.
        Existing subscriptions that have already had products swapped are not
        affected.


        **Deletion Behavior:**

        - Permanently removes the swap automation

        - Does not reverse past swaps that have already occurred

        - Future orders will not have this swap applied

        - Cannot be undone - swap configuration must be recreated if needed


        **Impact on Subscriptions:**

        - **Active Subscriptions**: Will continue with current products (no
        automatic reversion)

        - **Future Orders**: Swap will not be applied

        - **Past Orders**: Already swapped products remain unchanged

        - **Queued Swaps**: Pending swaps for this automation are cancelled


        **When to Delete:**

        - Discontinuing a seasonal product rotation

        - Removing outdated swap rules

        - Cleaning up test or experimental swaps

        - Product lines being discontinued

        - Correcting misconfigured swaps


        **Important Notes:**

        - This operation is permanent and cannot be undone

        - Consider deactivating instead of deleting if you might reuse the
        configuration

        - Activity logs for past swaps are retained

        - Customers are not automatically notified of swap deletion


        **Best Practices:**

        - Review affected subscriptions before deletion

        - Consider communicating changes to affected customers

        - Export swap configuration if you might need it later

        - Use deactivation for temporary pauses instead of deletion


        **Authentication:** Requires valid X-API-Key header
      operationId: deleteProductSwap
      parameters:
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '204':
          description: Product swap successfully deleted - No content returned
        '400':
          description: Invalid product swap ID or swap doesn't belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid id
                status: 400
                detail: Product swap does not belong to this shop or ID is invalid
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to delete product swaps
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to delete product swaps
        '404':
          description: Product swap not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Resource not found
                status: 404
                detail: Product swap with ID 10782 not found
  /api/external/v2/manage-subscription-link:
    get:
      tags:
        - Customers
      summary: Generate customer portal access link by customer ID or email
      description: >-
        Generates a secure, time-limited magic link that allows customers to
        access their subscription management portal. This endpoint supports
        lookup by either customer ID or email address, making it flexible for
        different integration scenarios.


        **Key Features:**

        - **Dual Lookup**: Find customer by ID or email

        - **Auto Customer Discovery**: Automatically finds customer from email

        - **Secure Tokens**: Encrypted tokens with 2-hour expiration

        - **Custom Domains**: Supports shop's public domain

        - **Zero-Auth Access**: Customers don't need passwords


        **Customer Lookup Logic:**


        **Option 1: By Customer ID (Preferred)**

        ```

        GET /api/external/v2/manage-subscription-link?customerId=12345

        ```

        - Direct lookup by Shopify customer ID

        - Fastest and most reliable method

        - No ambiguity


        **Option 2: By Email**

        ```

        GET
        /api/external/v2/manage-subscription-link?emailId=customer@example.com

        ```

        - Searches for customer by email in subscription database

        - Finds customer ID automatically

        - If not found: Returns error


        **Validation Rules:**

        - Either `customerId` OR `emailId` must be provided

        - Cannot provide both (customerId takes precedence)

        - Email must match a customer with subscriptions

        - Customer must belong to authenticated shop


        **Token Generation:**


        **Token Contents:**

        - Encrypted customer ID

        - Shop domain

        - Generation timestamp

        - Expiration time (2 hours)


        **Security Features:**

        - Cryptographically secure encryption

        - Cannot be forged or modified

        - Automatic expiration after 2 hours

        - Single-use recommended (though not enforced)

        - Tied to specific shop and customer


        **Generated URL Structure:**

        ```

        https://[shop-domain]/[manage-subscriptions-path]?token=[encrypted-token]

        ```


        **Example URLs:**

        ```

        https://mystore.com/tools/recurring/customer_portal?token=eyJhbGc...

        https://shop.myshopify.com/tools/recurring/customer_portal?token=eyJhbGc...

        ```


        **Use Cases:**


        **1. Email Campaigns:**

        - Add "Manage Subscription" button to transactional emails

        - Include in billing reminder emails

        - Send in order confirmation emails

        - Add to marketing campaigns


        **2. Customer Support:**

        - Provide customers quick portal access

        - Avoid "forgot password" issues

        - Enable instant self-service

        - Reduce support ticket volume


        **3. Post-Purchase Flows:**

        - Thank you page portal links

        - First order welcome emails

        - Onboarding email sequences

        - Re-engagement campaigns


        **4. Account Management:**

        - SMS notifications with portal links

        - Push notification deep links

        - Customer dashboard integrations

        - Third-party app integrations


        **Response Format:**

        ```json

        {
          "manageSubscriptionLink": "https://mystore.com/tools/recurring/customer_portal?token=eyJhbGciOiJIUzI1NiJ9...",
          "tokenExpirationTime": "2024-03-15T14:30:00Z"
        }

        ```


        **Response Fields:**

        - `manageSubscriptionLink`: Complete URL ready to use

        - `tokenExpirationTime`: ISO 8601 timestamp when token expires


        **Integration Examples:**


        **Email Template:**

        ```javascript

        const response = await fetch(
          `/api/external/v2/manage-subscription-link?emailId=${customerEmail}`,
          { headers: { 'X-API-Key': 'your-key' } }
        ).then(r => r.json());


        const emailHtml = `
          <p>Hi ${customerName},</p>
          <p>Manage your subscription:</p>
          <a href="${response.manageSubscriptionLink}">Manage Subscription</a>
          <p><small>Link expires ${formatDate(response.tokenExpirationTime)}</small></p>
        `;

        ```


        **SMS Notification:**

        ```javascript

        const { manageSubscriptionLink } = await getPortalLink(customerId);

        const shortUrl = await shortenUrl(manageSubscriptionLink);


        await sendSMS(customerPhone, 
          `Your subscription ships tomorrow! Manage it here: ${shortUrl}`
        );

        ```


        **Important Considerations:**


        **Token Expiration:**

        - Tokens expire after exactly 2 hours

        - Generate new token if expired

        - Don't store tokens long-term

        - Best practice: Generate on-demand


        **Domain Selection:**

        - Uses shop's `publicDomain` if configured

        - Falls back to Shopify domain (.myshopify.com)

        - Respects custom domain settings

        - Maintains brand consistency


        **Customer Lookup Errors:**

        - Email not found: Returns 400 error

        - Invalid customer ID: Returns error

        - No parameters provided: Returns 400

        - Both parameters provided: Uses customerId


        **Security Notes:**

        - Tokens cannot be used across different shops

        - Cannot be used for different customers

        - Tampering invalidates token

        - Consider rate limiting token generation


        **Best Practices:**


        1. **Generate On-Demand**: Create tokens when needed, not in advance

        2. **Use HTTPS**: Always serve links over HTTPS

        3. **Show Expiry**: Inform customers when link expires

        4. **URL Shortening**: Use URL shorteners for SMS/print materials

        5. **Track Usage**: Monitor which emails drive portal visits

        6. **Prefer Customer ID**: Use customerId when available for faster
        lookup


        **Comparison with /manage-subscription-link/{customerId}:**

        - This endpoint: Flexible lookup (ID or email)

        - Path parameter version: Customer ID only

        - Both generate identical tokens

        - Use this for email-based flows


        **Authentication:** Requires valid X-API-Key header
      operationId: getManageSubscriptionLinkv3
      parameters:
        - name: api_key
          in: query
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: customerId
          in: query
          required: false
          schema:
            type: integer
            format: int64
        - name: emailId
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Successfully generated manage subscription link
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenDetails'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    manageSubscriptionLink: >-
                      https://mystore.com/tools/recurring/customer_portal?token=eyJhbGciOiJIUzI1NiJ9.eyJjdXN0b21lcklkIjoxMjM0NSwic2hvcCI6Im15c3RvcmUubXlzaG9waWZ5LmNvbSIsInRpbWVzdGFtcCI6MTcwOTU2MjAwMH0.abc123xyz
                    tokenExpirationTime: '2024-03-15T14:30:00Z'
        '400':
          description: Bad request - Missing parameters or customer not found
          content:
            application/json:
              examples:
                Missing Parameters:
                  description: Missing Parameters
                  value:
                    type: https://example.com/errors/bad-request
                    title: Missing required parameter
                    status: 400
                    detail: Either customerId or emailId must be provided.
                Customer Not Found:
                  description: Customer Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Customer not found
                    status: 400
                    detail: >-
                      Customer not found for the provided email:
                      customer@example.com
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Forbidden - Customer does not belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: Customer does not belong to your shop
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-error
                title: Token generation failed
                status: 500
                detail: Failed to generate customer portal token
  /api/external/v2/manage-subscription-link/{customerId}:
    get:
      tags:
        - Customers
      summary: Generate customer portal link
      description: >-
        Generates a secure, time-limited link that allows customers to access
        their subscription management portal. This link provides customers with
        self-service capabilities to manage their subscriptions without
        requiring login credentials.


        **Key Features:**

        - Generates unique encrypted token for customer authentication

        - Token expires after 2 hours for security

        - Direct access to subscription management without password

        - Uses store's custom domain when available

        - Supports white-label customer portals


        **Token Security:**

        - Token contains encrypted customer ID, shop, and timestamp

        - Cannot be reused after expiration

        - Unique token generated for each request

        - Cryptographically secure encryption


        **Customer Portal Access:**

        Once customers click the link, they can:

        - View all active subscriptions

        - Update payment methods

        - Change delivery addresses

        - Modify product quantities

        - Pause or cancel subscriptions

        - Update delivery schedules

        - Apply discount codes

        - View order history


        **Use Cases:**

        - Email campaigns with 'Manage Subscription' CTAs

        - Customer service providing quick access

        - Post-purchase email flows

        - Account management integrations

        - Reducing support ticket volume


        **URL Structure:**

        The generated URL follows this pattern:

        `https://[store-domain]/[manage-subscription-path]?token=[encrypted-token]`


        **Important Notes:**

        - Links are single-use and expire after 2 hours

        - New link must be generated after expiration

        - Customer ID must be valid and active

        - Store must have customer portal configured


        **Authentication:** Requires valid X-API-Key header
      operationId: getManageSubscriptionLink
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: customerId
          in: path
          description: >-
            Customer ID to generate portal link for. Provide the numeric ID
            without the gid:// prefix
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 987654321
      responses:
        '200':
          description: Manage subscription link successfully generated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenDetails'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    manageSubscriptionLink: >-
                      https://store.example.com/pages/manage-subscriptions?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzaG9wIjoic3RvcmUuZXhhbXBsZS5jb20iLCJjdXN0b21lcklkIjo5ODc2NTQzMjEsImNyZWF0ZWRBdCI6MTcxMDUxMjQwMDAwMH0.dGhpcyBpcyBhIHNhbXBsZSB0b2tlbiBmb3IgZG9jdW1lbnRhdGlvbg
                    tokenExpirationTime: '2024-03-15T16:30:00.000Z'
                    expiresInMinutes: 120
                    customerId: 987654321
                    portalUrl: https://store.example.com/pages/manage-subscriptions
        '400':
          description: Invalid request parameters
          content:
            application/json:
              examples:
                Invalid Customer ID:
                  description: Invalid Customer ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid customer ID
                    status: 400
                    detail: Customer ID must be a positive number
                Portal Not Configured:
                  description: Portal Not Configured
                  value:
                    type: https://example.com/errors/bad-request
                    title: Customer portal not configured
                    status: 400
                    detail: Store has not configured a manage subscriptions URL
        '401':
          description: Authentication required - missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid API key is required to access this endpoint
        '403':
          description: Insufficient permissions
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to generate customer portal
                  links
        '404':
          description: Customer not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Customer not found
                status: 404
                detail: No customer found with ID 987654321
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-error
                title: Token generation failed
                status: 500
                detail: An error occurred while generating the secure token
  /api/external/v2/data/contract-delivery-options:
    get:
      tags:
        - Subscription Management
      summary: Get delivery options for subscription contract
      description: >-
        Retrieves all valid delivery methods available for a specific
        subscription contract. Returns shipping profiles and delivery options
        based on the contract's delivery address and product characteristics.


        **Delivery Information Returned:**

        - Available shipping profiles

        - Delivery methods for each profile

        - Shipping rates and costs

        - Delivery speed (standard, express, etc.)

        - Method names and descriptions

        - Eligibility based on address and products


        **Filtering Behavior:**

        By default, returns only delivery methods valid for the contract:

        - Matches delivery address country/region

        - Compatible with subscription products

        - Available for contract weight/dimensions


        **Include All Methods:**

        Use header `X-Include-All-Methods: true` to return all delivery methods
        regardless of eligibility. Useful for admin UIs where you want to show
        all options.


        **Use Cases:**

        - Display delivery method selector in customer portal

        - Allow customers to change shipping method

        - Calculate shipping costs for subscription

        - Validate delivery method during subscription updates

        - Show upgrade options (standard to express)


        **Common Scenarios:**


        **Customer Portal - Change Delivery Speed:**

        1. Call this endpoint with contractId

        2. Display available methods to customer

        3. Customer selects preferred method

        4. Update subscription with new delivery method ID


        **Subscription Creation - Delivery Selection:**

        1. Get delivery options for draft contract

        2. Present options during checkout/signup

        3. Create subscription with selected method


        **Important Notes:**

        - Delivery options depend on current contract address

        - Changing address may change available methods

        - Costs may vary based on products in subscription

        - Some methods may have minimum order requirements

        - International shipping may have additional restrictions


        **Authentication:** Requires X-API-Key header
      operationId: getContractDeliveryOptions
      parameters:
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: contractId
          in: query
          description: Contract Id
          required: true
          schema:
            type: integer
            format: int64
        - name: X-Include-All-Methods
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Delivery options retrieved successfully
          content:
            application/json:
              examples:
                Success Response:
                  description: Success Response
                  value:
                    - profileId: 12345
                      profileName: Standard Shipping
                      methods:
                        - id: method_123
                          name: Standard Delivery (5-7 days)
                          code: STANDARD
                          price: '5.99'
                          currency: USD
                        - id: method_124
                          name: Express Delivery (2-3 days)
                          code: EXPRESS
                          price: '12.99'
                          currency: USD
        '401':
          description: Invalid API key
          content:
            application/json:
              example:
                error: Invalid API key
        '403':
          description: Access denied - Contract belongs to different shop
          content:
            application/json:
              example:
                error: Unauthorized access to contract
        '404':
          description: Contract not found
          content:
            application/json:
              example:
                error: Subscription contract not found
  /api/external/v2/customer-portal-token:
    get:
      tags:
        - Customer Portal
      summary: Generate customer portal authentication token
      description: >-
        Generates a secure, time-limited authentication token that grants access
        to the customer portal. Supports lookup by either Shopify customer ID or
        customer email address, making it flexible for various integration
        patterns.


        **What This Endpoint Returns:**

        An encrypted JWT-like token that authenticates a customer for the
        subscription management portal, along with token metadata. Unlike the
        manage-subscription-link endpoint which returns a complete URL, this
        returns only the token itself.


        **Response Components:**


        **token (string):**

        - Encrypted authentication token

        - JWT-style format with cryptographic signature

        - Contains customer ID and shop information

        - Valid for 2 hours from generation

        - Cannot be forged or tampered with


        **customerId (long):**

        - Shopify customer ID (numeric)

        - Useful for verification

        - Same ID used to generate token


        **Customer Lookup Methods:**


        **Option 1: By Customer ID (Recommended)**

        ```

        GET /api/external/v2/customer-portal-token?customerId=12345

        ```

        - Direct lookup by numeric Shopify customer ID

        - Can use GraphQL GID format (automatically parsed)

        - Fastest and most reliable

        - No ambiguity


        **Option 2: By Email Address**

        ```

        GET /api/external/v2/customer-portal-token?email=customer@example.com

        ```

        - Searches subscription database for matching email

        - Finds associated customer ID automatically

        - Useful when customer ID unknown

        - Fails if email not found or invalid


        **Parameter Validation:**

        - Exactly ONE of `customerId` or `email` must be provided

        - Providing neither: Returns 400 error

        - Providing both: customerId takes precedence

        - Email must exist in subscription database


        **Token Security:**


        **Encryption:**

        - Uses HMAC-SHA256 cryptographic signing

        - Secret key stored securely on server

        - Token includes tamper detection

        - Modification invalidates token


        **Expiration:**

        - Tokens expire exactly 2 hours after generation

        - Timestamp embedded in token payload

        - Verified on each use

        - Cannot be extended


        **Scope:**

        - Token tied to specific customer

        - Token tied to specific shop

        - Cannot be used for other customers

        - Cannot be used across shops


        **Use Cases:**


        **1. Custom Portal Implementations:**

        - Build custom authentication flows

        - Integrate portal into existing apps

        - Create native mobile app authentication

        - Headless commerce integrations


        **2. API-First Architectures:**

        - Generate tokens programmatically

        - Pass tokens to frontend applications

        - Build microservice authentication

        - Separate auth from presentation


        **3. Single Sign-On (SSO):**

        - Authenticate users from existing system

        - Bypass password entry

        - Seamless portal access

        - Cross-platform authentication


        **4. Email/SMS Campaigns:**

        - Generate tokens for magic links

        - Embed in notification emails

        - Include in SMS messages

        - Create passwordless login links


        **5. Customer Support Tools:**

        - Generate portal access for support agents

        - View customer's portal perspective

        - Troubleshoot portal issues

        - Assist customers remotely


        **Response Format:**

        ```json

        {
          "customerId": 12345,
          "token": "eyJhbGciOiJIUzI1NiJ9.eyJjdXN0b21lcklkIjoxMjM0NSwic2hvcCI6Im15c3RvcmUubXlzaG9waWZ5LmNvbSIsInRpbWVzdGFtcCI6MTcwOTU2MjAwMH0.abc123xyz789"
        }

        ```


        **Using the Token:**


        **Append to Portal URL:**

        ```javascript

        const { token } = await getCustomerPortalToken(customerId);

        const portalUrl =
        `https://mystore.com/tools/recurring/customer_portal?token=${token}`;

        window.location.href = portalUrl;

        ```


        **Store in Session:**

        ```javascript

        // Store for authenticated API calls

        sessionStorage.setItem('portalToken', response.token);

        sessionStorage.setItem('customerId', response.customerId);


        // Use in subsequent requests

        fetch('/api/subscription-data', {
          headers: { 'Authorization': `Bearer ${sessionStorage.getItem('portalToken')}` }
        });

        ```


        **Mobile App Authentication:**

        ```javascript

        // Generate token server-side

        const tokenData = await generateToken(email);


        // Send to mobile app

        return {
          authToken: tokenData.token,
          customerId: tokenData.customerId,
          expiresIn: 7200 // 2 hours in seconds
        };

        ```


        **Important Considerations:**


        **Token vs. Full URL:**

        - This endpoint: Returns token only

        - `/manage-subscription-link` endpoint: Returns complete URL

        - Use this for custom implementations

        - Use manage-subscription-link for simple email links


        **Email Lookup Limitations:**

        - Email must exist in subscription database

        - Searches only customers with subscriptions

        - Won't find customers without subscriptions

        - Case-sensitive in some databases


        **Customer ID Formats:**

        - Accepts numeric ID: `12345`

        - Accepts GraphQL GID: `gid://shopify/Customer/12345`

        - Automatically extracts numeric portion

        - Always stores numeric format


        **Best Practices:**


        1. **Generate On-Demand**: Create tokens when needed, not in advance

        2. **Don't Store Long-Term**: Tokens expire in 2 hours

        3. **Use HTTPS**: Always transmit tokens over secure connections

        4. **Validate Expiry**: Check token age on frontend

        5. **Prefer Customer ID**: Use customerId lookup when available

        6. **Handle Errors**: Gracefully handle missing customers


        **Security Notes:**

        - Treat tokens like passwords

        - Don't log tokens in plain text

        - Don't expose in URLs if possible (use POST bodies)

        - Rotate tokens frequently

        - Monitor for suspicious token generation patterns


        **Comparison with Other Endpoints:**


        **vs. /manage-subscription-link:**

        - This: Token only

        - That: Complete URL

        - Use this for APIs, that for emails


        **vs. /subscription-contracts-email-magic-link:**

        - This: Returns token

        - That: Sends email

        - Use this for programmatic access, that for customer notifications


        **Authentication:** Requires valid X-API-Key header
      operationId: getCustomerPortalToken
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: customerId
          in: query
          description: Customer ID
          required: false
          schema:
            type: string
        - name: email
          in: query
          description: Customer email
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Successfully generated customer portal token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerTokenInfo'
              examples:
                Token Response:
                  description: Token Response
                  value:
                    customerId: 12345
                    token: >-
                      eyJhbGciOiJIUzI1NiJ9.eyJjdXN0b21lcklkIjoxMjM0NSwic2hvcCI6Im15c3RvcmUubXlzaG9waWZ5LmNvbSIsInRpbWVzdGFtcCI6MTcwOTU2MjAwMH0.abc123xyz789
        '400':
          description: Bad request - Missing parameters or invalid customer
          content:
            application/json:
              examples:
                Missing Parameters:
                  description: Missing Parameters
                  value:
                    type: https://example.com/errors/bad-request
                    title: Missing required parameter
                    status: 400
                    detail: Customer Id or Email does not exist
                Customer Not Found:
                  description: Customer Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Customer not found
                    status: 400
                    detail: Customer Id or Email does not exist
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Forbidden - Customer does not belong to authenticated shop
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: Customer does not belong to your shop
  /api/external/v2/customer-portal-settings/{id}:
    get:
      tags:
        - Customer Portal
      summary: Get customer portal settings
      description: >-
        Retrieves the customer portal configuration and settings for the
        authenticated shop. The customer portal is the self-service interface
        where subscribers can manage their subscriptions, update payment
        methods, modify delivery addresses, and more.


        **What is the Customer Portal?**

        The customer portal is a dedicated web interface that allows your
        subscribers to manage their subscription accounts independently. This
        reduces support burden and improves customer experience by enabling
        self-service subscription management.


        **Settings Returned:**

        - **Display Configuration**:
          - Portal theme and branding settings
          - Custom colors and logo
          - Layout preferences
          - Custom CSS selectors

        - **Feature Toggles**:
          - Enable/disable subscription pausing
          - Enable/disable order skipping
          - Enable/disable product swapping
          - Enable/disable frequency changes
          - Enable/disable quantity modifications
          - Enable/disable address editing
          - Enable/disable payment method updates
          - Enable/disable subscription cancellation

        - **Subscription Management Options**:
          - Maximum pause duration allowed
          - Minimum subscription duration requirements
          - Skip limits per billing cycle
          - Product swap availability
          - One-time product add-ons

        - **Communication Settings**:
          - Email notification preferences
          - Custom portal messaging
          - Support contact information
          - Help text and instructions

        - **Access Control**:
          - Portal authentication method
          - Password requirements
          - Magic link settings
          - Session duration

        - **Advanced Options**:
          - Custom domain configuration
          - Redirect URLs
          - Webhook endpoints
          - Analytics tracking settings

        **Use Cases:**

        - Display customer portal with correct branding and theme

        - Determine which features are available to subscribers

        - Build custom portal interfaces using your settings

        - Sync portal configuration across systems

        - Validate subscription management capabilities

        - Configure third-party integrations


        **Important Notes:**

        - Settings are shop-specific and unique per merchant

        - Some features may be restricted based on subscription plan

        - Changes to settings are reflected immediately in the portal

        - Custom CSS must be valid and secure

        - Portal URL is typically: shop-domain.com/apps/subscriptions


        **Common Configuration Scenarios:**


        **1. Standard Self-Service Portal:**

        - Allow pausing (up to 3 months)

        - Allow skipping (max 2 consecutive orders)

        - Allow frequency changes

        - Allow quantity updates

        - Allow address editing

        - Enable payment method updates

        - Enable cancellation with feedback


        **2. Locked-Down Portal (Minimal Self-Service):**

        - Disable pausing

        - Disable skipping

        - Disable cancellation (require support contact)

        - Allow address editing only

        - Allow payment method updates only


        **3. Full-Service Portal (Maximum Flexibility):**

        - Enable all subscription management features

        - Allow unlimited pauses and skips

        - Enable product swapping

        - Enable one-time add-ons

        - Allow subscription splitting/merging

        - Custom branding and domain


        **Authentication:** Requires valid X-API-Key header
      operationId: getCustomerPortalSettingsV2
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Customer portal settings successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerPortalSettingsDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: 12345
                    shop: example-shop.myshopify.com
                    portalEnabled: true
                    customDomain: subscriptions.example.com
                    allowPause: true
                    maxPauseDuration: 90
                    allowSkip: true
                    maxConsecutiveSkips: 2
                    allowFrequencyChange: true
                    allowQuantityChange: true
                    allowProductSwap: true
                    allowAddressEdit: true
                    allowPaymentMethodUpdate: true
                    allowCancellation: true
                    requireCancellationReason: true
                    enableOneTimeProducts: true
                    minimumSubscriptionCycles: 3
                    theme:
                      primaryColor: '#4A90E2'
                      secondaryColor: '#50E3C2'
                      accentColor: '#F5A623'
                      fontFamily: '''Helvetica Neue'', Arial, sans-serif'
                      logoUrl: >-
                        https://cdn.shopify.com/s/files/1/0000/0000/files/logo.png
                      customCss: '.subscription-card { border-radius: 8px; }'
                    authentication:
                      method: MAGIC_LINK
                      sessionDuration: 3600
                      requireEmailVerification: true
                    notifications:
                      sendSkipConfirmation: true
                      sendPauseConfirmation: true
                      sendFrequencyChangeConfirmation: true
                      sendCancellationConfirmation: true
                    supportContact:
                      email: support@example.com
                      phone: +1-800-123-4567
                      chatEnabled: true
                    createdAt: '2024-01-15T10:30:00Z'
                    updatedAt: '2024-02-20T14:45:00Z'
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to view customer portal settings
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to view portal settings
        '404':
          description: >-
            Customer portal settings not found - Settings may not be initialized
            yet
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Settings not found
                status: 404
                detail: >-
                  Customer portal settings have not been configured for this
                  shop
  /api/external/v2/contract-raw-response:
    get:
      tags:
        - Subscription Contracts
      summary: Retrieve raw Shopify GraphQL response for a subscription contract
      description: >-
        Fetches the complete, unprocessed JSON response directly from Shopify's
        GraphQL API for the specified subscription contract. This endpoint
        returns the full subscription data structure as provided by Shopify,
        including all nested objects and relationships.


        **Use Cases:**

        - Debugging subscription issues

        - Accessing all available subscription data

        - Understanding the complete data structure

        - Building custom integrations


        **Response Structure:**

        The response includes complete details about:

        - Customer information (email, name, ID)

        - Line items (products, quantities, pricing)

        - Billing and delivery policies

        - Payment method details

        - Discounts and pricing policies

        - Order history and billing attempts

        - Custom attributes and notes


        **Note:** This is a direct Shopify response with GraphQL type
        information (__typename fields)


        **Authentication:** Requires valid X-API-Key header
      operationId: getContractRawResponse
      parameters:
        - name: api_key
          in: query
          description: API Key (Deprecated - Use X-API-Key header instead)
          required: false
          deprecated: true
          schema:
            type: string
        - name: X-API-Key
          in: header
          description: API Key for authentication
          required: true
          schema:
            type: string
          example: sk_live_1234567890abcdef
        - name: contractId
          in: query
          description: >-
            The unique identifier of the subscription contract. Use the numeric
            ID without the 'gid://shopify/SubscriptionContract/' prefix. For
            example, use '26833420451' instead of
            'gid://shopify/SubscriptionContract/26833420451'.
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 26833420451
      responses:
        '200':
          description: Successfully retrieved raw contract data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Data'
              examples:
                Complete Subscription Contract Response:
                  description: Complete Subscription Contract Response
                  value:
                    subscriptionContract:
                      __typename: SubscriptionContract
                      id: gid://shopify/SubscriptionContract/26833420451
                      createdAt: '2025-06-19T12:19:21Z'
                      updatedAt: '2025-06-19T12:19:25Z'
                      nextBillingDate: '2025-07-19T12:00:00Z'
                      status: ACTIVE
                      deliveryPrice:
                        __typename: MoneyV2
                        amount: '0.0'
                        currencyCode: USD
                      lastPaymentStatus: null
                      billingPolicy:
                        __typename: SubscriptionBillingPolicy
                        interval: MONTH
                        intervalCount: 1
                        anchors: []
                        maxCycles: null
                        minCycles: null
                      deliveryPolicy:
                        __typename: SubscriptionDeliveryPolicy
                        interval: MONTH
                        intervalCount: 1
                        anchors: []
                      lines:
                        __typename: SubscriptionLineConnection
                        edges:
                          - __typename: SubscriptionLineEdge
                            node:
                              __typename: SubscriptionLine
                              id: >-
                                gid://shopify/SubscriptionLine/35d6970f-66bd-4ce0-a7a5-f1498096fec8
                              sellingPlanId: gid://shopify/SellingPlan/2598666403
                              sellingPlanName: Monthly Subscription
                              productId: gid://shopify/Product/8794161545379
                              title: Gift Card
                              variantId: gid://shopify/ProductVariant/45954331672739
                              quantity: 1
                              customAttributes: []
                              variantTitle: $10
                              currentPrice:
                                __typename: MoneyV2
                                amount: '9.0'
                                currencyCode: USD
                              pricingPolicy:
                                __typename: SubscriptionPricingPolicy
                                basePrice:
                                  __typename: MoneyV2
                                  amount: '10.0'
                                  currencyCode: USD
                                cycleDiscounts:
                                  - __typename: SubscriptionCyclePriceAdjustment
                                    afterCycle: 0
                                    computedPrice:
                                      __typename: MoneyV2
                                      amount: '9.0'
                                      currencyCode: USD
                                    adjustmentType: PERCENTAGE
                                    adjustmentValue:
                                      __typename: SellingPlanPricingPolicyPercentageValue
                                      percentage: 10
                      customerPaymentMethod:
                        __typename: CustomerPaymentMethod
                        id: >-
                          gid://shopify/CustomerPaymentMethod/e14bcaa08f882975bfe6c708642eb223
                        instrument:
                          __typename: CustomerCreditCard
                          brand: bogus
                          expiryMonth: 12
                          expiryYear: 2025
                          lastDigits: '1'
                          maskedNumber: •••• •••• •••• 1
                      customer:
                        __typename: Customer
                        id: gid://shopify/Customer/8718823227555
                        email: customer@example.com
                        displayName: John Doe
                        firstName: John
                        lastName: Doe
                      originOrder:
                        __typename: Order
                        id: gid://shopify/Order/6152668807331
                        name: '#1002'
                      note: null
                      customAttributes: []
                      discounts:
                        __typename: SubscriptionManualDiscountConnection
                        edges: []
        '400':
          description: Invalid request parameters
          content:
            application/json:
              examples:
                Missing Contract ID:
                  description: Missing Contract ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Missing required parameter
                    status: 400
                    detail: contractId parameter is required
                    instance: /api/external/v2/contract-raw-response
                Invalid Contract ID Format:
                  description: Invalid Contract ID Format
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid contractId format
                    status: 400
                    detail: contractId must be a numeric value
                    instance: /api/external/v2/contract-raw-response
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
                instance: /api/external/v2/contract-raw-response
        '403':
          description: Insufficient permissions to access the subscription contract
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Access denied
                status: 403
                detail: >-
                  You do not have permission to access this subscription
                  contract
                instance: /api/external/v2/contract-raw-response
        '404':
          description: Subscription contract not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Contract does not exist
                status: 404
                detail: 'No subscription contract found with ID: 123456789'
                instance: /api/external/v2/contract-raw-response
  /api/external/v2/cancellation-managements/{id}:
    get:
      tags:
        - Operations & Settings
      summary: Get cancellation management configuration
      description: >-
        Retrieves the cancellation management and retention settings for the
        authenticated shop. These settings control the subscription cancellation
        flow, retention strategies, and customer feedback collection when
        subscribers attempt to cancel their subscriptions.


        **What is Cancellation Management?**

        Cancellation management is a retention system that helps merchants
        reduce subscription churn by understanding why customers cancel and
        offering alternatives before they leave. It includes cancellation flows,
        feedback collection, retention offers (discounts, pauses, frequency
        changes), and automated win-back strategies.


        **Configuration Components:**


        **1. Cancellation Flow Settings:**

        - Enable/disable self-service cancellation in customer portal

        - Require customer to contact support for cancellation

        - Multi-step cancellation confirmation process

        - Cancellation cooldown period (prevent accidental cancellations)

        - Minimum subscription duration before cancellation allowed

        - Immediate vs. end-of-billing-cycle cancellation


        **2. Cancellation Reasons & Feedback:**

        - Predefined cancellation reasons list

        - Custom cancellation reason options

        - Required vs. optional feedback

        - Free-form text feedback field

        - Rating/satisfaction scale

        - Exit survey questions

        - Feedback sent to merchant email/dashboard


        **Common Cancellation Reasons:**

        - Too expensive / Can't afford

        - Don't use product enough / Have too much inventory

        - Product quality issues

        - Switching to competitor

        - Delivery issues / Shipping problems

        - Forgot to cancel earlier

        - Temporary pause needed (moving, travel, etc.)

        - Product doesn't meet expectations

        - Customer service issues

        - Other (with text field)


        **3. Retention Offers (Save Flow):**

        - Display retention offers before final cancellation

        - Offer discount (percentage or fixed amount)

        - Offer free product/gift with next order

        - Suggest subscription pause instead of cancel

        - Suggest frequency change (deliver less often)

        - Offer to skip next order

        - Offer to swap products

        - Personalized offers based on cancellation reason


        **Example Retention Logic:**

        ```

        Reason: "Too expensive"
          → Offer: 20% discount for next 3 months
          → Offer: Switch to smaller/cheaper variant

        Reason: "Have too much inventory"
          → Offer: Pause for 1-3 months
          → Offer: Change from monthly to every 2 months
          → Offer: Skip next 2 deliveries

        Reason: "Product quality issues"
          → Offer: Free replacement on next order
          → Offer: Try different product variant
          → Route to customer support
        ```


        **4. UI/UX Configuration:**

        - Cancellation button placement and styling

        - Warning messages and modal dialogs

        - Progress indicator for multi-step flow

        - Retention offer presentation (modal, inline, etc.)

        - Confirmation messages

        - Post-cancellation survey


        **5. Automation & Notifications:**

        - Send cancellation confirmation email

        - Notify merchant of cancellations

        - Trigger win-back email campaigns

        - Schedule feedback review

        - Alert for high cancellation rate

        - Integration with CRM/analytics tools


        **6. Metrics & Analytics:**

        - Track cancellation rate

        - Categorize cancellation reasons

        - Measure retention offer acceptance rate

        - Calculate customer lifetime value at cancellation

        - Identify churn patterns and trends

        - A/B test different retention strategies


        **7. Advanced Features:**

        - Conditional retention offers based on:
          - Customer lifetime value
          - Subscription duration
          - Product type
          - Cancellation history
          - Customer segment
        - Win-back campaigns for cancelled subscribers

        - Automatic re-engagement emails (30, 60, 90 days post-cancel)

        - Special offers to reactivate cancelled subscriptions


        **Cancellation Flow Examples:**


        **Basic Flow (No Retention):**

        1. Customer clicks "Cancel Subscription"

        2. Confirmation dialog: "Are you sure?"

        3. Optional: Select cancellation reason

        4. Subscription cancelled immediately or at period end

        5. Confirmation email sent


        **Advanced Retention Flow:**

        1. Customer clicks "Cancel Subscription"

        2. "Before you go..." - Select cancellation reason

        3. Display personalized retention offer based on reason

        4. Customer chooses: Accept offer OR Continue to cancel

        5. If continue: Additional offers or final confirmation

        6. If still cancelling: Exit survey

        7. Cancellation processed

        8. Thank you message + feedback confirmation

        9. Follow-up email campaign


        **Use Cases:**

        - Configure cancellation flow in customer portal

        - Customize retention offers and messaging

        - Analyze cancellation patterns and trends

        - Build custom cancellation interfaces

        - Integrate with customer support tools

        - Generate churn reports and analytics

        - A/B test different retention strategies

        - Automate win-back campaigns


        **Important Notes:**

        - Always comply with consumer protection laws regarding cancellation

        - Make cancellation process clear and accessible (FTC guidelines)

        - Don't make cancellation unnecessarily difficult

        - Respect customer's decision to cancel

        - Use retention offers ethically (not dark patterns)

        - Store cancellation feedback for product improvement

        - GDPR/privacy compliance for feedback data


        **Best Practices:**

        - Keep cancellation process simple (2-3 steps max)

        - Offer genuine value in retention offers

        - Personalize offers based on cancellation reason

        - Make pause/skip options prominent

        - Use cancellation feedback to improve product/service

        - Set up automated win-back campaigns

        - Monitor cancellation rate and take action on trends

        - Train customer support on retention strategies

        - Test different retention messaging and offers

        - Honor cancellations promptly and professionally


        **Legal & Compliance:**

        - FTC regulations require easy cancellation (Click-to-Cancel rule)

        - California automatic renewal law compliance

        - European consumer protection directives

        - Clear disclosure of cancellation terms

        - Process cancellations within legal timeframes

        - Provide confirmation of cancellation


        **Authentication:** Requires valid X-API-Key header
      operationId: getCancellationManagementV2
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Cancellation management configuration successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CancellationManagementDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    id: 12345
                    shop: example-shop.myshopify.com
                    enabled: true
                    allowSelfServiceCancellation: true
                    requireSupportContact: false
                    minimumSubscriptionDays: 30
                    cancellationTiming: END_OF_BILLING_CYCLE
                    requireCancellationReason: true
                    allowCustomReason: true
                    cancellationReasons:
                      - Too expensive
                      - Have too much product
                      - Product quality issues
                      - Switching to competitor
                      - Delivery problems
                      - Don't need anymore
                      - Temporary situation (moving, travel, etc.)
                      - Other
                    collectFeedback: true
                    feedbackRequired: false
                    showExitSurvey: true
                    retentionOffersEnabled: true
                    retentionStrategies:
                      Too expensive:
                        - type: DISCOUNT
                          value: '20'
                          duration: 3
                          description: 20% off for 3 months
                        - type: FREQUENCY_CHANGE
                          description: Deliver less often to save money
                      Have too much product:
                        - type: PAUSE
                          maxDuration: 90
                          description: Pause for up to 3 months
                        - type: SKIP
                          skipCount: 2
                          description: Skip your next 2 deliveries
                        - type: FREQUENCY_CHANGE
                          description: Switch to every 2 months
                      Product quality issues:
                        - type: SUPPORT_CONTACT
                          description: Let us make it right - contact support
                        - type: PRODUCT_SWAP
                          description: Try a different product
                    confirmationFlow:
                      multiStep: true
                      showAlternatives: true
                      requireConfirmation: true
                      cooldownPeriod: 24
                    notifications:
                      sendCustomerConfirmation: true
                      sendMerchantNotification: true
                      merchantEmail: subscriptions@example.com
                      enableWinBackCampaigns: true
                      winBackSchedule:
                        - 30
                        - 60
                        - 90
                    analytics:
                      trackCancellationRate: true
                      trackReasonFrequency: true
                      trackRetentionOfferAcceptance: true
                      alertOnHighChurnRate: true
                      churnRateThreshold: 15
                    uiSettings:
                      buttonText: Cancel Subscription
                      buttonColor: '#DC3545'
                      warningMessage: >-
                        We'll be sorry to see you go! Before you cancel, let us
                        try to help.
                      confirmationMessage: >-
                        Your subscription has been cancelled. You will receive a
                        confirmation email shortly.
                      thankYouMessage: >-
                        Thank you for being a subscriber. We hope to see you
                        again!
                    createdAt: '2024-01-15T10:30:00Z'
                    updatedAt: '2024-02-20T14:45:00Z'
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '403':
          description: Insufficient permissions to view cancellation management settings
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: >-
                  API key does not have permission to view cancellation
                  management settings
        '404':
          description: Cancellation management configuration not found
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Configuration not found
                status: 404
                detail: Cancellation management has not been configured for this shop
  /api/external/v2/build-a-box/{id}:
    get:
      tags:
        - Build-a-Box & Bundles
      summary: Retrieve a Build-A-Box bundle by ID
      description: >-
        Fetches the complete configuration and details of a specific Build-A-Box
        subscription bundle using its unique identifier. This endpoint returns
        all bundle settings including products, pricing, rules, and delivery
        options.


        **What You'll Receive:**

        - **Complete Bundle Configuration**: All settings and properties

        - **Product Information**: Full list of available products with details

        - **Pricing Structure**: Discount rules, pricing type, and promotional
        settings

        - **Delivery Options**: Subscription frequencies and delivery intervals

        - **Business Rules**: Product limits, combination rules, and
        restrictions

        - **Status Information**: Active/inactive state and timestamps

        - **Customization Settings**: Allow one-time purchases, product swaps,
        etc.


        **Use Cases:**

        1. **Bundle Management**: Retrieve current bundle settings for review or
        editing

        2. **Integration Sync**: Synchronize bundle data with external systems

        3. **Customer Portal**: Display bundle options and configurations

        4. **Audit & Reporting**: Track bundle configurations over time

        5. **Validation**: Verify bundle setup before making changes

        6. **Cloning**: Retrieve settings to duplicate a successful bundle

        7. **Troubleshooting**: Debug subscription issues by reviewing bundle
        config


        **Response Details:**

        The response includes comprehensive information about the bundle:

        - **Bundle Metadata**: ID, shop, name, handle, unique reference

        - **Product Pool**: All products available for customer selection

        - **Selection Rules**: Min/max product counts, quantity limits

        - **Pricing Configuration**: Discount percentages, pricing models

        - **Subscription Options**: Available delivery frequencies

        - **Display Settings**: Product view styles, custom HTML, button text

        - **Advanced Features**: Third-party rules, inventory tracking,
        selection types

        - **Timestamps**: Creation and last update dates


        **Authorization:**

        - You can only retrieve bundles that belong to your authenticated shop

        - The system verifies shop ownership before returning bundle data

        - Returns 404 if bundle doesn't exist or doesn't belong to your shop


        **Integration Tips:**

        - Cache bundle data to reduce API calls for frequently accessed bundles

        - Use this endpoint to verify bundle existence before creating
        subscriptions

        - Combine with update endpoint for edit workflows (get → modify →
        update)

        - Check the `active` field to determine if the bundle is available to
        customers

        - Review `availableProducts` array to ensure product inventory
        availability


        **Performance Considerations:**

        - Response size varies based on number of products in the bundle

        - Bundles with extensive custom HTML or large product pools return more
        data

        - Consider requesting only necessary fields if partial data is
        sufficient

        - Use batch operations if retrieving multiple bundles


        **Authentication:** Requires valid X-API-Key header or api_key parameter
        (deprecated)
      operationId: getSubscriptionBundling
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Build-A-Box bundle successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBundlingDTO'
              examples:
                Complete Bundle Details:
                  description: Complete Bundle Details
                  value:
                    id: 45678
                    shop: example-shop.myshopify.com
                    bundleName: Premium Coffee Selection
                    bundleHandle: premium-coffee-selection
                    uniqueRef: bab_abc123xyz
                    description: Choose your favorite coffee blends for monthly delivery
                    buildABoxType: SINGLE_PRODUCT
                    buildBoxVersion: V2
                    minProductCount: 2
                    maxProductCount: 5
                    minOrderAmount: 25
                    pricingType: PER_PRODUCT
                    discount: 10
                    discountType: PERCENTAGE
                    allowOneTimePurchase: true
                    thirdPartyRule: false
                    trackInventory: true
                    active: true
                    productViewStyle: GRID
                    proceedToCheckoutButtonText: Complete Your Subscription
                    chooseProductsText: Build Your Perfect Coffee Box
                    availableProducts:
                      - productId: 111111
                        variantId: 222222
                        title: Medium Roast Coffee - 12oz
                        price: '14.99'
                        imageUrl: https://cdn.shopify.com/coffee-medium.jpg
                        available: true
                      - productId: 111111
                        variantId: 333333
                        title: Dark Roast Coffee - 12oz
                        price: '15.99'
                        imageUrl: https://cdn.shopify.com/coffee-dark.jpg
                        available: true
                    frequencies:
                      - interval: MONTH
                        intervalCount: 1
                        displayName: Monthly
                      - interval: WEEK
                        intervalCount: 2
                        displayName: Bi-Weekly
                    createdAt: '2024-03-15T10:30:00Z'
                    updatedAt: '2024-03-20T14:45:00Z'
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header or api_key parameter is required
        '404':
          description: Bundle not found or does not belong to your shop
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Bundle not found
                status: 404
                detail: No Build-A-Box bundle found with ID 45678 for your shop
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-server-error
                title: Internal server error
                status: 500
                detail: >-
                  An unexpected error occurred while retrieving the Build-A-Box
                  bundle
    delete:
      tags:
        - Build-a-Box & Bundles
      summary: Delete a Build-A-Box subscription bundle
      description: >-
        Permanently removes a Build-A-Box subscription bundle from your shop.
        This operation is irreversible and will prevent new customers from
        subscribing to this bundle. However, existing subscriptions using this
        bundle will remain active.


        **Important Deletion Rules:**

        1. **Active Subscriptions Check**: The system prevents deletion if there
        are active subscriptions using this bundle

        2. **Alternative Approach**: If active subscriptions exist, you must
        first deactivate the bundle instead of deleting it

        3. **Shop Ownership**: You can only delete bundles that belong to your
        authenticated shop

        4. **Irreversible**: Once deleted, the bundle configuration cannot be
        recovered

        5. **Clean Deletion**: Only bundles with zero associated subscriptions
        can be permanently removed


        **Deletion Workflow:**

        ```

        1. Request deletion of bundle with ID

        2. System checks for shop ownership

        3. System counts active subscriptions using this bundle

        4. If subscriptions exist → Returns error with subscription count

        5. If no subscriptions → Deletes bundle permanently

        6. Returns success (204 No Content)

        ```


        **When Deletion is Blocked:**

        The system will prevent deletion and return a 400 error if:

        - One or more active subscriptions are using this bundle

        - The error message will include the exact count of active subscriptions

        - Example: "Deleting Build-A-Box is not possible, 47 subscriptions
        found. You may deactivate the Build-A-Box."


        **Recommended Workflow for Active Bundles:**

        If you want to stop offering a bundle that has active subscribers:

        1. **Update** the bundle to set `active: false` (this prevents new
        subscriptions)

        2. **Monitor** existing subscriptions until they naturally expire or are
        cancelled

        3. **Migrate** customers to a different bundle if needed

        4. **Delete** the bundle once all subscriptions have been resolved


        **Use Cases:**

        - **Testing Cleanup**: Remove test bundles created during development

        - **Failed Configurations**: Delete bundles that were incorrectly set up

        - **Seasonal Offerings**: Remove time-limited bundles after the season
        ends (if no subscriptions)

        - **Product Discontinuation**: Clean up bundles for discontinued product
        lines

        - **Duplicate Bundles**: Remove accidentally created duplicate
        configurations


        **Best Practices:**

        - **Check Before Deleting**: Always verify no active subscriptions exist

        - **Use Deactivation First**: Set bundles to inactive before attempting
        deletion

        - **Document Changes**: Keep records of when and why bundles were
        deleted

        - **Backup Configuration**: Save bundle settings before deletion for
        potential recreation

        - **Communicate Changes**: Inform team members about bundle removals

        - **Consider Archiving**: For historical reference, deactivate rather
        than delete when possible


        **What Happens After Deletion:**

        - Bundle configuration is permanently removed from the database

        - Bundle ID becomes available for reuse (though not recommended)

        - Bundle handle becomes available for new bundles

        - External integrations referencing this bundle will receive 404 errors

        - Analytics and historical data may reference the deleted bundle ID


        **Error Prevention:**

        Before attempting deletion, you can:

        1. Query active subscriptions to check for bundle usage

        2. Set the bundle to inactive status first

        3. Wait for all subscriptions to complete or migrate customers

        4. Then proceed with deletion


        **Authentication:** Requires valid X-API-Key header or api_key parameter
        (deprecated)
      operationId: deleteSubscriptionBundling
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '204':
          description: Build-A-Box bundle successfully deleted. No content returned.
          content:
            application/json: {}
        '400':
          description: Deletion blocked due to active subscriptions or validation failure
          content:
            application/json:
              examples:
                Active Subscriptions Exist:
                  description: Bundle has 47 active subscriptions and cannot be deleted
                  value:
                    type: https://example.com/errors/bad-request
                    title: Cannot delete bundle
                    status: 400
                    detail: >-
                      Deleting Build-A-Box is not possible, 47 subscriptions
                      found. You may deactivate the Build-A-Box.
                    entityName: subscriptionBundling
                    errorKey: activeSubscriptionsExist
                Unauthorized Access:
                  description: Unauthorized Access
                  value:
                    type: https://example.com/errors/bad-request
                    title: Unauthorized access
                    status: 400
                    detail: >-
                      Unauthorized access or resource not found. Bundle does not
                      belong to your shop.
                    entityName: subscriptionBundling
                    errorKey: unauthorized
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header or api_key parameter is required
        '404':
          description: Bundle not found or does not belong to your shop
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Bundle not found
                status: 404
                detail: No Build-A-Box bundle found with ID 45678 for your shop
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-server-error
                title: Internal server error
                status: 500
                detail: >-
                  An unexpected error occurred while deleting the Build-A-Box
                  bundle
  /api/external/v2/build-a-box/{handle}:
    get:
      tags:
        - Build-a-Box & Bundles
      summary: Retrieve Build-A-Box bundle details by handle for customer storefront
      description: >-
        Fetches comprehensive Build-A-Box bundle configuration using a
        user-friendly handle (URL slug) instead of numeric ID. This endpoint is
        specifically designed for customer-facing storefronts and integration
        scenarios where you want to reference bundles by their human-readable
        handles rather than database IDs.


        **Key Differences from GET /{id}:**

        - **Lookup Method**: Uses bundle handle (e.g., 'premium-coffee-box')
        instead of numeric ID (e.g., 12345)

        - **Response Format**: Returns SubscriptionBundlingResponseV3 with
        enhanced structure

        - **Customer Focus**: Optimized for storefront display and customer
        selection workflows

        - **Bundle + Subscription**: Returns both bundle details AND associated
        subscription plan information

        - **Public Access**: Designed for integration in customer-facing
        applications


        **What is a Bundle Handle?**

        A handle is a URL-friendly identifier for a bundle:

        - Format: lowercase letters, numbers, and hyphens only

        - Example: `premium-coffee-selection`, `monthly-snack-box`,
        `beauty-essentials`

        - Stable: Unlike IDs, handles remain consistent across environments

        - SEO-Friendly: Can be used in customer-facing URLs

        - Human-Readable: Easy to remember and communicate


        **Response Structure (SubscriptionBundlingResponseV3):**

        ```json

        {
          "bundle": {           // Complete bundle configuration
            "id": 45678,
            "bundleName": "Premium Coffee Selection",
            "bundleHandle": "premium-coffee-selection",
            "description": "...",
            "products": [...],
            "pricing": {...},
            "active": true
          },
          "subscription": {     // Associated subscription plan details
            "planId": 98765,
            "frequencies": [...],
            "deliveryOptions": {...},
            "sellingPlan": {...}
          }
        }

        ```


        **Primary Use Cases:**

        1. **Storefront Integration**: Display bundle details on product pages

        2. **Customer Portal**: Allow customers to browse available bundles

        3. **Landing Pages**: Create dedicated pages for specific bundles using
        handles

        4. **Marketing Campaigns**: Link directly to bundles with memorable URLs

        5. **Cross-Platform Sync**: Use stable handles for multi-platform
        integrations

        6. **Mobile Apps**: Retrieve bundle data using consistent identifiers

        7. **External Integrations**: Third-party systems can reference bundles
        by handle


        **When to Use Handle vs ID:**

        - **Use Handle** when:
          - Building customer-facing features
          - Creating shareable URLs
          - Syncing across environments (dev → staging → prod)
          - External systems need stable references
          - SEO and user experience are priorities

        - **Use ID** when:
          - You already have the numeric ID from another API response
          - Performing administrative operations
          - Internal system integration
          - Optimizing for query performance

        **Availability Validation:**

        The endpoint validates that:

        - Bundle exists and belongs to the specified shop

        - Bundle has an associated subscription configuration

        - If validation fails, returns 404 Not Found

        - Both bundle AND subscription must be present for success response


        **Integration Examples:**

        **Storefront Display:**

        ```javascript

        // Fetch bundle for display on product page

        const handle = 'premium-coffee-selection';

        const response = await fetch(
          `/api/external/v2/build-a-box/${handle}`,
          { headers: { 'X-API-Key': 'your-api-key' } }
        );

        const { bundle, subscription } = await response.json();

        displayBundleOptions(bundle, subscription);

        ```


        **Best Practices:**

        - **Handle Naming**: Use descriptive, SEO-friendly handles

        - **Caching**: Cache bundle data with handle as key for better
        performance

        - **Error Handling**: Always check for 404 - bundle may be deleted or
        deactivated

        - **Environment Sync**: Use handles to maintain consistency across
        environments

        - **URL Structure**: Incorporate handles into clean, readable URLs

        - **Documentation**: Document handle conventions for your team


        **Performance Considerations:**

        - Handle lookups may be slightly slower than ID lookups

        - Response includes full bundle + subscription data (larger payload)

        - Consider caching for frequently accessed bundles

        - Returns complete product catalog for the bundle


        **Authentication:** Requires valid X-API-Key header or api_key parameter
        (deprecated)
      operationId: getValidSubscriptionCustomerV2_2
      parameters:
        - name: handle
          in: path
          description: Bundle Handle
          required: true
          schema:
            type: string
        - name: api_key
          in: query
          description: API Key (Deprecated - Use Header X-API-Key instead)
          required: false
          schema:
            type: string
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Bundle and subscription details successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionBundlingResponseV3'
              examples:
                Complete Bundle and Subscription Response:
                  description: Complete Bundle and Subscription Response
                  value:
                    bundle:
                      id: 45678
                      shop: example-shop.myshopify.com
                      bundleName: Premium Coffee Selection
                      bundleHandle: premium-coffee-selection
                      uniqueRef: bab_abc123xyz
                      description: Choose your favorite coffee blends for monthly delivery
                      buildABoxType: SINGLE_PRODUCT
                      buildBoxVersion: V2
                      minProductCount: 2
                      maxProductCount: 5
                      discount: 10
                      discountType: PERCENTAGE
                      allowOneTimePurchase: true
                      active: true
                      products:
                        - productId: 111111
                          variantId: 222222
                          title: Medium Roast Coffee - 12oz
                          price: '14.99'
                          imageUrl: https://cdn.shopify.com/coffee-medium.jpg
                    subscription:
                      subscriptionPlanId: 98765
                      sellingPlanGroupId: gid://shopify/SellingPlanGroup/123456
                      frequencies:
                        - interval: MONTH
                          intervalCount: 1
                          displayName: Deliver every month
                        - interval: WEEK
                          intervalCount: 2
                          displayName: Deliver every 2 weeks
                      deliveryPolicy:
                        type: RECURRING
                        anchors: []
                    createdAt: '2024-03-15T10:30:00Z'
                    updatedAt: '2024-03-20T14:45:00Z'
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header or api_key parameter is required
        '404':
          description: >-
            Bundle not found, subscription not configured, or bundle not
            available
          content:
            application/json:
              examples:
                Bundle Not Found:
                  description: No bundle exists with the specified handle
                  value:
                    type: https://example.com/errors/not-found
                    title: Bundle not found
                    status: 404
                    detail: >-
                      No Build-A-Box bundle found with handle
                      'premium-coffee-selection'
                Subscription Not Configured:
                  description: Bundle found but subscription plan is not set up
                  value:
                    type: https://example.com/errors/not-found
                    title: Subscription configuration missing
                    status: 404
                    detail: >-
                      Bundle exists but has no associated subscription plan
                      configured
        '500':
          description: Internal server error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-server-error
                title: Internal server error
                status: 500
                detail: >-
                  An unexpected error occurred while retrieving the Build-A-Box
                  bundle
  /api/external/v2/associate-shopify-customer-to-external-payment-gateways:
    get:
      tags:
        - Billing & Payments
      summary: Associate external payment gateway customer with Shopify customer
      description: >-
        Links a customer's payment profile from an external payment gateway
        (Stripe, Braintree, PayPal, Authorize.Net) to their Shopify customer
        account. This enables Shopify subscription billing to charge payment
        methods stored in external gateways, which is essential for migrating
        existing subscriptions or integrating with legacy payment systems.


        **What This Endpoint Does:**

        Creates a connection between a Shopify customer and their corresponding
        customer profile in an external payment gateway. This allows Shopify's
        subscription system to send billing requests to the external gateway
        using the stored payment credentials, effectively enabling subscriptions
        to bill through payment methods managed outside of Shopify.


        **Supported Payment Gateways:**


        **1. Stripe** (`paymentGateway=stripe`):

        - Requires: `customerProfileId` (Stripe customer ID, e.g., `cus_xxxxx`)

        - Requires: `paymentProfileId` (Stripe payment method ID, e.g.,
        `pm_xxxxx` or card ID)

        - Links Shopify customer to Stripe customer and stored card/payment
        method


        **2. Braintree** (`paymentGateway=braintree`):

        - Requires: `customerProfileId` (Braintree customer ID)

        - Requires: `paymentProfileId` (Braintree payment method token)

        - Supports credit cards and PayPal accounts stored in Braintree vault


        **3. PayPal** (`paymentGateway=paypal`):

        - Requires: `paymentProfileId` (PayPal billing agreement ID)

        - Optional: `customerProfileId` (not required for PayPal)

        - Links Shopify customer to PayPal billing agreement


        **4. Authorize.Net** (`paymentGateway=authorize_net`):

        - Requires: `customerProfileId` (Authorize.Net customer profile ID)

        - Requires: `paymentProfileId` (Authorize.Net payment profile ID)

        - Links to Customer Information Manager (CIM) profiles


        **Request Parameters:**


        **Required Parameters:**

        - `paymentGateway` (string): Gateway name - `stripe`, `braintree`,
        `paypal`, or `authorize_net`

        - `paymentProfileId` (string): Payment method/card ID in the external
        gateway

        - `customerId` OR `email` (one required): Shopify customer identifier


        **Optional Parameters:**

        - `customerProfileId` (string): Customer ID in external gateway
        (required for Stripe, Braintree, Authorize.Net; optional for PayPal)


        **Customer Identification:**


        **By Customer ID (recommended):**

        - Provide Shopify `customerId` if known

        - Fastest and most reliable method

        - Avoids ambiguity with duplicate emails


        **By Email:**

        - Provide customer `email` if customer ID unknown

        - System looks up Shopify customer by email

        - If exactly one match: Uses that customer

        - If multiple matches: Returns error (ambiguous)

        - If no matches: Creates new Shopify customer with that email


        **Use Cases:**


        **1. Subscription Migration:**

        - Migrating subscriptions from legacy platform to Shopify

        - Preserving existing payment methods during migration

        - Avoiding customer disruption by not requiring payment re-entry

        - Maintaining payment history and customer profiles


        **2. Payment Gateway Integration:**

        - Using external payment processor for compliance reasons

        - Leveraging existing payment gateway relationships

        - Maintaining payment data in external PCI-compliant vault

        - Integrating with enterprise payment infrastructure


        **3. Multi-Platform Sync:**

        - Syncing payment methods from other sales channels

        - Centralizing payment methods across platforms

        - Enabling subscriptions for existing customer base


        **4. Custom Checkout Flows:**

        - Building custom subscription checkout with external gateway

        - Collecting payment via external gateway, then linking to Shopify

        - Supporting payment methods not natively available in Shopify


        **Process Flow:**


        1. **Customer Lookup**:
           - If `customerId` provided: Use directly
           - If `email` provided: Search for existing Shopify customer
           - If email not found: Create new Shopify customer

        2. **Validation**:
           - Validate payment gateway name
           - Check required parameters for selected gateway
           - Verify customer belongs to authenticated shop

        3. **Gateway Association**:
           - Call Shopify GraphQL mutation for gateway-specific association
           - Link customer profile ID and payment profile ID
           - Store association in Shopify's payment instrument vault

        4. **Response**:
           - Return Shopify's raw GraphQL response
           - Response includes payment instrument ID for future use
           - Contains success/error details from Shopify API

        **Example Requests:**


        **Stripe Example:**

        ```

        GET
        /api/external/v2/associate-shopify-customer-to-external-payment-gateways?
          paymentGateway=stripe&
          customerId=12345&
          customerProfileId=cus_ABC123&
          paymentProfileId=pm_XYZ789
        ```


        **Braintree with Email:**

        ```

        GET
        /api/external/v2/associate-shopify-customer-to-external-payment-gateways?
          paymentGateway=braintree&
          email=customer@example.com&
          customerProfileId=bt_customer_123&
          paymentProfileId=bt_card_token_456
        ```


        **PayPal Example:**

        ```

        GET
        /api/external/v2/associate-shopify-customer-to-external-payment-gateways?
          paymentGateway=paypal&
          customerId=12345&
          paymentProfileId=B-12345BILLING67890
        ```


        **Important Considerations:**


        **Gateway Setup:**

        - External payment gateway must be installed and configured in Shopify

        - Gateway must be activated for subscription billing

        - Appropriate credentials and API keys must be configured


        **Data Validation:**

        - Payment profile IDs are not validated against external gateway

        - Invalid IDs will be accepted but will fail during actual billing

        - Test associations before migrating production subscriptions


        **Customer Creation:**

        - If customer doesn't exist and email provided, new customer is created

        - Created customers have minimal information (just email initially)

        - Consider adding additional customer details after creation


        **Security:**

        - This endpoint does NOT store or handle actual payment credentials

        - Only references/tokens to external gateway profiles are used

        - Payment data remains in external gateway's PCI-compliant vault

        - Shopify never receives sensitive card data


        **Best Practices:**


        1. **Test First**: Test with sandbox/test gateway credentials before
        production

        2. **Verify Gateway Active**: Ensure external gateway is properly
        configured in Shopify

        3. **Use Customer ID**: Prefer `customerId` over `email` to avoid
        ambiguity

        4. **Handle Errors**: Implement robust error handling for gateway
        failures

        5. **Validate Externally**: Verify payment profiles exist in external
        gateway before associating

        6. **Document IDs**: Keep mapping of Shopify customer IDs to external
        gateway IDs


        **Migration Workflow Example:**


        ```

        For each legacy subscription:

        1. Get customer email and Stripe customer ID from legacy system

        2. Call this endpoint to link Shopify customer to Stripe customer

        3. Create subscription contract in Shopify using returned payment
        instrument

        4. Verify subscription created successfully

        5. Mark legacy subscription as migrated

        6. Test billing with external gateway

        ```


        **Troubleshooting:**


        **"More than one customer found for email"**:

        - Multiple Shopify customers exist with same email

        - Solution: Use specific `customerId` instead of email


        **"Invalid payment gateway"**:

        - Gateway name misspelled or unsupported

        - Solution: Use exact values: `stripe`, `braintree`, `paypal`,
        `authorize_net`


        **"customerProfileId required"**:

        - Missing required parameter for Stripe/Braintree/Authorize.Net

        - Solution: Provide customer ID from external gateway


        **Response Format:**

        Returns Shopify's raw GraphQL mutation response containing payment
        instrument details and success/error information.


        **Related Endpoints:**

        - `GET
        /api/external/v2/subscription-contract-details/shopify/customer/{customerId}/payment-methods`
        - Verify association successful

        - `PUT /api/external/v2/subscription-contracts-update-payment-method` -
        Use associated payment for subscription


        **Authentication:** Requires valid X-API-Key header
      operationId: associateShopifyCustomerToExternalPaymentGateways
      parameters:
        - name: X-API-Key
          in: header
          required: false
          schema:
            type: string
        - name: paymentGateway
          in: query
          description: Possible values (stripe, braintree, paypal, authorize_net)
          required: true
          schema:
            type: string
        - name: customerId
          in: query
          description: Id of the customer to associate payment method with
          required: false
          schema:
            type: integer
            format: int64
        - name: email
          in: query
          description: Email of the customer to associate payment method with
          required: false
          schema:
            type: string
        - name: customerProfileId
          in: query
          description: Id of customer in external payment gateway, not required for Paypal
          required: false
          schema:
            type: string
        - name: paymentProfileId
          in: query
          description: Card Id or payment profile Id in external payment gateway
          required: true
          schema:
            type: string
      responses:
        '200':
          description: >-
            Successfully associated external payment gateway customer with
            Shopify customer. Returns Shopify GraphQL raw response.
          content:
            application/json:
              examples:
                Successful Stripe association:
                  description: Successful Stripe association
                  value:
                    data:
                      customerPaymentMethodRemoteUserInfoCreate:
                        customerPaymentMethod:
                          id: gid://shopify/CustomerPaymentMethod/abc123
                          instrument:
                            __typename: CustomerCreditCard
                            brand: VISA
                            lastDigits: '4242'
                        userErrors: []
        '400':
          description: >-
            Bad request - Invalid parameters, missing required fields, or
            invalid payment gateway
          content:
            application/json:
              examples:
                Missing customer identifier:
                  description: Missing customer identifier
                  value:
                    type: https://example.com/errors/bad-request
                    title: Missing required parameter
                    status: 400
                    detail: CustomerId or email is required
                Invalid payment gateway:
                  description: Invalid payment gateway
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid payment gateway
                    status: 400
                    detail: >-
                      Invalid payment gateway: invalid_gateway. Supported:
                      stripe, braintree, paypal, authorize_net
                Missing customerProfileId for Stripe:
                  description: Missing customerProfileId for Stripe
                  value:
                    type: https://example.com/errors/bad-request
                    title: Missing required parameter
                    status: 400
                    detail: customerProfileId is required for stripe customers
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid X-API-Key header is required
        '404':
          description: Customer not found (when using customerId)
          content:
            application/json:
              example:
                type: https://example.com/errors/not-found
                title: Customer not found
                status: 404
                detail: No customer found with ID 12345 in Shopify
        '409':
          description: Conflict - Multiple customers found with provided email
          content:
            application/json:
              example:
                type: https://example.com/errors/conflict
                title: Multiple customers found
                status: 409
                detail: >-
                  More than one customer found for: customer@example.com. Please
                  provide specific customerId instead.
        '500':
          description: >-
            Internal error - Failed to associate payment method or Shopify API
            error
          content:
            application/json:
              example:
                type: https://example.com/errors/internal-error
                title: Association failed
                status: 500
                detail: 'Error in creating customer id with email: customer@example.com'
        '502':
          description: Bad gateway - External payment gateway or Shopify API error
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-gateway
                title: Payment gateway error
                status: 502
                detail: Failed to communicate with external payment gateway
  /api/external/v2/activity-logs:
    get:
      tags:
        - Operations & Settings
      summary: Get/Search activity logs
      description: >-
        Retrieves activity logs for all subscription-related events and changes
        in the authenticated shop. Activity logs provide a comprehensive audit
        trail of all subscription activities, changes, and system events.


        **What are Activity Logs?**

        Activity logs are detailed records of every action, event, and change
        that occurs within your subscription system. They capture who made the
        change, when it happened, what was changed, and the result of the
        operation. This provides full traceability and audit capabilities for
        compliance, debugging, and customer support.


        **Log Information Captured:**

        - **Entity Information**:
          - Entity ID: The specific subscription, billing attempt, or resource affected
          - Entity Type: Type of resource (subscription, billing attempt, plan, settings, etc.)
          - Event Type: Specific action performed (see Event Types below)
          - Event Source: Origin of the event (customer portal, merchant portal, API, system, etc.)

        - **Event Details**:
          - Status: SUCCESS, FAILURE, or INFO
          - Timestamp: When the event occurred
          - Activity By: User or system that triggered the event
          - Client IP: IP address of the requester (if applicable)
          - Additional Info: Detailed JSON payload with before/after values and context

        **Entity Types:**

        - `SUBSCRIPTION_BILLING_ATTEMPT` - Billing and payment attempt events

        - `SUBSCRIPTION_CONTRACT_DETAILS` - Subscription contract modifications

        - `SUBSCRIPTION_GROUP_PLAN` - Subscription plan changes

        - `SHIPPING_PROFILE` - Delivery profile and shipping updates

        - `CANCELLATION_MANAGEMENT` - Subscription cancellation events

        - `DUNNING_MANAGEMENT` - Payment retry and dunning activities

        - `PRODUCT_SWAP` - Product replacement events

        - `FREQUENCY_SWAP` - Billing/delivery frequency changes

        - `EMAIL_TEMPLATE` - Email template modifications

        - `SHOP_INFO` - Shop settings and configuration changes

        - `SUBSCRIPTION_WIDGET_SETTINGS` - Widget configuration updates

        - `CUSTOMER_PORTAL_SETTINGS` - Portal settings modifications

        - `SUBSCRIPTION_BUNDLING` - Bundle and bundling rule changes


        **Event Sources:**

        - `CUSTOMER_PORTAL` - Changes made by subscribers through the customer
        portal

        - `MERCHANT_PORTAL` - Changes made by merchants in the admin panel

        - `MERCHANT_EXTERNAL_API` - Changes made via API by merchants or
        integrations

        - `SHOPIFY_EVENT` - Events triggered by Shopify webhooks

        - `SHOPIFY_FLOW` - Events triggered by Shopify Flow automations

        - `SYSTEM_EVENT` - Automated system events (scheduled tasks, sync
        operations)

        - `MERCHANT_PORTAL_BULK_AUTOMATION` - Bulk operations initiated from
        admin panel


        **Common Event Types:**

        - **Subscription Changes**: CONTRACT_PAUSED, CONTRACT_ACTIVATED,
        CONTRACT_CANCELLED, CONTRACT_CREATED

        - **Product Changes**: PRODUCT_ADD, PRODUCT_REMOVE, PRODUCT_REPLACE,
        PRODUCT_QUANTITY_CHANGE, PRODUCT_PRICE_CHANGE

        - **Billing Changes**: NEXT_BILLING_DATE_CHANGE,
        BILLING_INTERVAL_CHANGE, BILLING_ATTEMPT_TRIGGERED,
        BILLING_ATTEMPT_SKIPPED

        - **Delivery Changes**: DELIVERY_INTERVAL_CHANGE,
        SHIPPING_ADDRESS_CHANGE, DELIVERY_METHOD_UPDATED

        - **Payment Changes**: PAYMENT_METHOD_UPDATED, SWITCH_PAYMENT_METHODS

        - **Email Events**: SEND_UPCOMING_ORDER_EMAIL,
        SEND_TRANSACTION_FAILED_EMAIL, SEND_SUBSCRIPTION_CREATED_EMAIL

        - **Discount Events**: DISCOUNT_APPLIED, DISCOUNT_REMOVED,
        PRICING_POLICY_DISCOUNT_APPLIED

        - **One-Time Products**: ONE_TIME_PURCHASE_PRODUCT_ADDED,
        ONE_TIME_PURCHASE_PRODUCT_REMOVED


        **Query Parameters and Filtering:**


        You can filter activity logs using query parameters. All filters support
        standard operations:

        - `equals` - Exact match

        - `in` - Match any value in list

        - `greaterThan`, `lessThan` - Date range filtering

        - `contains` - Partial text match


        **Example Filter Queries:**


        1. **Get all failed billing attempts:**
           `?entityType.equals=SUBSCRIPTION_BILLING_ATTEMPT&eventType.equals=BILLING_ATTEMPT_TRIGGERED&status.equals=FAILURE`

        2. **Get all customer portal changes:**
           `?eventSource.equals=CUSTOMER_PORTAL`

        3. **Get logs for a specific subscription:**
           `?entityId.equals=123456&entityType.equals=SUBSCRIPTION_CONTRACT_DETAILS`

        4. **Get logs within date range:**
           `?createAt.greaterThan=2024-01-01T00:00:00Z&createAt.lessThan=2024-01-31T23:59:59Z`

        5. **Get all cancellation events:**
           `?eventType.equals=CONTRACT_CANCELLED`

        6. **Get all API-triggered changes:**
           `?eventSource.equals=MERCHANT_EXTERNAL_API`

        **Pagination:**


        Results are paginated. Use standard Spring Data pagination parameters:

        - `page` - Page number (zero-indexed, default: 0)

        - `size` - Page size (default: 20, max: 100)

        - `sort` - Sort criteria (e.g., `createAt,desc` or `id,asc`)


        Example: `?page=0&size=50&sort=createAt,desc`


        **Use Cases:**

        - **Audit and Compliance**: Track all changes for regulatory compliance
        and internal auditing

        - **Customer Support**: Review subscription history to troubleshoot
        customer issues

        - **Debugging**: Investigate failed operations and system errors

        - **Analytics**: Analyze customer behavior and subscription lifecycle
        patterns

        - **Reporting**: Generate reports on subscription changes,
        cancellations, and modifications

        - **Integration Monitoring**: Track API usage and automated workflow
        executions

        - **Security**: Monitor for unusual activity patterns or unauthorized
        changes


        **Important Notes:**

        - Activity logs are immutable and cannot be modified or deleted via API

        - Logs are retained according to your subscription plan's retention
        policy

        - The `additionalInfo` field contains detailed JSON with event-specific
        context

        - For large exports, consider using pagination and filtering to reduce
        data transfer

        - Logs are scoped to your shop - you can only access logs for your own
        subscriptions

        - System events may not have an `activityBy` value as they're automated


        **Response Headers:**

        - `X-Total-Count` - Total number of matching records

        - `Link` - Pagination links (first, last, next, prev)


        **Authentication:** Requires valid api_key query parameter with
        appropriate permissions
      operationId: getAllActivityLogs
      parameters:
        - name: api_key
          in: query
          description: Your API Key
          required: true
          schema:
            type: string
        - name: criteria
          in: query
          description: Activity Log Search Criteria
          required: true
          schema:
            $ref: '#/components/schemas/ActivityLogCriteria'
        - name: pageable
          in: query
          description: Pagination parameters (page number and size)
          required: true
          schema:
            $ref: '#/components/schemas/Pageable'
          example:
            page: 0
            size: 10
            sort:
              - id,desc
      responses:
        '200':
          description: >-
            Activity logs successfully retrieved. Returns paginated list of
            activity log entries.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ActivityLogDTO'
              examples:
                Success Response:
                  description: Success Response
                  value:
                    - id: 789012
                      shop: example-shop.myshopify.com
                      entityId: 123456
                      entityType: SUBSCRIPTION_CONTRACT_DETAILS
                      eventSource: CUSTOMER_PORTAL
                      eventType: NEXT_BILLING_DATE_CHANGE
                      status: SUCCESS
                      createAt: '2024-02-15T10:30:45Z'
                      additionalInfo: >-
                        {"oldDate":"2024-03-01","newDate":"2024-03-15","reason":"Customer
                        requested delay"}
                      activityBy: customer@example.com
                      clientIp: 192.168.1.100
                    - id: 789013
                      shop: example-shop.myshopify.com
                      entityId: 123456
                      entityType: SUBSCRIPTION_CONTRACT_DETAILS
                      eventSource: CUSTOMER_PORTAL
                      eventType: PRODUCT_ADD
                      status: SUCCESS
                      createAt: '2024-02-15T11:15:22Z'
                      additionalInfo: >-
                        {"variantId":987654321,"quantity":2,"productTitle":"Premium
                        Coffee Beans","price":"24.99"}
                      activityBy: customer@example.com
                      clientIp: 192.168.1.100
                    - id: 789014
                      shop: example-shop.myshopify.com
                      entityId: 456789
                      entityType: SUBSCRIPTION_BILLING_ATTEMPT
                      eventSource: SYSTEM_EVENT
                      eventType: BILLING_ATTEMPT_TRIGGERED
                      status: FAILURE
                      createAt: '2024-02-15T08:00:00Z'
                      additionalInfo: >-
                        {"amount":"49.99","currency":"USD","errorCode":"INSUFFICIENT_FUNDS","errorMessage":"Card
                        declined - insufficient funds"}
                      activityBy: null
                      clientIp: null
                    - id: 789015
                      shop: example-shop.myshopify.com
                      entityId: 123456
                      entityType: SUBSCRIPTION_CONTRACT_DETAILS
                      eventSource: MERCHANT_PORTAL
                      eventType: CONTRACT_PAUSED
                      status: SUCCESS
                      createAt: '2024-02-14T16:45:30Z'
                      additionalInfo: >-
                        {"pauseReason":"Customer on
                        vacation","pauseDuration":30,"resumeDate":"2024-03-15"}
                      activityBy: merchant-admin@example.com
                      clientIp: 203.0.113.45
                    - id: 789016
                      shop: example-shop.myshopify.com
                      entityId: 789123
                      entityType: PRODUCT_SWAP
                      eventSource: MERCHANT_EXTERNAL_API
                      eventType: PRODUCT_REPLACE
                      status: SUCCESS
                      createAt: '2024-02-14T14:20:15Z'
                      additionalInfo: >-
                        {"oldVariantId":111222333,"newVariantId":444555666,"oldProductTitle":"Regular
                        Coffee","newProductTitle":"Premium
                        Coffee","priceChange":5.00}
                      activityBy: api-integration
                      clientIp: 198.51.100.25
        '400':
          description: Invalid request parameters or filter criteria
          content:
            application/json:
              example:
                type: https://example.com/errors/bad-request
                title: Invalid request parameters
                status: 400
                detail: 'Invalid filter criteria: createAt date format must be ISO-8601'
        '401':
          description: Authentication required - Missing or invalid API key
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Authentication required
                status: 401
                detail: Valid api_key parameter is required to access activity logs
        '403':
          description: Insufficient permissions to view activity logs
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to access activity logs
        '429':
          description: Rate limit exceeded - Too many requests
          content:
            application/json:
              example:
                type: https://example.com/errors/rate-limit
                title: Rate limit exceeded
                status: 429
                detail: API rate limit exceeded. Please retry after 60 seconds.
                retryAfter: 60
  /api/external/v2/subscription-contracts/{id}:
    delete:
      tags:
        - Subscription Contracts
      summary: Cancel a subscription contract
      description: >-
        Cancels an existing subscription contract. This operation terminates all
        future billing and delivery cycles for the subscription. The
        cancellation takes effect immediately.


        **Important Notes:**

        - Any pending/scheduled orders will be cancelled

        - The customer will receive a cancellation confirmation email if
        SUBSCRIPTION_CANCELLED email template is enabled

        - Cancellation feedback and notes are stored for analytics and reporting

        - Minimum cycle requirements ARE enforced via API (unlike internal
        cancellations)

        - If the subscription is under a free trial period, minimum cycles are
        not enforced


        **Validation Rules:**

        - Contract must exist and belong to the authenticated shop

        - Contract must not already be cancelled

        - Must have completed minimum required billing cycles (unless in trial)


        **Post-Cancellation:**

        - Status changes to 'cancelled' (lowercase)

        - Any pause settings are cleared

        - Cancellation feedback and notes are saved

        - Activity log entry is created

        - Cancellation email is sent (if enabled)

        - Any invalid discount codes are automatically removed


        **Authentication:** Requires valid X-API-Key header
      operationId: deleteSubscriptionContractV2
      parameters:
        - name: id
          in: path
          description: >-
            The unique identifier of the subscription contract to cancel. Must
            be a valid contract ID that belongs to the authenticated shop.
          required: true
          schema:
            minimum: 1
            type: integer
            format: int64
          example: 123456789
        - name: cancellationFeedback
          in: query
          description: >-
            Optional feedback from the customer about why they are cancelling.
            This information is valuable for understanding cancellation reasons
            and improving retention. Common values include: 'Too expensive', 'No
            longer needed', 'Found alternative', 'Quality issues', 'Delivery
            issues', 'Customer service', 'Product not as expected', etc. This
            field is stored permanently with the contract for analytics.
          required: false
          schema:
            maxLength: 500
            type: string
          example: Too expensive
        - name: cancellationNote
          in: query
          description: >-
            Optional internal note for recording additional cancellation
            context. This field is for internal use and not visible to
            customers. Can be used to track special circumstances, support
            ticket references, competitor information, or other relevant details
            about why the customer cancelled. This note is stored permanently
            with the contract.
          required: false
          schema:
            maxLength: 1000
            type: string
          example: >-
            Customer switching to competitor X due to pricing. Support ticket
            #12345
      responses:
        '204':
          description: Subscription successfully cancelled. No content returned.
          headers:
            X-Application-Context:
              description: Application context
              style: simple
              schema:
                type: string
        '400':
          description: Invalid request or business rule violation
          content:
            application/json:
              examples:
                Contract Not Found:
                  description: Contract Not Found
                  value:
                    type: https://example.com/errors/bad-request
                    title: Contract does not exist
                    status: 400
                    detail: No subscription contract found with the specified ID
                    instance: /api/external/v2/subscription-contracts/999999999
                Invalid Contract ID:
                  description: Invalid Contract ID
                  value:
                    type: https://example.com/errors/bad-request
                    title: Invalid id
                    status: 400
                    detail: Contract does not belong to this shop
                    instance: /api/external/v2/subscription-contracts/123456789
                Minimum Cycles Not Met:
                  description: Minimum Cycles Not Met
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:You need to complete at least 3 orders
                      before you can cancel this subscription.
                    status: 400
                    detail: >-
                      Subscription has a minimum commitment that has not been
                      fulfilled
                    instance: /api/external/v2/subscription-contracts/123456789
                Shopify API Error:
                  description: Shopify API Error
                  value:
                    type: https://example.com/errors/bad-request
                    title: >-
                      UserGeneratedError:Unable to cancel subscription at this
                      time
                    status: 400
                    detail: Shopify API returned an error when attempting to cancel
                    instance: /api/external/v2/subscription-contracts/123456789
        '401':
          description: Authentication required
          content:
            application/json:
              example:
                type: https://example.com/errors/unauthorized
                title: Shop does not exist
                status: 401
                detail: Valid X-API-Key header is required
                instance: /api/external/v2/subscription-contracts/123456789
        '403':
          description: Insufficient permissions to cancel the subscription
          content:
            application/json:
              example:
                type: https://example.com/errors/forbidden
                title: Insufficient permissions
                status: 403
                detail: API key does not have permission to cancel subscriptions
                instance: /api/external/v2/subscription-contracts/123456789
components:
  schemas:
    AdjustmentValue:
      type: object
      properties:
        get__typename:
          type: string
    Amount:
      type: object
      properties:
        get__typename:
          type: string
        amount:
          type: object
        currencyCode:
          type: string
          enum:
            - USD
            - EUR
            - GBP
            - CAD
            - AFN
            - ALL
            - DZD
            - AOA
            - ARS
            - AMD
            - AWG
            - AUD
            - BBD
            - AZN
            - BDT
            - BSD
            - BHD
            - BIF
            - BYN
            - BZD
            - BMD
            - BTN
            - BAM
            - BRL
            - BOB
            - BWP
            - BND
            - BGN
            - MMK
            - KHR
            - CVE
            - KYD
            - XAF
            - CLP
            - CNY
            - COP
            - KMF
            - CDF
            - CRC
            - HRK
            - CZK
            - DKK
            - DJF
            - DOP
            - XCD
            - EGP
            - ERN
            - ETB
            - FKP
            - XPF
            - FJD
            - GIP
            - GMD
            - GHS
            - GTQ
            - GYD
            - GEL
            - GNF
            - HTG
            - HNL
            - HKD
            - HUF
            - ISK
            - INR
            - IDR
            - ILS
            - IRR
            - IQD
            - JMD
            - JPY
            - JEP
            - JOD
            - KZT
            - KES
            - KID
            - KWD
            - KGS
            - LAK
            - LVL
            - LBP
            - LSL
            - LRD
            - LYD
            - LTL
            - MGA
            - MKD
            - MOP
            - MWK
            - MVR
            - MRU
            - MXN
            - MYR
            - MUR
            - MDL
            - MAD
            - MNT
            - MZN
            - NAD
            - NPR
            - ANG
            - NZD
            - NIO
            - NGN
            - NOK
            - OMR
            - PAB
            - PKR
            - PGK
            - PYG
            - PEN
            - PHP
            - PLN
            - QAR
            - RON
            - RUB
            - RWF
            - WST
            - SHP
            - SAR
            - RSD
            - SCR
            - SLL
            - SGD
            - SDG
            - SOS
            - SYP
            - ZAR
            - KRW
            - SSP
            - SBD
            - LKR
            - SRD
            - SZL
            - SEK
            - CHF
            - TWD
            - THB
            - TJS
            - TZS
            - TOP
            - TTD
            - TND
            - TRY
            - TMT
            - UGX
            - UAH
            - AED
            - UYU
            - UZS
            - VUV
            - VES
            - VND
            - XOF
            - YER
            - ZMW
            - USDC
            - BYR
            - STD
            - STN
            - VED
            - VEF
            - XXX
            - $UNKNOWN
    Anchor:
      type: object
      properties:
        get__typename:
          type: string
        cutoffDay:
          type: integer
          format: int32
        day:
          type: integer
          format: int32
        month:
          type: integer
          format: int32
        type:
          type: string
          enum:
            - WEEKDAY
            - MONTHDAY
            - YEARDAY
            - $UNKNOWN
    Anchor1:
      type: object
      properties:
        get__typename:
          type: string
        cutoffDay:
          type: integer
          format: int32
        day:
          type: integer
          format: int32
        month:
          type: integer
          format: int32
        type:
          type: string
          enum:
            - WEEKDAY
            - MONTHDAY
            - YEARDAY
            - $UNKNOWN
    BasePrice:
      type: object
      properties:
        get__typename:
          type: string
        amount:
          type: object
        currencyCode:
          type: string
          enum:
            - USD
            - EUR
            - GBP
            - CAD
            - AFN
            - ALL
            - DZD
            - AOA
            - ARS
            - AMD
            - AWG
            - AUD
            - BBD
            - AZN
            - BDT
            - BSD
            - BHD
            - BIF
            - BYN
            - BZD
            - BMD
            - BTN
            - BAM
            - BRL
            - BOB
            - BWP
            - BND
            - BGN
            - MMK
            - KHR
            - CVE
            - KYD
            - XAF
            - CLP
            - CNY
            - COP
            - KMF
            - CDF
            - CRC
            - HRK
            - CZK
            - DKK
            - DJF
            - DOP
            - XCD
            - EGP
            - ERN
            - ETB
            - FKP
            - XPF
            - FJD
            - GIP
            - GMD
            - GHS
            - GTQ
            - GYD
            - GEL
            - GNF
            - HTG
            - HNL
            - HKD
            - HUF
            - ISK
            - INR
            - IDR
            - ILS
            - IRR
            - IQD
            - JMD
            - JPY
            - JEP
            - JOD
            - KZT
            - KES
            - KID
            - KWD
            - KGS
            - LAK
            - LVL
            - LBP
            - LSL
            - LRD
            - LYD
            - LTL
            - MGA
            - MKD
            - MOP
            - MWK
            - MVR
            - MRU
            - MXN
            - MYR
            - MUR
            - MDL
            - MAD
            - MNT
            - MZN
            - NAD
            - NPR
            - ANG
            - NZD
            - NIO
            - NGN
            - NOK
            - OMR
            - PAB
            - PKR
            - PGK
            - PYG
            - PEN
            - PHP
            - PLN
            - QAR
            - RON
            - RUB
            - RWF
            - WST
            - SHP
            - SAR
            - RSD
            - SCR
            - SLL
            - SGD
            - SDG
            - SOS
            - SYP
            - ZAR
            - KRW
            - SSP
            - SBD
            - LKR
            - SRD
            - SZL
            - SEK
            - CHF
            - TWD
            - THB
            - TJS
            - TZS
            - TOP
            - TTD
            - TND
            - TRY
            - TMT
            - UGX
            - UAH
            - AED
            - UYU
            - UZS
            - VUV
            - VES
            - VND
            - XOF
            - YER
            - ZMW
            - USDC
            - BYR
            - STD
            - STN
            - VED
            - VEF
            - XXX
            - $UNKNOWN
    BillingAttempts:
      type: object
      properties:
        get__typename:
          type: string
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/Node3'
    BillingPolicy:
      type: object
      properties:
        get__typename:
          type: string
        interval:
          type: string
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
            - $UNKNOWN
        intervalCount:
          type: integer
          format: int32
        anchors:
          type: array
          items:
            $ref: '#/components/schemas/Anchor'
        maxCycles:
          type: integer
          format: int32
        minCycles:
          type: integer
          format: int32
    ComputedPrice:
      type: object
      properties:
        get__typename:
          type: string
        amount:
          type: object
        currencyCode:
          type: string
          enum:
            - USD
            - EUR
            - GBP
            - CAD
            - AFN
            - ALL
            - DZD
            - AOA
            - ARS
            - AMD
            - AWG
            - AUD
            - BBD
            - AZN
            - BDT
            - BSD
            - BHD
            - BIF
            - BYN
            - BZD
            - BMD
            - BTN
            - BAM
            - BRL
            - BOB
            - BWP
            - BND
            - BGN
            - MMK
            - KHR
            - CVE
            - KYD
            - XAF
            - CLP
            - CNY
            - COP
            - KMF
            - CDF
            - CRC
            - HRK
            - CZK
            - DKK
            - DJF
            - DOP
            - XCD
            - EGP
            - ERN
            - ETB
            - FKP
            - XPF
            - FJD
            - GIP
            - GMD
            - GHS
            - GTQ
            - GYD
            - GEL
            - GNF
            - HTG
            - HNL
            - HKD
            - HUF
            - ISK
            - INR
            - IDR
            - ILS
            - IRR
            - IQD
            - JMD
            - JPY
            - JEP
            - JOD
            - KZT
            - KES
            - KID
            - KWD
            - KGS
            - LAK
            - LVL
            - LBP
            - LSL
            - LRD
            - LYD
            - LTL
            - MGA
            - MKD
            - MOP
            - MWK
            - MVR
            - MRU
            - MXN
            - MYR
            - MUR
            - MDL
            - MAD
            - MNT
            - MZN
            - NAD
            - NPR
            - ANG
            - NZD
            - NIO
            - NGN
            - NOK
            - OMR
            - PAB
            - PKR
            - PGK
            - PYG
            - PEN
            - PHP
            - PLN
            - QAR
            - RON
            - RUB
            - RWF
            - WST
            - SHP
            - SAR
            - RSD
            - SCR
            - SLL
            - SGD
            - SDG
            - SOS
            - SYP
            - ZAR
            - KRW
            - SSP
            - SBD
            - LKR
            - SRD
            - SZL
            - SEK
            - CHF
            - TWD
            - THB
            - TJS
            - TZS
            - TOP
            - TTD
            - TND
            - TRY
            - TMT
            - UGX
            - UAH
            - AED
            - UYU
            - UZS
            - VUV
            - VES
            - VND
            - XOF
            - YER
            - ZMW
            - USDC
            - BYR
            - STD
            - STN
            - VED
            - VEF
            - XXX
            - $UNKNOWN
    CurrentPrice:
      type: object
      properties:
        get__typename:
          type: string
        amount:
          type: object
        currencyCode:
          type: string
          enum:
            - USD
            - EUR
            - GBP
            - CAD
            - AFN
            - ALL
            - DZD
            - AOA
            - ARS
            - AMD
            - AWG
            - AUD
            - BBD
            - AZN
            - BDT
            - BSD
            - BHD
            - BIF
            - BYN
            - BZD
            - BMD
            - BTN
            - BAM
            - BRL
            - BOB
            - BWP
            - BND
            - BGN
            - MMK
            - KHR
            - CVE
            - KYD
            - XAF
            - CLP
            - CNY
            - COP
            - KMF
            - CDF
            - CRC
            - HRK
            - CZK
            - DKK
            - DJF
            - DOP
            - XCD
            - EGP
            - ERN
            - ETB
            - FKP
            - XPF
            - FJD
            - GIP
            - GMD
            - GHS
            - GTQ
            - GYD
            - GEL
            - GNF
            - HTG
            - HNL
            - HKD
            - HUF
            - ISK
            - INR
            - IDR
            - ILS
            - IRR
            - IQD
            - JMD
            - JPY
            - JEP
            - JOD
            - KZT
            - KES
            - KID
            - KWD
            - KGS
            - LAK
            - LVL
            - LBP
            - LSL
            - LRD
            - LYD
            - LTL
            - MGA
            - MKD
            - MOP
            - MWK
            - MVR
            - MRU
            - MXN
            - MYR
            - MUR
            - MDL
            - MAD
            - MNT
            - MZN
            - NAD
            - NPR
            - ANG
            - NZD
            - NIO
            - NGN
            - NOK
            - OMR
            - PAB
            - PKR
            - PGK
            - PYG
            - PEN
            - PHP
            - PLN
            - QAR
            - RON
            - RUB
            - RWF
            - WST
            - SHP
            - SAR
            - RSD
            - SCR
            - SLL
            - SGD
            - SDG
            - SOS
            - SYP
            - ZAR
            - KRW
            - SSP
            - SBD
            - LKR
            - SRD
            - SZL
            - SEK
            - CHF
            - TWD
            - THB
            - TJS
            - TZS
            - TOP
            - TTD
            - TND
            - TRY
            - TMT
            - UGX
            - UAH
            - AED
            - UYU
            - UZS
            - VUV
            - VES
            - VND
            - XOF
            - YER
            - ZMW
            - USDC
            - BYR
            - STD
            - STN
            - VED
            - VEF
            - XXX
            - $UNKNOWN
    CustomAttribute:
      type: object
      properties:
        get__typename:
          type: string
        key:
          type: string
        value:
          type: string
    CustomAttribute1:
      type: object
      properties:
        get__typename:
          type: string
        key:
          type: string
        value:
          type: string
    Customer:
      type: object
      properties:
        get__typename:
          type: string
        id:
          type: string
        email:
          type: string
          deprecated: true
        displayName:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        phone:
          type: string
          deprecated: true
    CustomerPaymentMethod:
      type: object
      properties:
        get__typename:
          type: string
        id:
          type: string
        instrument:
          $ref: '#/components/schemas/Instrument'
        revokedAt:
          type: object
        revokedReason:
          type: string
          enum:
            - AUTHORIZE_NET_GATEWAY_NOT_ENABLED
            - AUTHORIZE_NET_RETURNED_NO_PAYMENT_METHOD
            - FAILED_TO_UPDATE_CREDIT_CARD
            - STRIPE_API_AUTHENTICATION_ERROR
            - STRIPE_API_INVALID_REQUEST_ERROR
            - STRIPE_GATEWAY_NOT_ENABLED
            - STRIPE_RETURNED_NO_PAYMENT_METHOD
            - STRIPE_PAYMENT_METHOD_NOT_CARD
            - BRAINTREE_API_AUTHENTICATION_ERROR
            - BRAINTREE_GATEWAY_NOT_ENABLED
            - BRAINTREE_RETURNED_NO_PAYMENT_METHOD
            - BRAINTREE_PAYMENT_METHOD_NOT_CARD
            - PAYMENT_METHOD_VERIFICATION_FAILED
            - THREE_D_SECURE_FLOW_IN_VERIFICATION_NOT_IMPLEMENTED
            - MANUALLY_REVOKED
            - FAILED_TO_RETRIEVE_BILLING_ADDRESS
            - MERGED
            - CUSTOMER_REDACTED
            - TOO_MANY_CONSECUTIVE_FAILURES
            - CVV_ATTEMPTS_LIMIT_EXCEEDED
            - $UNKNOWN
    CycleDiscount:
      type: object
      properties:
        get__typename:
          type: string
        afterCycle:
          type: integer
          format: int32
        computedPrice:
          $ref: '#/components/schemas/ComputedPrice'
        adjustmentType:
          type: string
          enum:
            - PERCENTAGE
            - FIXED_AMOUNT
            - PRICE
            - $UNKNOWN
        adjustmentValue:
          $ref: '#/components/schemas/AdjustmentValue'
    DeliveryMethod:
      type: object
      properties:
        get__typename:
          type: string
    DeliveryPolicy:
      type: object
      properties:
        get__typename:
          type: string
        interval:
          type: string
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
            - $UNKNOWN
        intervalCount:
          type: integer
          format: int32
        anchors:
          type: array
          items:
            $ref: '#/components/schemas/Anchor1'
    DeliveryPrice:
      type: object
      properties:
        get__typename:
          type: string
        amount:
          type: object
        currencyCode:
          type: string
          enum:
            - USD
            - EUR
            - GBP
            - CAD
            - AFN
            - ALL
            - DZD
            - AOA
            - ARS
            - AMD
            - AWG
            - AUD
            - BBD
            - AZN
            - BDT
            - BSD
            - BHD
            - BIF
            - BYN
            - BZD
            - BMD
            - BTN
            - BAM
            - BRL
            - BOB
            - BWP
            - BND
            - BGN
            - MMK
            - KHR
            - CVE
            - KYD
            - XAF
            - CLP
            - CNY
            - COP
            - KMF
            - CDF
            - CRC
            - HRK
            - CZK
            - DKK
            - DJF
            - DOP
            - XCD
            - EGP
            - ERN
            - ETB
            - FKP
            - XPF
            - FJD
            - GIP
            - GMD
            - GHS
            - GTQ
            - GYD
            - GEL
            - GNF
            - HTG
            - HNL
            - HKD
            - HUF
            - ISK
            - INR
            - IDR
            - ILS
            - IRR
            - IQD
            - JMD
            - JPY
            - JEP
            - JOD
            - KZT
            - KES
            - KID
            - KWD
            - KGS
            - LAK
            - LVL
            - LBP
            - LSL
            - LRD
            - LYD
            - LTL
            - MGA
            - MKD
            - MOP
            - MWK
            - MVR
            - MRU
            - MXN
            - MYR
            - MUR
            - MDL
            - MAD
            - MNT
            - MZN
            - NAD
            - NPR
            - ANG
            - NZD
            - NIO
            - NGN
            - NOK
            - OMR
            - PAB
            - PKR
            - PGK
            - PYG
            - PEN
            - PHP
            - PLN
            - QAR
            - RON
            - RUB
            - RWF
            - WST
            - SHP
            - SAR
            - RSD
            - SCR
            - SLL
            - SGD
            - SDG
            - SOS
            - SYP
            - ZAR
            - KRW
            - SSP
            - SBD
            - LKR
            - SRD
            - SZL
            - SEK
            - CHF
            - TWD
            - THB
            - TJS
            - TZS
            - TOP
            - TTD
            - TND
            - TRY
            - TMT
            - UGX
            - UAH
            - AED
            - UYU
            - UZS
            - VUV
            - VES
            - VND
            - XOF
            - YER
            - ZMW
            - USDC
            - BYR
            - STD
            - STN
            - VED
            - VEF
            - XXX
            - $UNKNOWN
    Discount:
      type: object
      properties:
        get__typename:
          type: string
    DiscountAllocation:
      type: object
      properties:
        get__typename:
          type: string
        amount:
          $ref: '#/components/schemas/Amount'
        discount:
          $ref: '#/components/schemas/Discount'
    Discounts:
      type: object
      properties:
        get__typename:
          type: string
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/Node2'
        pageInfo:
          $ref: '#/components/schemas/PageInfo2'
    FulfillmentOrders:
      type: object
      properties:
        get__typename:
          type: string
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/Node1'
        pageInfo:
          $ref: '#/components/schemas/PageInfo1'
    Instrument:
      type: object
      properties:
        get__typename:
          type: string
    LineDiscountedPrice:
      type: object
      properties:
        get__typename:
          type: string
        amount:
          type: object
        currencyCode:
          type: string
          enum:
            - USD
            - EUR
            - GBP
            - CAD
            - AFN
            - ALL
            - DZD
            - AOA
            - ARS
            - AMD
            - AWG
            - AUD
            - BBD
            - AZN
            - BDT
            - BSD
            - BHD
            - BIF
            - BYN
            - BZD
            - BMD
            - BTN
            - BAM
            - BRL
            - BOB
            - BWP
            - BND
            - BGN
            - MMK
            - KHR
            - CVE
            - KYD
            - XAF
            - CLP
            - CNY
            - COP
            - KMF
            - CDF
            - CRC
            - HRK
            - CZK
            - DKK
            - DJF
            - DOP
            - XCD
            - EGP
            - ERN
            - ETB
            - FKP
            - XPF
            - FJD
            - GIP
            - GMD
            - GHS
            - GTQ
            - GYD
            - GEL
            - GNF
            - HTG
            - HNL
            - HKD
            - HUF
            - ISK
            - INR
            - IDR
            - ILS
            - IRR
            - IQD
            - JMD
            - JPY
            - JEP
            - JOD
            - KZT
            - KES
            - KID
            - KWD
            - KGS
            - LAK
            - LVL
            - LBP
            - LSL
            - LRD
            - LYD
            - LTL
            - MGA
            - MKD
            - MOP
            - MWK
            - MVR
            - MRU
            - MXN
            - MYR
            - MUR
            - MDL
            - MAD
            - MNT
            - MZN
            - NAD
            - NPR
            - ANG
            - NZD
            - NIO
            - NGN
            - NOK
            - OMR
            - PAB
            - PKR
            - PGK
            - PYG
            - PEN
            - PHP
            - PLN
            - QAR
            - RON
            - RUB
            - RWF
            - WST
            - SHP
            - SAR
            - RSD
            - SCR
            - SLL
            - SGD
            - SDG
            - SOS
            - SYP
            - ZAR
            - KRW
            - SSP
            - SBD
            - LKR
            - SRD
            - SZL
            - SEK
            - CHF
            - TWD
            - THB
            - TJS
            - TZS
            - TOP
            - TTD
            - TND
            - TRY
            - TMT
            - UGX
            - UAH
            - AED
            - UYU
            - UZS
            - VUV
            - VES
            - VND
            - XOF
            - YER
            - ZMW
            - USDC
            - BYR
            - STD
            - STN
            - VED
            - VEF
            - XXX
            - $UNKNOWN
    Lines:
      type: object
      properties:
        get__typename:
          type: string
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/Node'
        pageInfo:
          $ref: '#/components/schemas/PageInfo'
    Node:
      type: object
      properties:
        get__typename:
          type: string
        id:
          type: string
        sellingPlanId:
          type: string
        sellingPlanName:
          type: string
        productId:
          type: string
        sku:
          type: string
        title:
          type: string
        variantId:
          type: string
        quantity:
          type: integer
          format: int32
        customAttributes:
          type: array
          items:
            $ref: '#/components/schemas/CustomAttribute'
        lineDiscountedPrice:
          $ref: '#/components/schemas/LineDiscountedPrice'
        variantImage:
          $ref: '#/components/schemas/VariantImage'
        variantTitle:
          type: string
        currentPrice:
          $ref: '#/components/schemas/CurrentPrice'
        discountAllocations:
          type: array
          items:
            $ref: '#/components/schemas/DiscountAllocation'
        pricingPolicy:
          $ref: '#/components/schemas/PricingPolicy'
        taxable:
          type: boolean
    Node1:
      type: object
      properties:
        get__typename:
          type: string
        fulfillAt:
          type: object
        id:
          type: string
        status:
          type: string
          enum:
            - OPEN
            - IN_PROGRESS
            - CANCELLED
            - INCOMPLETE
            - CLOSED
            - SCHEDULED
            - ON_HOLD
            - $UNKNOWN
    Node2:
      type: object
      properties:
        get__typename:
          type: string
        id:
          type: string
        title:
          type: string
        value:
          $ref: '#/components/schemas/Value'
        recurringCycleLimit:
          type: integer
          format: int32
        targetType:
          type: string
          enum:
            - LINE_ITEM
            - SHIPPING_LINE
            - $UNKNOWN
        type:
          type: string
          enum:
            - MANUAL
            - CODE_DISCOUNT
            - AUTOMATIC_DISCOUNT
            - $UNKNOWN
        rejectionReason:
          type: string
          enum:
            - NOT_FOUND
            - NO_ENTITLED_LINE_ITEMS
            - QUANTITY_NOT_IN_RANGE
            - PURCHASE_NOT_IN_RANGE
            - CUSTOMER_NOT_ELIGIBLE
            - USAGE_LIMIT_REACHED
            - CUSTOMER_USAGE_LIMIT_REACHED
            - CURRENTLY_INACTIVE
            - NO_ENTITLED_SHIPPING_LINES
            - INCOMPATIBLE_PURCHASE_TYPE
            - INTERNAL_ERROR
            - $UNKNOWN
    Node3:
      type: object
      properties:
        get__typename:
          type: string
        completedAt:
          type: object
        createdAt:
          type: object
        id:
          type: string
        idempotencyKey:
          type: string
        ready:
          type: boolean
    OriginOrder:
      type: object
      properties:
        get__typename:
          type: string
        id:
          type: string
        name:
          type: string
        fulfillmentOrders:
          $ref: '#/components/schemas/FulfillmentOrders'
    PageInfo:
      type: object
      properties:
        get__typename:
          type: string
        hasPreviousPage:
          type: boolean
        hasNextPage:
          type: boolean
        startCursor:
          type: string
        endCursor:
          type: string
    PageInfo1:
      type: object
      properties:
        get__typename:
          type: string
        hasPreviousPage:
          type: boolean
        hasNextPage:
          type: boolean
        startCursor:
          type: string
        endCursor:
          type: string
    PageInfo2:
      type: object
      properties:
        get__typename:
          type: string
        hasPreviousPage:
          type: boolean
        hasNextPage:
          type: boolean
        startCursor:
          type: string
        endCursor:
          type: string
    PricingPolicy:
      type: object
      properties:
        get__typename:
          type: string
        basePrice:
          $ref: '#/components/schemas/BasePrice'
        cycleDiscounts:
          type: array
          items:
            $ref: '#/components/schemas/CycleDiscount'
    SubscriptionContract:
      type: object
      properties:
        get__typename:
          type: string
        id:
          type: string
        createdAt:
          type: object
        updatedAt:
          type: object
        nextBillingDate:
          type: object
        status:
          type: string
          enum:
            - ACTIVE
            - PAUSED
            - CANCELLED
            - EXPIRED
            - FAILED
            - $UNKNOWN
        deliveryPrice:
          $ref: '#/components/schemas/DeliveryPrice'
        lastPaymentStatus:
          type: string
          enum:
            - SUCCEEDED
            - FAILED
            - $UNKNOWN
        billingPolicy:
          $ref: '#/components/schemas/BillingPolicy'
        deliveryPolicy:
          $ref: '#/components/schemas/DeliveryPolicy'
        lines:
          $ref: '#/components/schemas/Lines'
        customerPaymentMethod:
          $ref: '#/components/schemas/CustomerPaymentMethod'
        deliveryMethod:
          $ref: '#/components/schemas/DeliveryMethod'
        originOrder:
          $ref: '#/components/schemas/OriginOrder'
        customer:
          $ref: '#/components/schemas/Customer'
        discounts:
          $ref: '#/components/schemas/Discounts'
        note:
          type: string
        customAttributes:
          type: array
          items:
            $ref: '#/components/schemas/CustomAttribute1'
        billingAttempts:
          $ref: '#/components/schemas/BillingAttempts'
    Value:
      type: object
      properties:
        get__typename:
          type: string
    VariantImage:
      type: object
      properties:
        get__typename:
          type: string
        transformedSrc:
          type: object
          deprecated: true
    AppstleCycle:
      type: object
      properties:
        afterCycle:
          minimum: 1
          type: integer
          description: The billing cycle number after which this pricing applies
          format: int32
          example: 3
        discountType:
          type: string
          description: Type of discount to apply in pricing cycles
          example: PERCENTAGE
          enum:
            - PERCENTAGE
            - FIXED
            - PRICE
            - SHIPPING
            - FREE_PRODUCT
            - PERCENTAGE
            - FIXED
            - PRICE
            - SHIPPING
            - FREE_PRODUCT
        value:
          type: number
          description: >-
            Discount value. For PERCENTAGE: 0-100 (e.g., 10 for 10% off). For
            FIXED: amount to subtract from price. For PRICE: new fixed price.
            For SHIPPING: shipping discount amount. For FREE_PRODUCT: not used
            (set freeVariantId or freeProductHandle instead)
          format: double
          example: 10
        freeVariantId:
          type: integer
          description: >-
            Variant ID of a free product to add when discountType is
            FREE_PRODUCT
          format: int64
          example: 42549172011164
        freeProductHandle:
          type: string
          description: >-
            Product handle of a free product to add when discountType is
            FREE_PRODUCT
          example: free-gift-product
        repeatingCycle:
          type: boolean
          description: Whether this pricing should repeat for subsequent cycles
          example: true
        repeatingNumberOfCycle:
          minimum: 1
          type: integer
          description: >-
            Number of cycles to repeat this pricing for when repeatingCycle is
            true
          format: int32
          example: 6
        preventDuplicationFreeProduct:
          type: boolean
          description: Prevent adding duplicate free products if already in cart
          example: true
      description: Custom pricing cycle configuration for subscription line items
    FrequencyInfoDTO:
      type: object
      properties:
        frequencyCount:
          type: integer
          format: int32
        frequencyInterval:
          type: string
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
        billingFrequencyCount:
          type: integer
          format: int32
        payAsYouGoPrepaidBillingFrequencyCount:
          type: integer
          format: int32
        billingFrequencyInterval:
          type: string
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
        frequencyName:
          type: string
        frequencyDescription:
          type: string
        discountOffer:
          type: number
          format: double
        discountOffer2:
          type: number
          format: double
        afterCycle1:
          type: integer
          format: int32
        afterCycle2:
          type: integer
          format: int32
        discountType:
          type: string
          enum:
            - PERCENTAGE
            - FIXED
            - PRICE
        discountType2:
          type: string
          enum:
            - PERCENTAGE
            - FIXED
            - PRICE
        discountEnabled:
          type: boolean
        discountEnabled2:
          type: boolean
        discountEnabledMasked:
          type: boolean
        discountEnabled2Masked:
          type: boolean
        id:
          type: string
        frequencyType:
          type: string
          enum:
            - ON_PURCHASE_DAY
            - ON_SPECIFIC_DAY
        specificDayValue:
          type: integer
          format: int32
        specificMonthValue:
          type: integer
          format: int32
        specificDayEnabled:
          type: boolean
        maxCycles:
          type: integer
          format: int32
        minCycles:
          type: integer
          format: int32
        cutOff:
          type: integer
          format: int32
        prepaidFlag:
          type: string
        idNew:
          type: string
        planType:
          type: string
          enum:
            - PAY_AS_YOU_GO
            - PREPAID
            - ADVANCED_PREPAID
            - PAY_AS_YOU_GO_PREPAID
        deliveryPolicyPreAnchorBehavior:
          type: string
          enum:
            - ASAP
            - NEXT
            - $UNKNOWN
        freeTrialEnabled:
          type: boolean
        freeTrialCount:
          type: integer
          format: int32
        freeTrialInterval:
          type: string
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
        memberOnly:
          type: boolean
        nonMemberOnly:
          type: boolean
        memberInclusiveTags:
          type: string
        memberExclusiveTags:
          type: string
        formFieldJson:
          type: string
        upcomingOrderEmailBuffer:
          type: integer
          format: int32
        frequencySequence:
          type: integer
          format: int32
        groupName:
          type: string
        groupId:
          type: integer
          format: int64
        repeatingCycle:
          type: boolean
        repeatingNumberOfCycle:
          type: integer
          format: int32
        keepOriginalNextBillingDateAfterTrial:
          type: boolean
        defaultSelectedPlan:
          type: boolean
        inventoryPolicyReserve:
          type: string
          enum:
            - ON_FULFILLMENT
            - ON_SALE
            - $UNKNOWN
        appstleCycles:
          type: array
          items:
            $ref: '#/components/schemas/AppstleCycle'
    ProductVariantDTO:
      type: object
      properties:
        productIds:
          type: array
          items:
            type: integer
            format: int64
        variantIds:
          type: array
          items:
            type: integer
            format: int64
        allProduct:
          type: boolean
        collectionId:
          type: string
        deleteAllProduct:
          type: boolean
        productDetails:
          type: string
        variantDetails:
          type: string
    SubscriptionGroupV2DTO:
      type: object
      properties:
        id:
          type: integer
          format: int64
        productCount:
          type: integer
          format: int64
        productVariantCount:
          type: integer
          format: int64
        subscriptionPlans:
          type: array
          items:
            $ref: '#/components/schemas/FrequencyInfoDTO'
        groupName:
          type: string
        productIds:
          type: string
        productId:
          type: string
        variantIds:
          type: string
        accessoryProductIds:
          type: string
        updateProducts:
          $ref: '#/components/schemas/ProductVariantDTO'
        deleteProducts:
          $ref: '#/components/schemas/ProductVariantDTO'
        translations:
          type: string
    AddedProductsResponseDTO:
      type: object
      properties:
        addedProductIds:
          type: array
          items:
            type: integer
            format: int64
        addedVariantIds:
          type: array
          items:
            type: integer
            format: int64
    ChangeShippingAddressVM:
      type: object
      properties:
        address1:
          type: string
        address2:
          type: string
        city:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        phone:
          type: string
        province:
          type: string
        zip:
          type: string
        country:
          type: string
        countryCode:
          type: string
        provinceCode:
          type: string
        company:
          type: string
        locationId:
          type: string
        methodType:
          type: string
    AttributeInfo:
      type: object
      properties:
        key:
          type: string
        value:
          type: string
    Problem:
      type: object
      properties:
        instance:
          type: string
          format: uri
        type:
          type: string
          format: uri
        parameters:
          type: object
          additionalProperties:
            type: object
        status:
          $ref: '#/components/schemas/StatusType'
        detail:
          type: string
        title:
          type: string
    StatusType:
      type: object
      properties:
        statusCode:
          type: integer
          format: int32
        reasonPhrase:
          type: string
    SubscriptionContractOneOffDTO:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier of the one-time product record
          format: int64
          readOnly: true
          example: 12345
        shop:
          pattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*\.myshopify\.com$
          type: string
          description: The Shopify store domain that owns this subscription
          example: example-store.myshopify.com
        billingAttemptId:
          minimum: 1
          type: integer
          description: >-
            The billing attempt ID this one-time product is associated with.
            This determines which upcoming order will include this product.
          format: int64
          example: 54321
        subscriptionContractId:
          minimum: 1
          type: integer
          description: The subscription contract ID this one-time product belongs to
          format: int64
          example: 98765
        variantId:
          minimum: 1
          type: integer
          description: The Shopify product variant ID for this one-time product
          format: int64
          example: 42549172011164
        variantHandle:
          pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
          type: string
          description: >-
            The handle/slug of the product variant for URL-friendly
            identification
          example: premium-coffee-blend-500g
        quantity:
          maximum: 999
          minimum: 1
          type: integer
          description: The quantity of this product to include in the order
          format: int32
          example: 2
        price:
          maximum: 999999.99
          minimum: 0
          type: number
          description: >-
            The price per unit of this product in the shop's base currency. This
            may include any applicable discounts.
          format: double
          example: 19.99
      description: >-
        Represents a one-time product added to a subscription contract for a
        specific billing attempt
    Attributes:
      type: object
    Cart:
      type: object
      properties:
        token:
          type: string
        note:
          type: object
        attributes:
          $ref: '#/components/schemas/Attributes'
        original_total_price:
          type: integer
          format: int64
        total_price:
          type: integer
          format: int64
        total_discount:
          type: integer
          format: int64
        total_weight:
          type: integer
          format: int64
        item_count:
          type: integer
          format: int64
        items:
          type: array
          items:
            $ref: '#/components/schemas/Item'
        requires_shipping:
          type: boolean
        currency:
          type: string
        items_subtotal_price:
          type: integer
          format: int64
        cart_level_discount_applications:
          type: array
          items:
            type: object
    DiscountCodeRequest:
      type: object
      properties:
        cart:
          $ref: '#/components/schemas/Cart'
      description: Discount Code Request
    FeaturedImage:
      type: object
      properties:
        aspect_ratio:
          type: integer
          format: int64
        alt:
          type: string
        height:
          type: integer
          format: int64
        url:
          type: string
        width:
          type: integer
          format: int64
    Item:
      type: object
      properties:
        id:
          type: integer
          format: int64
        properties:
          $ref: '#/components/schemas/Properties'
        quantity:
          type: integer
          format: int64
        variant_id:
          type: integer
          format: int64
        key:
          type: string
        title:
          type: string
        price:
          type: integer
          format: int64
        original_price:
          type: integer
          format: int64
        discounted_price:
          type: integer
          format: int64
        line_price:
          type: integer
          format: int64
        original_line_price:
          type: integer
          format: int64
        total_discount:
          type: integer
          format: int64
        discounts:
          type: array
          items:
            type: object
        sku:
          type: string
        grams:
          type: integer
          format: int64
        vendor:
          type: string
        taxable:
          type: boolean
        product_id:
          type: integer
          format: int64
        product_has_only_default_variant:
          type: boolean
        gift_card:
          type: boolean
        final_price:
          type: integer
          format: int64
        final_line_price:
          type: integer
          format: int64
        url:
          type: string
        featured_image:
          $ref: '#/components/schemas/FeaturedImage'
        image:
          type: string
        handle:
          type: string
        requires_shipping:
          type: boolean
        product_type:
          type: string
        product_title:
          type: string
        product_description:
          type: string
        variant_title:
          type: object
        variant_options:
          type: array
          items:
            type: string
        options_with_values:
          type: array
          items:
            $ref: '#/components/schemas/OptionsWithValue'
        line_level_discount_allocations:
          type: array
          items:
            type: object
        line_level_total_discount:
          type: integer
          format: int64
    OptionsWithValue:
      type: object
      properties:
        name:
          type: string
        value:
          type: string
    Properties:
      type: object
    DiscountCodeResponse:
      type: object
      properties:
        discountCode:
          type: string
        errorMessage:
          type: string
        discountNeeded:
          type: boolean
        discountAmount:
          type: number
          format: double
    BuildABoxUpdate:
      type: object
      properties:
        babHandle:
          type: string
        sourceProducts:
          type: array
          items:
            $ref: '#/components/schemas/SourceProductDTO'
    SourceProductDTO:
      type: object
      properties:
        sourceProductId:
          type: integer
          format: int64
        addSubProductIds:
          type: array
          items:
            type: integer
            format: int64
        addSubVariantIds:
          type: array
          items:
            type: integer
            format: int64
        deleteSubProductIds:
          type: array
          items:
            type: integer
            format: int64
        deleteSubVariantIds:
          type: array
          items:
            type: integer
            format: int64
    SubscriptionBundlingDTO:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        subscriptionBundlingEnabled:
          type: boolean
        subscriptionId:
          type: integer
          format: int64
        minProductCount:
          type: integer
          format: int32
        maxProductCount:
          type: integer
          format: int32
        discount:
          type: number
          format: double
        uniqueRef:
          type: string
        groupName:
          type: string
        subscriptionBundleLink:
          type: string
        bundleRedirect:
          type: string
          enum:
            - CART
            - CHECKOUT
            - CUSTOM
            - NONE
        customRedirectURL:
          type: string
        minOrderAmount:
          type: number
          format: double
        tieredDiscount:
          type: string
        productViewStyle:
          type: string
          enum:
            - QUICK_ADD
            - VIEW_DETAILS
        buildABoxType:
          type: string
          enum:
            - CLASSIC
            - SINGLE_PRODUCT
            - MIX_AND_MATCH
            - INFINITE
            - CUSTOMIZE_BUNDLE
            - CLASSIC_BUILD_A_BOX
            - SINGLE_PRODUCT_BUILD_A_BOX
            - VOLUME_DISCOUNT
            - DISCOUNTED_PRICING
            - SHIPPING_DISCOUNT
            - BUY_X_GET_Y
            - SECTIONED_BUNDLE
        singleProductSettings:
          type: string
        subscriptionGroup:
          type: string
        bundleTopHtml:
          type: string
        bundleBottomHtml:
          type: string
        proceedToCheckoutButtonText:
          type: string
        chooseProductsText:
          type: string
        name:
          type: string
        trackInventory:
          type: boolean
        allowOneTimePurchase:
          type: boolean
        thirdPartyRule:
          type: boolean
        selectionType:
          type: string
          enum:
            - FIXED
            - FLEXIBLE
        variants:
          type: string
        discountedVariants:
          type: string
        sections:
          type: string
        appliesOn:
          type: string
          enum:
            - PRODUCT
            - COLLECTION
            - BOTH
            - ONE_TIME
            - SUBSCRIPTION
        productDiscountType:
          type: string
          enum:
            - SELECTED_PRODUCT
            - EACH_PRODUCT
        collectionData:
          type: string
        productSelectionType:
          type: string
          enum:
            - PRODUCT
            - COLLECTION
        sellingPlanIds:
          type: string
        minUniqueProductCheck:
          type: boolean
    SubscriptionBillingAttemptDTO:
      required:
        - retryingNeeded
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        billingAttemptId:
          type: string
        status:
          type: string
          enum:
            - SUCCESS
            - FAILURE
            - REQUESTING
            - PROGRESS
            - QUEUED
            - SKIPPED
            - SOCIAL_CONNECTION_NULL
            - CONTRACT_CANCELLED
            - CONTRACT_ENDED
            - CONTRACT_PAUSED
            - AUTO_CHARGE_DISABLED
            - SHOPIFY_EXCEPTION
            - SKIPPED_DUNNING_MGMT
            - SKIPPED_INVENTORY_MGMT
            - IMMEDIATE_TRIGGERED
            - SECURITY_CHALLENGE
            - CONTRACT_PAUSED_MAX_CYCLES
            - REFUNDED
            - SKIPPED_DEMO_SHOP
            - SKIPPED_SHOP_INFO_NOT_FOUND
            - SKIPPED_BILLING_DATE_STALE
            - SKIPPED_DUNNING_NOT_CONFIGURED
        billingDate:
          type: string
          format: date-time
        contractId:
          type: integer
          format: int64
        attemptCount:
          type: integer
          format: int32
        attemptTime:
          type: string
          format: date-time
        graphOrderId:
          type: string
        orderId:
          type: integer
          format: int64
        orderAmount:
          type: number
          format: double
        orderName:
          type: string
        retryingNeeded:
          type: boolean
        transactionFailedEmailSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - EMAIL_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_CANCELLED
        upcomingOrderEmailSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - EMAIL_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_CANCELLED
            - STOP_FROM_CONTRACT
            - CONTRACT_PAUSED
        applyUsageCharge:
          type: boolean
        recurringChargeId:
          type: integer
          format: int64
        transactionRate:
          type: number
          format: double
        usageChargeStatus:
          type: string
          enum:
            - SUCCESS
            - FAILED
            - TO_BE_TRIED
        transactionFailedSmsSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - SMS_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_CANCELLED
            - PHONE_NUMBER_EMPTY
        upcomingOrderSmsSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - SMS_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_CANCELLED
            - STOP_FROM_CONTRACT
            - CONTRACT_PAUSED
            - PHONE_NUMBER_EMPTY
        billingAttemptResponseMessage:
          type: string
        progressAttemptCount:
          type: integer
          format: int32
        orderNote:
          type: string
        variantList:
          type: array
          items:
            $ref: '#/components/schemas/VariantQuantity'
        securityChallengeSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - EMAIL_SETTINGS_DISABLED
            - CONTRACT_CANCELLED
        orderAmountUSD:
          type: number
          format: double
        orderCancelReason:
          type: string
          enum:
            - CUSTOMER
            - DECLINED
            - FRAUD
            - INVENTORY
            - STAFF
            - OTHER
            - $UNKNOWN
        orderCancelledAt:
          type: string
          format: date-time
        orderClosed:
          type: boolean
        orderClosedAt:
          type: string
          format: date-time
        orderConfirmed:
          type: boolean
        orderDisplayFinancialStatus:
          type: string
          enum:
            - PENDING
            - AUTHORIZED
            - PARTIALLY_PAID
            - PARTIALLY_REFUNDED
            - VOIDED
            - PAID
            - REFUNDED
            - EXPIRED
            - $UNKNOWN
        orderDisplayFulfillmentStatus:
          type: string
          enum:
            - UNFULFILLED
            - PARTIALLY_FULFILLED
            - FULFILLED
            - RESTOCKED
            - PENDING_FULFILLMENT
            - OPEN
            - IN_PROGRESS
            - ON_HOLD
            - SCHEDULED
            - REQUEST_DECLINED
            - $UNKNOWN
        orderProcessedAt:
          type: string
          format: date-time
        lastShippingUpdatedAt:
          type: string
          format: date-time
        inventorySkippedAttemptCount:
          type: integer
          format: int32
        inventorySkippedRetryingNeeded:
          type: boolean
        orderAttributes:
          type: array
          items:
            $ref: '#/components/schemas/AttributeInfo'
        partialLinesSkipped:
          type: string
          enum:
            - INVENTORY_MANAGEMENT
            - MANUAL
        orderAmountContractCurrency:
          type: number
          format: double
    VariantQuantity:
      type: object
      properties:
        variantId:
          type: integer
          format: int64
        quantity:
          type: integer
          format: int32
        title:
          type: string
        image:
          type: string
        productTitle:
          type: string
        productId:
          type: string
        variantTitle:
          type: string
        swapId:
          type: integer
          format: int64
    ProductSwapDTO:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        sourceVariants:
          type: string
        destinationVariants:
          type: string
        updatedFirstOrder:
          type: boolean
        checkForEveryRecurringOrder:
          type: boolean
        name:
          type: string
        changeNextOrderDateBy:
          type: integer
          format: int32
        forBillingCycle:
          type: integer
          format: int32
        carryDiscountForward:
          type: boolean
        ruleSequence:
          type: integer
          format: int32
        stopSwapEmails:
          type: boolean
        discountCarryForward:
          type: string
          enum:
            - NONE
            - EXISTING_PLAN
            - PRODUCT_PLAN
            - PRODUCT_THEN_EXISTING
    OrderNoteAttribute:
      required:
        - key
      type: object
      properties:
        key:
          type: string
          description: >-
            The attribute key. Should be a unique identifier for this attribute.
            Use descriptive keys like 'gift_message', 'delivery_instructions',
            etc.
          example: gift_message
        value:
          type: string
          description: >-
            The attribute value. Can be any string value including JSON-encoded
            data. Set to empty string to clear an attribute.
          example: Happy Birthday! Enjoy your subscription!
      description: A custom attribute consisting of a key and value
    UpdateAttributesRequest:
      required:
        - customAttributesList
        - subscriptionContractId
      type: object
      properties:
        subscriptionContractId:
          type: integer
          description: The ID of the subscription contract to update
          format: int64
          example: 123456789
        customAttributesList:
          type: array
          description: >-
            List of custom attributes to set on the subscription contract. Each
            attribute is a key-value pair that will be stored with the
            subscription.
          items:
            $ref: '#/components/schemas/OrderNoteAttribute'
      description: Request to update custom attributes on a subscription contract
    BulkAddProductsRequest:
      type: object
      properties:
        productIds:
          type: array
          items:
            type: integer
            format: int64
        variantIds:
          type: array
          items:
            type: integer
            format: int64
    ReplaceVariantsInfoV3:
      required:
        - contractId
        - shop
      type: object
      properties:
        shop:
          type: string
          description: The Shop of the subscription contract to modify
          example: abcStore.myshopify.com
        contractId:
          type: integer
          description: The ID of the subscription contract to modify
          format: int64
          example: 123456789
        oldVariants:
          type: array
          description: >-
            List of variant IDs to remove from the subscription. These are
            numeric Shopify variant IDs. Either provide oldVariants OR
            oldLineId, not both.
          example:
            - 42549172011164
            - 42549172022222
          items:
            type: integer
            description: >-
              List of variant IDs to remove from the subscription. These are
              numeric Shopify variant IDs. Either provide oldVariants OR
              oldLineId, not both.
            format: int64
        newVariants:
          type: object
          additionalProperties:
            type: integer
            description: >-
              Map of new variant IDs to their quantities. Key is the numeric
              Shopify variant ID, value is the desired quantity. If a variant
              already exists in the subscription and the system is configured to
              update existing quantities, the quantity will be added to the
              existing quantity.
            format: int32
          description: >-
            Map of new variant IDs to their quantities. Key is the numeric
            Shopify variant ID, value is the desired quantity. If a variant
            already exists in the subscription and the system is configured to
            update existing quantities, the quantity will be added to the
            existing quantity.
          example:
            '42549172033333': 2
            '42549172044444': 1
        newOneTimeVariants:
          type: object
          additionalProperties:
            type: integer
            description: >-
              Map of one-time product variant IDs to add with their quantities.
              These products will be charged only once with the next order and
              won't recur. Useful for add-ons, samples, or limited-time offers.
            format: int32
          description: >-
            Map of one-time product variant IDs to add with their quantities.
            These products will be charged only once with the next order and
            won't recur. Useful for add-ons, samples, or limited-time offers.
          example:
            '42549172066666': 1
            '42549172077777': 2
        oldOneTimeVariants:
          type: array
          description: >-
            List of one-time product variant IDs to remove from the
            subscription. Only removes one-time products that haven't been
            fulfilled yet.
          example:
            - 42549172055555
            - 42549172088888
          items:
            type: integer
            description: >-
              List of one-time product variant IDs to remove from the
              subscription. Only removes one-time products that haven't been
              fulfilled yet.
            format: int64
        oldLineId:
          type: string
          description: >-
            Specific subscription line ID to replace. Use this for targeted
            replacement of a single line item. When provided, oldVariants should
            be empty. Format: gid://shopify/SubscriptionLine/[ID]
          example: gid://shopify/SubscriptionLine/987654321
        eventSource:
          type: string
          enum:
            - CUSTOMER_PORTAL
            - MERCHANT_PORTAL
            - SHOPIFY_EVENT
            - SYSTEM_EVENT
            - MERCHANT_PORTAL_BULK_AUTOMATION
            - MERCHANT_EXTERNAL_API
            - SHOPIFY_FLOW
        carryForwardDiscount:
          type: string
          description: >-
            Determines how discounts are applied to new products when replacing
            variants. If not specified, uses the merchant's default setting.
          example: PRODUCT_THEN_EXISTING
          enum:
            - NONE
            - EXISTING_PLAN
            - PRODUCT_PLAN
            - PRODUCT_THEN_EXISTING
            - PRODUCT_THEN_EXISTING
            - PRODUCT_PLAN
            - EXISTING_PLAN
        stopSwapEmails:
          type: boolean
          description: >-
            If true, suppresses email notifications about the product swap.
            Default is false (emails will be sent).
          example: false
          default: false
      description: >-
        Product replacement configuration for subscription contracts. Allows
        replacing existing subscription products with new ones, managing
        quantities, and handling one-time purchases.
    AttributeInput:
      type: object
      description: Custom attributes to attach to the subscription contract
      example:
        - key: subscription_type
          value: premium
        - key: gift_message
          value: Happy Birthday!
    SubscriptionContractDTO:
      required:
        - billingIntervalCount
        - billingIntervalType
        - customerId
        - deliveryAddress1
        - deliveryCity
        - deliveryCountryCode
        - lines
        - nextBillingDate
        - status
      type: object
      properties:
        customerId:
          type: string
          description: Shopify customer ID (numeric ID without gid prefix)
          example: '987654321'
        paymentMethodId:
          type: string
          description: >-
            Customer payment method ID. If not provided, the default payment
            method will be used. Can be null if createWithoutPaymentMethod is
            true.
          example: gid://shopify/CustomerPaymentMethod/abc123
        createWithoutPaymentMethod:
          type: boolean
          description: >-
            If true, creates subscription without payment method. Status will be
            set to PAUSED. Charges cannot be processed until a valid payment
            method is added.
          example: false
          default: false
        status:
          type: string
          description: Initial status of the subscription contract
          example: ACTIVE
          enum:
            - ACTIVE
            - PAUSED
            - CANCELLED
            - EXPIRED
            - FAILED
            - $UNKNOWN
            - ACTIVE
            - PAUSED
            - CANCELLED
            - EXPIRED
            - FAILED
        nextBillingDate:
          type: string
          description: Date when the next billing/order will occur
          format: date-time
          example: '2024-02-01T00:00:00Z'
        billingIntervalType:
          type: string
          description: Billing frequency interval type
          example: MONTH
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
            - $UNKNOWN
            - DAY
            - WEEK
            - MONTH
            - YEAR
        billingIntervalCount:
          minimum: 1
          type: integer
          description: Number of intervals between billings
          format: int32
          example: 1
        maxCycles:
          minimum: 1
          type: integer
          description: Maximum number of billing cycles. Null for unlimited
          format: int32
          example: 12
        minCycles:
          minimum: 1
          type: integer
          description: >-
            Minimum number of billing cycles required before cancellation is
            allowed
          format: int32
          example: 3
        deliveryIntervalType:
          type: string
          description: >-
            Delivery frequency interval type. If not specified, uses billing
            interval
          example: MONTH
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
            - $UNKNOWN
            - DAY
            - WEEK
            - MONTH
            - YEAR
        deliveryIntervalCount:
          minimum: 1
          type: integer
          description: >-
            Number of intervals between deliveries. If not specified, uses
            billing interval count
          format: int32
          example: 1
        deliveryFirstName:
          type: string
          description: Delivery address first name
          example: John
        deliveryLastName:
          type: string
          description: Delivery address last name
          example: Doe
        deliveryAddress1:
          type: string
          description: Delivery address line 1
          example: 123 Main St
        deliveryAddress2:
          type: string
          description: Delivery address line 2
          example: Apt 4B
        deliveryProvinceCode:
          type: string
          description: Delivery address province/state code (ISO 3166-2)
          example: NY
        deliveryCity:
          type: string
          description: Delivery address city
          example: New York
        deliveryZip:
          type: string
          description: Delivery address postal/zip code
          example: '10001'
        deliveryCountryCode:
          type: string
          description: Delivery address country code (ISO 3166-1 alpha-2)
          example: US
        deliveryPhone:
          type: string
          description: Delivery phone number
          example: '+1234567890'
        deliveryPriceAmount:
          type: number
          description: Fixed delivery price amount in store currency
          format: double
          example: 5.99
        currencyCode:
          type: string
          description: >-
            Currency code for the subscription (ISO 4217). If not provided, uses
            store default currency
          example: USD
        lines:
          type: array
          description: Product line items to include in the subscription
          items:
            $ref: '#/components/schemas/SubscriptionContractLineDTO'
        allowDeliveryAddressOverride:
          type: boolean
          description: Allow customer to change delivery address in customer portal
          example: false
          default: false
        allowDeliveryPriceOverride:
          type: boolean
          description: Allow delivery price to be overridden
          example: false
          default: false
        customAttributes:
          $ref: '#/components/schemas/AttributeInput'
      description: Request object for creating a new subscription contract
    SubscriptionContractLineDTO:
      required:
        - quantity
        - variantId
      type: object
      properties:
        quantity:
          minimum: 1
          type: integer
          description: Quantity of the product variant
          format: int32
          example: 2
        variantId:
          type: string
          description: Shopify product variant ID (numeric ID without gid prefix)
          example: '42549172011164'
        productId:
          type: string
          description: Shopify product ID (numeric ID without gid prefix)
          example: '7234567890123'
        sellingPlanId:
          type: string
          description: >-
            Selling plan ID to apply to this line item. Required for
            subscription pricing
          example: gid://shopify/SellingPlan/123456
        currentPrice:
          type: number
          description: >-
            Current price per unit after discounts. If not provided, calculated
            from selling plan
          format: double
          example: 25.99
        unitPrice:
          type: number
          description: Base price per unit before any discounts
          format: double
          example: 29.99
        customAttributes:
          type: array
          description: Custom attributes for this line item
          example:
            - key: engraving
              value: Happy Birthday
          items:
            $ref: '#/components/schemas/AttributeInput'
        linePricingPolicy:
          type: string
          description: Pricing policy type for subscription line items
          example: SELLING_PLAN_PRICING_POLICY
          enum:
            - SELLING_PLAN_PRICING_POLICY
            - CUSTOM_PRICING_POLICY
            - NO_PRICING_POLICY
        pricingPolicy:
          type: array
          description: >-
            Custom pricing policy cycles when linePricingPolicy is
            CUSTOM_PRICING_POLICY
          items:
            $ref: '#/components/schemas/AppstleCycle'
      description: Product line item for subscription contract
    VariantQuantityInfo:
      type: object
      properties:
        variantQuantityList:
          type: array
          items:
            $ref: '#/components/schemas/VariantQuantity'
    CountryInfoV3:
      type: object
      properties:
        value:
          type: string
        label:
          type: string
        includeAllProvinces:
          type: boolean
        provinces:
          type: array
          items:
            $ref: '#/components/schemas/Province'
    CreateShippingProfileRequestV3:
      type: object
      properties:
        name:
          type: string
        sellingPlanGroups:
          type: array
          items:
            $ref: '#/components/schemas/SellingPlanGroupInfo'
        locations:
          type: array
          items:
            $ref: '#/components/schemas/LocationInfoV3'
        zones:
          type: array
          items:
            $ref: '#/components/schemas/ZoneInfo'
        id:
          type: string
        profileId:
          type: integer
          format: int64
        locationInfos:
          type: array
          items:
            $ref: '#/components/schemas/LocationInfoV3'
    DeliveryMethodInfoV3:
      type: object
      properties:
        name:
          type: string
        amount:
          type: number
          format: double
        deliveryConditionType:
          type: string
        currencyCode:
          type: string
          enum:
            - USD
            - EUR
            - GBP
            - CAD
            - AFN
            - ALL
            - DZD
            - AOA
            - ARS
            - AMD
            - AWG
            - AUD
            - BBD
            - AZN
            - BDT
            - BSD
            - BHD
            - BIF
            - BYN
            - BZD
            - BMD
            - BTN
            - BAM
            - BRL
            - BOB
            - BWP
            - BND
            - BGN
            - MMK
            - KHR
            - CVE
            - KYD
            - XAF
            - CLP
            - CNY
            - COP
            - KMF
            - CDF
            - CRC
            - HRK
            - CZK
            - DKK
            - DJF
            - DOP
            - XCD
            - EGP
            - ERN
            - ETB
            - FKP
            - XPF
            - FJD
            - GIP
            - GMD
            - GHS
            - GTQ
            - GYD
            - GEL
            - GNF
            - HTG
            - HNL
            - HKD
            - HUF
            - ISK
            - INR
            - IDR
            - ILS
            - IRR
            - IQD
            - JMD
            - JPY
            - JEP
            - JOD
            - KZT
            - KES
            - KID
            - KWD
            - KGS
            - LAK
            - LVL
            - LBP
            - LSL
            - LRD
            - LYD
            - LTL
            - MGA
            - MKD
            - MOP
            - MWK
            - MVR
            - MRU
            - MXN
            - MYR
            - MUR
            - MDL
            - MAD
            - MNT
            - MZN
            - NAD
            - NPR
            - ANG
            - NZD
            - NIO
            - NGN
            - NOK
            - OMR
            - PAB
            - PKR
            - PGK
            - PYG
            - PEN
            - PHP
            - PLN
            - QAR
            - RON
            - RUB
            - RWF
            - WST
            - SHP
            - SAR
            - RSD
            - SCR
            - SLL
            - SGD
            - SDG
            - SOS
            - SYP
            - ZAR
            - KRW
            - SSP
            - SBD
            - LKR
            - SRD
            - SZL
            - SEK
            - CHF
            - TWD
            - THB
            - TJS
            - TZS
            - TOP
            - TTD
            - TND
            - TRY
            - TMT
            - UGX
            - UAH
            - AED
            - UYU
            - UZS
            - VUV
            - VES
            - VND
            - XOF
            - YER
            - ZMW
            - USDC
            - BYR
            - STD
            - STN
            - VED
            - VEF
            - XXX
            - $UNKNOWN
        minValue:
          type: number
          format: double
        maxValue:
          type: number
          format: double
        weightUnit:
          type: string
        definitionType:
          type: string
        carrierServiceId:
          type: string
        carrierPercentageFee:
          type: number
          format: double
        carrierFixedFee:
          type: number
          format: double
    LocationInfoV3:
      type: object
      properties:
        label:
          type: string
        value:
          type: string
    Province:
      type: object
      properties:
        label:
          type: string
        value:
          type: string
    SellingPlanGroupInfo:
      type: object
      properties:
        label:
          type: string
        value:
          type: string
    ZoneInfo:
      type: object
      properties:
        countries:
          type: array
          items:
            $ref: '#/components/schemas/CountryInfoV3'
        restOfWorld:
          type: boolean
        deliveryMethods:
          type: array
          items:
            $ref: '#/components/schemas/DeliveryMethodInfoV3'
    CountryInfo:
      type: object
      properties:
        shouldIncludeAllProvince:
          type: boolean
        code:
          type: string
        deliveryMethodInfo:
          type: array
          items:
            $ref: '#/components/schemas/DeliveryMethodInfo'
        restOfWorld:
          type: boolean
        provinceCode:
          type: string
    CreateShippingProfileRequestV2:
      type: object
      properties:
        name:
          type: string
        locationInfos:
          type: array
          items:
            $ref: '#/components/schemas/LocationInfo'
        id:
          type: string
      description: Shipping Profile Request View Modelf
    DeliveryMethodInfo:
      type: object
      properties:
        amount:
          type: number
          format: double
        currencyCode:
          type: string
          enum:
            - USD
            - EUR
            - GBP
            - CAD
            - AFN
            - ALL
            - DZD
            - AOA
            - ARS
            - AMD
            - AWG
            - AUD
            - BBD
            - AZN
            - BDT
            - BSD
            - BHD
            - BIF
            - BYN
            - BZD
            - BMD
            - BTN
            - BAM
            - BRL
            - BOB
            - BWP
            - BND
            - BGN
            - MMK
            - KHR
            - CVE
            - KYD
            - XAF
            - CLP
            - CNY
            - COP
            - KMF
            - CDF
            - CRC
            - HRK
            - CZK
            - DKK
            - DJF
            - DOP
            - XCD
            - EGP
            - ERN
            - ETB
            - FKP
            - XPF
            - FJD
            - GIP
            - GMD
            - GHS
            - GTQ
            - GYD
            - GEL
            - GNF
            - HTG
            - HNL
            - HKD
            - HUF
            - ISK
            - INR
            - IDR
            - ILS
            - IRR
            - IQD
            - JMD
            - JPY
            - JEP
            - JOD
            - KZT
            - KES
            - KID
            - KWD
            - KGS
            - LAK
            - LVL
            - LBP
            - LSL
            - LRD
            - LYD
            - LTL
            - MGA
            - MKD
            - MOP
            - MWK
            - MVR
            - MRU
            - MXN
            - MYR
            - MUR
            - MDL
            - MAD
            - MNT
            - MZN
            - NAD
            - NPR
            - ANG
            - NZD
            - NIO
            - NGN
            - NOK
            - OMR
            - PAB
            - PKR
            - PGK
            - PYG
            - PEN
            - PHP
            - PLN
            - QAR
            - RON
            - RUB
            - RWF
            - WST
            - SHP
            - SAR
            - RSD
            - SCR
            - SLL
            - SGD
            - SDG
            - SOS
            - SYP
            - ZAR
            - KRW
            - SSP
            - SBD
            - LKR
            - SRD
            - SZL
            - SEK
            - CHF
            - TWD
            - THB
            - TJS
            - TZS
            - TOP
            - TTD
            - TND
            - TRY
            - TMT
            - UGX
            - UAH
            - AED
            - UYU
            - UZS
            - VUV
            - VES
            - VND
            - XOF
            - YER
            - ZMW
            - USDC
            - BYR
            - STD
            - STN
            - VED
            - VEF
            - XXX
            - $UNKNOWN
        carrierServiceId:
          type: string
        name:
          type: string
        carrierRate:
          type: boolean
        deliveryConditionType:
          type: string
        priceConditions:
          type: array
          items:
            $ref: '#/components/schemas/PriceCondition'
        weightConditions:
          type: array
          items:
            $ref: '#/components/schemas/WeightCondition'
    LocationInfo:
      type: object
      properties:
        locationId:
          type: string
        countryInfos:
          type: array
          items:
            $ref: '#/components/schemas/CountryInfo'
    PriceCondition:
      type: object
      properties:
        amount:
          type: number
          format: double
        deliverCondtion:
          type: string
    WeightCondition:
      type: object
      properties:
        deliveryCondition:
          type: string
        weight:
          type: number
          format: double
        weightUnit:
          type: string
    DeliveryProfileDTO:
      required:
        - deliveryProfileId
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        deliveryProfileId:
          type: string
        sellerGroupIds:
          uniqueItems: true
          type: array
          items:
            type: string
        name:
          type: string
    CreateShippingProfileRequestVM:
      type: object
      properties:
        name:
          type: string
        id:
          type: integer
          format: int64
        deliveryMethodInfo:
          type: array
          items:
            $ref: '#/components/schemas/DeliveryMethodInfo'
        countryInfos:
          type: array
          items:
            $ref: '#/components/schemas/DeliveryCountryInfo'
        locationInfos:
          type: array
          items:
            $ref: '#/components/schemas/LocationInfo'
        restOfWorld:
          type: boolean
      description: Shipping Profile Request View Model
    DeliveryCountryInfo:
      type: object
      properties:
        code:
          type: string
        restOfWorld:
          type: boolean
        provinceCode:
          type: string
        shouldIncludeAllProvince:
          type: boolean
    SubscriptionContractIdsWrapper:
      type: object
      properties:
        subscriptionIds:
          type: string
    SubscriptionGroupDTO:
      type: object
      properties:
        id:
          type: integer
          format: int64
        productCount:
          type: integer
          format: int64
        productVariantCount:
          type: integer
          format: int64
        frequencyCount:
          type: integer
          format: int32
        frequencyInterval:
          type: string
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
        frequencyName:
          type: string
        groupName:
          type: string
        productIds:
          type: string
        discountOffer:
          type: number
          format: double
        discountType:
          type: string
          enum:
            - PERCENTAGE
            - FIXED
            - PRICE
        discountEnabled:
          type: boolean
    SubscriptionContractDetailsDTO:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        graphSubscriptionContractId:
          type: string
        subscriptionContractId:
          type: integer
          format: int64
        billingPolicyInterval:
          type: string
        billingPolicyIntervalCount:
          type: integer
          format: int32
        currencyCode:
          type: string
        customerId:
          type: integer
          format: int64
        graphCustomerId:
          type: string
        deliveryPolicyInterval:
          type: string
        deliveryPolicyIntervalCount:
          type: integer
          format: int32
        status:
          type: string
        graphOrderId:
          type: string
        orderId:
          type: integer
          format: int64
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        nextBillingDate:
          type: string
          format: date-time
        orderAmount:
          type: number
          format: double
        orderName:
          type: string
        customerName:
          type: string
        customerEmail:
          type: string
        subscriptionCreatedEmailSent:
          type: boolean
        endsAt:
          type: string
          format: date-time
        startsAt:
          type: string
          format: date-time
        subscriptionCreatedEmailSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - EMAIL_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_PAUSED_STATUS
        minCycles:
          type: integer
          format: int32
        maxCycles:
          type: integer
          format: int32
        customerFirstName:
          type: string
        customerLastName:
          type: string
        autoCharge:
          type: boolean
        importedId:
          type: string
        stopUpComingOrderEmail:
          type: boolean
        pausedFromActive:
          type: boolean
        subscriptionCreatedSmsSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - SMS_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_PAUSED_STATUS
            - PHONE_NUMBER_EMPTY
        phone:
          type: string
        activatedOn:
          type: string
          format: date-time
        pausedOn:
          type: string
          format: date-time
        cancelledOn:
          type: string
          format: date-time
        contractDetailsJSON:
          type: string
        deletedVariantIds:
          type: string
        cancellationFeedback:
          type: string
        orderNote:
          type: string
        orderNoteAttributes:
          type: string
        allowDeliveryPriceOverride:
          type: boolean
        disableFixEmptyQueue:
          type: boolean
        orderAmountUSD:
          type: number
          format: double
        originType:
          type: string
          enum:
            - STORE_FRONT
            - IMPORTED
            - SPLIT_ATTEMPT_BILLING
            - SPLIT_CONTRACT
        originalContractId:
          type: integer
          format: int64
        cancellationNote:
          type: string
        subscriptionType:
          type: string
          enum:
            - REGULAR_SUBSCRIPTION
            - BUILD_A_BOX_CLASSIC
            - BUILD_A_BOX_SINGLE_PRODUCT
            - BUNDLING_CLASSIC
            - BUNDLING_MIX_AND_MATCH
            - SECTIONED_BUNDLE
            - VOLUME_DISCOUNT
        subscriptionTypeIdentifier:
          type: string
        upcomingEmailBufferDays:
          type: integer
          format: int32
        upcomingEmailTaskUrl:
          type: string
        contractAmount:
          type: number
          format: double
        contractAmountUSD:
          type: number
          format: double
        lastSuccessfulOrder:
          type: string
        totalSuccessfulOrders:
          type: integer
          format: int32
        lifetimeValue:
          type: number
          format: double
        lifetimeValueUSD:
          type: number
          format: double
        allowDeliveryAddressOverride:
          type: boolean
        billingDateAfterTrial:
          type: string
          format: date-time
        pauseReason:
          type: string
        pauseFeedback:
          type: string
        pauseTillDate:
          type: string
          format: date-time
        pauseDurationCycle:
          type: integer
          format: int32
        emailBouncedOrFailed:
          type: boolean
        updatingQueue:
          type: boolean
        customerTag:
          type: string
        queueUpdatedAt:
          type: string
          format: date-time
        orderAmountShopCurrency:
          type: number
          format: double
        orderAmountContractCurrency:
          type: number
          format: double
        billingCountryCode:
          type: string
        deliveryCountryCode:
          type: string
    SubscriptionCustomCssDTO:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        customCss:
          type: string
        customerPoratlCSS:
          type: string
        bundlingCSS:
          type: string
        bundlingIframeCSS:
          type: string
    Pageable:
      type: object
      properties:
        page:
          minimum: 0
          type: integer
          format: int32
        size:
          minimum: 1
          type: integer
          format: int32
        sort:
          type: array
          items:
            type: string
    Order:
      type: object
      properties:
        get__typename:
          type: string
        id:
          type: string
        fulfillmentOrders:
          $ref: '#/components/schemas/FulfillmentOrders'
    PaymentMethods:
      type: object
      properties:
        get__typename:
          type: string
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/Node'
        pageInfo:
          $ref: '#/components/schemas/PageInfo'
    CustomerInfo:
      type: object
      properties:
        customerId:
          type: integer
          format: int64
        name:
          type: string
        email:
          type: string
        activeSubscriptions:
          type: integer
          format: int64
        nextOrderDate:
          type: string
          format: date-time
        inActiveSubscriptions:
          type: integer
          format: int64
        lifetimeValue:
          type: number
          format: double
    ContractAnalytics:
      type: object
      properties:
        totalOrderCount:
          type: integer
          format: int64
        totalOrderAmount:
          type: number
          format: double
        totalOrderRevenue:
          type: string
    ProductInfo:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        productId:
          type: integer
          format: int64
        productTitle:
          type: string
        productHandle:
          type: string
    SubscriptionBundling:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        subscriptionBundlingEnabled:
          type: boolean
        subscriptionId:
          type: integer
          format: int64
        minProductCount:
          type: integer
          format: int32
        maxProductCount:
          type: integer
          format: int32
        discount:
          type: number
          format: double
        uniqueRef:
          type: string
        bundleRedirect:
          type: string
          enum:
            - CART
            - CHECKOUT
            - CUSTOM
            - NONE
        customRedirectURL:
          type: string
        minOrderAmount:
          type: number
          format: double
        tieredDiscount:
          type: string
        productViewStyle:
          type: string
          enum:
            - QUICK_ADD
            - VIEW_DETAILS
        buildABoxType:
          type: string
          enum:
            - CLASSIC
            - SINGLE_PRODUCT
            - MIX_AND_MATCH
            - INFINITE
            - CUSTOMIZE_BUNDLE
            - CLASSIC_BUILD_A_BOX
            - SINGLE_PRODUCT_BUILD_A_BOX
            - VOLUME_DISCOUNT
            - DISCOUNTED_PRICING
            - SHIPPING_DISCOUNT
            - BUY_X_GET_Y
            - SECTIONED_BUNDLE
        singleProductSettings:
          type: string
        subscriptionGroup:
          type: string
        bundleTopHtml:
          type: string
        bundleBottomHtml:
          type: string
        proceedToCheckoutButtonText:
          type: string
        chooseProductsText:
          type: string
        name:
          type: string
        trackInventory:
          type: boolean
        allowOneTimePurchase:
          type: boolean
        thirdPartyRule:
          type: boolean
        selectionType:
          type: string
          enum:
            - FIXED
            - FLEXIBLE
        variants:
          type: string
        discountedVariants:
          type: string
        sections:
          type: string
        appliesOn:
          type: string
          enum:
            - PRODUCT
            - COLLECTION
            - BOTH
            - ONE_TIME
            - SUBSCRIPTION
        productDiscountType:
          type: string
          enum:
            - SELECTED_PRODUCT
            - EACH_PRODUCT
        collectionData:
          type: string
        productSelectionType:
          type: string
          enum:
            - PRODUCT
            - COLLECTION
        sellingPlanIds:
          type: string
        minUniqueProductCheck:
          type: boolean
    SubscriptionBundlingResponse:
      type: object
      properties:
        bundle:
          $ref: '#/components/schemas/SubscriptionBundling'
        subscriptions:
          type: array
          items:
            $ref: '#/components/schemas/SubscriptionGroupPlan'
        products:
          type: array
          items:
            $ref: '#/components/schemas/ProductInfo'
        variants:
          type: array
          items:
            type: string
    SubscriptionGroupPlan:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        groupName:
          type: string
        subscriptionId:
          type: integer
          format: int64
        productCount:
          type: integer
          format: int32
        productVariantCount:
          type: integer
          format: int32
        infoJson:
          type: string
        productIds:
          type: string
        variantIds:
          type: string
        variantProductIds:
          type: string
        translations:
          type: string
    SubscriptionBundleSettingsDTO:
      required:
        - addButtonText
        - myDeliveryText
        - proceedToCheckoutButtonText
        - productsToProceedText
        - selectMinimumProductButtonText
        - selectedFrequencyLabelText
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        selectedFrequencyLabelText:
          type: string
        addButtonText:
          type: string
        selectMinimumProductButtonText:
          type: string
        productsToProceedText:
          type: string
        proceedToCheckoutButtonText:
          type: string
        myDeliveryText:
          type: string
        bundleTopHtml:
          type: string
        bundleBottomHtml:
          type: string
        failedToAddTitleText:
          type: string
        okBtnText:
          type: string
        failedToAddMsgText:
          type: string
        buttonColor:
          type: string
        backgroundColor:
          type: string
        pageBackgroundColor:
          type: string
        buttonBackgroundColor:
          type: string
        variantNotAvailable:
          type: string
        bundleRedirect:
          type: string
          enum:
            - CART
            - CHECKOUT
            - CUSTOM
        isBundleWithoutScroll:
          type: boolean
        descriptionLength:
          type: integer
          format: int32
        currencySwitcherClassName:
          type: string
        productPriceFormatField:
          type: string
        customRedirectURL:
          type: string
        viewProduct:
          type: string
        productDetails:
          type: string
        editQuantity:
          type: string
        cart:
          type: string
        shoppingCart:
          type: string
        title:
          type: string
        tieredDiscount:
          type: string
        subtotal:
          type: string
        checkoutMessage:
          type: string
        continueShopping:
          type: string
        spendAmountGetDiscount:
          type: string
        buyQuantityGetDiscount:
          type: string
        removeItem:
          type: string
        showCompareAtPrice:
          type: boolean
        enableRedirectToProductPage:
          type: boolean
        disableProductDescription:
          type: boolean
        enableDisplayProductVendor:
          type: boolean
        enableDisplayProductType:
          type: boolean
        enableCustomAdvancedFields:
          type: boolean
        hideProductSearchBox:
          type: boolean
        productFilterConfig:
          type: string
        enableProductDetailButton:
          type: boolean
        enableShowProductBasePrice:
          type: boolean
        enableClearCartSelectedProducts:
          type: boolean
        enableSkieyBABHeader:
          type: boolean
        enableOpeningSidebar:
          type: boolean
        rightSidebarHTML:
          type: string
        leftSidebarHTML:
          type: string
        isMergeIntoSingleBABVariantDropdown:
          type: boolean
        enableEditQuantityTextbox:
          type: boolean
        displayUnavailableProduct:
          type: boolean
        allowAddUnavailableProduct:
          type: boolean
        showOrderNoteField:
          type: boolean
        showSubLoyaltyTable:
          type: boolean
        restrictPriceRateCalculation:
          type: boolean
        disableProductCardImageSlider:
          type: boolean
        skipFilterVariantsByAllocationsId:
          type: boolean
        openingSidebarType:
          type: string
          enum:
            - DEFAULT
            - MAX_QUANTITY
            - STOP_AUTO_OPEN
            - MIN_AMOUNT
        moveOneTimePurchaseToTop:
          type: boolean
        skipFirstPage:
          type: boolean
        congratsMessageText:
          type: string
        spentText:
          type: string
        quantityLabel:
          type: string
        variantLabelTextV2:
          type: string
        itemsText:
          type: string
        shopCustomizationData:
          type: array
          items:
            $ref: '#/components/schemas/UpdateShopCustomizationRequest'
        productTitleFontColor:
          type: string
        additionalProperty:
          type: object
          additionalProperties:
            type: object
          writeOnly: true
    UpdateShopCustomizationRequest:
      type: object
      properties:
        id:
          type: integer
          format: int64
        labelId:
          type: integer
          format: int64
        value:
          type: string
    SubscriptionBillingAttempt:
      required:
        - retryingNeeded
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        billingAttemptId:
          type: string
        status:
          type: string
          enum:
            - SUCCESS
            - FAILURE
            - REQUESTING
            - PROGRESS
            - QUEUED
            - SKIPPED
            - SOCIAL_CONNECTION_NULL
            - CONTRACT_CANCELLED
            - CONTRACT_ENDED
            - CONTRACT_PAUSED
            - AUTO_CHARGE_DISABLED
            - SHOPIFY_EXCEPTION
            - SKIPPED_DUNNING_MGMT
            - SKIPPED_INVENTORY_MGMT
            - IMMEDIATE_TRIGGERED
            - SECURITY_CHALLENGE
            - CONTRACT_PAUSED_MAX_CYCLES
            - REFUNDED
            - SKIPPED_DEMO_SHOP
            - SKIPPED_SHOP_INFO_NOT_FOUND
            - SKIPPED_BILLING_DATE_STALE
            - SKIPPED_DUNNING_NOT_CONFIGURED
        billingDate:
          type: string
          format: date-time
        contractId:
          type: integer
          format: int64
        attemptCount:
          type: integer
          format: int32
        attemptTime:
          type: string
          format: date-time
        graphOrderId:
          type: string
        orderId:
          type: integer
          format: int64
        orderAmount:
          type: number
          format: double
        orderName:
          type: string
        retryingNeeded:
          type: boolean
        transactionFailedEmailSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - EMAIL_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_CANCELLED
        upcomingOrderEmailSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - EMAIL_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_CANCELLED
            - STOP_FROM_CONTRACT
            - CONTRACT_PAUSED
        applyUsageCharge:
          type: boolean
        recurringChargeId:
          type: integer
          format: int64
        transactionRate:
          type: number
          format: double
        usageChargeStatus:
          type: string
          enum:
            - SUCCESS
            - FAILED
            - TO_BE_TRIED
        transactionFailedSmsSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - SMS_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_CANCELLED
            - PHONE_NUMBER_EMPTY
        upcomingOrderSmsSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - SMS_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_CANCELLED
            - STOP_FROM_CONTRACT
            - CONTRACT_PAUSED
            - PHONE_NUMBER_EMPTY
        billingAttemptResponseMessage:
          type: string
        progressAttemptCount:
          type: integer
          format: int32
        orderNote:
          type: string
        securityChallengeSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - EMAIL_SETTINGS_DISABLED
            - CONTRACT_CANCELLED
        orderAmountUSD:
          type: number
          format: double
        lastShippingUpdatedAt:
          type: string
          format: date-time
        inventorySkippedAttemptCount:
          type: integer
          format: int32
        inventorySkippedRetryingNeeded:
          type: boolean
        partialLinesSkipped:
          type: string
          enum:
            - INVENTORY_MANAGEMENT
            - MANUAL
        orderAmountContractCurrency:
          type: number
          format: double
    SubscriptionBillingAttemptDetails:
      type: object
      properties:
        subscriptionBillingAttempt:
          $ref: '#/components/schemas/SubscriptionBillingAttempt'
        subscriptionContractDetails:
          $ref: '#/components/schemas/SubscriptionContractDetails'
    SubscriptionContractDetails:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        graphSubscriptionContractId:
          type: string
        subscriptionContractId:
          type: integer
          format: int64
        billingPolicyInterval:
          type: string
        billingPolicyIntervalCount:
          type: integer
          format: int32
        currencyCode:
          type: string
        customerId:
          type: integer
          format: int64
        graphCustomerId:
          type: string
        deliveryPolicyInterval:
          type: string
        deliveryPolicyIntervalCount:
          type: integer
          format: int32
        status:
          type: string
        graphOrderId:
          type: string
        orderId:
          type: integer
          format: int64
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        nextBillingDate:
          type: string
          format: date-time
        orderAmount:
          type: number
          format: double
        orderName:
          type: string
        customerName:
          type: string
        customerEmail:
          type: string
        subscriptionCreatedEmailSent:
          type: boolean
        endsAt:
          type: string
          format: date-time
        startsAt:
          type: string
          format: date-time
        subscriptionCreatedEmailSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - EMAIL_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_PAUSED_STATUS
        minCycles:
          type: integer
          format: int32
        maxCycles:
          type: integer
          format: int32
        customerFirstName:
          type: string
        customerLastName:
          type: string
        autoCharge:
          type: boolean
        importedId:
          type: string
        stopUpComingOrderEmail:
          type: boolean
        pausedFromActive:
          type: boolean
        subscriptionCreatedSmsSentStatus:
          type: string
          enum:
            - SENT
            - UNSENT
            - FAILED
            - SMS_SETTINGS_DISABLED
            - CUSTOMER_PAYMENT_EMPTY
            - CONTRACT_PAUSED_STATUS
            - PHONE_NUMBER_EMPTY
        phone:
          type: string
        activatedOn:
          type: string
          format: date-time
        pausedOn:
          type: string
          format: date-time
        cancelledOn:
          type: string
          format: date-time
        contractDetailsJSON:
          type: string
        deletedVariantIds:
          type: string
        cancellationFeedback:
          type: string
        orderNote:
          type: string
        orderNoteAttributes:
          type: string
        allowDeliveryPriceOverride:
          type: boolean
        disableFixEmptyQueue:
          type: boolean
        orderAmountUSD:
          type: number
          format: double
        originType:
          type: string
          enum:
            - STORE_FRONT
            - IMPORTED
            - SPLIT_ATTEMPT_BILLING
            - SPLIT_CONTRACT
        originalContractId:
          type: integer
          format: int64
        cancellationNote:
          type: string
        subscriptionType:
          type: string
          enum:
            - REGULAR_SUBSCRIPTION
            - BUILD_A_BOX_CLASSIC
            - BUILD_A_BOX_SINGLE_PRODUCT
            - BUNDLING_CLASSIC
            - BUNDLING_MIX_AND_MATCH
            - SECTIONED_BUNDLE
            - VOLUME_DISCOUNT
        subscriptionTypeIdentifier:
          type: string
        upcomingEmailBufferDays:
          type: integer
          format: int32
        upcomingEmailTaskUrl:
          type: string
        contractAmount:
          type: number
          format: double
        contractAmountUSD:
          type: number
          format: double
        lastSuccessfulOrder:
          type: string
        totalSuccessfulOrders:
          type: integer
          format: int32
        lifetimeValue:
          type: number
          format: double
        lifetimeValueUSD:
          type: number
          format: double
        allowDeliveryAddressOverride:
          type: boolean
        billingDateAfterTrial:
          type: string
          format: date-time
        pauseReason:
          type: string
        pauseFeedback:
          type: string
        pauseTillDate:
          type: string
          format: date-time
        pauseDurationCycle:
          type: integer
          format: int32
        emailBouncedOrFailed:
          type: boolean
        updatingQueue:
          type: boolean
        customerTag:
          type: string
        queueUpdatedAt:
          type: string
          format: date-time
        orderAmountShopCurrency:
          type: number
          format: double
        orderAmountContractCurrency:
          type: number
          format: double
        billingCountryCode:
          type: string
        deliveryCountryCode:
          type: string
    TokenDetails:
      type: object
      properties:
        manageSubscriptionLink:
          type: string
        tokenExpirationTime:
          type: string
          format: date-time
    CustomerTokenInfo:
      type: object
      properties:
        customerId:
          type: integer
          format: int64
        token:
          type: string
        appstleExternalToken:
          type: string
    CustomerPortalSettingsDTO:
      required:
        - amountLbl
        - cancelAccordionTitle
        - cancelFreqBtnText
        - cancelSubscriptionBtnText
        - cardExpiryText
        - cardHolderNameText
        - cardLastFourDigitText
        - cardTypeText
        - editFrequencyBtnText
        - nextOrderDateLbl
        - nextOrderText
        - noSubscriptionMessage
        - orderFrequencyText
        - orderNoLbl
        - paymentDetailAccordionTitle
        - paymentInfoText
        - paymentMethodTypeText
        - quantityLbl
        - shop
        - statusLbl
        - statusText
        - subscriptionNoText
        - totalProductsText
        - upcomingOrderAccordionTitle
        - updateFreqBtnText
        - updatePaymentBtnText
        - updatePaymentMessage
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        orderFrequencyText:
          type: string
        totalProductsText:
          type: string
        nextOrderText:
          type: string
        statusText:
          type: string
        cancelSubscriptionBtnText:
          type: string
        noSubscriptionMessage:
          type: string
        subscriptionNoText:
          type: string
        updatePaymentMessage:
          type: string
        cardLastFourDigitText:
          type: string
        cardExpiryText:
          type: string
        cardHolderNameText:
          type: string
        cardTypeText:
          type: string
        paymentMethodTypeText:
          type: string
        cancelAccordionTitle:
          type: string
        paymentDetailAccordionTitle:
          type: string
        upcomingOrderAccordionTitle:
          type: string
        paymentInfoText:
          type: string
        updatePaymentBtnText:
          type: string
        nextOrderDateLbl:
          type: string
        statusLbl:
          type: string
        quantityLbl:
          type: string
        amountLbl:
          type: string
        orderNoLbl:
          type: string
        editFrequencyBtnText:
          type: string
        cancelFreqBtnText:
          type: string
        updateFreqBtnText:
          type: string
        pauseResumeSub:
          type: boolean
        changeNextOrderDate:
          type: boolean
        cancelSub:
          type: boolean
        changeOrderFrequency:
          type: boolean
        createAdditionalOrder:
          type: boolean
        manageSubscriptionButtonText:
          type: string
        editChangeOrderBtnText:
          type: string
        cancelChangeOrderBtnText:
          type: string
        updateChangeOrderBtnText:
          type: string
        editProductButtonText:
          type: string
        deleteButtonText:
          type: string
        updateButtonText:
          type: string
        cancelButtonText:
          type: string
        addProductButtonText:
          type: string
        addProductLabelText:
          type: string
        activeBadgeText:
          type: string
        closeBadgeText:
          type: string
        skipOrderButtonText:
          type: string
        productLabelText:
          type: string
        seeMoreDetailsText:
          type: string
        hideDetailsText:
          type: string
        productInSubscriptionText:
          type: string
        subTotalLabelText:
          type: string
        paymentNotificationText:
          type: string
        editProductFlag:
          type: boolean
        deleteProductFlag:
          type: boolean
        showShipment:
          type: boolean
        magicLinkEmailFlag:
          type: boolean
        addAdditionalProduct:
          type: boolean
        successText:
          type: string
        cancelSubscriptionConfirmPrepaidText:
          type: string
        cancelSubscriptionConfirmPayAsYouGoText:
          type: string
        cancelSubscriptionPrepaidButtonText:
          type: string
        cancelSubscriptionPayAsYouGoButtonText:
          type: string
        upcomingFulfillmentText:
          type: string
        creditCardText:
          type: string
        endingWithText:
          type: string
        weekText:
          type: string
        dayText:
          type: string
        monthText:
          type: string
        yearText:
          type: string
        skipBadgeText:
          type: string
        queueBadgeText:
          type: string
        shippingLabelText:
          type: string
        failureText:
          type: string
        sendEmailText:
          type: string
        chooseDifferentProductActionText:
          type: string
        chooseDifferentProductText:
          type: string
        confirmSkipFulfillmentBtnText:
          type: string
        confirmSkipOrder:
          type: string
        skipFulfillmentButtonText:
          type: string
        confirmCommonText:
          type: string
        orderNowDescriptionText:
          type: string
        discountDetailsTitleText:
          type: string
        emailAddressText:
          type: string
        emailMagicLinkText:
          type: string
        retriveMagicLinkText:
          type: string
        validEmailMessage:
          type: string
        saveButtonText:
          type: string
        orderDateText:
          type: string
        address1LabelText:
          type: string
        address2LabelText:
          type: string
        companyLabelText:
          type: string
        cityLabelText:
          type: string
        countryLabelText:
          type: string
        firstNameLabelText:
          type: string
        lastNameLabelText:
          type: string
        phoneLabelText:
          type: string
        provinceLabelText:
          type: string
        zipLabelText:
          type: string
        addressHeaderTitleText:
          type: string
        changeShippingAddressFlag:
          type: boolean
        updateEditShippingButtonText:
          type: string
        cancelEditShippingButtonText:
          type: string
        pauseSubscriptionText:
          type: string
        resumeSubscriptionText:
          type: string
        pauseBadgeText:
          type: string
        customerPortalSettingJson:
          type: string
        productFilterConfig:
          type: string
        discountNoteTitle:
          type: string
        initialDiscountNoteDescription:
          type: string
        afterCycleDiscountNoteDescription:
          type: string
        productRemovedTooltip:
          type: string
        deliveryPriceText:
          type: string
        shippingOptionText:
          type: string
        nextDeliveryDate:
          type: string
        everyLabelText:
          type: string
        orderNoteFlag:
          type: boolean
        orderNoteText:
          type: string
        useUrlWithCustomerId:
          type: boolean
        expiredTokenText:
          type: string
        portalLoginLinkText:
          type: string
        localeDate:
          type: string
        productSelectionOption:
          type: string
          enum:
            - ALL_PRODUCTS
            - PRODUCTS_FROM_ALL_PLANS
            - PRODUCTS_FROM_CURRENT_PLAN
        includeOutOfStockProduct:
          type: boolean
        customerIdText:
          type: string
        helloNameText:
          type: string
        goBackButtonText:
          type: string
        changeVariantLabelText:
          type: string
        provinceCodeLabelText:
          type: string
        countryCodeLabelText:
          type: string
        pleaseWaitLoaderText:
          type: string
        openBadgeText:
          type: string
        cancelSubscriptionMinimumBillingIterationsMessage:
          type: string
        topHtml:
          type: string
        bottomHtml:
          type: string
        updateShipmentBillingDate:
          type: boolean
        discountCodeText:
          type: string
        discountCodeApplyButtonText:
          type: string
        discountCode:
          type: boolean
        applySellingPlanBasedDiscount:
          type: boolean
        overrideDaysToRescheduleOrder:
          type: boolean
        applySubscriptionDiscountForOtp:
          type: boolean
        applySubscriptionDiscount:
          type: boolean
        allowSwapWhenContractIsFreeze:
          type: boolean
        removeDiscountCodeAutomatically:
          type: boolean
        removeDiscountCodeLabel:
          type: string
        enableSplitContract:
          type: boolean
        splitContractMessage:
          type: string
        splitContractText:
          type: string
        enableMergeContract:
          type: boolean
        subscriptionDiscountTypeUnit:
          type: string
          enum:
            - PERCENTAGE
            - AMOUNT
        subscriptionDiscount:
          type: number
          format: double
        upSellMessage:
          type: string
        freezeOrderTillMinCycle:
          type: boolean
        freezeUpdateSubscriptionMessage:
          type: string
        subscriptionContractFreezeMessage:
          type: string
        preventCancellationBeforeDaysMessage:
          type: string
        offerDiscountOnCancellation:
          type: boolean
        enableSkipFulFillment:
          type: boolean
        discountPercentageOnCancellation:
          type: string
        discountMessageOnCancellation:
          type: string
        discountRecurringCycleLimitOnCancellation:
          type: string
        frequencyChangeWarningTitle:
          type: string
        frequencyChangeWarningDescription:
          type: string
        discountCouponRemoveText:
          type: string
        pleaseSelectText:
          type: string
        shippingAddressNotAvailableText:
          type: string
        sellingPlanNameText:
          type: string
        discountCouponNotAppliedText:
          type: string
        shopPayPaymentUpdateText:
          type: string
        addOneTimeProduct:
          type: boolean
        allowOrderNow:
          type: boolean
        selectProductLabelText:
          type: string
        purchaseOptionLabelText:
          type: string
        finishLabelText:
          type: string
        nextBtnText:
          type: string
        previousBtnText:
          type: string
        closeBtnText:
          type: string
        deleteConfirmationMsgText:
          type: string
        deleteMsgText:
          type: string
        yesBtnText:
          type: string
        noBtnText:
          type: string
        oneTimePurchaseNoteText:
          type: string
        clickHereText:
          type: string
        productAddMessageText:
          type: string
        choosePurchaseOptionLabelText:
          type: string
        oneTimePurchaseMessageText:
          type: string
        contractUpdateMessageText:
          type: string
        oneTimePurchaseDisplayMessageText:
          type: string
        addProductFinishedMessageText:
          type: string
        contractErrorMessageText:
          type: string
        addToSubscriptionTitleCP:
          type: string
        oneTimePurchaseTitleCP:
          type: string
        seeMoreProductBtnText:
          type: string
        viewAttributeLabelText:
          type: string
        attributeNameLabelText:
          type: string
        swapProductLabelText:
          type: string
        swapProductSearchBarText:
          type: string
        enableSwapProductFeature:
          type: boolean
        enableTabletForceView:
          type: boolean
        swapProductBtnText:
          type: string
        attributeValue:
          type: string
        addNewButtonText:
          type: string
        attributeHeadingText:
          type: string
        enableViewAttributes:
          type: boolean
        enableSkipIndividualProduct:
          type: boolean
        enableEditOrderNotes:
          type: boolean
        showSellingPlanFrequencies:
          type: boolean
        totalPricePerDeliveryText:
          type: string
        fulfilledText:
          type: string
        dateFormat:
          type: string
        discountCouponAppliedText:
          type: string
        subscriptionPausedMessageText:
          type: string
        subscriptionActivatedMessageText:
          type: string
        unableToUpdateSubscriptionStatusMessageText:
          type: string
        selectCancellationReasonLabelText:
          type: string
        upcomingOrderChangePopupSuccessTitleText:
          type: string
        upcomingOrderChangePopupSuccessDescriptionText:
          type: string
        upcomingOrderChangePopupSuccessClosebtnText:
          type: string
        upcomingOrderChangePopupFailureTitleText:
          type: string
        upcomingOrderChangePopupFailureDescriptionText:
          type: string
        upcomingOrderChangePopupFailureClosebtnText:
          type: string
        variantIdsToFreezeEditRemove:
          type: string
        preventCancellationBeforeDays:
          type: string
        preventAddRemoveSwapBeforeDays:
          type: string
        allowCancellationBeforeDays:
          type: string
        allowAddRemoveSwapBeforeDays:
          type: string
        disAllowVariantIdsForOneTimeProductAdd:
          type: string
        disAllowProductIdsForOneTimeProductAdd:
          type: string
        disAllowVariantIdsForSubscriptionProductAdd:
          type: string
        allowProductIdsForSubscriptionProductAdd:
          type: string
        hideAddSubscriptionProductSection:
          type: boolean
        allowOnlyOneTimeProductOnAddProductFlag:
          type: boolean
        requireFieldMessage:
          type: string
        validNumberRequiredMessage:
          type: string
        variantLbl:
          type: string
        priceLbl:
          type: string
        oneTimePurchaseOnlyText:
          type: string
        rescheduleText:
          type: string
        popUpSuccessMessage:
          type: string
        popUpErrorMessage:
          type: string
        orderNowText:
          type: string
        upcomingOrderPlaceNowAlertText:
          type: string
        upcomingOrderSkipAlertText:
          type: string
        deliveryFrequencyText:
          type: string
        editDeliveryInternalText:
          type: string
        maxCycleText:
          type: string
        minCycleText:
          type: string
        selectProductToAdd:
          type: string
        searchProductBtnText:
          type: string
        areyousureCommonMessageText:
          type: string
        areyousureResumeMessageText:
          type: string
        areyousurePauseMessageText:
          type: string
        editCommonText:
          type: string
        viewMoreText:
          type: string
        variantLblText:
          type: string
        totalLblText:
          type: string
        deleteProductTitleText:
          type: string
        greetingText:
          type: string
        productLblText:
          type: string
        hasBeenRemovedText:
          type: string
        orderTotalText:
          type: string
        addDiscountCodeText:
          type: string
        addDiscountCodeAlertText:
          type: string
        removeDiscountCodeAlertText:
          type: string
        shopPayLblText:
          type: string
        paypalLblText:
          type: string
        unknownPaymentReachoutUsText:
          type: string
        addToOrderLabelText:
          type: string
        upcomingTabTitle:
          type: string
        scheduledTabTitle:
          type: string
        historyTabTitle:
          type: string
        noOrderNotAvailableMessage:
          type: string
        continueText:
          type: string
        confirmSwapText:
          type: string
        confirmAddProduct:
          type: string
        minQtyToAllowDuringAddProduct:
          type: integer
          format: int32
        allowSplitContract:
          type: boolean
        enableSwapProductVariant:
          type: boolean
        enableEditAttributes:
          type: boolean
        discountAccordionTitle:
          type: string
        redeemRewardsTextV2:
          type: string
        rewardsTextV2:
          type: string
        yourRewardsTextV2:
          type: string
        yourAvailableRewardsPointsTextV2:
          type: string
        cancellationDateTitleText:
          type: string
        pauseTillDateTitleText:
          type: string
        selectedCancellationReasonTitleText:
          type: string
        selectedPauseReasonTitleText:
          type: string
        cancellationNoteTitleText:
          type: string
        pauseNoteTitleText:
          type: string
        selectSplitMethodLabelText:
          type: string
        splitWithOrderPlacedSelectOptionText:
          type: string
        splitWithoutOrderPlacedSelectOptionText:
          type: string
        contractCancelledBadgeText:
          type: string
        chooseAnotherPaymentMethodTitleText:
          type: string
        selectPaymentMethodTitleText:
          type: string
        changePaymentMessage:
          type: string
        updatePaymentMethodTitleText:
          type: string
        enableRedirectMyAccountButton:
          type: boolean
        reschedulingPolicies:
          type: string
        enableRedirectToProductPage:
          type: boolean
        enableAllowOnlyOneDiscountCode:
          type: boolean
        upcomingTabHeaderHTML:
          type: string
        schedulesTabHeaderHTML:
          type: string
        historyTabHeaderHTML:
          type: string
        allowedProductIdsForOneTimeProductAdd:
          type: string
        allowToAddProductQuantityMinMaxReached:
          type: boolean
        allowReschedulingContractTrialPeriod:
          type: boolean
        allowToEditQuantityIfProductOutOfStock:
          type: boolean
        displayCountryByLanguage:
          type: boolean
        allowToEditQuantityInSingleBABProduct:
          type: boolean
        fromDeliveryDateAddDay:
          type: integer
          format: int32
        toDeliveryDateAddDay:
          type: integer
          format: int32
        showNextOrderDeliveryDate:
          type: boolean
        singleBABDeletedProductPlaceholderImage:
          type: string
        allowToSpecificZipCode:
          type: string
        allowToSpecificZipCodeForLocalDelivery:
          type: string
        customJs:
          type: string
        allowAddOneTimeProductOrderIdPrepaid:
          type: boolean
        discountMessageOnPause:
          type: string
        swapMessageOnPause:
          type: string
        giftMessageOnPause:
          type: string
        skipMessageOnPause:
          type: string
        pauseMessageOnPause:
          type: string
        changeDateMessageOnPause:
          type: string
        changeAddressMessageOnPause:
          type: string
        updateFrequencyMessageOnPause:
          type: string
        skipDaysFromCurrentDate:
          type: integer
          format: int32
        skipDaysToCurrentDate:
          type: integer
          format: int32
        goBackRedirectLink:
          type: string
        resumeSub:
          type: boolean
        allowToSameReasonAgain:
          type: boolean
        deleteOneTimePurchaseProduct:
          type: boolean
        billingDateRestrictFromDate:
          type: string
        billingDateRestrictToDays:
          type: integer
          format: int32
        multiCurrencyAvailable:
          type: boolean
        babProductBadgeTextV2:
          type: string
        addAdditionalProductInBAB:
          type: boolean
        disableRescheduleTimeSelector:
          type: boolean
        filterDeliveryFrequencyOnCustomerTags:
          type: boolean
        customerPortalLandingPage:
          type: string
        pauseAccordionTitle:
          type: string
        disabledKeyFieldFlag:
          type: boolean
        discountCarryForward:
          type: string
          enum:
            - NONE
            - EXISTING_PLAN
            - PRODUCT_PLAN
            - PRODUCT_THEN_EXISTING
        allowProductTagsForSubscriptionProductAdd:
          type: string
        disAllowProductTagsForSubscriptionProductAdd:
          type: string
        allowEditQuantityPrepaidSeparatePlan:
          type: boolean
        enableUpsellProducts:
          type: boolean
        maxIterationReachedText:
          type: string
        nextTierAmountTieredDiscountText:
          type: string
        nextTierPercentageTieredDiscountText:
          type: string
        amountTieredDiscountText:
          type: string
        percentageTieredDiscountText:
          type: string
        sectionTitleText:
          type: string
        sectionMinMaxTextV2:
          type: string
        sectionedBabBadgeText:
          type: string
        noDeliveryMethodLabelText:
          type: string
        selectedProductLabelTextV2:
          type: string
        discountAppliedTextV2:
          type: string
        minProductsInSubscriptionContract:
          type: string
        addToSubscriptionDiscriptionTextV2:
          type: string
        splitContractConfirmButtonText:
          type: string
        welcomeText:
          type: string
        enableProductDescription:
          type: boolean
        allowToAutoAddProduct:
          type: boolean
        rescheduleOrderDescription:
          type: string
        splitWithoutOrderPlacedSelectOptionHelpText:
          type: string
        splitWithOrderPlacedSelectOptionHelpText:
          type: string
        splitContractNoteText:
          type: string
        retryFailedOrderConfirmationTextV2:
          type: string
        retryFailedOrderDescriptionTextV2:
          type: string
        enableUpdateDeliveryMethod:
          type: boolean
        shopCustomizationData:
          type: array
          items:
            $ref: '#/components/schemas/UpdateShopCustomizationRequest'
        editQuantityLabelText:
          type: string
    Data:
      type: object
      properties:
        subscriptionContract:
          $ref: '#/components/schemas/SubscriptionContract'
    CancellationManagementDTO:
      required:
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        cancellationType:
          type: string
          enum:
            - CANCEL_IMMEDIATELY
            - CANCELLATION_INSTRUCTIONS
            - CUSTOMER_RETENTION_FLOW
            - CANCEL_AFTER_PAUSE
        cancellationInstructionsText:
          type: string
        cancellationReasonsJSON:
          type: string
        pauseInstructionsText:
          type: string
        pauseDurationCycle:
          type: integer
          format: int32
        enableDiscountEmail:
          type: boolean
        discountEmailAddress:
          type: string
        pauseType:
          type: string
          enum:
            - PAUSE_IMMEDIATELY
            - PAUSE_INSTRUCTIONS
            - CUSTOMER_RETENTION_FLOW
        pauseReasonsJSON:
          type: string
        dynamicallyPauseCycleOnCancellation:
          type: boolean
    SubscriptionBundlingResponseV3:
      type: object
      properties:
        bundle:
          $ref: '#/components/schemas/SubscriptionBundling'
        subscriptionPlanProductInfoMap:
          type: object
          additionalProperties:
            type: array
            items:
              $ref: '#/components/schemas/ProductInfo'
        subscriptionPlanVariantMap:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
        subscriptionGroupPlans:
          type: array
          items:
            $ref: '#/components/schemas/SubscriptionGroupPlan'
        subscription:
          $ref: '#/components/schemas/SubscriptionGroupPlan'
        products:
          type: array
          items:
            $ref: '#/components/schemas/ProductInfo'
        variants:
          type: array
          items:
            type: string
    ActivityLogCriteria:
      type: object
      properties:
        id:
          $ref: '#/components/schemas/LongFilter'
        shop:
          $ref: '#/components/schemas/StringFilter'
        entityId:
          $ref: '#/components/schemas/LongFilter'
        entityType:
          $ref: '#/components/schemas/ActivityLogEntityTypeFilter'
        eventSource:
          $ref: '#/components/schemas/ActivityLogEventSourceFilter'
        eventType:
          $ref: '#/components/schemas/ActivityLogEventTypeFilter'
        status:
          $ref: '#/components/schemas/ActivityLogStatusFilter'
        createAt:
          $ref: '#/components/schemas/ZonedDateTimeFilter'
        activityBy:
          $ref: '#/components/schemas/StringFilter'
    ActivityLogEntityTypeFilter:
      type: object
      properties:
        equals:
          type: string
          enum:
            - SUBSCRIPTION_BILLING_ATTEMPT
            - SUBSCRIPTION_CONTRACT_DETAILS
            - SUBSCRIPTION_GROUP_PLAN
            - SHIPPING_PROFILE
            - CANCELLATION_MANAGEMENT
            - DUNNING_MANAGEMENT
            - PRODUCT_SWAP
            - FREQUENCY_SWAP
            - EMAIL_TEMPLATE
            - SHOP_INFO
            - SUBSCRIPTION_WIDGET_SETTINGS
            - CUSTOMER_PORTAL_SETTINGS
            - SUBSCRIPTION_BUNDLING
            - BULK_AUTOMATION
        notEquals:
          type: string
          enum:
            - SUBSCRIPTION_BILLING_ATTEMPT
            - SUBSCRIPTION_CONTRACT_DETAILS
            - SUBSCRIPTION_GROUP_PLAN
            - SHIPPING_PROFILE
            - CANCELLATION_MANAGEMENT
            - DUNNING_MANAGEMENT
            - PRODUCT_SWAP
            - FREQUENCY_SWAP
            - EMAIL_TEMPLATE
            - SHOP_INFO
            - SUBSCRIPTION_WIDGET_SETTINGS
            - CUSTOMER_PORTAL_SETTINGS
            - SUBSCRIPTION_BUNDLING
            - BULK_AUTOMATION
        specified:
          type: boolean
        in:
          type: array
          items:
            type: string
            enum:
              - SUBSCRIPTION_BILLING_ATTEMPT
              - SUBSCRIPTION_CONTRACT_DETAILS
              - SUBSCRIPTION_GROUP_PLAN
              - SHIPPING_PROFILE
              - CANCELLATION_MANAGEMENT
              - DUNNING_MANAGEMENT
              - PRODUCT_SWAP
              - FREQUENCY_SWAP
              - EMAIL_TEMPLATE
              - SHOP_INFO
              - SUBSCRIPTION_WIDGET_SETTINGS
              - CUSTOMER_PORTAL_SETTINGS
              - SUBSCRIPTION_BUNDLING
              - BULK_AUTOMATION
        notIn:
          type: array
          items:
            type: string
            enum:
              - SUBSCRIPTION_BILLING_ATTEMPT
              - SUBSCRIPTION_CONTRACT_DETAILS
              - SUBSCRIPTION_GROUP_PLAN
              - SHIPPING_PROFILE
              - CANCELLATION_MANAGEMENT
              - DUNNING_MANAGEMENT
              - PRODUCT_SWAP
              - FREQUENCY_SWAP
              - EMAIL_TEMPLATE
              - SHOP_INFO
              - SUBSCRIPTION_WIDGET_SETTINGS
              - CUSTOMER_PORTAL_SETTINGS
              - SUBSCRIPTION_BUNDLING
              - BULK_AUTOMATION
    ActivityLogEventSourceFilter:
      type: object
      properties:
        equals:
          type: string
          enum:
            - CUSTOMER_PORTAL
            - MERCHANT_PORTAL
            - SHOPIFY_EVENT
            - SYSTEM_EVENT
            - MERCHANT_PORTAL_BULK_AUTOMATION
            - MERCHANT_EXTERNAL_API
            - SHOPIFY_FLOW
        notEquals:
          type: string
          enum:
            - CUSTOMER_PORTAL
            - MERCHANT_PORTAL
            - SHOPIFY_EVENT
            - SYSTEM_EVENT
            - MERCHANT_PORTAL_BULK_AUTOMATION
            - MERCHANT_EXTERNAL_API
            - SHOPIFY_FLOW
        specified:
          type: boolean
        in:
          type: array
          items:
            type: string
            enum:
              - CUSTOMER_PORTAL
              - MERCHANT_PORTAL
              - SHOPIFY_EVENT
              - SYSTEM_EVENT
              - MERCHANT_PORTAL_BULK_AUTOMATION
              - MERCHANT_EXTERNAL_API
              - SHOPIFY_FLOW
        notIn:
          type: array
          items:
            type: string
            enum:
              - CUSTOMER_PORTAL
              - MERCHANT_PORTAL
              - SHOPIFY_EVENT
              - SYSTEM_EVENT
              - MERCHANT_PORTAL_BULK_AUTOMATION
              - MERCHANT_EXTERNAL_API
              - SHOPIFY_FLOW
    ActivityLogEventTypeFilter:
      type: object
      properties:
        equals:
          type: string
          enum:
            - NEXT_BILLING_DATE_CHANGE
            - NEXT_BILLING_TIME_CHANGE
            - BILLING_INTERVAL_CHANGE
            - DELIVERY_INTERVAL_CHANGE
            - BILLING_ATTEMPT_TRIGGERED
            - BILLING_ATTEMPT_SKIPPED
            - PRODUCT_ADD
            - PRODUCT_REMOVE
            - PRODUCT_REPLACE
            - PRODUCT_QUANTITY_CHANGE
            - PRODUCT_PRICE_CHANGE
            - PRODUCT_PRICING_POLICY_CHANGE
            - PRODUCT_SELLING_PLAN_CHANGE
            - PRODUCT_DELETED_SYNC
            - CONTRACT_PAUSED
            - CONTRACT_ACTIVATED
            - CONTRACT_CANCELLED
            - DELIVERY_METHOD_UPDATED
            - SYSTEM_UPDATED_DELIVERY_PRICE
            - MANUAL_DELIVERY_PRICE_UPDATED
            - DELIVERY_PRICE_OVERRIDE_CHANGED
            - SHIPPING_ADDRESS_CHANGE
            - SHIPPING_ADDRESS_CHANGE_SYNC
            - SEND_SUBSCRIPTION_CREATED_EMAIL
            - SEND_TRANSACTION_FAILED_EMAIL
            - SEND_UPCOMING_ORDER_EMAIL
            - SEND_EXPIRING_CREDIT_CARD_EMAIL
            - SEND_SHIPPING_ADDRESS_UPDATED_EMAIL
            - SEND_ORDER_FREQUENCY_UPDATED_EMAIL
            - SEND_NEXT_ORDER_DATE_UPDATED_EMAIL
            - SEND_SUBSCRIPTION_PAUSED_EMAIL
            - SEND_SUBSCRIPTION_CANCELED_EMAIL
            - SEND_SUBSCRIPTION_RESUMED_EMAIL
            - SEND_SUBSCRIPTION_PRODUCT_ADDED_EMAIL
            - SEND_SUBSCRIPTION_PRODUCT_REMOVED_EMAIL
            - SEND_SUBSCRIPTION_PRODUCT_REPLACED_EMAIL
            - SEND_ORDER_SKIPPED_EMAIL
            - ONE_TIME_PURCHASE_PRODUCT_ADDED
            - ONE_TIME_PURCHASE_PRODUCT_REMOVED
            - ONE_TIME_PURCHASE_PRODUCT_UPDATE
            - SEND_SECURITY_CHALLENGE_EMAIL
            - DISCOUNT_APPLIED
            - DISCOUNT_REMOVED
            - DUNNING_CANCELLED
            - DUNNING_SKIPPED
            - DUNNING_PAUSED
            - DUNNING_ATTEMPT_SKIPPED
            - BILLING_ATTEMPT_NOTIFICATION
            - SEND_SUBSCRIPTION_MANAGEMENT_LINK
            - PRICE_CHANGE_SYNC
            - UPDATE_QUEUED_ATTEMPTS
            - WEBHOOK
            - SPLIT_CONTRACT
            - SWITCH_PAYMENT_METHODS
            - PAYMENT_METHOD_UPDATED
            - SEND_OUT_OF_STOCK_EMAIL
            - INFORMATIONAL_EVENT
            - BULK_EMAIL
            - CONTRACT_CREATED
            - ANCHOR_DAY_REMOVED
            - UPCOMING_ORDER_UPDATED
            - SUBSCRIPTION_CONTRACT_UPDATED
            - BILLING_ATTEMPT_UPDATED
            - RESCHEDULE_FULFILLMENT
            - FULFILLMENT_REFUNDED
            - SWAP_AUTOMATION_TRIGGERED
            - BAB_DISCOUNT_ADJUSTMENT
            - BAB_PRODUCT_ADD
            - BAB_PRODUCT_REMOVE
            - BAB_QUANTITY_CHANGE
            - STOP_UPCOMING_ORDER_EMAIL_UPDATED
            - ORDER_TAGS_ADDED
            - EMAIL
            - SEND_TRANSACTION_SUCCESS_EMAIL
            - TAGS_UPDATED
            - SEND_PRODUCT_PRICE_UPDATED_EMAIL
            - SUBSCRIPTION_GROUP_PLAN_UPDATE
            - SUBSCRIPTION_GROUP_PLAN_CREATE
            - SUBSCRIPTION_GROUP_PLAN_DELETE
            - CREATED
            - UPDATED
            - SEND_SUSPENSION_EMAIL
            - SEND_SUSPENSION_WARNING_EMAIL
            - DELETED
            - CURRENCY_MISMATCH_DETECTED
            - PRICING_METHOD_APPLIED
            - PRICING_POLICY_DISCOUNT_APPLIED
            - PRICING_POLICY_SYNC_SKIPPED
            - PRICING_POLICY_SYNC_FAILED
            - PRICING_POLICY_NO_APPLICABLE_CYCLE
            - PRICING_POLICY_REMOVED
            - PRICING_POLICY_OVERRIDE
            - AUTOMATIC_DISCOUNT_UPDATE
            - BILLING_ATTEMPT_REFRESHED
            - PRICE_CHANGE_SYNC_SKIPPED
            - BASE_PRICE_CALCULATION
            - LINE_DUTY_ADDED
            - IMMEDIATE_RETRY_TRIGGERED
            - PRICE_CHANGE_SYNC_BULK_AUTOMATION
            - SCHEDULE_EXPIRING_CREDIT_CARD_EMAIL
            - STARTED_BULK_AUTOMATION_PROCESSING
            - DUPLICATE_BILLING_ATTEMPT_DETECTED
            - AUTO_RESUME_SCHEDULED
            - BILLING_CYCLE_PRODUCTS_SKIPPED
            - ORDER_ATTRIBUTES_SYNCED
            - DATE_ATTRIBUTE_MODIFIED_BEFORE_SYNC
            - ORDER_DATE_SYNC_FAILED
            - DELIVERY_DATE_SETTINGS_APPLIED
        notEquals:
          type: string
          enum:
            - NEXT_BILLING_DATE_CHANGE
            - NEXT_BILLING_TIME_CHANGE
            - BILLING_INTERVAL_CHANGE
            - DELIVERY_INTERVAL_CHANGE
            - BILLING_ATTEMPT_TRIGGERED
            - BILLING_ATTEMPT_SKIPPED
            - PRODUCT_ADD
            - PRODUCT_REMOVE
            - PRODUCT_REPLACE
            - PRODUCT_QUANTITY_CHANGE
            - PRODUCT_PRICE_CHANGE
            - PRODUCT_PRICING_POLICY_CHANGE
            - PRODUCT_SELLING_PLAN_CHANGE
            - PRODUCT_DELETED_SYNC
            - CONTRACT_PAUSED
            - CONTRACT_ACTIVATED
            - CONTRACT_CANCELLED
            - DELIVERY_METHOD_UPDATED
            - SYSTEM_UPDATED_DELIVERY_PRICE
            - MANUAL_DELIVERY_PRICE_UPDATED
            - DELIVERY_PRICE_OVERRIDE_CHANGED
            - SHIPPING_ADDRESS_CHANGE
            - SHIPPING_ADDRESS_CHANGE_SYNC
            - SEND_SUBSCRIPTION_CREATED_EMAIL
            - SEND_TRANSACTION_FAILED_EMAIL
            - SEND_UPCOMING_ORDER_EMAIL
            - SEND_EXPIRING_CREDIT_CARD_EMAIL
            - SEND_SHIPPING_ADDRESS_UPDATED_EMAIL
            - SEND_ORDER_FREQUENCY_UPDATED_EMAIL
            - SEND_NEXT_ORDER_DATE_UPDATED_EMAIL
            - SEND_SUBSCRIPTION_PAUSED_EMAIL
            - SEND_SUBSCRIPTION_CANCELED_EMAIL
            - SEND_SUBSCRIPTION_RESUMED_EMAIL
            - SEND_SUBSCRIPTION_PRODUCT_ADDED_EMAIL
            - SEND_SUBSCRIPTION_PRODUCT_REMOVED_EMAIL
            - SEND_SUBSCRIPTION_PRODUCT_REPLACED_EMAIL
            - SEND_ORDER_SKIPPED_EMAIL
            - ONE_TIME_PURCHASE_PRODUCT_ADDED
            - ONE_TIME_PURCHASE_PRODUCT_REMOVED
            - ONE_TIME_PURCHASE_PRODUCT_UPDATE
            - SEND_SECURITY_CHALLENGE_EMAIL
            - DISCOUNT_APPLIED
            - DISCOUNT_REMOVED
            - DUNNING_CANCELLED
            - DUNNING_SKIPPED
            - DUNNING_PAUSED
            - DUNNING_ATTEMPT_SKIPPED
            - BILLING_ATTEMPT_NOTIFICATION
            - SEND_SUBSCRIPTION_MANAGEMENT_LINK
            - PRICE_CHANGE_SYNC
            - UPDATE_QUEUED_ATTEMPTS
            - WEBHOOK
            - SPLIT_CONTRACT
            - SWITCH_PAYMENT_METHODS
            - PAYMENT_METHOD_UPDATED
            - SEND_OUT_OF_STOCK_EMAIL
            - INFORMATIONAL_EVENT
            - BULK_EMAIL
            - CONTRACT_CREATED
            - ANCHOR_DAY_REMOVED
            - UPCOMING_ORDER_UPDATED
            - SUBSCRIPTION_CONTRACT_UPDATED
            - BILLING_ATTEMPT_UPDATED
            - RESCHEDULE_FULFILLMENT
            - FULFILLMENT_REFUNDED
            - SWAP_AUTOMATION_TRIGGERED
            - BAB_DISCOUNT_ADJUSTMENT
            - BAB_PRODUCT_ADD
            - BAB_PRODUCT_REMOVE
            - BAB_QUANTITY_CHANGE
            - STOP_UPCOMING_ORDER_EMAIL_UPDATED
            - ORDER_TAGS_ADDED
            - EMAIL
            - SEND_TRANSACTION_SUCCESS_EMAIL
            - TAGS_UPDATED
            - SEND_PRODUCT_PRICE_UPDATED_EMAIL
            - SUBSCRIPTION_GROUP_PLAN_UPDATE
            - SUBSCRIPTION_GROUP_PLAN_CREATE
            - SUBSCRIPTION_GROUP_PLAN_DELETE
            - CREATED
            - UPDATED
            - SEND_SUSPENSION_EMAIL
            - SEND_SUSPENSION_WARNING_EMAIL
            - DELETED
            - CURRENCY_MISMATCH_DETECTED
            - PRICING_METHOD_APPLIED
            - PRICING_POLICY_DISCOUNT_APPLIED
            - PRICING_POLICY_SYNC_SKIPPED
            - PRICING_POLICY_SYNC_FAILED
            - PRICING_POLICY_NO_APPLICABLE_CYCLE
            - PRICING_POLICY_REMOVED
            - PRICING_POLICY_OVERRIDE
            - AUTOMATIC_DISCOUNT_UPDATE
            - BILLING_ATTEMPT_REFRESHED
            - PRICE_CHANGE_SYNC_SKIPPED
            - BASE_PRICE_CALCULATION
            - LINE_DUTY_ADDED
            - IMMEDIATE_RETRY_TRIGGERED
            - PRICE_CHANGE_SYNC_BULK_AUTOMATION
            - SCHEDULE_EXPIRING_CREDIT_CARD_EMAIL
            - STARTED_BULK_AUTOMATION_PROCESSING
            - DUPLICATE_BILLING_ATTEMPT_DETECTED
            - AUTO_RESUME_SCHEDULED
            - BILLING_CYCLE_PRODUCTS_SKIPPED
            - ORDER_ATTRIBUTES_SYNCED
            - DATE_ATTRIBUTE_MODIFIED_BEFORE_SYNC
            - ORDER_DATE_SYNC_FAILED
            - DELIVERY_DATE_SETTINGS_APPLIED
        specified:
          type: boolean
        in:
          type: array
          items:
            type: string
            enum:
              - NEXT_BILLING_DATE_CHANGE
              - NEXT_BILLING_TIME_CHANGE
              - BILLING_INTERVAL_CHANGE
              - DELIVERY_INTERVAL_CHANGE
              - BILLING_ATTEMPT_TRIGGERED
              - BILLING_ATTEMPT_SKIPPED
              - PRODUCT_ADD
              - PRODUCT_REMOVE
              - PRODUCT_REPLACE
              - PRODUCT_QUANTITY_CHANGE
              - PRODUCT_PRICE_CHANGE
              - PRODUCT_PRICING_POLICY_CHANGE
              - PRODUCT_SELLING_PLAN_CHANGE
              - PRODUCT_DELETED_SYNC
              - CONTRACT_PAUSED
              - CONTRACT_ACTIVATED
              - CONTRACT_CANCELLED
              - DELIVERY_METHOD_UPDATED
              - SYSTEM_UPDATED_DELIVERY_PRICE
              - MANUAL_DELIVERY_PRICE_UPDATED
              - DELIVERY_PRICE_OVERRIDE_CHANGED
              - SHIPPING_ADDRESS_CHANGE
              - SHIPPING_ADDRESS_CHANGE_SYNC
              - SEND_SUBSCRIPTION_CREATED_EMAIL
              - SEND_TRANSACTION_FAILED_EMAIL
              - SEND_UPCOMING_ORDER_EMAIL
              - SEND_EXPIRING_CREDIT_CARD_EMAIL
              - SEND_SHIPPING_ADDRESS_UPDATED_EMAIL
              - SEND_ORDER_FREQUENCY_UPDATED_EMAIL
              - SEND_NEXT_ORDER_DATE_UPDATED_EMAIL
              - SEND_SUBSCRIPTION_PAUSED_EMAIL
              - SEND_SUBSCRIPTION_CANCELED_EMAIL
              - SEND_SUBSCRIPTION_RESUMED_EMAIL
              - SEND_SUBSCRIPTION_PRODUCT_ADDED_EMAIL
              - SEND_SUBSCRIPTION_PRODUCT_REMOVED_EMAIL
              - SEND_SUBSCRIPTION_PRODUCT_REPLACED_EMAIL
              - SEND_ORDER_SKIPPED_EMAIL
              - ONE_TIME_PURCHASE_PRODUCT_ADDED
              - ONE_TIME_PURCHASE_PRODUCT_REMOVED
              - ONE_TIME_PURCHASE_PRODUCT_UPDATE
              - SEND_SECURITY_CHALLENGE_EMAIL
              - DISCOUNT_APPLIED
              - DISCOUNT_REMOVED
              - DUNNING_CANCELLED
              - DUNNING_SKIPPED
              - DUNNING_PAUSED
              - DUNNING_ATTEMPT_SKIPPED
              - BILLING_ATTEMPT_NOTIFICATION
              - SEND_SUBSCRIPTION_MANAGEMENT_LINK
              - PRICE_CHANGE_SYNC
              - UPDATE_QUEUED_ATTEMPTS
              - WEBHOOK
              - SPLIT_CONTRACT
              - SWITCH_PAYMENT_METHODS
              - PAYMENT_METHOD_UPDATED
              - SEND_OUT_OF_STOCK_EMAIL
              - INFORMATIONAL_EVENT
              - BULK_EMAIL
              - CONTRACT_CREATED
              - ANCHOR_DAY_REMOVED
              - UPCOMING_ORDER_UPDATED
              - SUBSCRIPTION_CONTRACT_UPDATED
              - BILLING_ATTEMPT_UPDATED
              - RESCHEDULE_FULFILLMENT
              - FULFILLMENT_REFUNDED
              - SWAP_AUTOMATION_TRIGGERED
              - BAB_DISCOUNT_ADJUSTMENT
              - BAB_PRODUCT_ADD
              - BAB_PRODUCT_REMOVE
              - BAB_QUANTITY_CHANGE
              - STOP_UPCOMING_ORDER_EMAIL_UPDATED
              - ORDER_TAGS_ADDED
              - EMAIL
              - SEND_TRANSACTION_SUCCESS_EMAIL
              - TAGS_UPDATED
              - SEND_PRODUCT_PRICE_UPDATED_EMAIL
              - SUBSCRIPTION_GROUP_PLAN_UPDATE
              - SUBSCRIPTION_GROUP_PLAN_CREATE
              - SUBSCRIPTION_GROUP_PLAN_DELETE
              - CREATED
              - UPDATED
              - SEND_SUSPENSION_EMAIL
              - SEND_SUSPENSION_WARNING_EMAIL
              - DELETED
              - CURRENCY_MISMATCH_DETECTED
              - PRICING_METHOD_APPLIED
              - PRICING_POLICY_DISCOUNT_APPLIED
              - PRICING_POLICY_SYNC_SKIPPED
              - PRICING_POLICY_SYNC_FAILED
              - PRICING_POLICY_NO_APPLICABLE_CYCLE
              - PRICING_POLICY_REMOVED
              - PRICING_POLICY_OVERRIDE
              - AUTOMATIC_DISCOUNT_UPDATE
              - BILLING_ATTEMPT_REFRESHED
              - PRICE_CHANGE_SYNC_SKIPPED
              - BASE_PRICE_CALCULATION
              - LINE_DUTY_ADDED
              - IMMEDIATE_RETRY_TRIGGERED
              - PRICE_CHANGE_SYNC_BULK_AUTOMATION
              - SCHEDULE_EXPIRING_CREDIT_CARD_EMAIL
              - STARTED_BULK_AUTOMATION_PROCESSING
              - DUPLICATE_BILLING_ATTEMPT_DETECTED
              - AUTO_RESUME_SCHEDULED
              - BILLING_CYCLE_PRODUCTS_SKIPPED
              - ORDER_ATTRIBUTES_SYNCED
              - DATE_ATTRIBUTE_MODIFIED_BEFORE_SYNC
              - ORDER_DATE_SYNC_FAILED
              - DELIVERY_DATE_SETTINGS_APPLIED
        notIn:
          type: array
          items:
            type: string
            enum:
              - NEXT_BILLING_DATE_CHANGE
              - NEXT_BILLING_TIME_CHANGE
              - BILLING_INTERVAL_CHANGE
              - DELIVERY_INTERVAL_CHANGE
              - BILLING_ATTEMPT_TRIGGERED
              - BILLING_ATTEMPT_SKIPPED
              - PRODUCT_ADD
              - PRODUCT_REMOVE
              - PRODUCT_REPLACE
              - PRODUCT_QUANTITY_CHANGE
              - PRODUCT_PRICE_CHANGE
              - PRODUCT_PRICING_POLICY_CHANGE
              - PRODUCT_SELLING_PLAN_CHANGE
              - PRODUCT_DELETED_SYNC
              - CONTRACT_PAUSED
              - CONTRACT_ACTIVATED
              - CONTRACT_CANCELLED
              - DELIVERY_METHOD_UPDATED
              - SYSTEM_UPDATED_DELIVERY_PRICE
              - MANUAL_DELIVERY_PRICE_UPDATED
              - DELIVERY_PRICE_OVERRIDE_CHANGED
              - SHIPPING_ADDRESS_CHANGE
              - SHIPPING_ADDRESS_CHANGE_SYNC
              - SEND_SUBSCRIPTION_CREATED_EMAIL
              - SEND_TRANSACTION_FAILED_EMAIL
              - SEND_UPCOMING_ORDER_EMAIL
              - SEND_EXPIRING_CREDIT_CARD_EMAIL
              - SEND_SHIPPING_ADDRESS_UPDATED_EMAIL
              - SEND_ORDER_FREQUENCY_UPDATED_EMAIL
              - SEND_NEXT_ORDER_DATE_UPDATED_EMAIL
              - SEND_SUBSCRIPTION_PAUSED_EMAIL
              - SEND_SUBSCRIPTION_CANCELED_EMAIL
              - SEND_SUBSCRIPTION_RESUMED_EMAIL
              - SEND_SUBSCRIPTION_PRODUCT_ADDED_EMAIL
              - SEND_SUBSCRIPTION_PRODUCT_REMOVED_EMAIL
              - SEND_SUBSCRIPTION_PRODUCT_REPLACED_EMAIL
              - SEND_ORDER_SKIPPED_EMAIL
              - ONE_TIME_PURCHASE_PRODUCT_ADDED
              - ONE_TIME_PURCHASE_PRODUCT_REMOVED
              - ONE_TIME_PURCHASE_PRODUCT_UPDATE
              - SEND_SECURITY_CHALLENGE_EMAIL
              - DISCOUNT_APPLIED
              - DISCOUNT_REMOVED
              - DUNNING_CANCELLED
              - DUNNING_SKIPPED
              - DUNNING_PAUSED
              - DUNNING_ATTEMPT_SKIPPED
              - BILLING_ATTEMPT_NOTIFICATION
              - SEND_SUBSCRIPTION_MANAGEMENT_LINK
              - PRICE_CHANGE_SYNC
              - UPDATE_QUEUED_ATTEMPTS
              - WEBHOOK
              - SPLIT_CONTRACT
              - SWITCH_PAYMENT_METHODS
              - PAYMENT_METHOD_UPDATED
              - SEND_OUT_OF_STOCK_EMAIL
              - INFORMATIONAL_EVENT
              - BULK_EMAIL
              - CONTRACT_CREATED
              - ANCHOR_DAY_REMOVED
              - UPCOMING_ORDER_UPDATED
              - SUBSCRIPTION_CONTRACT_UPDATED
              - BILLING_ATTEMPT_UPDATED
              - RESCHEDULE_FULFILLMENT
              - FULFILLMENT_REFUNDED
              - SWAP_AUTOMATION_TRIGGERED
              - BAB_DISCOUNT_ADJUSTMENT
              - BAB_PRODUCT_ADD
              - BAB_PRODUCT_REMOVE
              - BAB_QUANTITY_CHANGE
              - STOP_UPCOMING_ORDER_EMAIL_UPDATED
              - ORDER_TAGS_ADDED
              - EMAIL
              - SEND_TRANSACTION_SUCCESS_EMAIL
              - TAGS_UPDATED
              - SEND_PRODUCT_PRICE_UPDATED_EMAIL
              - SUBSCRIPTION_GROUP_PLAN_UPDATE
              - SUBSCRIPTION_GROUP_PLAN_CREATE
              - SUBSCRIPTION_GROUP_PLAN_DELETE
              - CREATED
              - UPDATED
              - SEND_SUSPENSION_EMAIL
              - SEND_SUSPENSION_WARNING_EMAIL
              - DELETED
              - CURRENCY_MISMATCH_DETECTED
              - PRICING_METHOD_APPLIED
              - PRICING_POLICY_DISCOUNT_APPLIED
              - PRICING_POLICY_SYNC_SKIPPED
              - PRICING_POLICY_SYNC_FAILED
              - PRICING_POLICY_NO_APPLICABLE_CYCLE
              - PRICING_POLICY_REMOVED
              - PRICING_POLICY_OVERRIDE
              - AUTOMATIC_DISCOUNT_UPDATE
              - BILLING_ATTEMPT_REFRESHED
              - PRICE_CHANGE_SYNC_SKIPPED
              - BASE_PRICE_CALCULATION
              - LINE_DUTY_ADDED
              - IMMEDIATE_RETRY_TRIGGERED
              - PRICE_CHANGE_SYNC_BULK_AUTOMATION
              - SCHEDULE_EXPIRING_CREDIT_CARD_EMAIL
              - STARTED_BULK_AUTOMATION_PROCESSING
              - DUPLICATE_BILLING_ATTEMPT_DETECTED
              - AUTO_RESUME_SCHEDULED
              - BILLING_CYCLE_PRODUCTS_SKIPPED
              - ORDER_ATTRIBUTES_SYNCED
              - DATE_ATTRIBUTE_MODIFIED_BEFORE_SYNC
              - ORDER_DATE_SYNC_FAILED
              - DELIVERY_DATE_SETTINGS_APPLIED
    ActivityLogStatusFilter:
      type: object
      properties:
        equals:
          type: string
          enum:
            - SUCCESS
            - FAILURE
            - INFO
            - SKIPPED
            - PARTIAL_FAILURE
        notEquals:
          type: string
          enum:
            - SUCCESS
            - FAILURE
            - INFO
            - SKIPPED
            - PARTIAL_FAILURE
        specified:
          type: boolean
        in:
          type: array
          items:
            type: string
            enum:
              - SUCCESS
              - FAILURE
              - INFO
              - SKIPPED
              - PARTIAL_FAILURE
        notIn:
          type: array
          items:
            type: string
            enum:
              - SUCCESS
              - FAILURE
              - INFO
              - SKIPPED
              - PARTIAL_FAILURE
    LongFilter:
      type: object
      properties:
        equals:
          type: integer
          format: int64
        notEquals:
          type: integer
          format: int64
        specified:
          type: boolean
        in:
          type: array
          items:
            type: integer
            format: int64
        notIn:
          type: array
          items:
            type: integer
            format: int64
        greaterThan:
          type: integer
          format: int64
        lessThan:
          type: integer
          format: int64
        greaterThanOrEqual:
          type: integer
          format: int64
        lessThanOrEqual:
          type: integer
          format: int64
    StringFilter:
      type: object
      properties:
        equals:
          type: string
        notEquals:
          type: string
        specified:
          type: boolean
        in:
          type: array
          items:
            type: string
        notIn:
          type: array
          items:
            type: string
        contains:
          type: string
        doesNotContain:
          type: string
    ZonedDateTimeFilter:
      type: object
      properties:
        equals:
          type: string
          format: date-time
        notEquals:
          type: string
          format: date-time
        specified:
          type: boolean
        in:
          type: array
          items:
            type: string
            format: date-time
        notIn:
          type: array
          items:
            type: string
            format: date-time
        greaterThan:
          type: string
          format: date-time
        lessThan:
          type: string
          format: date-time
        greaterThanOrEqual:
          type: string
          format: date-time
        lessThanOrEqual:
          type: string
          format: date-time
    ActivityLogDTO:
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        entityId:
          type: integer
          format: int64
        entityType:
          type: string
          enum:
            - SUBSCRIPTION_BILLING_ATTEMPT
            - SUBSCRIPTION_CONTRACT_DETAILS
            - SUBSCRIPTION_GROUP_PLAN
            - SHIPPING_PROFILE
            - CANCELLATION_MANAGEMENT
            - DUNNING_MANAGEMENT
            - PRODUCT_SWAP
            - FREQUENCY_SWAP
            - EMAIL_TEMPLATE
            - SHOP_INFO
            - SUBSCRIPTION_WIDGET_SETTINGS
            - CUSTOMER_PORTAL_SETTINGS
            - SUBSCRIPTION_BUNDLING
            - BULK_AUTOMATION
        eventSource:
          type: string
          enum:
            - CUSTOMER_PORTAL
            - MERCHANT_PORTAL
            - SHOPIFY_EVENT
            - SYSTEM_EVENT
            - MERCHANT_PORTAL_BULK_AUTOMATION
            - MERCHANT_EXTERNAL_API
            - SHOPIFY_FLOW
        eventType:
          type: string
          enum:
            - NEXT_BILLING_DATE_CHANGE
            - NEXT_BILLING_TIME_CHANGE
            - BILLING_INTERVAL_CHANGE
            - DELIVERY_INTERVAL_CHANGE
            - BILLING_ATTEMPT_TRIGGERED
            - BILLING_ATTEMPT_SKIPPED
            - PRODUCT_ADD
            - PRODUCT_REMOVE
            - PRODUCT_REPLACE
            - PRODUCT_QUANTITY_CHANGE
            - PRODUCT_PRICE_CHANGE
            - PRODUCT_PRICING_POLICY_CHANGE
            - PRODUCT_SELLING_PLAN_CHANGE
            - PRODUCT_DELETED_SYNC
            - CONTRACT_PAUSED
            - CONTRACT_ACTIVATED
            - CONTRACT_CANCELLED
            - DELIVERY_METHOD_UPDATED
            - SYSTEM_UPDATED_DELIVERY_PRICE
            - MANUAL_DELIVERY_PRICE_UPDATED
            - DELIVERY_PRICE_OVERRIDE_CHANGED
            - SHIPPING_ADDRESS_CHANGE
            - SHIPPING_ADDRESS_CHANGE_SYNC
            - SEND_SUBSCRIPTION_CREATED_EMAIL
            - SEND_TRANSACTION_FAILED_EMAIL
            - SEND_UPCOMING_ORDER_EMAIL
            - SEND_EXPIRING_CREDIT_CARD_EMAIL
            - SEND_SHIPPING_ADDRESS_UPDATED_EMAIL
            - SEND_ORDER_FREQUENCY_UPDATED_EMAIL
            - SEND_NEXT_ORDER_DATE_UPDATED_EMAIL
            - SEND_SUBSCRIPTION_PAUSED_EMAIL
            - SEND_SUBSCRIPTION_CANCELED_EMAIL
            - SEND_SUBSCRIPTION_RESUMED_EMAIL
            - SEND_SUBSCRIPTION_PRODUCT_ADDED_EMAIL
            - SEND_SUBSCRIPTION_PRODUCT_REMOVED_EMAIL
            - SEND_SUBSCRIPTION_PRODUCT_REPLACED_EMAIL
            - SEND_ORDER_SKIPPED_EMAIL
            - ONE_TIME_PURCHASE_PRODUCT_ADDED
            - ONE_TIME_PURCHASE_PRODUCT_REMOVED
            - ONE_TIME_PURCHASE_PRODUCT_UPDATE
            - SEND_SECURITY_CHALLENGE_EMAIL
            - DISCOUNT_APPLIED
            - DISCOUNT_REMOVED
            - DUNNING_CANCELLED
            - DUNNING_SKIPPED
            - DUNNING_PAUSED
            - DUNNING_ATTEMPT_SKIPPED
            - BILLING_ATTEMPT_NOTIFICATION
            - SEND_SUBSCRIPTION_MANAGEMENT_LINK
            - PRICE_CHANGE_SYNC
            - UPDATE_QUEUED_ATTEMPTS
            - WEBHOOK
            - SPLIT_CONTRACT
            - SWITCH_PAYMENT_METHODS
            - PAYMENT_METHOD_UPDATED
            - SEND_OUT_OF_STOCK_EMAIL
            - INFORMATIONAL_EVENT
            - BULK_EMAIL
            - CONTRACT_CREATED
            - ANCHOR_DAY_REMOVED
            - UPCOMING_ORDER_UPDATED
            - SUBSCRIPTION_CONTRACT_UPDATED
            - BILLING_ATTEMPT_UPDATED
            - RESCHEDULE_FULFILLMENT
            - FULFILLMENT_REFUNDED
            - SWAP_AUTOMATION_TRIGGERED
            - BAB_DISCOUNT_ADJUSTMENT
            - BAB_PRODUCT_ADD
            - BAB_PRODUCT_REMOVE
            - BAB_QUANTITY_CHANGE
            - STOP_UPCOMING_ORDER_EMAIL_UPDATED
            - ORDER_TAGS_ADDED
            - EMAIL
            - SEND_TRANSACTION_SUCCESS_EMAIL
            - TAGS_UPDATED
            - SEND_PRODUCT_PRICE_UPDATED_EMAIL
            - SUBSCRIPTION_GROUP_PLAN_UPDATE
            - SUBSCRIPTION_GROUP_PLAN_CREATE
            - SUBSCRIPTION_GROUP_PLAN_DELETE
            - CREATED
            - UPDATED
            - SEND_SUSPENSION_EMAIL
            - SEND_SUSPENSION_WARNING_EMAIL
            - DELETED
            - CURRENCY_MISMATCH_DETECTED
            - PRICING_METHOD_APPLIED
            - PRICING_POLICY_DISCOUNT_APPLIED
            - PRICING_POLICY_SYNC_SKIPPED
            - PRICING_POLICY_SYNC_FAILED
            - PRICING_POLICY_NO_APPLICABLE_CYCLE
            - PRICING_POLICY_REMOVED
            - PRICING_POLICY_OVERRIDE
            - AUTOMATIC_DISCOUNT_UPDATE
            - BILLING_ATTEMPT_REFRESHED
            - PRICE_CHANGE_SYNC_SKIPPED
            - BASE_PRICE_CALCULATION
            - LINE_DUTY_ADDED
            - IMMEDIATE_RETRY_TRIGGERED
            - PRICE_CHANGE_SYNC_BULK_AUTOMATION
            - SCHEDULE_EXPIRING_CREDIT_CARD_EMAIL
            - STARTED_BULK_AUTOMATION_PROCESSING
            - DUPLICATE_BILLING_ATTEMPT_DETECTED
            - AUTO_RESUME_SCHEDULED
            - BILLING_CYCLE_PRODUCTS_SKIPPED
            - ORDER_ATTRIBUTES_SYNCED
            - DATE_ATTRIBUTE_MODIFIED_BEFORE_SYNC
            - ORDER_DATE_SYNC_FAILED
            - DELIVERY_DATE_SETTINGS_APPLIED
        status:
          type: string
          enum:
            - SUCCESS
            - FAILURE
            - INFO
            - SKIPPED
            - PARTIAL_FAILURE
        createAt:
          type: string
          format: date-time
        additionalInfo:
          type: string
        activityBy:
          type: string
        clientIp:
          type: string
x-tagGroups:
  - name: Subscription Management
    tags:
      - Subscription Management
      - Subscription Payments
      - Subscription Contracts
      - Subscription Products
      - Billing & Payments
      - Subscription Discounts
      - Subscription One-Time Products
  - name: Other APIs
    tags:
      - Subscription Plans
      - Build-a-Box & Bundles
      - Product Catalog
      - Operations & Settings
      - Customer Portal
      - Customers
