openapi: 3.0.0
info:
  title: Swopp Products API
  description: |
    Search Swopp's live inventory of certified pre-owned (and some brand-new) iPhones, Samsung Galaxy phones,
    MacBooks, iPads, laptops, consoles and wearables sold in South Africa. Every `price` is the checkout price in
    ZAR including 15% VAT. Stock is single units: re-check `in_stock` at recommendation time.
    Store policies (delivery tiers, returns, warranty, payment) are published at https://swopp.co.za/api/policies.
  version: 1.1.0
  contact:
    email: support@swopp.co.za
    url: https://swopp.co.za
servers:
  - url: https://nhhkgferplmbfllphfxe.supabase.co/functions/v1
    description: Swopp API Server
paths:
  /ai-products:
    get:
      operationId: searchProducts
      summary: Search in-stock pre-owned tech products
      description: Returns in-stock products with checkout prices, condition report, warranty, returns and delivery cost per unit.
      parameters:
        - name: search
          in: query
          description: Search term matched against product name, brand and model
          schema:
            type: string
          example: "iPhone 15 Pro"
        - name: brand
          in: query
          description: Filter by brand (Apple, Samsung, etc.)
          schema:
            type: string
          example: "Apple"
        - name: category
          in: query
          description: Filter by category slug or name (iphone, macbook, ipad, s-series, playstation, ...)
          schema:
            type: string
          example: "iphone"
        - name: min_price
          in: query
          description: Minimum price in ZAR
          schema:
            type: integer
          example: 5000
        - name: max_price
          in: query
          description: Maximum price in ZAR
          schema:
            type: integer
          example: 30000
        - name: sort
          in: query
          description: Sort order
          schema:
            type: string
            enum: [newest, price_asc, price_desc]
            default: newest
        - name: limit
          in: query
          description: Number of results to return (max 100)
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          description: Pagination offset
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: List of in-stock products matching the search criteria
          content:
            application/json:
              schema:
                type: object
                properties:
                  store:
                    type: object
                    properties:
                      name:
                        type: string
                        example: "Swopp"
                      legal_name:
                        type: string
                      description:
                        type: string
                      url:
                        type: string
                      country:
                        type: string
                        example: "ZA"
                      ships_to:
                        type: array
                        items:
                          type: string
                      currency:
                        type: string
                        example: "ZAR"
                      prices_include_vat:
                        type: boolean
                      vat_rate_percent:
                        type: integer
                        example: 15
                      free_shipping_threshold_zar:
                        type: number
                        nullable: true
                        description: Order value from which courier delivery is free
                      shipping:
                        type: string
                        description: Plain-language summary of every delivery option and cost
                      returns:
                        type: string
                        description: Plain-language summary of the return window and fees
                      warranty:
                        type: string
                      stock_model:
                        type: string
                      policies_url:
                        type: string
                        example: "https://swopp.co.za/api/policies"
                      ai_info_url:
                        type: string
                      llms_txt:
                        type: string
                      openapi:
                        type: string
                      contact:
                        type: object
                        properties:
                          email:
                            type: string
                          phone:
                            type: string
                          whatsapp:
                            type: string
                  pagination:
                    type: object
                    properties:
                      total:
                        type: integer
                      limit:
                        type: integer
                      offset:
                        type: integer
                      has_more:
                        type: boolean
                      sort:
                        type: string
                  products:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        url:
                          type: string
                        brand:
                          type: string
                        model:
                          type: string
                        price:
                          type: number
                          description: Checkout price in ZAR including VAT (already sale-adjusted)
                        original_price:
                          type: number
                          nullable: true
                          description: Previous / strike-through price when there is a real one
                        discount_percent:
                          type: integer
                        sale_active:
                          type: boolean
                        sale_ends_at:
                          type: string
                          nullable: true
                        currency:
                          type: string
                        price_includes_vat:
                          type: boolean
                        condition:
                          type: string
                          enum: ["New", "Certified Pre-Owned"]
                        condition_grade:
                          type: string
                          nullable: true
                        body_condition:
                          type: string
                          nullable: true
                        screen_condition:
                          type: string
                          nullable: true
                        category:
                          type: string
                          nullable: true
                          description: Category slug
                        category_name:
                          type: string
                          nullable: true
                        color:
                          type: string
                        storage:
                          type: string
                        battery_health:
                          type: string
                          nullable: true
                          example: "91%"
                        warranty_months:
                          type: integer
                          nullable: true
                        warranty:
                          type: string
                          description: Human-readable warranty for this unit
                        returns:
                          type: string
                          description: Return window and fees that apply to this unit's condition
                        in_stock:
                          type: boolean
                        quantity_available:
                          type: integer
                        shipping:
                          type: object
                          nullable: true
                          description: Cheapest always-available courier option for this unit's price
                          properties:
                            cost_zar:
                              type: number
                            free:
                              type: boolean
                            method:
                              type: string
                            delivery_time:
                              type: string
                              nullable: true
                            note:
                              type: string
                              nullable: true
                        shipped_from_supplier:
                          type: boolean
                        image_url:
                          type: string
                        description:
                          type: string
                        last_updated:
                          type: string
                          format: date-time
        '400':
          description: Invalid characters in search parameters
        '429':
          description: Rate limit exceeded (100 requests per minute per IP)
