openapi: 3.0.3
info:
  title: Customer Tiers API
  description: API for managing customer tiers and tier-based promotions in Medusa
  version: 1.0.0
  contact:
    name: Medusa
    url: https://www.medusajs.com

servers:
  - url: http://localhost:9000
    description: Local development server
  - url: https://api.example.com
    description: Production server

tags:
  - name: Admin Tiers
    description: Admin endpoints for managing customer tiers
  - name: Store Tiers
    description: Store endpoints for customer tier information

paths:
  /admin/tiers:
    get:
      tags:
        - Admin Tiers
      summary: List all tiers
      description: Retrieve a paginated list of all customer tiers
      operationId: listTiers
      security:
        - bearerAuth: []
      parameters:
        - name: limit
          in: query
          description: Limit the number of tiers returned
          required: false
          schema:
            type: integer
            default: 15
            minimum: 1
            maximum: 100
        - name: offset
          in: query
          description: Number of tiers to skip
          required: false
          schema:
            type: integer
            default: 0
            minimum: 0
        - name: fields
          in: query
          description: Comma-separated list of fields to include in the response
          required: false
          schema:
            type: string
            default: "id,name,promotion.id,promotion.code"
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TierListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'

    post:
      tags:
        - Admin Tiers
      summary: Create a new tier
      description: Create a new customer tier with rules and optional promotion
      operationId: createTier
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTierRequest'
      responses:
        '200':
          description: Tier created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TierResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /admin/tiers/{id}:
    get:
      tags:
        - Admin Tiers
      summary: Get a tier by ID
      description: Retrieve a specific tier by its ID
      operationId: getTier
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          description: The tier ID
          schema:
            type: string
        - name: fields
          in: query
          description: Comma-separated list of fields to include in the response
          required: false
          schema:
            type: string
            default: "id,name,promotion.id,promotion.code,tier_rules.*"
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TierResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

    post:
      tags:
        - Admin Tiers
      summary: Update a tier
      description: Update an existing tier's name, promotion, and rules
      operationId: updateTier
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          description: The tier ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateTierRequest'
      responses:
        '200':
          description: Tier updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TierResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

    delete:
      tags:
        - Admin Tiers
      summary: Delete a tier
      description: Delete a tier and its associated rules
      operationId: deleteTier
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          description: The tier ID
          schema:
            type: string
      responses:
        '200':
          description: Tier deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: The ID of the deleted tier
                  deleted:
                    type: boolean
                    example: true
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /admin/tiers/{id}/customers:
    get:
      tags:
        - Admin Tiers
      summary: List customers in a tier
      description: Retrieve a paginated list of customers assigned to a specific tier
      operationId: listTierCustomers
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          description: The tier ID
          schema:
            type: string
        - name: limit
          in: query
          description: Limit the number of customers returned
          required: false
          schema:
            type: integer
            default: 15
            minimum: 1
            maximum: 100
        - name: offset
          in: query
          description: Number of customers to skip
          required: false
          schema:
            type: integer
            default: 0
            minimum: 0
        - name: fields
          in: query
          description: Comma-separated list of fields to include in the response
          required: false
          schema:
            type: string
            default: "id,email,first_name,last_name"
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /store/customers/me/next-tier:
    get:
      tags:
        - Store Tiers
      summary: Get next tier upgrade information
      description: Get information about the customer's current tier and next tier upgrade requirements
      operationId: getNextTier
      security:
        - bearerAuth: []
      parameters:
        - name: region_id
          in: query
          required: true
          description: The region ID to calculate tier based on purchase value
          schema:
            type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NextTierResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT token for authentication

  schemas:
    Tier:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the tier
        name:
          type: string
          description: Name of the tier
        promo_id:
          type: string
          nullable: true
          description: ID of the promotion associated with this tier
        promotion:
          type: object
          nullable: true
          properties:
            id:
              type: string
            code:
              type: string
        tier_rules:
          type: array
          items:
            $ref: '#/components/schemas/TierRule'
          description: List of rules that define tier eligibility

    TierRule:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the tier rule
        min_purchase_value:
          type: number
          description: Minimum purchase value required to qualify for this tier
          format: float
        currency_code:
          type: string
          description: Currency code for the minimum purchase value
          example: USD
        tier_id:
          type: string
          description: ID of the tier this rule belongs to

    CreateTierRequest:
      type: object
      required:
        - name
        - tier_rules
      properties:
        name:
          type: string
          description: Name of the tier
          example: Gold
        promo_id:
          type: string
          nullable: true
          description: ID of the promotion to associate with this tier
        tier_rules:
          type: array
          minItems: 1
          items:
            type: object
            required:
              - min_purchase_value
              - currency_code
            properties:
              min_purchase_value:
                type: number
                description: Minimum purchase value required to qualify for this tier
                format: float
                example: 1000.00
              currency_code:
                type: string
                description: Currency code for the minimum purchase value
                example: USD

    UpdateTierRequest:
      type: object
      required:
        - name
        - tier_rules
      properties:
        name:
          type: string
          description: Name of the tier
          example: Gold
        promo_id:
          type: string
          nullable: true
          description: ID of the promotion to associate with this tier
        tier_rules:
          type: array
          minItems: 1
          items:
            type: object
            required:
              - min_purchase_value
              - currency_code
            properties:
              min_purchase_value:
                type: number
                description: Minimum purchase value required to qualify for this tier
                format: float
                example: 1000.00
              currency_code:
                type: string
                description: Currency code for the minimum purchase value
                example: USD

    TierResponse:
      type: object
      properties:
        tier:
          $ref: '#/components/schemas/Tier'

    TierListResponse:
      type: object
      properties:
        tiers:
          type: array
          items:
            $ref: '#/components/schemas/Tier'
        count:
          type: integer
          description: Total number of tiers
        offset:
          type: integer
          description: Number of tiers skipped
        limit:
          type: integer
          description: Maximum number of tiers returned

    Customer:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the customer
        email:
          type: string
          format: email
          description: Customer email address
        first_name:
          type: string
          nullable: true
          description: Customer first name
        last_name:
          type: string
          nullable: true
          description: Customer last name

    CustomerListResponse:
      type: object
      properties:
        customers:
          type: array
          items:
            $ref: '#/components/schemas/Customer'
        count:
          type: integer
          description: Total number of customers
        offset:
          type: integer
          description: Number of customers skipped
        limit:
          type: integer
          description: Maximum number of customers returned

    NextTierResponse:
      type: object
      properties:
        current_tier:
          $ref: '#/components/schemas/Tier'
          nullable: true
          description: The customer's current tier, or null if not assigned
        current_purchase_value:
          type: number
          format: float
          description: Total purchase value for the customer in the specified region
          example: 750.50
        currency_code:
          type: string
          nullable: true
          description: Currency code for the purchase value
          example: USD
        next_tier_upgrade:
          type: object
          nullable: true
          description: Information about the next tier upgrade, or null if no upgrade available
          properties:
            tier:
              $ref: '#/components/schemas/Tier'
            required_amount:
              type: number
              format: float
              description: Additional purchase amount needed to reach the next tier
              example: 249.50
            current_purchase_value:
              type: number
              format: float
              description: Current total purchase value
              example: 750.50
            next_tier_min_purchase:
              type: number
              format: float
              description: Minimum purchase value required for the next tier
              example: 1000.00

    Error:
      type: object
      properties:
        message:
          type: string
          description: Error message
        type:
          type: string
          description: Error type
        code:
          type: string
          description: Error code

  responses:
    BadRequest:
      description: Bad request - Invalid input parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: "Invalid request body"
            type: "INVALID_DATA"
            code: "INVALID_DATA"

    Unauthorized:
      description: Unauthorized - Authentication required
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: "Unauthorized"
            type: "UNAUTHORIZED"
            code: "UNAUTHORIZED"

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: "Tier not found"
            type: "NOT_FOUND"
            code: "NOT_FOUND"

    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: "An unexpected error occurred"
            type: "UNEXPECTED_STATE"
            code: "UNEXPECTED_STATE"

