openapi: 3.0.1
info:
  title: Admin APIs
  description: ''
servers:
  - url: https://loyalty-admin.appstle.com
tags:
  - name: Admin APIs
    description: >-
      Admin APIs for third-party integrations to manage customer loyalty
      programs, points, rewards, and redemptions. All endpoints require
      X-API-Key authentication header.
paths:
  /api/external/update-discount:
    put:
      tags:
        - Admin APIs
      summary: Update discount code status
      description: >
        Updates the status of a customer's discount code after checkout or
        subscription events.


        **Primary use case:**

        Mark a discount code as "USED" after a customer completes checkout with
        the code.

        This prevents the code from being used again and keeps reward tracking
        accurate.


        **Request body:**

        - customerId: Shopify customer ID (required)

        - discountCode: The discount code to update (required)

        - status: New status for the code (required)


        **Valid status values:**

        - USED: Mark code as used after checkout (most common)

        - SUBSCRIPTION_ACTIVE: Mark code as active for subscription renewals

        - UNUSED: Reset code to unused state (use carefully)

        - EXPIRED: Manually expire a code


        **What happens when you update status:**

        1. Validates discount code exists and belongs to customer

        2. Updates the reward status in database

        3. Syncs status to Shopify discount code system

        4. Updates customer metafields in Shopify

        5. Logs activity for audit trail

        6. For subscriptions: manages discount code lifecycle


        **Subscription handling (SUBSCRIPTION_ACTIVE):**

        - When subscription is created: Set to SUBSCRIPTION_ACTIVE

        - System automatically manages code for each renewal

        - When subscription ends: Can revert to USED or delete

        - Code may be deleted/recreated for each billing cycle


        **Common workflows:**


        **One-time checkout:**

        1. Customer applies loyalty code at checkout

        2. Order is created in Shopify

        3. Call this endpoint with status="USED"

        4. Code is now marked as used and can't be reused


        **Subscription checkout:**

        1. Customer applies code to subscription

        2. Subscription is created

        3. Call with status="SUBSCRIPTION_ACTIVE"

        4. Code stays active for renewals

        5. When subscription cancelled, call with status="USED"


        **Important notes:**

        - Marking code as USED is irreversible in normal operations

        - SUBSCRIPTION_ACTIVE codes can be used for recurring orders

        - System prevents using USED codes even if status is reset

        - Activity log tracks all status changes

        - Metafield sync updates customer data in Shopify theme


        **Error scenarios:**

        - Code already USED: Cannot mark as USED again (400 error)

        - Code not found: Invalid discount code or customer (400 error)

        - Wrong customer: Code belongs to different customer (400 error)


        **Best practices:**

        - Always call this after order creation webhooks

        - Use order confirmation webhooks to trigger status update

        - Handle 400 errors gracefully (code may already be marked used)

        - For subscriptions, track subscription lifecycle events

        - Don't call multiple times for same order (idempotency)
      operationId: updateDiscount
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateDiscountRequest'
        required: true
      responses:
        '200':
          description: Discount code status successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerReward'
              example:
                id: 12345
                customerId: 67890
                discountCode: LOYALTY15OFF
                discountType: PERCENTAGE
                discountValue: 15
                status: USED
                expiryDate: '2025-06-30T23:59:59Z'
                pointsRedeemed: 100
                usedAt: '2025-01-29T10:45:00Z'
                createAt: '2025-01-15T10:30:00Z'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Discount code already marked as used
                  currentStatus: USED
                  usedAt: '2025-01-20T14:30:00Z'
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Invalid API key
      security:
        - X-API-Key: []
  /api/external/update-discount-code-status:
    put:
      tags:
        - Admin APIs
      summary: Update discount code status (legacy endpoint)
      description: >-
        Updates the status of a customer's discount code. This is a legacy
        endpoint similar to update-discount but returns full customer loyalty
        details after update. Commonly used to mark discount codes as USED after
        checkout.
      operationId: externalMarkDiscountCodeAsUsed
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateDiscountCodeStatusRequestVM'
        required: true
      responses:
        '200':
          description: Discount code status updated and customer loyalty details returned
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerLoyaltyResponseVM'
        '400':
          description: Invalid request
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
      security:
        - X-API-Key: []
  /api/external/update-customer-birth-date:
    put:
      tags:
        - Admin APIs
      summary: Update customer birth date
      description: >-
        Updates or sets a customer's birth date in the loyalty system. Used for
        birthday reward programs and customer segmentation. Validates the birth
        date format and triggers any applicable birthday point earning rules.
      operationId: addCustomerBirthDate
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerBirthDateRequestVM'
        required: true
      responses:
        '200':
          description: Customer birth date successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Customer'
        '400':
          description: Invalid request - Invalid date format or customer not found
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
        '500':
          description: Internal server error during update
      security:
        - X-API-Key: []
  /api/external/check-discount:
    put:
      tags:
        - Admin APIs
      summary: Check discount code validity
      description: >
        Validates a discount code for a specific customer before checkout.


        **When to use this:**

        - During checkout when customer enters a loyalty discount code

        - Before applying discount to verify it belongs to the customer

        - To check discount status and expiry

        - To retrieve discount details (type, value, restrictions)


        **Request body:**

        - customerId: Shopify customer ID (required)

        - discountCode: The discount code to validate (required,
        case-insensitive)


        **What this endpoint checks:**

        - Discount code exists in the system

        - Code belongs to the specified customer

        - Code status is "UNUSED" or "ACTIVE"

        - Code has not expired

        - Code is valid for current context


        **Response includes:**

        - Discount type (PERCENTAGE, FIXED_AMOUNT, FREE_SHIPPING, FREE_PRODUCT)

        - Discount value (percentage or fixed amount)

        - Expiry date

        - Usage restrictions (minimum purchase, specific products, etc.)

        - Points that were redeemed for this code

        - Shopify discount code ID for reference


        **Discount statuses:**

        - UNUSED: Code has not been used yet (valid)

        - ACTIVE: Code is being used in an active subscription (valid for
        renewals)

        - USED: Code has already been redeemed (invalid)

        - EXPIRED: Code has passed expiry date (invalid)


        **Integration pattern:**

        1. Customer enters loyalty code at checkout

        2. Call this endpoint to validate the code

        3. If 200 response, apply discount in checkout

        4. After order is placed, call update-discount to mark as USED

        5. Handle 400/404 by showing error message to customer


        **Common scenarios:**

        - Valid code: 200 with full discount details

        - Wrong customer: 404 (code exists but for different customer)

        - Already used: 400 with "Discount already used" message

        - Expired: 400 with expiry information

        - Invalid code: 404 (code doesn't exist)
      operationId: checkRewards
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckDiscountRequest'
        required: true
      responses:
        '200':
          description: Discount code is valid and reward details returned
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerReward'
              example:
                id: 12345
                customerId: 67890
                discountCode: LOYALTY15OFF
                discountType: PERCENTAGE
                discountValue: 15
                status: UNUSED
                expiryDate: '2025-06-30T23:59:59Z'
                pointsRedeemed: 100
                shopifyDiscountCodeId: gid://shopify/DiscountCode/123
                minimumPurchaseAmount: 50
                createAt: '2025-01-15T10:30:00Z'
        '400':
          description: Discount code not valid
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Discount code already used
                  status: USED
                  usedAt: '2025-01-20T14:30:00Z'
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Invalid API key
        '404':
          description: Discount code not found for this customer
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Discount code not found for the specified customer
      security:
        - X-API-Key: []
  /api/external/approve-pending-transactions:
    put:
      tags:
        - Admin APIs
      summary: Approve pending point transactions
      description: >
        Approves pending point transactions and converts them to available
        points.


        **When points are pending:**

        - Orders with pending fulfillment

        - High-risk transactions requiring manual review

        - Bulk point grants awaiting approval

        - Refund/return waiting periods

        - Custom approval workflows


        **Two approval modes:**


        **Mode 1: Approve all pending transactions**

        - Set approveAllPendingTransactions=true

        - Request body is ignored

        - Approves ALL pending transactions for the shop

        - Use for bulk approvals or automated workflows


        **Mode 2: Approve specific transactions**

        - Set approveAllPendingTransactions=false (or omit parameter)

        - Provide pendingPointsApprovalList in request body

        - Each item needs: customerId, points, transaction details

        - Approves only specified transactions

        - Use for selective/manual approval


        **How approval works:**

        1. Validates pending transactions exist

        2. Queues approval process (asynchronous via AWS Step Functions)

        3. Returns 204 immediately (doesn't wait for completion)

        4. Background process:
           - Updates transaction status from PENDING to APPROVED
           - Adds points to customer's availablePoints
           - Updates creditedPoints total
           - Syncs to Shopify metafields
           - Logs approval activity
           - Triggers any applicable notifications

        **Important notes:**

        - This is an ASYNCHRONOUS operation

        - Returns 204 immediately, processing happens in background

        - Points may take a few seconds to appear in customer account

        - No rollback after 204 response

        - Cannot approve already-approved transactions

        - Cannot approve rejected transactions


        **Request body structure (for specific approvals):**

        ```json

        [
          {
            "customerId": 12345,
            "points": 50.0,
            "transactionId": 98765,
            "note": "Order fulfilled, approving points"
          }
        ]

        ```


        **Best practices:**

        - Use approveAllPendingTransactions=true for scheduled/automated
        approvals

        - Use specific approval list for manual review workflows

        - Monitor for completion by checking customer point balance

        - Set up webhooks/polling to detect when approval completes

        - Don't call repeatedly - it's queued asynchronously

        - Consider rate limiting on your side for bulk approvals


        **Common use cases:**

        - Approve points after order fulfillment

        - Batch approval at end of day/week

        - Manual approval after fraud review

        - Approve after return/refund window closes

        - Integration with external approval systems


        **Error handling:**

        - 204: Success, approval queued (this is success, not an error)

        - 400: Invalid request format or missing required data

        - 401: Invalid API key
      operationId: approvePendingTransaction
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
        - name: approveAllPendingTransactions
          in: query
          description: >-
            Set to true to approve all pending transactions (ignores
            pendingPointsApprovalList)
          required: false
          schema:
            type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: array
              description: >-
                List of specific pending transactions to approve (ignored if
                approveAllPendingTransactions=true)
              items:
                $ref: '#/components/schemas/PendingPointsApprovalRequest'
      responses:
        '204':
          description: >-
            Approval process started successfully (asynchronous operation).
            Points will be added to customer accounts within a few seconds.
        '400':
          description: >-
            Invalid request - Must provide either
            approveAllPendingTransactions=true OR a valid
            pendingPointsApprovalList
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Invalid request
                  details: >-
                    Must provide either approveAllPendingTransactions=true or a
                    list of pending transactions to approve
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Invalid API key
      security:
        - X-API-Key: []
  /api/external/redeem-points:
    post:
      tags:
        - Admin APIs
      summary: Redeem customer points for rewards
      description: >
        Processes a point redemption request and generates a discount code or
        reward.


        **How it works:**

        1. Validates customer has sufficient available points

        2. Deducts points from customer's balance

        3. Creates a discount code in Shopify (if applicable)

        4. Creates a reward record with status "UNUSED"

        5. Logs the transaction for audit trail

        6. Returns updated customer loyalty information


        **Request body fields:**

        - customerId OR customerEmail: Identify the customer (provide one, not
        both)

        - redeemRuleId: ID of the redemption rule to use (required)

        - points: Number of points to redeem (optional - uses rule default if
        not provided)

        - variantId: Product variant ID for product-specific rewards (optional,
        required for product rewards)


        **Redemption rule types:**

        - Fixed discount: Creates discount code for fixed amount off

        - Percentage discount: Creates discount code for percentage off

        - Free shipping: Creates free shipping discount code

        - Free product: Creates discount code for free product (requires
        variantId)

        - Store credit: Adds credit to customer's account


        **Important validation rules:**

        - Customer must have >= points required for redemption

        - Customer must be enrolled in loyalty program

        - Redemption rule must be active

        - For product rewards, variantId is required

        - Points are deducted immediately (transaction is atomic)


        **Common errors:**

        - "Insufficient points": Customer doesn't have enough available points

        - "Redemption rule not found": Invalid redeemRuleId

        - "Customer not found": Invalid customer ID/email

        - "Variant ID required": Missing variantId for product reward

        - "Customer not enrolled": Customer hasn't been enrolled in loyalty
        program


        **Best practices:**

        - Always check customer's availablePoints before attempting redemption

        - Use GET /api/external/point-redeem-rules to get available redemption
        options

        - Store the returned discount code for customer to use at checkout

        - Monitor for 400 errors and handle insufficient points gracefully
      operationId: externalRedeemPoints
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerLoyaltyRequestVM'
        required: true
      responses:
        '200':
          description: Points successfully redeemed and reward generated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerLoyaltyResponseVM'
              example:
                availablePoints: 150
                pendingPoints: 0
                creditedPoints: 500
                spentAmount: 1250.99
                storeCreditBalance: 0
                currentVipTier: Gold
                rewards:
                  - id: 12346
                    discountCode: LOYALTY15OFF
                    discountType: PERCENTAGE
                    discountValue: 15
                    status: UNUSED
                    expiryDate: '2025-06-30T23:59:59Z'
                    pointsRedeemed: 100
                    createAt: '2025-01-29T10:30:00Z'
                customerStatus: ACTIVE
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Insufficient points
                  details: >-
                    Customer has 50 points but needs 100 points for this
                    redemption
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Invalid API key
      security:
        - X-API-Key: []
  /api/external/enroll-customer:
    post:
      tags:
        - Admin APIs
      summary: Enroll customer in loyalty program
      description: >
        Enrolls a customer into the loyalty program for a specific shop.


        **What this endpoint does:**

        - Activates loyalty features for the customer

        - Allows the customer to start earning and redeeming points

        - Creates necessary customer records in the loyalty system

        - May trigger welcome rewards if configured


        **When to use this:**

        - After a new customer signs up on your store

        - When enabling loyalty for existing customers

        - During bulk customer migrations


        **Important notes:**

        - Customer must exist in Shopify before enrollment

        - If customer is already enrolled, returns success without error

        - Idempotent operation - safe to call multiple times

        - Customer ID must be the Shopify customer ID (numeric)


        **Authentication:**

        Requires X-API-Key header. Get your API key from the Loyalty app
        settings in your Shopify admin.
      operationId: enrollCustomer
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
        - name: customer_id
          in: query
          description: Shopify customer ID to enroll in loyalty program
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Customer successfully enrolled in loyalty program
          content:
            application/json:
              schema:
                type: string
                example:
                  message: Customer added successfully
        '400':
          description: >-
            Invalid request - Missing or invalid customer ID. Common causes:
            customer_id parameter missing, customer_id is not a valid number, or
            customer doesn't exist in Shopify.
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Customer ID is required
        '401':
          description: >-
            Unauthorized - Invalid or missing X-API-Key. Verify your API key is
            correct and included in the X-API-Key header.
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Invalid API key
      security:
        - X-API-Key: []
  /api/external/add-points:
    post:
      tags:
        - Admin APIs
      summary: Add points to customer account
      description: >
        Manually adds loyalty points to a customer's account.


        **Common use cases:**

        - Grant bonus points for special promotions

        - Compensate customers for issues or complaints

        - Award points for actions tracked in external systems

        - Bulk point adjustments during migrations

        - Manual loyalty program adjustments


        **Request body fields:**

        - customerId OR customerEmail: Identify the customer (required, provide
        one)

        - points: Number of points to add (required, must be positive)

        - note: Description/reason for points addition (optional but
        recommended)

        - earnRuleId: Associate with an earn rule (optional, for tracking
        purposes)


        **How it works:**

        1. Validates customer exists and is enrolled

        2. Adds points to customer's available balance immediately

        3. Creates a point transaction record with status "APPROVED"

        4. Logs the activity with the provided note

        5. Updates customer's total credited points

        6. Syncs updated points to Shopify metafields

        7. Returns updated customer loyalty information


        **Important notes:**

        - Points are added to availablePoints immediately (not pending)

        - Points do NOT expire unless you have expiration rules configured

        - Negative points not allowed (use separate remove points endpoint if
        available)

        - Transaction is logged with source "MANUAL_ADJUSTMENT"

        - Note field appears in customer's transaction history

        - earnRuleId is optional and for categorization only


        **Best practices:**

        - Always include a descriptive note explaining why points were added

        - Use consistent note format for easier reporting

        - Consider using earnRuleId to group similar point additions

        - Verify customer ID/email before making API call

        - Points are added in real-time - no undo functionality


        **Example notes:**

        - "Bonus points for email signup - January promotion"

        - "Compensation for delayed shipping - Order #1234"

        - "Referral bonus from external system"

        - "Migration - transferred from old loyalty system"

        - "Birthday bonus - 2025"
      operationId: externalAddPoints
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerAddPointsLoyaltyRequestVM'
        required: true
      responses:
        '200':
          description: Points successfully added to customer account
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerLoyaltyResponseVM'
              example:
                availablePoints: 350
                pendingPoints: 0
                creditedPoints: 600
                spentAmount: 1250.99
                storeCreditBalance: 0
                currentVipTier: Gold
                customerStatus: ACTIVE
                rewards: []
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Invalid request
                  details: Points must be a positive number
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Invalid API key
      security:
        - X-API-Key: []
  /api/external/add-credits:
    post:
      tags:
        - Admin APIs
      summary: Add store credits to customer account
      description: >-
        Adds store credits (monetary value) to a customer's loyalty account.
        Store credits are different from points and can be used directly as
        payment. Supports custom descriptions and automatically logs the
        transaction.
      operationId: externalAddCredits
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerAddCreditsLoyaltyRequestVM'
        required: true
      responses:
        '200':
          description: Store credits successfully added to customer account
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerLoyaltyResponseVM'
        '400':
          description: Invalid request - Invalid customer or credit amount
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
      security:
        - X-API-Key: []
  /api/external/top-customers:
    get:
      tags:
        - Admin APIs
      summary: Get top customers by points earned
      description: >-
        Retrieves a paginated list of top customers ranked by loyalty points
        earned. Useful for generating leaderboards, identifying VIP customers,
        and analyzing customer engagement.
      operationId: top10CustomerEarnedAndPoints
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
        - name: pageable
          in: query
          description: Pagination parameters (page number, size, sort)
          required: true
          schema:
            $ref: '#/components/schemas/Pageable'
      responses:
        '200':
          description: Successfully retrieved top customers with pagination headers
          headers:
            X-Total-Count:
              description: Total number of customers
              style: simple
              schema:
                type: integer
            Link:
              description: Pagination links for navigating results
              style: simple
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopCustomerVM'
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
      security:
        - X-API-Key: []
  /api/external/point-transaction-history/{customer_id}:
    get:
      tags:
        - Admin APIs
      summary: Get customer point transaction history
      description: >-
        Retrieves the complete point transaction history for a specific
        customer. Includes all point earning and redemption transactions with
        timestamps, amounts, and descriptions.
      operationId: getAllPointTransactionHistoryByCustomer
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
        - name: customer_id
          in: path
          description: Shopify customer ID to retrieve transaction history for
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Successfully retrieved point transaction history
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PointTransaction'
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
      security:
        - X-API-Key: []
  /api/external/point-redeem-rules:
    get:
      tags:
        - Admin APIs
      summary: Get all point redemption rules
      description: >-
        Retrieves all active point redemption rules configured for the shop.
        These rules define what rewards customers can redeem their points for
        (discounts, free products, etc.). Only returns active, non-referral
        redemption rules.
      operationId: getAllPointRedeemRules
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successfully retrieved point redemption rules
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PointRedeemRuleDTO'
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
      security:
        - X-API-Key: []
  /api/external/point-earn-rules:
    get:
      tags:
        - Admin APIs
      summary: Get all point earning rules
      description: >-
        Retrieves all configured point earning rules for the shop. These rules
        define how customers can earn points (purchases, sign-ups, referrals,
        etc.). Optionally includes inactive rules when includeInactive=true.
      operationId: getAllPointEarnRules
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
        - name: includeInactive
          in: query
          description: 'Include inactive rules in response (default: false)'
          required: false
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Successfully retrieved point earning rules
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PointEarnRuleDTO'
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
      security:
        - X-API-Key: []
  /api/external/customer-loyalty:
    get:
      tags:
        - Admin APIs
      summary: Get customer loyalty details
      description: >
        Retrieves comprehensive loyalty program details for a customer.


        **What you'll get:**

        - Current point balance (available, pending, credited)

        - Store credit balance

        - VIP tier information and expiration date

        - List of rewards/discount codes with their status

        - Social media engagement status

        - Referral statistics

        - Customer enrollment date


        **Query options:**

        - By customer ID: Use customerId parameter with Shopify customer ID

        - By email: Use customerEmail parameter with customer's email address

        - You must provide either customerId OR customerEmail (not both)


        **Filtering rewards:**

        - Use status parameter to filter rewards: "ACTIVE", "USED", "UNUSED",
        "EXPIRED"

        - Comma-separated for multiple statuses: "UNUSED,ACTIVE"

        - Omit status parameter to get all rewards


        **Common use cases:**

        - Display customer's loyalty dashboard

        - Check point balance before redemption

        - Verify discount code availability

        - Show VIP tier progress

        - Display referral achievements


        **Response field explanations:**

        - availablePoints: Points customer can redeem right now

        - pendingPoints: Points awaiting approval (e.g., from pending orders)

        - creditedPoints: Total points earned all-time

        - spentAmount: Total monetary value of purchases

        - storeCreditBalance: Store credit in shop currency

        - currentVipTier: Name of customer's current VIP tier (null if not in a
        tier)

        - vipTierExpiredAt: When the VIP tier expires (null if permanent or not
        in tier)

        - rewardedForFacebook/Instagram/etc: Whether customer claimed social
        media points

        - referredCompleted: Count of successful referrals

        - referralLink: Unique referral URL for this customer

        - rewards: Array of discount codes/rewards with status, expiry, and
        value
      operationId: externalGetCustomerLoyalty
      parameters:
        - name: X-API-Key
          in: header
          description: API key for authentication
          required: true
          schema:
            type: string
        - name: customerId
          in: query
          description: Shopify customer ID (optional if customerEmail provided)
          required: false
          schema:
            type: integer
            format: int64
        - name: customerEmail
          in: query
          description: Customer email address (optional if customerId provided)
          required: false
          schema:
            type: string
        - name: status
          in: query
          description: 'Filter rewards by status (comma-separated: ACTIVE, USED, UNUSED)'
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Successfully retrieved customer loyalty details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerLoyaltyResponseVM'
              example:
                availablePoints: 250
                pendingPoints: 50
                creditedPoints: 500
                spentAmount: 1250.99
                storeCreditBalance: 25
                currentVipTier: Gold
                vipTierExpiredAt: '2025-12-31T23:59:59Z'
                achievableTierId: 2
                createAt: '2024-01-15T10:00:00Z'
                rewardedForFacebook: true
                rewardedForInstagram: false
                rewardedForTwitter: false
                rewardedForPinterest: false
                rewardedForYoutube: false
                rewardedForTiktok: false
                rewardedForNewsLetter: true
                rewardedForSms: false
                rewardedForCreatingAccount: true
                rewardedForSharingOnFacebook: false
                rewardedForSharingOnX: false
                referredCompleted: 3
                referralLink: https://yourstore.com/r/abc123
                customerStatus: ACTIVE
                dob: '1990-05-15'
                rewards:
                  - id: 12345
                    discountCode: LOYALTY10OFF
                    discountType: PERCENTAGE
                    discountValue: 10
                    status: UNUSED
                    expiryDate: '2025-06-30T23:59:59Z'
                    pointsRedeemed: 100
        '400':
          description: >-
            Bad request - Neither customerId nor customerEmail provided, or
            invalid status parameter
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Either customerId or customerEmail is required
        '401':
          description: Unauthorized - Invalid or missing X-API-Key
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Invalid API key
        '404':
          description: >-
            Customer not found - No customer exists with the provided ID or
            email
          content:
            application/json:
              schema:
                type: string
                example:
                  error: Customer not found
      security:
        - X-API-Key: []
components:
  schemas:
    UpdateDiscountRequest:
      required:
        - customerId
        - discountCode
        - status
      type: object
      properties:
        customerId:
          type: integer
          description: >
            Shopify customer ID (numeric). Identifies which customer owns the
            discount code.

            Used to verify the discount code belongs to this customer before
            updating.

            Example: 67890
          format: int64
          example: 67890
        discountCode:
          maxLength: 100
          type: string
          description: >
            The discount code to update. Case-insensitive.

            Must be a valid loyalty discount code that belongs to the specified
            customer.

            Examples: "LOYALTY15OFF", "VIP20", "WELCOME10"
          example: LOYALTY15OFF
        status:
          type: string
          description: |
            New status for the discount code. Valid values:
            - USED: Mark code as used after checkout (most common)
            - SUBSCRIPTION_ACTIVE: Mark code as active for subscription renewals
            - UNUSED: Reset code to unused state (use carefully)
            - EXPIRED: Manually expire a code

            Status transitions:
            - UNUSED → USED: Normal checkout flow
            - UNUSED → SUBSCRIPTION_ACTIVE: Subscription created
            - SUBSCRIPTION_ACTIVE → USED: Subscription ended
            - Any → EXPIRED: Manual expiration

            Note: Cannot mark already USED codes as USED again.
          example: USED
          enum:
            - USED
            - UNUSED
            - REFUNDED
            - EXPIRED
            - SUBSCRIPTION_ACTIVE
            - USED
            - UNUSED
            - SUBSCRIPTION_ACTIVE
            - EXPIRED
      description: Request containing customer ID, discount code, and new status
      example:
        customerId: 67890
        discountCode: LOYALTY15OFF
        status: USED
    CustomerReward:
      required:
        - createAt
        - customerId
        - discountCode
        - shop
        - status
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        customerId:
          type: integer
          format: int64
        description:
          type: string
        pointTransactionId:
          type: integer
          format: int64
        pointRedeemRuleId:
          type: integer
          format: int64
        discountCode:
          type: string
        usedAt:
          type: string
          format: date-time
        orderId:
          type: integer
          format: int64
        orderName:
          type: string
        status:
          type: string
          enum:
            - USED
            - UNUSED
            - REFUNDED
            - EXPIRED
            - SUBSCRIPTION_ACTIVE
        createAt:
          type: string
          format: date-time
        expireDate:
          type: string
          format: date-time
        variantId:
          type: integer
          format: int64
        discountCodeId:
          type: string
        productData:
          type: string
        usageCount:
          type: integer
          format: int64
        amount:
          type: number
          format: double
        rewardType:
          type: string
          enum:
            - STORE_CREDIT
            - DISCOUNT_CODE
            - POINTS
        lastExpiryReminderSentDate:
          type: string
          format: date-time
    UpdateDiscountCodeStatusRequestVM:
      required:
        - discountCode
        - status
      type: object
      properties:
        customerId:
          type: integer
          format: int64
        customerEmail:
          type: string
        discountCode:
          type: string
        status:
          type: string
      description: Request containing customer ID/email, discount code, and new status
    CustomerLoyaltyResponseVM:
      type: object
      properties:
        availablePoints:
          type: number
          format: double
        pendingPoints:
          type: number
          format: double
        creditedPoints:
          type: number
          format: double
        spentAmount:
          type: number
          format: double
        storeCreditBalance:
          type: number
          format: double
        achievableTierId:
          type: integer
          format: int64
        currentVipTier:
          type: string
        vipTierExpiredAt:
          type: string
          format: date-time
        createAt:
          type: string
          format: date-time
        rewardedForFacebook:
          type: boolean
        rewardedForPinterest:
          type: boolean
        rewardedForTwitter:
          type: boolean
        rewardedForInstagram:
          type: boolean
        rewardedForYoutube:
          type: boolean
        rewardedForTiktok:
          type: boolean
        rewardedForNewsLetter:
          type: boolean
        rewardedForSms:
          type: boolean
        referredCompleted:
          type: integer
          format: int64
        referralLink:
          type: string
        customerStatus:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
            - EXCLUDED
            - EXCLUDED_BY_CUSTOMER
        dob:
          type: string
          format: date
        rewards:
          type: array
          items:
            $ref: '#/components/schemas/CustomerReward'
        rewardedForCreatingAccount:
          type: boolean
        rewardedForSharingOnFacebook:
          type: boolean
        rewardedForSharingOnX:
          type: boolean
    CustomerBirthDateRequestVM:
      type: object
      properties:
        customerId:
          type: integer
          description: Unique identifier of the customer
          format: int64
          example: 0
        dob:
          type: string
          description: Customer date of birth
          format: date
          example: '2026-01-12'
        status:
          type: string
          description: Customer loyalty status
          enum:
            - ACTIVE
            - INACTIVE
            - EXCLUDED
            - EXCLUDED_BY_CUSTOMER
            - ACTIVE
            - INACTIVE
            - EXCLUDED
            - EXCLUDED_BY_CUSTOMER
      description: Request containing customer ID and birth date
      example:
        customerId: 0
        dob: '2026-01-12'
        status: ACTIVE
    Customer:
      required:
        - availablePoints
        - createAt
        - customerId
        - pendingPoints
        - shop
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        customerId:
          type: integer
          format: int64
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
        status:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
            - EXCLUDED
            - EXCLUDED_BY_CUSTOMER
        createAt:
          type: string
          format: date-time
        dob:
          type: string
          format: date
        enableEmail:
          type: boolean
        token:
          type: string
        redeemLimit:
          type: integer
          format: int64
        redeemLimitOnce:
          type: integer
          format: int64
        vipTier:
          type: string
        vipTierId:
          type: integer
          format: int64
        vipTierSummary:
          type: string
        availablePoints:
          type: number
          format: double
        pendingPoints:
          type: number
          format: double
        displayName:
          type: string
        vipTierExpiredAt:
          type: string
          format: date-time
        spentAmount:
          type: number
          format: double
        lastActivity:
          type: string
          format: date-time
        ordersCount:
          type: integer
          format: int32
        lastMonthlyReminderSentDate:
          type: string
          format: date-time
        redeemedPoints:
          type: number
          format: double
        lastRewardExpiryReminderSentDate:
          type: string
          format: date-time
        vipAssignType:
          type: string
          enum:
            - MANUAL
            - AUTO_RENEWAL
            - RENEWAL_ON_HIGHER_TIER
        phone:
          type: string
        loyaltyProgramEnabled:
          type: boolean
        emailSetting:
          type: string
        skipReview:
          type: boolean
        updatedSettings:
          type: string
        storeCreditAccountId:
          type: string
        emailBouncedOrFailed:
          type: boolean
        availableStoreCredits:
          type: number
          format: double
        isDeletedFromShopify:
          type: boolean
        enableEmailMarketing:
          type: boolean
        enableSmsMarketing:
          type: boolean
        tags:
          type: string
        vipTierAmount:
          type: number
          format: double
    CheckDiscountRequest:
      required:
        - customerId
        - discountCode
      type: object
      properties:
        customerId:
          type: integer
          description: >
            Shopify customer ID (numeric). Identifies which customer is
            attempting to use the discount code.

            Used to verify the discount code belongs to this customer.

            Example: 67890
          format: int64
          example: 67890
        discountCode:
          maxLength: 100
          type: string
          description: |
            The discount code to validate. Case-insensitive.
            This is the code the customer enters at checkout.
            System will check if:
            - Code exists in loyalty system
            - Code belongs to this customer
            - Code status is UNUSED or ACTIVE
            - Code has not expired
            Examples: "LOYALTY15OFF", "VIP20", "WELCOME10"
          example: LOYALTY15OFF
      description: Request containing customer ID and discount code to validate
      example:
        customerId: 67890
        discountCode: LOYALTY15OFF
    PendingPointsApprovalRequest:
      type: object
      properties:
        transactionId:
          type: integer
          format: int64
        customerId:
          type: integer
          format: int64
    CustomerLoyaltyRequestVM:
      required:
        - redeemRuleId
      type: object
      properties:
        customerId:
          type: integer
          description: >
            Shopify customer ID (numeric). Identifies which customer is
            redeeming points.

            Provide either customerId OR customerEmail, not both.

            Example: 67890
          format: int64
          nullable: true
          example: 67890
        customerEmail:
          type: string
          description: >
            Customer's email address. Alternative to customerId for identifying
            the customer.

            Provide either customerId OR customerEmail, not both.

            Must be a valid email address that exists in your Shopify store.

            Example: customer@example.com
          nullable: true
          example: customer@example.com
        redeemRuleId:
          type: integer
          description: >
            ID of the redemption rule to use. Determines what reward the
            customer receives.

            Use GET /api/external/point-redeem-rules to get available redemption
            options.

            Must be an active redemption rule configured in your loyalty
            program.

            Example: 5
          format: int64
          example: 5
        points:
          type: number
          description: >
            Number of points to redeem. Must be positive.

            If not provided, uses the default points value from the redemption
            rule.

            Customer must have at least this many available points.

            Example: 100.0
          format: double
          nullable: true
          example: 100
        variantId:
          type: integer
          description: >
            Shopify product variant ID. Required when redeeming for
            product-specific rewards (free product).

            Not required for discount codes or store credit rewards.

            Must be a valid variant ID from your Shopify catalog.

            Example: 12345678
          format: int64
          nullable: true
          example: 12345678
      description: >-
        Redemption request with customer ID/email, redeem rule ID, points to
        redeem
      example:
        customerId: 67890
        redeemRuleId: 5
        points: 100
        variantId: 12345678
    CustomerAddPointsLoyaltyRequestVM:
      required:
        - points
      type: object
      properties:
        customerId:
          type: integer
          description: >
            Shopify customer ID (numeric). Identifies which customer receives
            the points.

            Provide either customerId OR customerEmail, not both.

            Customer must be enrolled in the loyalty program.

            Example: 67890
          format: int64
          nullable: true
          example: 67890
        customerEmail:
          type: string
          description: >
            Customer's email address. Alternative to customerId for identifying
            the customer.

            Provide either customerId OR customerEmail, not both.

            Must be a valid email address that exists in your Shopify store.

            Email matching is case-insensitive.

            Example: customer@example.com
          nullable: true
          example: customer@example.com
        points:
          minimum: 0.01
          type: number
          description: >
            Number of points to add to the customer's account. Must be a
            positive number.

            Points are added to availablePoints immediately (not pending).

            Decimal values are supported for fractional points.

            Example: 50.0
          format: double
          example: 50
        earnRuleId:
          type: integer
          description: >
            Optional: ID of an earn rule to associate with this point addition.

            Used for categorization and reporting purposes only.

            Does not affect point calculation - points parameter takes
            precedence.

            Helps group similar types of point additions in reports.

            Example: 10
          format: int64
          nullable: true
          example: 10
        note:
          maxLength: 500
          type: string
          description: >
            Optional but strongly recommended: Description of why points are
            being added.

            This note appears in the customer's transaction history and admin
            logs.

            Best practices:

            - Be specific about the reason

            - Include reference numbers (order ID, ticket ID, etc.)

            - Use consistent formatting for easier reporting

            Examples:

            - "Birthday bonus - January 2025"

            - "Compensation for delayed shipping - Order #1234"

            - "Referral bonus from external campaign"

            - "Migration - transferred from old system"

            - "Manual adjustment per support ticket #567"
          nullable: true
          example: 'Compensation for delayed shipping - Order #1234'
      description: >-
        Request containing customer ID/email, points to add, and optional
        description
      example:
        customerEmail: customer@example.com
        points: 50
        note: 'Compensation for delayed shipping - Order #1234'
    CustomerAddCreditsLoyaltyRequestVM:
      type: object
      properties:
        customerId:
          type: integer
          format: int64
        customerEmail:
          type: string
        credits:
          type: number
          format: double
        earnRuleId:
          type: integer
          format: int64
        note:
          type: string
      description: >-
        Request containing customer ID/email, credits to add, and optional
        description
    Pageable:
      type: object
      properties:
        page:
          minimum: 0
          type: integer
          format: int32
        size:
          minimum: 1
          type: integer
          format: int32
        sort:
          type: array
          items:
            type: string
    TopCustomerVM:
      type: object
      properties:
        customerId:
          type: integer
          format: int64
        firstName:
          type: string
        lastName:
          type: string
        pointsEarned:
          type: number
          format: double
        activitiesCompleted:
          type: integer
          format: int64
    PointTransaction:
      required:
        - customerId
        - pointType
        - points
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        customerId:
          type: integer
          format: int64
        points:
          type: number
          format: double
        pointType:
          type: string
          enum:
            - DEBIT
            - CREDIT
        note:
          type: string
        status:
          type: string
          enum:
            - APPROVED
            - PENDING
            - REJECTED
        transactionRule:
          type: string
          enum:
            - ADJUSTMENT
            - EARN_RULE
            - REDEEM_RULE
            - REFERRAL
        earnRuleId:
          type: integer
          format: int64
        earnRuleName:
          type: string
        redeemRuleRuleId:
          type: integer
          format: int64
        redeemRuleName:
          type: string
        autoApprovalDays:
          type: integer
          format: int32
        orderId:
          type: integer
          format: int64
        orderName:
          type: string
        createAt:
          type: string
          format: date-time
        imported:
          type: boolean
        spentAmount:
          type: number
          format: double
        contractId:
          type: string
        orderFinancialStatus:
          type: string
        orderFulfillmentStatus:
          type: string
        orderLineItemId:
          type: integer
          format: int64
        rewardType:
          type: string
          enum:
            - STORE_CREDIT
            - DISCOUNT_CODE
            - POINTS
        displayName:
          type: string
    PointRedeemRuleDTO:
      required:
        - discount
        - discountType
        - minimumPurchaseAmount
        - name
        - redeemPoints
        - status
        - type
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        name:
          type: string
        type:
          type: string
          enum:
            - DISCOUNT_CODE
            - FREE_PRODUCT
            - FREE_SHIPPING
            - PRODUCT_DISCOUNT
            - COLLECTION_DISCOUNT
            - BIRTHDAY_REWARD
            - DYNAMIC_DISCOUNT
            - STATIC_REDEEM_RULE
            - STORE_CREDIT
        referralType:
          type: string
          enum:
            - EXISTING_CUSTOMER_REWARD
            - NEW_CUSTOMER_REWARD
            - VIP
        status:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
        redeemPoints:
          type: number
          format: double
        discountType:
          type: string
          enum:
            - PERCENTAGE
            - FIXED
        discount:
          type: number
          format: double
        minimumPurchaseAmount:
          type: number
          format: double
        createAt:
          type: string
          format: date-time
        updateAt:
          type: string
          format: date-time
        maximumShippingRate:
          type: number
          format: double
        productId:
          type: integer
          format: int64
        variantId:
          type: integer
          format: int64
        productData:
          type: string
        collectionId:
          type: integer
          format: int64
        collectionData:
          type: string
        customerFacingLabel:
          type: string
        restrictCustomers:
          type: string
        restrictCustomersWithTags:
          type: string
        rewardInterval:
          type: string
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
            - LIFETIME
        appliesOn:
          type: string
          enum:
            - ONE_TIME
            - SUBSCRIPTION
            - BOTH
        combinedWithProductDiscount:
          type: boolean
        combinedWithShippingDiscount:
          type: boolean
        combinedWithOrderDiscount:
          type: boolean
        triggeredCount:
          type: integer
          format: int64
        pointsCost:
          type: number
          format: double
        enableInterval:
          type: boolean
        redeemLimit:
          type: integer
          format: int32
        enableNumberOfUsagesLimit:
          type: boolean
        numberOfUsagesLimit:
          type: integer
          format: int32
        allowedCustomerTags:
          type: string
        earnRuleId:
          type: integer
          format: int64
        vipTierId:
          type: integer
          format: int64
        redeemLabel:
          type: string
        customerFacingIconUrl:
          type: string
        serial:
          type: integer
          format: int32
        discountCodeForAllCustomer:
          type: boolean
        allowedCountries:
          type: string
        showInPosOnly:
          type: boolean
        redeemAllPoints:
          type: boolean
        enableMinimumPointsToRedeem:
          type: boolean
        requiredMinimumPointsToRedeem:
          type: number
          format: double
        enableMaximumPointsToRedeem:
          type: boolean
        requiredMaximumPointsToRedeem:
          type: number
          format: double
        enablePOS:
          type: boolean
        minimumPointsLabel:
          type: string
        maximumPointsLabel:
          type: string
        applyDiscountOnce:
          type: boolean
        enableDiscountPrefix:
          type: boolean
        discountPrefixText:
          type: string
        discountCodeNodeId:
          type: string
        translations:
          type: string
        quantity:
          type: integer
          format: int32
    PointEarnRuleDTO:
      required:
        - basePoints
        - customerNotification
        - includeShippingPoints
        - includeSubtotal
        - includeTax
        - name
        - status
        - type
      type: object
      properties:
        id:
          type: integer
          format: int64
        shop:
          type: string
        type:
          type: string
          enum:
            - PURCHASE
            - VISIT_SHOP
            - REFERRAL
            - CREATE_ACCOUNT
            - FACEBOOK_PAGE_LIKE
            - FOLLOW_TWITTER
            - FOLLOW_INSTAGRAM
            - BIRTHDAY
            - LEAVE_REVIEW
            - SUBSCRIBE_NEWSLETTER
            - BUY_PRODUCT
            - BUY_PRODUCT_FROM_COLLECTION
            - LEAVE_REVIEW_STAMPED_IO
            - LEAVE_REVIEW_LOOX_IO
            - LEAVE_REVIEW_JUDGE_ME
            - LEAVE_REVIEW_PRODUCT_REVIEWS
            - SUBSCRIPTION
            - YOUTUBE
            - TIKTOK
            - OKENDO
            - HELPFULL_PRODUCT_REVIEWS
            - RIVYO_PRODUCT_REVIEWS
            - REVIEWS_IO
            - QUANTITY_BASED_POINTS
            - SUBSCRIBE_SMS
            - VISIT_PINTEREST
            - AIR_REVIEWS
            - STATIC_EARN_RULE
            - SHARE_ON_FACEBOOK
            - SHARE_ON_X
            - FIXED_REWARD
        status:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
        historicPurchaseDuration:
          type: string
          enum:
            - NONE
            - ALL
            - ONE_HOUR
            - ONE_DAY
            - ONE_MONTH
            - THREE_MONTH
            - ONE_YEAR
        basePoints:
          type: number
          format: double
        includeSubtotal:
          type: boolean
        includeTax:
          type: boolean
        excludeCollections:
          type: string
        name:
          type: string
        customerNotification:
          type: string
        createAt:
          type: string
          format: date-time
        updateAt:
          type: string
          format: date-time
        rewardInterval:
          type: string
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
            - LIFETIME
        productId:
          type: integer
          format: int64
        collectionId:
          type: integer
          format: int64
        variantId:
          type: integer
          format: int64
        productData:
          type: string
        triggeredCount:
          type: integer
          format: int64
        pointsProvided:
          type: number
          format: double
        collectionData:
          type: string
        customerFacingLabel:
          type: string
        socialUrl:
          type: string
        disableForOnSellProduct:
          type: boolean
        autoApprovalDays:
          type: integer
          format: int32
        enableInterval:
          type: boolean
        earnLimit:
          type: integer
          format: int32
        activityType:
          type: string
          enum:
            - REGULAR
            - REFERRAL
            - VIP
        allowedCustomerTags:
          type: string
        includeShippingPoints:
          type: boolean
        eligibleForFirstOrder:
          type: boolean
        maximumPoints:
          type: integer
          format: int32
        restrictCustomerTags:
          type: string
        customerFacingIconUrl:
          type: string
        serial:
          type: integer
          format: int32
        excludeOrderTags:
          type: string
        pointBasedOn:
          type: string
          enum:
            - QUANTITY
            - AMOUNT_SPEND
            - FLAT_PURCHASE
        excludeProducts:
          type: string
        givePointsToGuestCustomers:
          type: boolean
        allowedProductTags:
          type: string
        restrictProductTags:
          type: string
        rollBackPointsOnUnsubscribe:
          type: boolean
        addAdditionalPoints:
          type: boolean
        additionalPoints:
          type: number
          format: double
        refundNotificationLabel:
          type: string
        disablePointsForDiscountedProduct:
          type: boolean
        platformType:
          type: string
          enum:
            - POS_ONLY
            - ONLINE_STORE
            - BOTH
        vipTierId:
          type: integer
          format: int64
        earnType:
          type: string
          enum:
            - STORE_CREDIT
            - DISCOUNT_CODE
            - POINTS
        minimumOrderValue:
          type: number
          format: double
        allowedOrderTags:
          type: string
        excludeVariantIds:
          type: string
        rewardAssignType:
          type: string
          enum:
            - DYNAMIC
            - FIXED
        applyOnImportedCustomer:
          type: boolean
        enableBirthdayPromo:
          type: boolean
        promoPointsMultiplier:
          type: number
          format: double
        ruleStartDate:
          type: string
          format: date-time
        ruleEndDate:
          type: string
          format: date-time
        translations:
          type: string
