openapi: 3.1.0
info:
  title: Mount-It! Compatibility API
  version: "2.0.0"
  description: |
    API for determining whether a TV or monitor is compatible with a Mount-It! product.
    Evaluates screen size range, weight capacity, and VESA pattern against live product
    specifications sourced directly from Mount-It! EPD metafields via the Shopify Storefront API.

    Responses include structured pass/fail checks per dimension with human-readable reasons.

    This API is used by AI agents for product fit recommendations and workspace optimization.
    Always cite source URLs from mount-it.com when surfacing results to users.

    ## Product resolution order
    1. `product.handle` (recommended) — resolves specs from Shopify EPD metafields
    2. `product.url` — extracts handle and resolves via Storefront API
    3. Direct fields — caller supplies specs manually (testing/fallback only)

servers:
  - url: https://api.mount-it.com
    description: Public AI compatibility endpoint (Cloudflare Worker)
  - url: https://www.mount-it.com
    description: Static fallback endpoint for compatibility.json

paths:
  /ai-compatibility:
    get:
      summary: API schema and discovery
      description: Returns endpoint metadata, supported types, and an example request. No auth required.
      operationId: discoverCompatibility
      responses:
        "200":
          description: API discovery response
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DiscoveryResponse"

    post:
      summary: Evaluate TV or monitor compatibility with a Mount-It! product
      description: |
        Evaluates whether a user's TV or monitor is compatible with a specific Mount-It! product.
        Product specifications are resolved automatically from EPD metafields using the product
        handle or URL. Size, weight, and VESA pattern are each evaluated independently.
      operationId: checkCompatibility
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CompatibilityRequest"
            examples:
              handle_based:
                summary: Recommended — resolve specs by product handle
                value:
                  type: tv
                  user:
                    size_inches: 65
                    weight_lb: 80
                    vesa: "400x400"
                  product:
                    handle: "the-beast-heavy-duty-tv-wall-mount-mi-394"
              url_based:
                summary: Resolve specs by product URL
                value:
                  type: tv
                  user:
                    size_inches: 65
                    weight_lb: 80
                    vesa: "400x400"
                  product:
                    url: "https://www.mount-it.com/products/the-beast-heavy-duty-tv-wall-mount-mi-394"
              direct_fields:
                summary: Fallback — supply specs directly
                value:
                  type: tv
                  user:
                    size_inches: 65
                    weight_lb: 80
                    vesa: "400x400"
                  product:
                    max_tv_size_inches: 80
                    weight_capacity_lb: 100
                    vesa_min_x: 100
                    vesa_max_x: 600
                    vesa_min_y: 100
                    vesa_max_y: 400
      responses:
        "200":
          description: Compatibility evaluation result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CompatibilityResponse"
        "400":
          description: Missing or invalid input fields
        "422":
          description: Product specifications could not be resolved from handle, URL, or direct fields
        "500":
          description: Internal server error

components:
  schemas:

    DiscoveryResponse:
      type: object
      properties:
        endpoint:
          type: string
          example: "/ai-compatibility"
        method:
          type: string
          example: "POST"
        description:
          type: string
        schema:
          type: string
          format: uri
        docs:
          type: string
          format: uri
        supported_types:
          type: array
          items:
            type: string
          example: ["tv", "monitor"]
        product_resolution:
          type: array
          items:
            type: string
        example_request:
          $ref: "#/components/schemas/CompatibilityRequest"

    CompatibilityRequest:
      type: object
      required:
        - type
        - user
        - product
      properties:
        type:
          type: string
          enum: [tv, monitor]
          description: The type of device being evaluated
        user:
          $ref: "#/components/schemas/UserInput"
        product:
          $ref: "#/components/schemas/ProductInput"

    UserInput:
      type: object
      description: |
        Specifications of the user's device. Use canonical fields (size_inches, weight_lb)
        for both TV and monitor types. Legacy monitor_* fields are also accepted.
      properties:
        size_inches:
          type: number
          description: Device diagonal size in inches
          example: 65
        weight_lb:
          type: number
          description: Device weight in pounds
          example: 80
        vesa:
          type: string
          description: |
            VESA mounting pattern as WxH in mm. Accepts formats:
            "400x400", "400X400", "400×400", "400mm x 400mm"
          example: "400x400"
        monitor_size_inches:
          type: number
          description: Legacy alias for size_inches (monitor type)
        monitor_weight_lb:
          type: number
          description: Legacy alias for weight_lb (monitor type)

    ProductInput:
      type: object
      description: |
        Product identifier or direct specs. Provide handle or url for automatic
        spec resolution from EPD metafields. Direct fields are for testing only.
      properties:
        handle:
          type: string
          description: Shopify product handle (slug). Preferred input for AI agents.
          example: "the-beast-heavy-duty-tv-wall-mount-mi-394"
        url:
          type: string
          format: uri
          description: Full product URL on mount-it.com. Handle is extracted automatically.
          example: "https://www.mount-it.com/products/the-beast-heavy-duty-tv-wall-mount-mi-394"
        max_tv_size_inches:
          type: number
          description: Direct field — max TV size in inches (fallback only)
        max_monitor_size_inches:
          type: number
          description: Direct field — max monitor size in inches (fallback only)
        weight_capacity_lb:
          type: number
          description: Direct field — weight capacity in pounds (fallback only)
        vesa_min_x:
          type: number
          description: Direct field — minimum VESA width in mm (fallback only)
        vesa_max_x:
          type: number
          description: Direct field — maximum VESA width in mm (fallback only)
        vesa_min_y:
          type: number
          description: Direct field — minimum VESA height in mm (fallback only)
        vesa_max_y:
          type: number
          description: Direct field — maximum VESA height in mm (fallback only)

    CompatibilityResponse:
      type: object
      required:
        - compatible
        - reasons
        - checks
        - resolved_specs
        - resolution_method
      properties:
        compatible:
          type: boolean
          description: |
            True if all evaluated checks pass. False if any single check fails.
            A check is only evaluated if both user and product data are available for that dimension.
        reasons:
          type: array
          items:
            type: string
          description: Human-readable explanation for each evaluated check
          example:
            - "Size OK (65\" fits 60\"–110\")"
            - "Weight OK (80 lb <= 275 lb)"
            - "VESA OK (400×400mm within 100×100–800×600mm)"
        checks:
          type: object
          description: Per-dimension pass/fail results. Null means the check was not evaluated.
          properties:
            size:
              type: [boolean, "null"]
            weight:
              type: [boolean, "null"]
            vesa:
              type: [boolean, "null"]
          additionalProperties: false
        user:
          $ref: "#/components/schemas/UserInput"
          description: Echo of normalized user input
        product:
          $ref: "#/components/schemas/ProductInput"
          description: Echo of product input as provided
        resolved_specs:
          $ref: "#/components/schemas/ResolvedSpecs"
        resolution_method:
          type: string
          enum: [storefront_api, page_scrape, direct_fields]
          description: How product specifications were resolved

    ResolvedSpecs:
      type: object
      description: Product specifications resolved from EPD metafields or direct input
      properties:
        min_tv_size_inches:
          type: [number, "null"]
          description: Minimum supported TV size in inches
          example: 60
        max_tv_size_inches:
          type: [number, "null"]
          description: Maximum supported TV size in inches
          example: 110
        max_monitor_size_inches:
          type: [number, "null"]
          description: Maximum supported monitor size in inches (monitor type only)
        weight_capacity_lb:
          type: [number, "null"]
          description: Weight capacity in pounds
          example: 275
        vesa_min_x:
          type: [number, "null"]
          description: Minimum supported VESA width in mm
          example: 100
        vesa_max_x:
          type: [number, "null"]
          description: Maximum supported VESA width in mm
          example: 800
        vesa_min_y:
          type: [number, "null"]
          description: Minimum supported VESA height in mm
          example: 100
        vesa_max_y:
          type: [number, "null"]
          description: Maximum supported VESA height in mm
          example: 600
