openapi: 3.0.0
info:
  title: Boya Categories API
  version: 1.0.0
  description: API for managing expense categories in the Boya platform
servers:
  - url: https://api.boyahq.com/v1
    description: Boya API server
paths:
  /categories:
    get:
      summary: List all categories with subcategories
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Category'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      summary: Create a new category
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CategoryInput'
            example:
              name: PT Certs
              description: PT Certs
      responses:
        '201':
          description: Category created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Category'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /categories/{categoryId}:
    get:
      summary: Get a specific category
      parameters:
        - in: path
          name: categoryId
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Category'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      summary: Update a category
      description: Update a category's details
      parameters:
        - in: path
          name: categoryId
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CategoryUpdateInput'
      responses:
        '200':
          description: Category updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Category'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      summary: Archive a category
      description: Archives a category by setting its status to INACTIVE
      parameters:
        - in: path
          name: categoryId
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Category archived successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Category archived successfully
                  status:
                    type: string
                    example: ARCHIVED
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /categories/{categoryId}/subcategories:
    post:
      summary: Add a subcategory to a category
      description: >-
        Create a new subcategory within a category. Can be made available to
        specific teams or all teams.
      parameters:
        - in: path
          name: categoryId
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubcategoryInput'
            examples:
              specificTeams:
                summary: Create subcategory for specific teams
                value:
                  name: Free
                  description: free courses
                  code: F9034
                  groupid: 67bb3fecdc7a527982f1b790
                  category_id: 67bb3fecdc7a527982f1b790
                  teams:
                    - 672dd361617c24141539cd96
              allTeams:
                summary: Create subcategory for all teams
                value:
                  name: Gifts
                  description: gift courses
                  code: G90ere
                  groupid: 67bb3fecdc7a527982f1b790
                  category_id: 67bb3fecdc7a527982f1b790
                  teams: []
      responses:
        '201':
          description: Subcategory created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Subcategory'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /categories/{categoryId}/subcategories/{subcategoryId}:
    patch:
      summary: Update a subcategory
      description: Update a subcategory's details
      parameters:
        - in: path
          name: categoryId
          required: true
          schema:
            type: string
        - in: path
          name: subcategoryId
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubcategoryUpdateInput'
            examples:
              updateWithTeams:
                summary: Update subcategory and assign to specific teams
                value:
                  name: Updated Free
                  description: Updated free courses description
                  teams:
                    - 672dd361617c24141539cd96
              updateForAllTeams:
                summary: Update subcategory and make available to all teams
                value:
                  name: Updated Gifts
                  description: Updated gift courses description
                  teams: []
      responses:
        '200':
          description: Subcategory updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Subcategory'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    delete:
      summary: Archive a subcategory
      description: Archives a subcategory by setting its status to INACTIVE
      parameters:
        - in: path
          name: categoryId
          required: true
          schema:
            type: string
        - in: path
          name: subcategoryId
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Subcategory archived successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Subcategory archived successfully
                  status:
                    type: string
                    example: INACTIVE
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
  schemas:
    CategoryUpdateInput:
      type: object
      properties:
        name:
          type: string
          description: Updated name of the category
          example: Updated PT Certs
        description:
          type: string
          description: Updated description of the category
          example: Updated PT Certs description
        status:
          type: string
          enum:
            - ACTIVE
            - ARCHIVED
          description: Updated status of the category
    SubcategoryUpdateInput:
      type: object
      properties:
        name:
          type: string
          description: Updated name of the subcategory
        description:
          type: string
          description: Updated description of the subcategory
        code:
          type: string
          description: Updated code for the subcategory
        teams:
          type: array
          description: Updated array of team IDs. Empty array means available to all teams.
          items:
            type: string
        status:
          type: string
          enum:
            - ACTIVE
            - ARCHIVED
          description: Updated status of the subcategory
    Category:
      type: object
      properties:
        _id:
          type: string
        groupid:
          type: string
        name:
          type: string
        description:
          type: string
        status:
          type: string
          enum:
            - ACTIVE
            - ARCHIVED
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        __v:
          type: integer
        subcategories:
          type: array
          items:
            $ref: '#/components/schemas/Subcategory'
    CategoryInput:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          example: PT Certs
        description:
          type: string
          example: PT Certs
    Subcategory:
      type: object
      properties:
        _id:
          type: string
        group_id:
          type: string
        category:
          type: string
        code:
          type: string
        name:
          type: string
        description:
          type: string
        status:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        __v:
          type: integer
        mapping_id:
          type: string
        teams:
          type: array
          items:
            type: string
    SubcategoryInput:
      type: object
      required:
        - name
        - code
        - groupid
        - category_id
      properties:
        name:
          type: string
          description: Name of the subcategory
        code:
          type: string
          description: Unique code for the subcategory
        description:
          type: string
          description: Description of the subcategory
        groupid:
          type: string
          description: ID of the group this subcategory belongs to
        category_id:
          type: string
          description: ID of the parent category
        teams:
          type: array
          description: Array of team IDs. Empty array means available to all teams.
          items:
            type: string
        status:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
          default: ACTIVE
          description: Status of the subcategory
  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              message:
                type: string
    Unauthorized:
      description: Authentication failed
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              message:
                type: string
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              message:
                type: string
security:
  - ApiKeyAuth: []
