openapi: 3.0.3
info:
  title: Markatty Mobile API v2
  description: |
    Standalone Laravel 11 reimplementation of all Mobikul v2 mobile API endpoints.
    All requests require the `api_token` header and a `domain` query/body parameter.
  version: "2.0.0"
  contact:
    name: Markatty Dev Team

servers:
  - url: http://localhost:8090/mobikulhttp/v3
    description: Local Docker

  - url: https://api.markatty.com/mobikulhttp/v3
    description: Production

security: []

# ─── Global security scheme ───────────────────────────────────────────────────
components:
  securitySchemes:
    ApiTokenHeader:
      type: apiKey
      in: header
      name: api_token
      description: md5(username:password) of the Mobikul admin configuration

  parameters:
    domain:
      name: domain
      in: query
      required: true
      schema:
        type: string
      description: Store domain (e.g. mystore.markatty.com)

    locale:
      name: locale
      in: query
      required: false
      schema:
        type: string
        example: en
      description: Locale code — falls back to channel default if omitted

    branchId:
      name: branchId
      in: query
      required: false
      schema:
        type: integer
      description: Branch ID — falls back to company first branch if omitted

    token:
      name: token
      in: query
      required: false
      schema:
        type: string
      description: JWT auth token returned by the login endpoint

  schemas:
    SuccessEnvelope:
      type: object
      required: [success]
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
          example: ""

    ErrorEnvelope:
      type: object
      required: [success, message, error_code, trace_id]
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          example: "Domain not found or invalid"
        error_code:
          type: string
          example: DOMAIN_NOT_FOUND
          enum:
            - DOMAIN_NOT_FOUND
            - AUTHENTICATION_FAILED
            - INVALID_API_HEADER
            - VALIDATION_ERROR
            - UNAUTHENTICATED
            - NOT_FOUND
            - INTERNAL_ERROR
            - HTTP_ERROR
        trace_id:
          type: string
          format: uuid
          example: "550e8400-e29b-41d4-a716-446655440000"

    PriceFormat:
      type: object
      properties:
        pattern:
          type: string
          example: "%s"
        precision:
          type: integer
          example: 2
        requiredPrecision:
          type: integer
          example: 2
        decimalSymbol:
          type: string
          example: "."
        groupSymbol:
          type: string
          example: ","
        groupLength:
          type: integer
          example: 3

    CustomerInfo:
      type: object
      properties:
        id:
          type: integer
          example: 0
        name:
          type: string
          example: ""
        email:
          type: string
          example: ""
        profile:
          type: string
          example: ""
        banner:
          type: string
          example: ""

    HomepageResponse:
      allOf:
        - $ref: '#/components/schemas/SuccessEnvelope'
        - type: object
          properties:
            defaultStoreId:
              type: integer
            allowedCurrencies:
              type: array
              items:
                type: object
            defaultCurrency:
              type: string
              example: SAR
            showSwatchOnCollection:
              type: boolean
            priceFormat:
              $ref: '#/components/schemas/PriceFormat'
            mainBannerList:
              type: array
              items:
                type: object
            featuredCategoryList:
              type: array
              items:
                type: object
            popularCategoryList:
              type: array
              items:
                type: object
            newProductList:
              type: array
              items:
                type: object
            hotOfferList:
              type: array
              items:
                type: object
            cartCount:
              type: integer
            customerInfo:
              $ref: '#/components/schemas/CustomerInfo'
            eTag:
              type: string
            haveData:
              type: boolean
            carouselList:
              type: array
              items:
                type: object
            channelList:
              type: array
              items:
                type: object
            allowedCmsPages:
              type: array
              items:
                type: object

    LoginResponse:
      allOf:
        - $ref: '#/components/schemas/SuccessEnvelope'
        - type: object
          properties:
            customerId:
              type: integer
            companyId:
              type: integer
            customerName:
              type: string
            customerEmail:
              type: string
              format: email
            token:
              type: string
            bannerImage:
              type: string
            profileImage:
              type: string
            cartCount:
              type: integer
            customerPhone:
              type: string
              nullable: true
            customerMobile:
              type: string
              nullable: true

# ─── Paths ────────────────────────────────────────────────────────────────────
paths:

  /health:
    get:
      tags: [Health]
      summary: Health check
      security: []
      responses:
        '200':
          description: Healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: healthy
                  checks:
                    type: object
                    properties:
                      db:
                        type: string
                        example: ok
                      redis:
                        type: string
                        example: ok
        '503':
          description: Unhealthy

  /catalog/homepage:
    get:
      tags: [Catalog]
      summary: Homepage data
      security:
        - ApiTokenHeader: []
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/locale'
        - $ref: '#/components/parameters/branchId'
        - $ref: '#/components/parameters/token'
        - name: currency
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Homepage payload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HomepageResponse'
        '401':
          description: Invalid API header
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: Domain not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'

  /catalog/homeExtraData:
    get:
      tags: [Catalog]
      summary: Homepage extra data (cart + wishlist counts)
      security:
        - ApiTokenHeader: []
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/token'
      responses:
        '200':
          description: Extra data
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  cartProductsData:
                    type: array
                    items:
                      type: object
                  cartProductsCount:
                    type: integer
                  WishListProductIds:
                    type: array
                    items:
                      type: integer
                  WishListProductsCount:
                    type: integer

  /catalog/settings:
    get:
      tags: [Catalog]
      summary: Store settings
      security:
        - ApiTokenHeader: []
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/locale'
        - $ref: '#/components/parameters/token'
      responses:
        '200':
          description: Settings payload
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  defaultStoreId:
                    type: integer
                  baseUrl:
                    type: string
                  allowGuestCheckout:
                    type: boolean
                  priceFormat:
                    $ref: '#/components/schemas/PriceFormat'
                  eTag:
                    type: string

  /catalog/categoryPageData:
    get:
      tags: [Catalog]
      summary: Category page with layered navigation
      security:
        - ApiTokenHeader: []
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/locale'
        - name: categoryId
          in: query
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Category page

  /catalog/productpagedata:
    get:
      tags: [Catalog]
      summary: Product detail page
      security:
        - ApiTokenHeader: []
      parameters:
        - $ref: '#/components/parameters/domain'
        - name: productId
          in: query
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Product detail

  /catalog/productCollection:
    get:
      tags: [Catalog]
      summary: Product collection / listing
      security:
        - ApiTokenHeader: []
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/locale'
        - name: categoryId
          in: query
          schema:
            type: integer
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
            maximum: 20
      responses:
        '200':
          description: Product list

  /catalog/getBranches:
    get:
      tags: [Catalog]
      summary: Store branches
      security:
        - ApiTokenHeader: []
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Branch list

  /customer/login:
    post:
      tags: [Customer]
      summary: Customer login
      security:
        - ApiTokenHeader: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [domain, username, password]
              properties:
                domain:
                  type: string
                username:
                  type: string
                  format: email
                password:
                  type: string
                  format: password
                companyId:
                  type: integer
                  nullable: true
      responses:
        '200':
          description: Login response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginResponse'
        '401':
          description: Authentication failed

  /customer/createaccount:
    post:
      tags: [Customer]
      summary: Create customer account
      security:
        - ApiTokenHeader: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [domain, firstName, lastName, email, password]
              properties:
                domain:
                  type: string
                firstName:
                  type: string
                lastName:
                  type: string
                email:
                  type: string
                  format: email
                password:
                  type: string
                  minLength: 6
                phone:
                  type: string
      responses:
        '200':
          description: Account created

  /customer/orderlist:
    get:
      tags: [Customer]
      summary: Customer order list
      security:
        - ApiTokenHeader: []
      parameters:
        - $ref: '#/components/parameters/domain'
        - $ref: '#/components/parameters/token'
        - name: page
          in: query
          schema:
            type: integer
        - name: pageSize
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Order list

  /checkout/addtocart:
    post:
      tags: [Checkout]
      summary: Add product to cart
      security:
        - ApiTokenHeader: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [domain, productId, quoteId]
              properties:
                domain:
                  type: string
                productId:
                  type: integer
                quoteId:
                  type: integer
                qty:
                  type: integer
                  default: 1
                token:
                  type: string
      responses:
        '200':
          description: Cart updated

  /extra/domainDestails:
    get:
      tags: [Extra]
      summary: Domain details
      security:
        - ApiTokenHeader: []
      parameters:
        - $ref: '#/components/parameters/domain'
      responses:
        '200':
          description: Domain details payload
