openapi: 3.0.0
info:
  title: Boya API
  version: 2.0.0
  description: >-
    Boya is the financial operating system for business operations. The v2 API
    uses OAuth2 client-credentials authentication and signed webhooks.


    Operations badged **Private label** require a commercial entitlement —
    [contact sales](mailto:sales@boyahq.com).
  contact:
    name: Boya API Support
    email: apisupport@boyahq.com
servers:
  - url: https://api.boyahq.com/v2
    description: Production
  - url: https://sandbox.api.boyahq.com/v2
    description: Sandbox
tags:
  - name: bills
    x-displayName: Bills · Manage
    description: Create, list, update, and cancel bills.
  - name: bills-payments
    x-displayName: Bills · Payments
    description: Add, approve, reject, retry, and check bill payments.
  - name: bills-workflows
    x-displayName: Bills · Approval workflows
    description: Configure bill approval workflows.
  - name: bills-budgets
    x-displayName: Bills · Budgets & setup
    description: Budgets for bill assignment and vendor payment methods.
  - name: bills-attachments
    x-displayName: Bills · Attachments
    description: Upload and attach bill files. Back-office / secondary.
  - name: payments
    description: Payouts and disbursements. Private label.
  - name: approvals
    description: Approve or reject requests. Private label.
  - name: fx
    description: Foreign-exchange rates. FX transfers are private label.
  - name: expenses
    x-displayName: Expenses · Retrieve
    description: List, search, and read expenses.
  - name: expenses-review
    x-displayName: Expenses · Review & approvals
    description: Approve, reject, request details, and annotate expenses under review.
  - name: expenses-reports
    x-displayName: Expenses · Reports
    description: Aggregate category and team-category expense reports.
  - name: expenses-exports
    x-displayName: Expenses · Exports
    description: Export and download expense receipts. Back-office / secondary.
  - name: cards
    x-displayName: Cards · Manage
    description: Create, list, read, and update cards; balances and transactions.
  - name: cards-controls
    x-displayName: Cards · Controls
    description: Block, unblock, retire, and reissue cards.
  - name: cards-single-use
    x-displayName: Cards · Single-use
    description: Single-use card requests and policy.
  - name: cards-physical
    x-displayName: Cards · Physical cards
    description: Physical card order approvals.
  - name: cards-auth
    x-displayName: Cards · Authorization
    description: Card authorization and fingerprint. Back-office / secondary.
  - name: subscriptions
    description: Recurring spend management.
  - name: tags
    description: Expense tag metadata.
  - name: transactions
    description: Read the transaction ledger, tag transactions and attach documents.
  - name: accounts
    description: Business wallets — balances, transactions and cashflow.
  - name: categories
    description: Chart of accounts — categories and subcategories for accounting.
  - name: taxes
    description: Withholding tax configuration and transactions.
  - name: vendors
    description: Payables master data — the businesses you pay.
  - name: customers
    description: Receivables master data — the businesses that pay you.
  - name: employees
    description: Team members and their wallets.
  - name: teams
    description: Organisational teams and their members.
  - name: investments
    x-displayName: Investments · Portfolio & accounts
    description: Fund catalogue, accounts, and portfolio analytics.
  - name: investments-movements
    x-displayName: Investments · Fund movements
    description: Opt-in, invest, top-up, and withdraw.
  - name: investments-access
    x-displayName: Investments · Access & permissions
    description: Treasury operator access and permissions.
  - name: business-policies
    description: Spend policy configuration. Private label.
  - name: wallet-policies
    x-displayName: Wallet policies · Policies
    description: Grant, read, modify, suspend, and revoke wallet policies.
  - name: wallet-policies-permissions
    x-displayName: Wallet policies · Permissions
    description: Available permissions and computed permissions.
  - name: wallet-policies-checks
    x-displayName: Wallet policies · Access checks
    description: Check access and transaction limits.
  - name: wallet-policies-audit
    x-displayName: Wallet policies · Audit
    description: Query and read wallet-policy audit logs. Back-office / secondary.
  - name: roles
    description: Roles, permissions and approval mandates. Private label.
  - name: audit-trail
    description: Immutable audit-trail events. Private label.
x-tagGroups:
  - name: Money movement
    tags:
      - bills
      - bills-payments
      - bills-workflows
      - bills-budgets
      - bills-attachments
      - payments
      - approvals
      - fx
  - name: Spend & cards
    tags:
      - expenses
      - expenses-review
      - expenses-reports
      - expenses-exports
      - cards
      - cards-controls
      - cards-single-use
      - cards-physical
      - cards-auth
      - subscriptions
      - tags
  - name: Ledger & accounting
    tags:
      - transactions
      - accounts
      - categories
      - taxes
  - name: Relationships
    tags:
      - vendors
      - customers
      - employees
      - teams
  - name: Treasury
    tags:
      - investments
      - investments-movements
      - investments-access
  - name: Governance
    tags:
      - business-policies
      - wallet-policies
      - wallet-policies-permissions
      - wallet-policies-checks
      - wallet-policies-audit
      - roles
      - audit-trail
security:
  - oauth2ClientCredentials: []
paths:
  /expenses:
    get:
      operationId: ExpensesController_listUserExpenses
      summary: List expenses (role-scoped)
      description: >-
        Returns a paginated list of expenses filtered by the caller's role.


        - **CARD USER** – own expenses only

        - **REVIEWER** – expenses belonging to teams the reviewer manages

        - **ADMIN / APPROVER / SUPER ADMIN** – all business expenses


        For dashboard roles, expenses are fetched across **all business currency
        wallets** in parallel and merged. Pass `accountref` to restrict results
        to a single currency wallet.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
        - name: accountref
          required: false
          in: query
          description: >-
            Wallet org_wallet_ref to scope expenses to a specific currency. When
            omitted, all business currency wallets are fetched and merged.
          schema:
            example: '1'
            type: string
        - name: to
          required: false
          in: query
          description: End date for filtering expenses (ISO 8601, e.g. 2026-04-30)
          schema:
            example: '2026-04-30'
            type: string
        - name: from
          required: false
          in: query
          description: Start date for filtering expenses (ISO 8601, e.g. 2026-01-01)
          schema:
            example: '2026-01-01'
            type: string
      responses:
        '200':
          description: Paginated list of expenses scoped to the caller's role
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedExpenseResponseDto'
        '400':
          description: Bad Request – invalid page or limit parameters
        '401':
          description: Unauthorized – missing or invalid bearer token
        '403':
          description: Forbidden – valid token but insufficient permissions
      tags:
        - expenses
      security:
        - oauth2ClientCredentials:
            - expenses:read
  /expenses/export-receipts:
    post:
      operationId: ExpensesController_exportReceipts
      summary: Start receipt export job
      description: >-
        Forwards the receipt export request to the expenses service and returns
        a background job id.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExportReceiptsDto'
      responses:
        '202':
          description: Receipt export job accepted
        '403':
          description: Forbidden - role is not allowed to export receipts
      tags:
        - expenses-exports
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /expenses/export-receipts/status/{jobId}:
    get:
      operationId: ExpensesController_getReceiptExportStatus
      summary: Get receipt export job status
      description: >-
        Returns progress, completion state, and download URL for a receipt
        export job.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: jobId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Receipt export job status
        '403':
          description: Forbidden - role is not allowed to access receipt export jobs
      tags:
        - expenses-exports
      security:
        - oauth2ClientCredentials:
            - expenses:read
  /expenses/downloadExpenseReceipt/{transactionRef}:
    get:
      operationId: ExpensesController_downloadExpenseReceipt
      summary: Get a signed download URL for an expense receipt
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: transactionRef
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Signed receipt download URL
      tags:
        - expenses-exports
      security:
        - oauth2ClientCredentials:
            - expenses:read
  /expenses/{id}:
    get:
      operationId: ExpensesController_getExpense
      summary: Get expense by ID
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Expense details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExpenseV1Dto'
      tags:
        - expenses
      security:
        - oauth2ClientCredentials:
            - expenses:read
  /expenses/notes/{id}:
    post:
      operationId: ExpensesController_updateExpenseNotes
      summary: Update an expense description or notes
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateExpenseNoteDto'
      responses:
        '200':
          description: Expense updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExpenseV1Dto'
      tags:
        - expenses-review
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /expenses/changeSubCategory/{expenseId}:
    post:
      operationId: ExpensesController_updateExpenseSubcategory
      summary: Update expense subcategory
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: expenseId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateExpenseSubcategoryDto'
      responses:
        '200':
          description: Expense subcategory updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExpenseV1Dto'
        '400':
          description: Bad Request - Invalid subcategory ID
        '404':
          description: Expense not found
      tags:
        - expenses-review
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /expenses/byCategory/{categoryId}:
    get:
      operationId: ExpensesController_getExpensesByCategory
      summary: Get expenses by category
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: categoryId
          required: true
          in: path
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of expenses by category
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedExpenseResponseDto'
        '400':
          description: Bad Request - Invalid page or limit parameters
      tags:
        - expenses
      security:
        - oauth2ClientCredentials:
            - expenses:read
  /expenses/bySubCategory/{subcategoryId}:
    get:
      operationId: ExpensesController_getExpensesBySubCategory
      summary: Get expenses by subcategory _id
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: subcategoryId
          required: true
          in: path
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of expenses by subcategory
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedExpenseResponseDto'
        '400':
          description: Bad Request - Invalid page or limit parameters
      tags:
        - expenses
      security:
        - oauth2ClientCredentials:
            - expenses:read
  /expenses/byVendor/{vendor}:
    get:
      operationId: ExpensesController_getExpensesByVendor
      summary: Get expenses by vendor
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: vendor
          required: true
          in: path
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of expenses by vendor
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedExpenseResponseDto'
        '400':
          description: Bad Request - Invalid page or limit parameters
      tags:
        - expenses
      security:
        - oauth2ClientCredentials:
            - expenses:read
  /expenses/approve:
    post:
      operationId: ExpensesController_approveMultipleExpenses
      summary: Approve multiple expenses
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApproveMultipleExpensesDto'
      responses:
        '200':
          description: Expenses approved successfully
        '400':
          description: Bad Request - Invalid expense IDs or request body
      tags:
        - expenses-review
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /expenses/approve/{expenseId}:
    post:
      operationId: ExpensesController_approveSingleExpense
      summary: Approve single expense
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: expenseId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApproveRejectNotesDto'
      responses:
        '200':
          description: Expense approved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExpenseV1Dto'
        '404':
          description: Expense not found
      tags:
        - expenses-review
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /expenses/reject:
    post:
      operationId: ExpensesController_rejectMultipleExpenses
      summary: Reject multiple expenses
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RejectMultipleExpensesDto'
      responses:
        '200':
          description: Expenses rejected successfully
        '400':
          description: Bad Request - Invalid expense IDs or request body
      tags:
        - expenses-review
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /expenses/reject/{expenseId}:
    post:
      operationId: ExpensesController_rejectSingleExpense
      summary: Reject single expense
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: expenseId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestNotesDTO'
      responses:
        '200':
          description: Expense rejected successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExpenseV1Dto'
        '404':
          description: Expense not found
      tags:
        - expenses-review
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /expenses/requestDetails/{expenseId}:
    post:
      operationId: ExpensesController_requestExpenseDetails
      summary: Request details for a specific expense with mandatory notes
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: expenseId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestNotesDTO'
      responses:
        '200':
          description: Expense details request submitted successfully
        '400':
          description: Bad Request - Missing or invalid notes
        '404':
          description: Expense not found
      tags:
        - expenses-review
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /expenses/category-report:
    post:
      operationId: ExpensesController_getCategoryReport
      summary: Get category report for expenses
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CategoryReportQueryV1Dto'
      responses:
        '200':
          description: Category report generated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CategoryReportResponseV1Dto'
        '400':
          description: Bad Request - Invalid parameters
      tags:
        - expenses-reports
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /expenses/team-category-report:
    post:
      operationId: ExpensesController_getTeamCategoryReport
      summary: Get hierarchical team-category-subcategory expense report
      description: >-
        Returns a hierarchical report of expenses grouped by team, category, and
        subcategory. Supports filtering by period, account reference, team code,
        and category. 
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TeamCategoryReportQueryV1Dto'
      responses:
        '200':
          description: Hierarchical expense report generated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TeamCategoryReportResponseV1Dto'
        '400':
          description: Bad Request - Invalid parameters
        '401':
          description: Unauthorized - missing or invalid bearer token
        '403':
          description: Forbidden - valid token but insufficient permissions
      tags:
        - expenses-reports
      security:
        - oauth2ClientCredentials:
            - expenses:write
  /cards:
    get:
      operationId: CardsController_listUserCards
      summary: List user cards
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of user cards
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedCardResponseDto'
        '400':
          description: Bad Request - Invalid page or limit parameters
      tags:
        - cards
      security:
        - oauth2ClientCredentials:
            - cards:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        List user cards
    post:
      operationId: CardsController_createCard
      summary: Create a new card
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCardV1Dto'
      responses:
        '201':
          description: Card created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardV1Dto'
        '400':
          description: Bad Request - Invalid card data
      tags:
        - cards
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Create a new card
  /cards/employee/{employeeId}:
    get:
      operationId: CardsController_listEmployeeCards
      summary: List cards for a specific employee
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns paginated cards for the given employee. Accessible by CARD_USER
        and admin roles.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employeeId
          required: true
          in: path
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Number of items per page
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of employee cards
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedCardResponseDto'
        '400':
          description: Bad Request
      tags:
        - cards
      security:
        - oauth2ClientCredentials:
            - cards:read
      x-boya-access: private-label
  /cards/business:
    get:
      operationId: CardsController_listBusinessCards
      summary: List business cards
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of user cards
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedCardResponseDto'
        '400':
          description: Bad Request - Invalid page or limit parameters
      tags:
        - cards
      security:
        - oauth2ClientCredentials:
            - cards:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        List business cards
  /cards/single-use/request:
    post:
      operationId: CardsController_requestSingleUseCard
      summary: Request a Single Use Card
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Creates a Single Use Card (SUC) approval request for an employee.


        **Customer resolution**

        transaction dump so it is available on expense records without an
        additional lookup.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestSingleUseCardDto'
            examples:
              with_customer_object:
                summary: Request with full customer object (preferred)
                value:
                  employee_id: EMP001
                  amount: 5000
                  currency: KES
                  notes: Purchase office supplies
                  subcategory_id: CAT_OFFICE
                  customer:
                    _id: 69dd1e56d2756bba9fa9983b
                    name: Giraffe Center
                    email: giraffe@acme.com
                    phone: '+254700000012'
                    address: 123 Karen Street, Nairobi
                    type: regular
                    status: active
                    person:
                      - '123'
                    taxPin: A123456789Z
              with_customer_id:
                summary: Request with customer_id (legacy)
                value:
                  employee_id: EMP001
                  amount: 5000
                  currency: KES
                  notes: Purchase office supplies
                  subcategory_id: CAT_OFFICE
                  customer_id: 69dd1e56d2756bba9fa9983b
                  customer_name: Giraffe Center
      responses:
        '201':
          description: Single use card request created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateSingleUseCardResponseDto'
        '400':
          description: Bad Request — missing required fields or negative amount
        '403':
          description: Forbidden — insufficient permissions
        '404':
          description: Not Found — employee or business not found
      tags:
        - cards-single-use
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
  /cards/single-use/policy:
    get:
      operationId: CardsController_getSucPolicy
      summary: Get the business SUC policy
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns the Single Use Card policy for the authenticated employee
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Business SUC policy
          content:
            application/json:
              schema:
                example:
                  single_use_cards_funding: pre_funded
                  single_use_cards_source_strategy: business_wallet
                  single_use_cards_workflow: null
                  single_use_cards_auto_expiry_hours: '1440'
                  required_fields:
                    amount: true
                    vendor: false
                    customer: false
                    category: true
                    tags: false
                    reference: false
                    notes: true
                    receipt: false
      tags:
        - cards-single-use
      security:
        - oauth2ClientCredentials:
            - cards:read
      x-boya-access: private-label
  /cards/{id}:
    get:
      operationId: CardsController_getCard
      summary: Get card by ID
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Card details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardV1Dto'
        '404':
          description: Card not found
      tags:
        - cards
      security:
        - oauth2ClientCredentials:
            - cards:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get card by ID
    put:
      operationId: CardsController_updateCard
      summary: Update card details
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Card updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardV1Dto'
        '404':
          description: Card not found
      tags:
        - cards
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Update card details
  /cards/{id}/balance:
    get:
      operationId: CardsController_getCardBalance
      summary: Get card balance
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Card balance details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardBalanceDto'
        '404':
          description: Card not found
      tags:
        - cards
      security:
        - oauth2ClientCredentials:
            - cards:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get card balance
  /cards/{id}/transactions:
    get:
      operationId: CardsController_getCardTransactions
      summary: Get card transactions
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of card transactions
        '400':
          description: Bad Request - Invalid page or limit parameters
        '404':
          description: Card not found
      tags:
        - cards
      security:
        - oauth2ClientCredentials:
            - cards:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get card transactions
  /cards/{id}/block:
    put:
      operationId: CardsController_blockCard
      summary: Block a card
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Blocks the card belonging to the authenticated employee. Accessible by
        CARD_USER and admin roles. The card must belong to the calling employee.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                  description: Reason for blocking card
      responses:
        '200':
          description: Card blocked successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardV1Dto'
        '403':
          description: Card does not belong to this employee
        '404':
          description: Card not found
      tags:
        - cards-controls
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
  /cards/{id}/unblock:
    put:
      operationId: CardsController_unblockCard
      summary: Unblock a card
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Unblocks the card belonging to the authenticated employee. Accessible by
        CARD_USER and admin roles. The card must belong to the calling employee.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Card unblocked successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardV1Dto'
        '403':
          description: Card does not belong to this employee
        '404':
          description: Card not found
      tags:
        - cards-controls
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
  /cards/{id}/retire:
    put:
      operationId: CardsController_retireCard
      summary: Retire (cancel) a card
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Permanently retires the card belonging to the authenticated employee.
        Accessible by CARD_USER and admin roles. The card must belong to the
        calling employee.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                  description: Reason for retiring card
      responses:
        '200':
          description: Card retired successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardV1Dto'
        '403':
          description: Card does not belong to this employee
        '404':
          description: Card not found
      tags:
        - cards-controls
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
  /cards/physical/orders:
    get:
      operationId: CardsController_getPhysicalCardOrders
      summary: List physical card orders with pagination
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of physical card orders
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedPhysicalCardOrderResponseDto'
        '400':
          description: Bad Request - Invalid page or limit parameters
      tags:
        - cards-physical
      security:
        - oauth2ClientCredentials:
            - cards:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        List physical card orders with pagination
    post:
      operationId: CardsController_approvePhysicalCardOrders
      summary: Approve one or multiple physical card orders
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApprovePhysicalCardOrdersDto'
      responses:
        '200':
          description: Physical card orders approved successfully
        '400':
          description: Bad Request - Invalid order IDs or request body
      tags:
        - cards-physical
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Approve one or multiple physical card orders
    patch:
      operationId: CardsController_rejectPhysicalCardOrders
      summary: Reject one or multiple physical card orders
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RejectPhysicalCardOrdersDto'
      responses:
        '200':
          description: Physical card orders rejected successfully
        '400':
          description: Bad Request - Invalid order IDs or missing rejection notes
      tags:
        - cards-physical
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Reject one or multiple physical card orders
  /cards/{id}/reissue:
    post:
      operationId: CardsController_reIssueCard
      summary: Re-issue a virtual card (retire old, create new)
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Card re-issued successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardV1Dto'
        '400':
          description: Bad Request - Card is not virtual or already retired
        '404':
          description: Card not found
      tags:
        - cards-controls
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Re-issue a virtual card (retire old, create new)
  /cards/authorize:
    post:
      operationId: CardsController_authorizeBTSession
      summary: Authorize a BT session for card
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Authorizes a Basis Theory session so the caller can reveal sensitive
        card details (PAN/CVV). Accessible by CARD_USER and admin roles. The
        nonce must be obtained from a BT session created client-side, and the
        VCN must belong to the authenticated employee.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        description: BT session authorization details
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthorizeBTSessionDto'
      responses:
        '200':
          description: BT session authorized successfully
        '400':
          description: Bad Request - Invalid nonce or VCN
        '403':
          description: >-
            Forbidden - missing business_id header or card does not belong to
            this employee
      tags:
        - cards-auth
      security:
        - oauth2ClientCredentials:
            - cards:write
      x-boya-access: private-label
  /cards/getFingerPrint/{vcn}:
    get:
      operationId: CardsController_getCardFingerprint
      summary: Get card fingerprint by VCN
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: vcn
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Card fingerprint retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardFingerprintDto'
        '404':
          description: Card fingerprint not found
      tags:
        - cards-auth
      security:
        - oauth2ClientCredentials:
            - cards:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get card fingerprint by VCN
  /approvals/all:
    get:
      operationId: ApprovalsController_listApprovals
      summary: List all approvals with filtering and pagination
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: status
          required: false
          in: query
          description: Approval status (PENDING, APPROVED, REJECTED, CANCELLED, DRAFT)
          schema:
            enum:
              - PENDING
              - APPROVED
              - REJECTED
              - CANCELLED
              - DRAFT
            type: string
        - name: page
          required: false
          in: query
          description: Page number for pagination
          schema:
            default: 1
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Number of items per page
          schema:
            default: 100
            example: 100
            type: number
        - name: action_type
          required: false
          in: query
          description: >-
            Filter by approval action type (e.g., PAYOUT, INVOICE,
            SUBSCRIPTION_REQUEST)
          schema:
            enum:
              - PAYOUT
              - TOPUP
              - KYC
              - DEBIT
              - INVOICE
              - APP_TRANSACTION
              - SINGLE_CARD_REQUEST
              - ALLOCATION_REQUEST
              - BANK_TRANSFER_REQUEST
              - INVESTMENT_OPTIN_REQUEST
              - POLICY_BASED
              - SUBSCRIPTION_REQUEST
            type: string
        - name: from
          required: false
          in: query
          description: Start date filter (ISO format)
          schema:
            example: '2026-01-01'
            type: string
        - name: to
          required: false
          in: query
          description: End date filter (ISO format)
          schema:
            example: '2026-12-31'
            type: string
      responses:
        '200':
          description: Paginated list of approvals
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedApprovalsResponseDto'
        '400':
          description: Bad Request - Invalid query parameters
        '401':
          description: Unauthorized - Missing or invalid bearer token
      tags:
        - approvals
      security:
        - oauth2ClientCredentials:
            - approvals:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        List all approvals with filtering and pagination
  /approvals/all/digest:
    get:
      operationId: ApprovalsController_listApprovalsDigest
      summary: List approvals with UX-friendly digest format
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns approvals transformed into a UX-friendly format with risk
        scoring, approval chain tracking, urgency flags, and recommended
        actions.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: status
          required: false
          in: query
          description: Approval status (PENDING, APPROVED, REJECTED, CANCELLED, DRAFT)
          schema:
            enum:
              - PENDING
              - APPROVED
              - REJECTED
              - CANCELLED
              - DRAFT
            type: string
        - name: page
          required: false
          in: query
          description: Page number for pagination
          schema:
            default: 1
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Number of items per page
          schema:
            default: 100
            example: 100
            type: number
        - name: action_type
          required: false
          in: query
          description: >-
            Filter by approval action type (e.g., PAYOUT, INVOICE,
            SUBSCRIPTION_REQUEST)
          schema:
            enum:
              - PAYOUT
              - TOPUP
              - KYC
              - DEBIT
              - INVOICE
              - APP_TRANSACTION
              - SINGLE_CARD_REQUEST
              - ALLOCATION_REQUEST
              - BANK_TRANSFER_REQUEST
              - INVESTMENT_OPTIN_REQUEST
              - POLICY_BASED
              - SUBSCRIPTION_REQUEST
            type: string
        - name: from
          required: false
          in: query
          description: Start date filter (ISO format)
          schema:
            example: '2026-01-01'
            type: string
        - name: to
          required: false
          in: query
          description: End date filter (ISO format)
          schema:
            example: '2026-12-31'
            type: string
      responses:
        '200':
          description: Paginated list of approvals in digest format
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedApprovalsDigestResponseDto'
        '400':
          description: Bad Request - Invalid query parameters
        '401':
          description: Unauthorized - Missing or invalid bearer token
      tags:
        - approvals
      security:
        - oauth2ClientCredentials:
            - approvals:read
      x-boya-access: private-label
  /approvals/approve:
    post:
      operationId: ApprovalsController_approvePaymentRequest
      summary: Approve a payment request
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApprovePaymentRequestDto'
      responses:
        '200':
          description: Payment request approved successfully
        '400':
          description: Bad Request - Invalid ref or validation error
        '401':
          description: Unauthorized - Missing or invalid bearer token
        '404':
          description: Payment request not found
      tags:
        - approvals
      security:
        - oauth2ClientCredentials:
            - approvals:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Approve a payment request
  /approvals/reject:
    post:
      operationId: ApprovalsController_rejectPaymentRequest
      summary: Reject a payment request
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RejectPaymentRequestDto'
      responses:
        '200':
          description: Payment request rejected successfully
        '400':
          description: Bad Request - Invalid ref/reason or validation error
        '401':
          description: Unauthorized - Missing or invalid bearer token
        '404':
          description: Payment request not found
      tags:
        - approvals
      security:
        - oauth2ClientCredentials:
            - approvals:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Reject a payment request
  /approvals/bills/reject:
    delete:
      operationId: ApprovalsController_rejectBillPayment
      summary: Reject a bill payment
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: query
          schema:
            type: string
        - name: paymentId
          required: true
          in: query
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RejectBillPaymentDto'
      responses:
        '200':
          description: Bill payment rejected successfully
        '400':
          description: Bad Request - Invalid billId/paymentId or validation error
        '401':
          description: Unauthorized - Missing or invalid bearer token
        '404':
          description: Bill payment not found
      tags:
        - approvals
      security:
        - oauth2ClientCredentials:
            - approvals:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Reject a bill payment
  /accounts:
    get:
      operationId: AccountsController_listUserAccounts
      summary: List user accounts
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of user accounts
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedResponseDto'
        '400':
          description: Bad Request - Invalid page or limit parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:read
    post:
      operationId: AccountsController_createAccount
      summary: Create a new account
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAccountV1Dto'
      responses:
        '201':
          description: Account created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BaseResponseDto'
        '400':
          description: Bad Request - Invalid account data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:write
  /accounts/business-currencies:
    get:
      operationId: AccountsController_getBusinessCurrencies
      summary: Get business wallet references/currencies
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: List of business wallet references with their currencies
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BusinessCurrencyV1Dto'
        '400':
          description: Bad Request - Missing required headers
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:read
  /accounts/create-new-currency:
    post:
      operationId: AccountsController_createNewCurrency
      summary: Provision a new business currency
      description: >-
        Creates a new currency record for the business on the upstream service.
        The currency is required before any wallet can be created in that
        currency.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCurrencyV1Dto'
      responses:
        '201':
          description: Currency provisioned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BaseResponseDto'
        '400':
          description: Bad Request - Invalid currency code
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '409':
          description: Currency already exists for this business
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:write
  /accounts/add-new-account:
    post:
      operationId: AccountsController_addNewAccount
      summary: Create a new account (wallet) for the business
      description: >-
        Creates a wallet for the business in the requested currency. If the
        currency does not yet exist for the business it is provisioned first.
        Wallets are unique per (currency, walletType).
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddAccountV1Dto'
      responses:
        '201':
          description: Account created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AddAccountResponseV1Dto'
        '400':
          description: Bad Request - Invalid payload or wallet type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '409':
          description: Account already exists for the requested currency and wallet type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:write
  /accounts/cashflow-report:
    get:
      operationId: AccountsController_getCashflowReport
      summary: Get cashflow report for accounts
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: from
          required: true
          in: query
          description: Start date for the report period (YYYY-MM-DD)
          schema:
            example: '2026-04-18'
            type: string
        - name: to
          required: true
          in: query
          description: End date for the report period (YYYY-MM-DD)
          schema:
            example: '2026-05-18'
            type: string
        - name: org_wallet_ref
          required: false
          in: query
          description: Organization wallet reference ID to filter by specific currency
          schema:
            example: '1'
            type: string
        - name: account
          required: false
          in: query
          description: Account filter
          schema:
            example: acc-123
            type: string
      responses:
        '200':
          description: Cashflow report generated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CashflowReportResponseV1Dto'
        '400':
          description: Bad Request - Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:read
  /accounts/{id}:
    get:
      operationId: AccountsController_getAccount
      summary: Get account by ID
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Account details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BaseResponseDto'
        '404':
          description: Account not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:read
    put:
      operationId: AccountsController_updateAccount
      summary: Update account details
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Account updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AccountV1Dto'
        '404':
          description: Account not found
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:write
  /accounts/{id}/balance:
    get:
      operationId: AccountsController_getAccountBalance
      summary: Get account balance
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Account balance details
        '404':
          description: Account not found
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:read
  /accounts/{id}/transactions:
    get:
      operationId: AccountsController_getAccountTransactions
      summary: Get account transactions
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
        - name: to
          required: false
          in: query
          description: To Date
          schema:
            format: date-time
            example: '2025-12-01'
            type: string
        - name: from
          required: false
          in: query
          description: From Date
          schema:
            format: date-time
            example: '2025-10-01'
            type: string
      responses:
        '200':
          description: Paginated list of account transactions
        '400':
          description: Bad Request - Invalid page or limit parameters
        '404':
          description: Account not found
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:read
  /accounts/{id}/suspend:
    put:
      operationId: AccountsController_suspendAccount
      summary: Suspend account
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Account suspended successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AccountV1Dto'
        '404':
          description: Account not found
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:write
  /accounts/{id}/activate:
    put:
      operationId: AccountsController_activateAccount
      summary: Activate account
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Account activated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AccountV1Dto'
        '404':
          description: Account not found
      tags:
        - accounts
      security:
        - oauth2ClientCredentials:
            - accounts:write
  /transactions/new:
    post:
      operationId: TransactionsController_createTransaction
      summary: Create a new transaction
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTransactionV1Dto'
      responses:
        '201':
          description: Transaction created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionDto'
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:write
  /transactions/money-movement:
    get:
      operationId: TransactionsController_getMoneyMovement
      summary: Get money movement analytics for a specific month
      description: >-
        Returns aggregated money in/out data with top sources, top spends, and
        last 3 months trend
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: month
          required: true
          in: query
          description: Month (0-11, where 0 = January, 11 = December)
          schema:
            example: 0
            type: number
        - name: year
          required: true
          in: query
          description: Year (4-digit year)
          schema:
            example: 2026
            type: number
        - name: currency
          required: true
          in: query
          description: Currency code (e.g., KES, USD)
          schema:
            example: KES
            type: string
      responses:
        '200':
          description: Money movement analytics data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MoneyMovementResponseV1Dto'
        '400':
          description: Bad Request - Invalid query parameters
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:read
  /transactions/fees:
    get:
      operationId: TransactionsController_getFees
      summary: Get transaction fees
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Transaction fees retrieved successfully
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:read
  /transactions/recent:
    get:
      operationId: TransactionsController_getRecentTransactions
      summary: Get recent transactions
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Recent transactions retrieved successfully
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:read
  /transactions/{id}:
    get:
      operationId: TransactionsController_getTransaction
      summary: Get transaction by ID
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Transaction details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionDto'
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:read
  /transactions:
    get:
      operationId: TransactionsController_listAllTransactions
      summary: List transactions
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: true
          in: query
          schema:
            type: number
        - name: limit
          required: true
          in: query
          schema:
            type: number
        - name: account
          required: false
          in: query
          schema:
            type: string
        - name: export
          required: false
          in: query
          schema:
            type: string
        - name: search
          required: false
          in: query
          description: Search across description, reference
          schema:
            type: string
        - name: to
          required: false
          in: query
          description: To Date
          schema:
            format: date-time
            example: '2026-01-01T23:59:59'
            type: string
        - name: from
          required: false
          in: query
          description: From Date
          schema:
            format: date-time
            example: '2025-11-01'
            type: string
      responses:
        '200':
          description: List of transactions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTransactionResponseDto'
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:read
  /transactions/{id}/approve:
    put:
      operationId: TransactionsController_approveTransaction
      summary: Approve a transaction
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Transaction approved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionDto'
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:write
  /transactions/{id}/reject:
    put:
      operationId: TransactionsController_rejectTransaction
      summary: Reject a transaction
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Transaction rejected
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionDto'
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:write
  /transactions/{id}/tag:
    post:
      operationId: TransactionsController_tagTransaction
      summary: Tag a transaction with a subcategory
      description: >-
        Tags an expense or topup transaction with a subcategory. IFT and REFUND
        transactions are not supported.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TagTransactionDto'
      responses:
        '200':
          description: Transaction tagged successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionV1Dto'
        '400':
          description: >-
            Bad Request - Transaction type does not support tagging or
            subcategory not found/inactive
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:write
  /transactions/{id}/supporting-document:
    post:
      operationId: TransactionsController_uploadSupportingDocument
      summary: Upload a supporting document for a transaction
      description: >-
        Uploads a supporting document (PDF, XLS, XLSX, DOCX, CSV, PNG, JPEG) to
        S3 for a specific transaction. Maximum file size is 10MB.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UploadSupportingDocumentDto'
      responses:
        '201':
          description: Document uploaded successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadSupportingDocumentResponseDto'
        '400':
          description: >-
            Bad Request - Invalid content type, file format, or file size
            exceeds limit
        '404':
          description: Transaction not found
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:write
  /transactions/{id}/remove-document:
    post:
      operationId: TransactionsController_removeTransactionDocument
      summary: Remove a document from a transaction
      description: Removes an attachment from an EXPENSE or TOPUP transaction
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RemoveDocumentDto'
      responses:
        '200':
          description: Document removed successfully
        '400':
          description: Bad Request - Transaction not found or unsupported transaction type
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:write
  /transactions/supporting-document:
    post:
      operationId: TransactionsController_uploadAnySupportingDocument
      summary: Upload a supporting document for a transaction
      description: >-
        Uploads a supporting document (PDF, XLS, XLSX, DOCX, CSV, PNG, JPEG) to
        S3 for a specific transaction. Maximum file size is 10MB.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: query
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UploadSupportingDocumentDto'
      responses:
        '201':
          description: Document uploaded successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadSupportingDocumentResponseDto'
        '400':
          description: >-
            Bad Request - Invalid content type, file format, or file size
            exceeds limit
        '404':
          description: Transaction not found
      tags:
        - transactions
      security:
        - oauth2ClientCredentials:
            - transactions:write
  /categories:
    get:
      operationId: CategoriesController_listCategories
      summary: List categories
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: Page number
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Items per page (max 1000)
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: List of categories
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedCategoryResponseDto'
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:read
    post:
      operationId: CategoriesController_createCategory
      summary: Create a new category
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCategoryV1Dto'
      responses:
        '201':
          description: Category created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CategoryV1Dto'
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:write
  /categories/{id}:
    get:
      operationId: CategoriesController_getCategory
      summary: Get category by ID
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Category details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CategoryV1Dto'
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:read
    put:
      operationId: CategoriesController_updateCategory
      summary: Update a category
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateCategoryV1Dto'
      responses:
        '200':
          description: Category updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CategoryV1Dto'
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:write
    delete:
      operationId: CategoriesController_deleteCategory
      summary: Delete category
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Category deleted successfully
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:write
  /categories/bulk:
    post:
      operationId: CategoriesController_bulkCreateCategories
      summary: Bulk create categories and subcategories
      description: >-
        Creates multiple categories and subcategories in a single request.
        Automatically groups subcategories under their parent categories.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateCategoryV1Dto'
      responses:
        '201':
          description: Categories and subcategories created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkCreateCategoryResponseV1Dto'
        '400':
          description: Bad Request - Invalid input data or empty array
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:write
  /categories/{categoryId}/subcategories:
    get:
      operationId: CategoriesController_listSubcategories
      summary: List subcategories for a category
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: categoryId
          required: true
          in: path
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: Page number
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Items per page (max 1000)
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: List of subcategories
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedSubcategoryResponseDto'
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:read
    post:
      operationId: CategoriesController_createSubcategory
      summary: Create a new subcategory
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: categoryId
          required: true
          in: path
          description: Category ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSubcategoryV1Dto'
      responses:
        '201':
          description: Subcategory created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubcategoryV1Dto'
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Category not found
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:write
  /categories/{categoryId}/subcategories/{subcategoryId}:
    get:
      operationId: CategoriesController_getSubcategory
      summary: Get subcategory by ID
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: categoryId
          required: true
          in: path
          schema:
            type: string
        - name: subcategoryId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Subcategory details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubcategoryV1Dto'
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:read
    put:
      operationId: CategoriesController_updateSubcategory
      summary: Update a subcategory
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: categoryId
          required: true
          in: path
          description: Category ID
          schema:
            type: string
        - name: subcategoryId
          required: true
          in: path
          description: Subcategory ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSubcategoryV1Dto'
      responses:
        '200':
          description: Subcategory updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubcategoryV1Dto'
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Category or subcategory not found
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:write
    delete:
      operationId: CategoriesController_deleteSubcategory
      summary: Delete subcategory
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: categoryId
          required: true
          in: path
          schema:
            type: string
        - name: subcategoryId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Subcategory deleted successfully
      tags:
        - categories
      security:
        - oauth2ClientCredentials:
            - categories:write
  /teams:
    get:
      operationId: TeamsController_listTeams
      summary: List teams
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: Paginated list of teams
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTeamResponseDto'
        '400':
          description: Bad Request - Invalid page or limit parameters
      tags:
        - teams
      security:
        - oauth2ClientCredentials:
            - teams:read
    post:
      operationId: TeamsController_createTeam
      summary: Create new team
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTeamV1Dto'
      responses:
        '201':
          description: Team created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TeamV1Dto'
      tags:
        - teams
      security:
        - oauth2ClientCredentials:
            - teams:write
  /teams/{id}:
    get:
      operationId: TeamsController_getTeam
      summary: Get team by ID
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Team details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TeamV1Dto'
      tags:
        - teams
      security:
        - oauth2ClientCredentials:
            - teams:read
    put:
      operationId: TeamsController_updateTeam
      summary: Update team
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateTeamV1Dto'
      responses:
        '200':
          description: Team updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TeamV1Dto'
      tags:
        - teams
      security:
        - oauth2ClientCredentials:
            - teams:write
    delete:
      operationId: TeamsController_deleteTeam
      summary: Delete team
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Team deleted successfully
      tags:
        - teams
      security:
        - oauth2ClientCredentials:
            - teams:write
  /employees:
    get:
      operationId: EmployeesController_listEmployees
      summary: List employees
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
        - name: team_id
          required: false
          in: query
          description: Filter by team ID
          schema:
            type: string
        - name: status
          required: false
          in: query
          description: Filter by employee status (e.g., ACTIVE, INACTIVE)
          schema:
            example: ACTIVE
            type: string
      responses:
        '200':
          description: Paginated list of employees
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedEmployeeResponseDto'
        '400':
          description: Bad Request - Invalid page or limit parameters
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:read
    post:
      operationId: EmployeesController_createEmployee
      summary: Create new employee
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateEmployeeV1Dto'
      responses:
        '201':
          description: Employee created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeeV1Dto'
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/balances:
    get:
      operationId: EmployeesController_getEmployeeBalances
      summary: Get employee wallet balances
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employee_id
          required: true
          in: query
          description: Employee identifier
          schema:
            type: string
      responses:
        '200':
          description: Employee wallet balances
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/EmployeeBalanceDto'
        '400':
          description: Bad Request - employee_id is required
        '404':
          description: Not Found - Employee not found
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:read
  /employees/view-statement:
    get:
      operationId: EmployeesController_viewStatement
      summary: View employee transaction statement
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employee_id
          required: true
          in: query
          description: Employee identifier
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 20
            type: number
        - name: from
          required: false
          in: query
          description: Start date filter (ISO 8601 format)
          schema:
            example: '2024-01-01T00:00:00Z'
            type: string
        - name: to
          required: false
          in: query
          description: End date filter (ISO 8601 format)
          schema:
            example: '2024-12-31T23:59:59Z'
            type: string
      responses:
        '200':
          description: Paginated employee statement
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedStatementResponseDto'
        '400':
          description: Bad Request - Invalid parameters
        '401':
          description: Unauthorized
        '404':
          description: Not Found - Employee not found
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:read
  /employees/{employee_id}:
    get:
      operationId: EmployeesController_getEmployee
      summary: Get employee by employee_id
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employee_id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Employee details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmployeeV1Dto'
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:read
    delete:
      operationId: EmployeesController_deleteEmployee
      summary: Delete employee
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employee_id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Employee deleted successfully
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/remove-employee-team-reviewer:
    delete:
      operationId: EmployeesController_removeEmployeeTeamReviewer
      summary: Remove employee from team reviewers
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReviewerManagementV1Dto'
      responses:
        '200':
          description: Employee successfully removed from team reviewers
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Not Found - Employee or team not found
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/move-to-team:
    post:
      operationId: EmployeesController_moveEmployeeToTeam
      summary: Move employee to a different team
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MoveEmployeeToTeamV1Dto'
      responses:
        '200':
          description: Employee successfully moved to team
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Not Found - Employee or team not found
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/make-employee-team-reviewer:
    post:
      operationId: EmployeesController_makeEmployeeTeamReviewer
      summary: Add employee as team reviewer
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReviewerManagementV1Dto'
      responses:
        '200':
          description: Employee successfully added as team reviewer
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Not Found - Employee or team not found
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/update-profile:
    post:
      operationId: EmployeesController_updateEmployeeProfile
      summary: Update employee profile
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateProfileV1Dto'
      responses:
        '200':
          description: Employee profile updated successfully
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Not Found - Employee not found
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/activate-employee:
    patch:
      operationId: EmployeesController_activateEmployee
      summary: Activate an employee
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ActivateEmployeeV1Dto'
      responses:
        '200':
          description: Employee activated successfully
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/{_id}/suspend-employee:
    patch:
      operationId: EmployeesController_suspendEmployee
      summary: Suspend an employee
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: _id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Employee suspended successfully
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/transfer-ownership:
    post:
      operationId: EmployeesController_transferOwnership
      summary: Transfer employee ownership to a new person
      description: >-
        Suspends (or deletes) the existing employee account and provisions a new
        employee in its place, inheriting the same team and supervisor. Requires
        the caller to have PEOPLE_EDIT permission.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransferOwnershipV1Dto'
      responses:
        '200':
          description: >-
            Ownership transferred successfully. Returns the new employee ID and
            the old employee's updated status.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransferOwnershipResponseV1Dto'
        '400':
          description: >-
            Bad Request – missing required fields (employee_id/external_id,
            name, email, phone), or the provided email/phone is already in use
            by an active user.
        '401':
          description: >-
            Unauthorized – the authenticated user does not have PEOPLE_EDIT
            permission.
        '404':
          description: >-
            Not Found – no employee record matches the provided employee_id or
            external_id.
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/allocate-funds:
    post:
      operationId: EmployeesController_allocateFunds
      summary: Allocate funds to employee wallet
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AllocateFundsV1Dto'
      responses:
        '200':
          description: Funds allocated successfully
        '400':
          description: Bad Request - Invalid input data
        '401':
          description: Unauthorized
        '404':
          description: Not Found - Employee not found
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /employees/remove-funds:
    post:
      operationId: EmployeesController_removeFunds
      summary: Remove funds from employee wallet
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeductFundsV1Dto'
      responses:
        '200':
          description: Funds removed successfully
        '400':
          description: Bad Request - Invalid input data
        '401':
          description: Unauthorized
        '404':
          description: Not Found - Employee not found
      tags:
        - employees
      security:
        - oauth2ClientCredentials:
            - employees:write
  /permissions:
    get:
      operationId: PermissionsController_listAllPermissions
      summary: list all permissions
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: permissions fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PermissionResponseV1Dto'
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        list all permissions
  /permissions/employees/{employee_id}/role:
    patch:
      operationId: PermissionsController_updateUsersRole
      summary: Update users role
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employee_id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRoleV1Dto'
      responses:
        '200':
          description: User role updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateUsersRoleResponseV1Dto'
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Update users role
  /permissions/employees/{employee_id}:
    patch:
      operationId: PermissionsController_updateEmployeePermissions
      summary: Update employee permissions
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Update employee permissions
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employee_id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateEmployeePermissionsV1Dto'
      responses:
        '200':
          description: Employee permissions updated successfully
        '400':
          description: Bad Request - Invalid permission values or structure
        '404':
          description: Employee not found
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:write
      x-boya-access: private-label
    post:
      operationId: PermissionsController_getEmployeePermissions
      summary: Fetch employee permissions
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Fetch grouped permissions for a specific employee
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employee_id
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Employee permissions fetched successfully
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:write
      x-boya-access: private-label
  /permissions/update/{role_id}:
    put:
      operationId: PermissionsController_updateRolePermissions
      summary: Update role permissions
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Update permissions for a specific role
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: role_id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateRolePermissionsV1Dto'
      responses:
        '200':
          description: Role permissions updated successfully
        '400':
          description: Bad Request - Invalid permission structure
        '401':
          description: Unauthorized
        '404':
          description: Role not found
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:write
      x-boya-access: private-label
  /permissions/mandates:
    put:
      operationId: PermissionsController_listMandates
      summary: get set mandates
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: mandates fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MandateResponseV1Dto'
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        get set mandates
  /permissions/mandates/{mandate_id}:
    patch:
      operationId: PermissionsController_updateMandate
      summary: Update mandate minimum approvers
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: mandate_id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateMandateV1Dto'
      responses:
        '200':
          description: Mandate updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MandateResponseV1Dto'
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Update mandate minimum approvers
  /permissions/mandates/{mandate_id}/approvers/{approver_id}:
    patch:
      operationId: PermissionsController_updateSingleApprover
      summary: update user mandate
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: mandate_id
          required: true
          in: path
          schema:
            type: string
        - name: approver_id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSingleApproverV1Dto'
      responses:
        '200':
          description: Mandate updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MandateResponseV1Dto'
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        update user mandate
  /permissions/mandates/{mandate_id}/approvers:
    delete:
      operationId: PermissionsController_removeApproverFromMandate
      summary: Remove approvers from mandate
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Remove one or more approvers from a mandate by providing their IDs
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: mandate_id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RemoveApproverFromMandateV1Dto'
      responses:
        '200':
          description: Approvers removed from mandate successfully
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:write
      x-boya-access: private-label
    post:
      operationId: PermissionsController_addApproversToMandate
      summary: Add approvers to mandate
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Add one or more approvers to a mandate by providing their IDs and
        configuration
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: mandate_id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddApproversToMandateV1Dto'
      responses:
        '200':
          description: Approvers added to mandate successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MandateResponseV1Dto'
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Mandate not found
      tags:
        - roles
      security:
        - oauth2ClientCredentials:
            - roles:write
      x-boya-access: private-label
  /vendors:
    get:
      operationId: VendorsController_listVendors
      summary: List vendors
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: Page number
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Items per page (max 1000)
          schema:
            example: 20
            type: number
      responses:
        '200':
          description: List of vendors
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedVendorResponseDto'
      tags:
        - vendors
      security:
        - oauth2ClientCredentials:
            - vendors:read
    post:
      operationId: VendorsController_createVendor
      summary: Create a new vendor
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateVendorV1Dto'
      responses:
        '201':
          description: Vendor created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VendorV1Dto'
        '400':
          description: Bad Request - Invalid input data
      tags:
        - vendors
      security:
        - oauth2ClientCredentials:
            - vendors:write
  /vendors/recent/{channel}:
    get:
      operationId: VendorsController_getRecentVendors
      summary: Get recent vendors by channel
      description: >-
        Returns a merged list of recently paid vendors from suppliers and
        expenses. Vendors from suppliers have an _id, while vendors derived from
        expenses lack an _id to indicate they can be created as new vendors.
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: channel
          required: true
          in: path
          description: Payment channel type
          schema:
            enum:
              - mpesa
              - mtn
              - pochi
              - airtel
              - xentebanktransfer
              - bank
              - rtgs
              - paybill
              - till
              - airtime
              - internal
            type: string
      responses:
        '200':
          description: List of recent vendors
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RecentVendorV1Dto'
      tags:
        - vendors
      security:
        - oauth2ClientCredentials:
            - vendors:read
  /vendors/{id}:
    get:
      operationId: VendorsController_getVendor
      summary: Get vendor by ID
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Vendor ID
          schema:
            type: string
      responses:
        '200':
          description: Vendor details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VendorV1Dto'
        '404':
          description: Vendor not found
      tags:
        - vendors
      security:
        - oauth2ClientCredentials:
            - vendors:read
    put:
      operationId: VendorsController_updateVendor
      summary: Update a vendor
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Vendor ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateVendorV1Dto'
      responses:
        '200':
          description: Vendor updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VendorV1Dto'
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Vendor not found
      tags:
        - vendors
      security:
        - oauth2ClientCredentials:
            - vendors:write
    delete:
      operationId: VendorsController_deleteVendor
      summary: Delete vendor
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Vendor ID
          schema:
            type: string
      responses:
        '200':
          description: Vendor deleted successfully
        '404':
          description: Vendor not found
      tags:
        - vendors
      security:
        - oauth2ClientCredentials:
            - vendors:write
  /vendors/{id}/payment-instruction:
    post:
      operationId: VendorsController_updatePaymentInstruction
      summary: Update vendor payment instruction
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Vendor ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdatePaymentInstructionV1Dto'
      responses:
        '200':
          description: Payment instruction updated successfully
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Vendor not found
      tags:
        - vendors
      security:
        - oauth2ClientCredentials:
            - vendors:write
  /vendors/{id}/payment-instruction/add:
    post:
      operationId: VendorsController_addPaymentInstruction
      summary: Add vendor payment instruction
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Vendor ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddPaymentInstructionV1Dto'
      responses:
        '200':
          description: Payment instruction added successfully
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Vendor not found
      tags:
        - vendors
      security:
        - oauth2ClientCredentials:
            - vendors:write
  /payments/channels:
    get:
      operationId: PaymentsController_getPaymentChannels
      summary: Get payment channels for a country
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: country
          required: true
          in: query
          description: Country code (e.g., KENYA)
          schema:
            example: KENYA
            type: string
      responses:
        '200':
          description: Payment channels retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentChannelsResponseV1Dto'
        '400':
          description: Bad Request - Missing country parameter
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get payment channels for a country
  /payments:
    get:
      operationId: PaymentsController_listPayments
      summary: List bulk payments with pagination
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: Page number
          schema:
            example: 1
            type: number
        - name: per_page
          required: false
          in: query
          description: Items per page (max 100)
          schema:
            example: 25
            type: number
        - name: status
          required: false
          in: query
          description: Payment status filter
          schema:
            enum:
              - pending
              - processed
              - cancelled
              - draft
            type: string
        - name: from
          required: false
          in: query
          description: From Date
          schema:
            format: date-time
            example: 2026-02-01 00:00
            type: string
        - name: to
          required: false
          in: query
          description: To Date
          schema:
            format: date-time
            example: 2026-02-07 23:59
            type: string
        - name: account
          required: false
          in: query
          description: Account filter
          schema:
            example: all
            type: string
        - name: channel
          required: false
          in: query
          description: Payment channel filter
          schema:
            example: all
            type: string
        - name: all_currency
          required: false
          in: query
          description: Fetch across all currencies
          schema:
            example: 'true'
            type: string
      responses:
        '200':
          description: List of bulk payments
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedPaymentsResponseV1Dto'
        '400':
          description: Bad Request - Invalid parameters
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        List bulk payments with pagination
    post:
      operationId: PaymentsController_createBulkPayout
      summary: Create bulk payout
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateBulkPayoutV1Dto'
      responses:
        '201':
          description: Bulk payout batch created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkPaymentV1Dto'
        '400':
          description: Bad Request - Invalid input or validation errors
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Create bulk payout
  /payments/banks:
    get:
      operationId: PaymentsController_getBanks
      summary: Get banks for a country
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: country
          required: true
          in: query
          description: Country code (e.g., KENYA)
          schema:
            example: KENYA
            type: string
      responses:
        '200':
          description: Banks retrieved successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BankV1Dto'
        '400':
          description: Bad Request - Missing country parameter
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get banks for a country
  /payments/intent:
    post:
      operationId: PaymentsController_createPaymentIntent
      summary: Create payment intent
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePaymentIntentV1Dto'
      responses:
        '201':
          description: Payment intent created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentIntentResponseV1Dto'
        '400':
          description: Bad Request - Invalid input
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Create payment intent
  /payments/confirm:
    post:
      operationId: PaymentsController_confirmPaymentIntent
      summary: Confirm payment intent with OTP
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfirmPaymentIntentV1Dto'
      responses:
        '200':
          description: Payment confirmed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentConfirmationResponseV1Dto'
        '400':
          description: Bad Request - Intent expired or invalid
        '401':
          description: Unauthorized - Invalid OTP or secret
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Confirm payment intent with OTP
  /payments/request-mpesa-payment:
    post:
      operationId: PaymentsController_requestMpesaPayment
      summary: Request M-Pesa STK push payment
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestMpesaPaymentV1Dto'
      responses:
        '200':
          description: M-Pesa payment request initiated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MpesaPaymentResponseV1Dto'
        '400':
          description: Bad Request - Invalid parameters
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Request M-Pesa STK push payment
  /payments/{batch_no}/initiate:
    patch:
      operationId: PaymentsController_initiateDraftPayout
      summary: Initiate draft payout
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: batch_no
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InitiateBulkPayoutV1Dto'
      responses:
        '200':
          description: Payout initiated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkPaymentV1Dto'
        '400':
          description: Bad Request - Invalid batch number or batch not in draft status
        '404':
          description: Not Found - Batch number does not exist
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Initiate draft payout
  /payments/{batch_no}/draft:
    patch:
      operationId: PaymentsController_cancelPayout
      summary: Return payout to draft status
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: batch_no
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: Payout returned to draft
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkPaymentV1Dto'
        '400':
          description: Bad Request - Invalid batch number
        '404':
          description: Not Found - Batch number does not exist
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Return payout to draft status
  /payments/payout/cancel:
    post:
      operationId: PaymentsController_rejectPayout
      summary: cancel a payout batch
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RejectPayoutV1Dto'
      responses:
        '200':
          description: Payout rejected successfully
        '400':
          description: Bad Request - Invalid ref/reason or validation error
        '401':
          description: Unauthorized - Missing or invalid bearer token
        '404':
          description: Payout batch not found
      tags:
        - payments
      security:
        - oauth2ClientCredentials:
            - payments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        cancel a payout batch
  /wallet-policies/permissions:
    get:
      operationId: WalletAccessPolicyController_listPermissions
      summary: List all available permissions
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Permissions retrieved successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PermissionV1Dto'
      tags:
        - wallet-policies-permissions
      security:
        - oauth2ClientCredentials:
            - wallet-policies:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        List all available permissions
  /wallet-policies/permissions/sync:
    post:
      operationId: WalletAccessPolicyController_syncPermissions
      summary: Sync permission seed data
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Permissions synced successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PermissionSyncResultDto'
      tags:
        - wallet-policies-permissions
      security:
        - oauth2ClientCredentials:
            - wallet-policies:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Sync permission seed data
  /wallet-policies/permissions/{employeeId}/{walletId}:
    get:
      operationId: WalletAccessPolicyController_getComputedPermissions
      summary: Get computed permissions for employee on wallet
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employeeId
          required: true
          in: path
          description: Employee ID
          schema:
            type: string
        - name: walletId
          required: true
          in: path
          description: Wallet ID
          schema:
            type: string
      responses:
        '200':
          description: Computed permissions retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ComputedPermissionsDto'
      tags:
        - wallet-policies-permissions
      security:
        - oauth2ClientCredentials:
            - wallet-policies:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get computed permissions for employee on wallet
  /wallet-policies/check-access:
    post:
      operationId: WalletAccessPolicyController_checkAccess
      summary: Check if employee has permission on wallet
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckAccessV1Dto'
      responses:
        '200':
          description: Access check completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AccessCheckResultDto'
      tags:
        - wallet-policies-checks
      security:
        - oauth2ClientCredentials:
            - wallet-policies:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Check if employee has permission on wallet
  /wallet-policies/check-limits:
    post:
      operationId: WalletAccessPolicyController_checkLimits
      summary: Check transaction limits
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckLimitsV1Dto'
      responses:
        '200':
          description: Limits check completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LimitsCheckResultDto'
      tags:
        - wallet-policies-checks
      security:
        - oauth2ClientCredentials:
            - wallet-policies:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Check transaction limits
  /wallet-policies/audit/query:
    post:
      operationId: WalletAccessPolicyController_queryAuditLogs
      summary: Query audit logs with filters
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueryAuditLogsV1Dto'
      responses:
        '200':
          description: Audit logs retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedAuditLogsResponseDto'
      tags:
        - wallet-policies-audit
      security:
        - oauth2ClientCredentials:
            - wallet-policies:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Query audit logs with filters
  /wallet-policies/wallet/{walletId}:
    get:
      operationId: WalletAccessPolicyController_getPoliciesByWallet
      summary: Get policies by wallet ID
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: walletId
          required: true
          in: path
          description: Wallet ID
          schema:
            type: string
        - name: status
          required: false
          in: query
          description: Filter by status
          schema:
            enum:
              - ACTIVE
              - SUSPENDED
              - EXPIRED
              - REVOKED
            type: string
        - name: includeExpired
          required: false
          in: query
          description: Include expired/revoked policies
          schema:
            default: false
            type: string
      responses:
        '200':
          description: Policies retrieved successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PolicyV1Dto'
      tags:
        - wallet-policies
      security:
        - oauth2ClientCredentials:
            - wallet-policies:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get policies by wallet ID
  /wallet-policies/wallet/{walletId}/audit:
    get:
      operationId: WalletAccessPolicyController_getWalletAuditLog
      summary: Get audit log for wallet
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: walletId
          required: true
          in: path
          description: Wallet ID
          schema:
            type: string
      responses:
        '200':
          description: Audit logs retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedAuditLogsResponseDto'
      tags:
        - wallet-policies-audit
      security:
        - oauth2ClientCredentials:
            - wallet-policies:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get audit log for wallet
  /wallet-policies/employee/{employeeId}:
    get:
      operationId: WalletAccessPolicyController_getPoliciesByEmployee
      summary: Get policies by employee ID
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: employeeId
          required: true
          in: path
          description: Employee ID
          schema:
            type: string
        - name: status
          required: false
          in: query
          description: Filter by status
          schema:
            enum:
              - ACTIVE
              - SUSPENDED
              - EXPIRED
              - REVOKED
            type: string
        - name: includeExpired
          required: false
          in: query
          description: Include expired/revoked policies
          schema:
            default: false
            type: string
      responses:
        '200':
          description: Policies retrieved successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PolicyV1Dto'
      tags:
        - wallet-policies
      security:
        - oauth2ClientCredentials:
            - wallet-policies:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get policies by employee ID
  /wallet-policies/{policyId}:
    get:
      operationId: WalletAccessPolicyController_getPolicy
      summary: Get single policy by ID
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: policyId
          required: true
          in: path
          description: Policy ID
          schema:
            type: string
      responses:
        '200':
          description: Policy retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyV1Dto'
      tags:
        - wallet-policies
      security:
        - oauth2ClientCredentials:
            - wallet-policies:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get single policy by ID
    patch:
      operationId: WalletAccessPolicyController_modifyPolicy
      summary: Modify policy
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: policyId
          required: true
          in: path
          description: Policy ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ModifyAccessV1Dto'
      responses:
        '200':
          description: Policy modified successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyV1Dto'
      tags:
        - wallet-policies
      security:
        - oauth2ClientCredentials:
            - wallet-policies:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Modify policy
    delete:
      operationId: WalletAccessPolicyController_revokePolicy
      summary: Revoke policy
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: policyId
          required: true
          in: path
          description: Policy ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RevokeAccessV1Dto'
      responses:
        '200':
          description: Policy revoked successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyV1Dto'
      tags:
        - wallet-policies
      security:
        - oauth2ClientCredentials:
            - wallet-policies:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Revoke policy
  /wallet-policies/{policyId}/suspend:
    post:
      operationId: WalletAccessPolicyController_suspendPolicy
      summary: Suspend policy
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: policyId
          required: true
          in: path
          description: Policy ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SuspendAccessV1Dto'
      responses:
        '200':
          description: Policy suspended successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyV1Dto'
      tags:
        - wallet-policies
      security:
        - oauth2ClientCredentials:
            - wallet-policies:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Suspend policy
  /wallet-policies/{policyId}/reactivate:
    post:
      operationId: WalletAccessPolicyController_reactivatePolicy
      summary: Reactivate policy
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: policyId
          required: true
          in: path
          description: Policy ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReactivateAccessV1Dto'
      responses:
        '200':
          description: Policy reactivated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyV1Dto'
      tags:
        - wallet-policies
      security:
        - oauth2ClientCredentials:
            - wallet-policies:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Reactivate policy
  /wallet-policies/{policyId}/audit:
    get:
      operationId: WalletAccessPolicyController_getPolicyAuditLog
      summary: Get audit log for specific policy
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: policyId
          required: true
          in: path
          description: Policy ID
          schema:
            type: string
      responses:
        '200':
          description: Audit logs retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedAuditLogsResponseDto'
      tags:
        - wallet-policies-audit
      security:
        - oauth2ClientCredentials:
            - wallet-policies:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get audit log for specific policy
  /wallet-policies:
    post:
      operationId: WalletAccessPolicyController_grantAccess
      summary: Grant access (create policy)
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GrantAccessV1Dto'
      responses:
        '201':
          description: Access granted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyV1Dto'
      tags:
        - wallet-policies
      security:
        - oauth2ClientCredentials:
            - wallet-policies:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Grant access (create policy)
  /taxes:
    get:
      operationId: TaxesController_listTaxes
      summary: List all withholding tax settings
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: List of tax settings
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTaxResponseDto'
      tags:
        - taxes
      security:
        - oauth2ClientCredentials:
            - taxes:read
  /taxes/create:
    post:
      operationId: TaxesController_createTax
      summary: Create a new withholding tax setting
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTaxV1Dto'
      responses:
        '201':
          description: Tax setting created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TaxV1Dto'
        '400':
          description: Bad Request - Invalid input data
      tags:
        - taxes
      security:
        - oauth2ClientCredentials:
            - taxes:write
  /taxes/{taxId}/edit:
    put:
      operationId: TaxesController_updateTax
      summary: Edit a withholding tax setting
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: taxId
          required: true
          in: path
          description: Tax ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateTaxV1Dto'
      responses:
        '200':
          description: Tax setting updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TaxV1Dto'
        '400':
          description: Bad Request - Invalid input data
        '404':
          description: Tax setting not found
      tags:
        - taxes
      security:
        - oauth2ClientCredentials:
            - taxes:write
  /taxes/{taxId}/archive:
    put:
      operationId: TaxesController_archiveTax
      summary: Archive/delete a withholding tax setting
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: taxId
          required: true
          in: path
          description: Tax ID
          schema:
            type: string
      responses:
        '200':
          description: Tax setting archived successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TaxV1Dto'
        '404':
          description: Tax setting not found
      tags:
        - taxes
      security:
        - oauth2ClientCredentials:
            - taxes:write
  /taxes/transactions:
    get:
      operationId: TaxesController_getTaxTransactions
      summary: Fetch all withholding tax transactions
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: List of tax transactions retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TaxTransactionsResponseV1Dto'
        '400':
          description: Bad Request - Missing required headers
        '401':
          description: Unauthorized - Invalid or missing authentication token
      tags:
        - taxes
      security:
        - oauth2ClientCredentials:
            - taxes:read
  /subscriptions:
    get:
      operationId: SubscriptionsController_listSubscriptions
      summary: List subscriptions
      description: >-
        Retrieves a paginated list of subscriptions with optional filtering by
        search term and status
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: 'Page number (minimum: 1)'
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: 'Number of items per page (minimum: 1, maximum: 1000)'
          schema:
            example: 50
            type: number
        - name: search
          required: false
          in: query
          description: Search term to filter subscriptions by name or merchant
          schema:
            example: Netflix
            type: string
        - name: status
          required: false
          in: query
          description: Filter subscriptions by status
          schema:
            enum:
              - DRAFT
              - ACTIVE
              - PAUSED
              - REJECTED
              - DELETED
              - PENDING
            type: string
      responses:
        '200':
          description: List of subscriptions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedSubscriptionResponseDto'
        '400':
          description: Bad Request - Invalid query parameters
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:read
  /subscriptions/expenses:
    get:
      operationId: SubscriptionsController_getSubscriptionExpenses
      summary: Get subscription expenses
      description: Retrieves paginated list of expenses for a specific subscription
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: subscription_id
          required: true
          in: query
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: Page number
          schema:
            example: 1
            type: number
      responses:
        '200':
          description: Paginated subscription expenses
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedExpensesDto'
        '400':
          description: Bad Request - Missing subscription_id
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:read
  /subscriptions/amount-spent:
    post:
      operationId: SubscriptionsController_getAmountSpent
      summary: Get amount spent per subscription
      description: Retrieves amount spent per subscription with period breakdown
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AmountSpentRequestDto'
      responses:
        '200':
          description: Amount spent data with period breakdown
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AmountSpentResponseDto'
        '400':
          description: Bad Request - Invalid request body
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:write
  /subscriptions/create:
    post:
      operationId: SubscriptionsController_createSubscription
      summary: Create subscription
      description: Creates a new subscription with specified configuration
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSubscriptionRequestDto'
      responses:
        '201':
          description: Subscription created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionV1Dto'
        '400':
          description: Bad Request - Invalid request body
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:write
  /subscriptions/status:
    put:
      operationId: SubscriptionsController_updateStatus
      summary: Update subscription status
      description: Updates the status of a subscription (ACTIVE or PAUSED)
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: subscription_id
          required: true
          in: query
          description: Subscription ID
          schema:
            example: 67b44aea86c1ccabbe965827
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateStatusRequestDto'
      responses:
        '200':
          description: Updated subscription
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionV1Dto'
        '400':
          description: Bad Request - Missing subscription_id or invalid status
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:write
  /subscriptions/team:
    put:
      operationId: SubscriptionsController_updateTeam
      summary: Update subscription team
      description: Updates team information for a subscription
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: subscription_id
          required: true
          in: query
          description: Subscription ID
          schema:
            example: 67b44aea86c1ccabbe965827
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateTeamRequestDto'
      responses:
        '200':
          description: Updated subscription with new team
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionV1Dto'
        '400':
          description: Bad Request - Missing subscription_id or invalid team data
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:write
  /subscriptions/limits-billing-frequency:
    put:
      operationId: SubscriptionsController_updateLimitsBillingFrequency
      summary: Update subscription limits and billing frequency
      description: Updates the limits and billing frequency for a subscription
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: subscription_id
          required: true
          in: query
          description: Subscription ID
          schema:
            example: 67b44aea86c1ccabbe965827
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateLimitsBillingFrequencyRequestDto'
      responses:
        '200':
          description: Updated subscription with new limits and billing frequency
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionV1Dto'
        '400':
          description: Bad Request - Missing subscription_id or invalid data
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:write
  /subscriptions/assign-employee:
    put:
      operationId: SubscriptionsController_assignEmployee
      summary: Assign employee to subscription
      description: Assigns an employee and card to a subscription
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: subscription_id
          required: true
          in: query
          description: Subscription ID
          schema:
            example: 67b44aea86c1ccabbe965827
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AssignEmployeeRequestDto'
      responses:
        '200':
          description: Updated subscription with assigned employee
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionV1Dto'
        '400':
          description: Bad Request - Missing subscription_id or invalid data
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:write
  /subscriptions/subcategory:
    put:
      operationId: SubscriptionsController_updateSubcategory
      summary: Update subscription subcategory
      description: Updates the subcategory for a subscription
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: subscription_id
          required: true
          in: query
          description: Subscription ID
          schema:
            example: 67b44aea86c1ccabbe965827
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSubcategoryRequestDto'
      responses:
        '200':
          description: Updated subscription with new subcategory
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionV1Dto'
        '400':
          description: Bad Request - Missing subscription_id or invalid data
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:write
  /subscriptions/auto-generate:
    post:
      operationId: SubscriptionsController_autoGenerateSubscriptions
      summary: Auto generate subscriptions
      description: Automatically generates subscriptions from transaction patterns
      parameters:
        - name: org_wallet_ref
          in: header
          description: Organization wallet reference, defaults to "1" if not provided
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Auto generated subscriptions response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AutoGenerateResponseDto'
        '400':
          description: Bad Request
      tags:
        - subscriptions
      security:
        - oauth2ClientCredentials:
            - subscriptions:write
  /audit-trail:
    get:
      operationId: AuditTrailController_listAuditEvents
      summary: List audit trail events
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: Page number
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Items per page (max 1000)
          schema:
            example: 15
            type: number
      responses:
        '200':
          description: List of audit trail events
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedAuditEventResponseDto'
        '401':
          description: Unauthorized
      tags:
        - audit-trail
      security:
        - oauth2ClientCredentials:
            - audit-trail:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        List audit trail events
  /audit-trail/digest:
    get:
      operationId: AuditTrailController_getAuditDigest
      summary: Get intelligent audit trail digest with grouped insights
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          description: Page number for underlying events
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          description: Number of events to analyze (max 1000)
          schema:
            example: 100
            type: number
      responses:
        '200':
          description: Audit trail digest with grouped insights and statistics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuditDigestResponseDto'
        '401':
          description: Unauthorized
      tags:
        - audit-trail
      security:
        - oauth2ClientCredentials:
            - audit-trail:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Get intelligent audit trail digest with grouped insights
  /tags:
    get:
      operationId: TagsController_listTags
      summary: List all expense tags
      description: >-
        Returns all active expense tags for the business. Used to populate the
        tags dropdown on the single-use card request form and expense forms.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: List of tags returned successfully
        '400':
          description: Bad Request — business_id header missing
        '401':
          description: Unauthorized
      tags:
        - tags
      security:
        - oauth2ClientCredentials:
            - tags:read
  /tags/groups:
    get:
      operationId: TagsController_listTagGroups
      summary: List tag groups with their tags
      description: >-
        Returns all tag groups (e.g. "Project", "Department") and their
        associated tags for the business.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Tag groups returned successfully
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
      tags:
        - tags
      security:
        - oauth2ClientCredentials:
            - tags:read
  /customers:
    get:
      operationId: CustomersController_listCustomers
      summary: List business customers
      description: >-
        Returns customers associated with the business. By default returns only
        ACTIVE customers; pass ?status=DELETED to list soft-deleted customers or
        ?status=ALL to list both populations.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: page
          required: false
          in: query
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          schema:
            example: 50
            type: number
        - name: status
          required: false
          in: query
          description: Filter by customer status. Defaults to ACTIVE when omitted.
          schema:
            enum:
              - ACTIVE
              - DELETED
              - ALL
            type: string
      responses:
        '200':
          description: Customer list returned successfully
        '400':
          description: Bad Request — invalid status filter
        '401':
          description: Unauthorized — missing or invalid bearer token
        '403':
          description: Forbidden — business_id header missing
      tags:
        - customers
      security:
        - oauth2ClientCredentials:
            - customers:read
    post:
      operationId: CustomersController_createCustomer
      summary: Create a customer
      description: >-
        Creates a new customer.


        - **regular**: only `name` is required. `email`, `phone`, `address`,
        `taxPin` and `person` are optional.

        - **walkIn**: only `type` is required. Name is auto-set to "WalkIn" and
        all other fields are null. Only one Walk-In customer is allowed per
        business at a time (active OR archived).
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCustomerDto'
            examples:
              regular_customer:
                summary: >-
                  Regular customer (only name is required; everything else is
                  optional)
                value:
                  type: regular
                  name: Acme Corp
                  taxPin: A123456789Z
                  email: billing@acme.com
                  phone: '+254700000000'
                  address: 123 Main Street, Nairobi
                  person: []
              walkin_customer:
                summary: Walk-In customer (type only required)
                value:
                  type: walkIn
      responses:
        '201':
          description: Customer created successfully
        '400':
          description: >-
            Bad Request — invalid type, or `name`/`taxPin` missing when `type`
            is `regular`
        '401':
          description: Unauthorized — missing or invalid bearer token
        '409':
          description: Conflict — an active Walk-In customer already exists
      tags:
        - customers
      security:
        - oauth2ClientCredentials:
            - customers:write
  /customers/{id}:
    get:
      operationId: CustomersController_getCustomer
      summary: Get a customer by ID
      description: Fetches a single customer document by its MongoDB ObjectId.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Customer MongoDB ObjectId
          schema:
            example: 64f4205154a6357a7f85f656
            type: string
      responses:
        '200':
          description: Customer returned successfully
        '400':
          description: Bad Request — customer ID is required
        '401':
          description: Unauthorized — missing or invalid bearer token
        '404':
          description: Not Found — customer not found
      tags:
        - customers
      security:
        - oauth2ClientCredentials:
            - customers:read
    put:
      operationId: CustomersController_updateCustomer
      summary: Update a customer by ID
      description: >-
        Updates an active regular customer. Walk-In customers are immutable and
        cannot be edited.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Customer MongoDB ObjectId
          schema:
            example: 64f4205154a6357a7f85f656
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateCustomerDto'
      responses:
        '200':
          description: Customer updated successfully
        '400':
          description: Bad Request — empty payload, or Walk-In customer
        '401':
          description: Unauthorized — missing or invalid bearer token
        '404':
          description: Not Found — customer not found
      tags:
        - customers
      security:
        - oauth2ClientCredentials:
            - customers:write
    delete:
      operationId: CustomersController_deleteCustomer
      summary: Soft-delete a customer by ID
      description: >-
        Marks an active customer as deleted. The record is retained but excluded
        from all active customer queries.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Customer MongoDB ObjectId
          schema:
            example: 64f4205154a6357a7f85f656
            type: string
      responses:
        '200':
          description: Customer deleted successfully
        '401':
          description: Unauthorized — missing or invalid bearer token
        '404':
          description: Not Found — active customer not found
      tags:
        - customers
      security:
        - oauth2ClientCredentials:
            - customers:write
  /customers/{id}/reactivate:
    patch:
      operationId: CustomersController_reactivateCustomer
      summary: Reactivate a soft-deleted customer by ID
      description: >-
        Flips a soft-deleted customer back to ACTIVE. Idempotent: calling on an
        already-active customer is a no-op.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Customer MongoDB ObjectId
          schema:
            example: 64f4205154a6357a7f85f656
            type: string
      responses:
        '200':
          description: Customer reactivated successfully
        '401':
          description: Unauthorized — missing or invalid bearer token
        '404':
          description: Not Found — customer not found
      tags:
        - customers
      security:
        - oauth2ClientCredentials:
            - customers:write
  /customers/search:
    get:
      operationId: CustomersController_searchCustomers
      summary: Search active customers
      description: >-
        Full-text search across customer name, phone, and email. Returns up to
        10 active matches.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: q
          required: true
          in: query
          description: Search query string
          schema:
            example: Acme
            type: string
      responses:
        '200':
          description: Search results returned successfully
        '400':
          description: Bad Request — search query is required
        '401':
          description: Unauthorized — missing or invalid bearer token
      tags:
        - customers
      security:
        - oauth2ClientCredentials:
            - customers:read
  /business-policies:
    get:
      operationId: BusinessPoliciesController_listPolicyGroups
      summary: List all business policy groups
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns all policy groups configured for the authenticated business,
        each containing their associated policies and rules.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Policy groups returned successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PolicyGroupV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:read
      x-boya-access: private-label
  /business-policies/policy-group-policies:
    get:
      operationId: BusinessPoliciesController_getPolicyGroupPolicies
      summary: Fetch all policy groups with their policies
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns all policy groups, each with their associated policy types
        (CHANNELS, SUBCATEGORY, VENDORS, TIME, RECEIPTS, TAGS, etc.) including
        both business-specific policies and default rules.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Policy groups with policies returned successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PolicyGroupWithPoliciesV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:read
      x-boya-access: private-label
  /business-policies/{policyId}/policies:
    get:
      operationId: BusinessPoliciesController_getPoliciesByGroupId
      summary: Get business policies by policy group ID
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns the policy group and all its associated business policies,
        including rules, conditions, targets, and funding strategies.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: policyId
          required: true
          in: path
          description: >-
            Policy group ID (the _id of a policy group from GET
            /v1/business-policies)
          schema:
            example: 66788af92805e9ffbda6dcee
            type: string
      responses:
        '200':
          description: Policies returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyWithBusinessPoliciesV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
        '404':
          description: Policy group not found
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:read
      x-boya-access: private-label
  /business-policies/single/{businessPolicyId}:
    get:
      operationId: BusinessPoliciesController_getPolicyById
      summary: Get a single business policy by ID
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns a specific business policy document by its ID. Includes the
        associated policy type, rules, conditions, targets, and funding
        strategy.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: businessPolicyId
          required: true
          in: path
          description: >-
            Unique business policy document ID (the _id from a business_policies
            entry)
          schema:
            example: 697b6c810a21d470ffaca828
            type: string
      responses:
        '200':
          description: Business policy returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessPolicyV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
        '404':
          description: Business policy not found
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:read
      x-boya-access: private-label
  /business-policies/summary/{businessId}:
    get:
      operationId: BusinessPoliciesController_getBusinessPolicySummary
      summary: Get full business policy summary
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns the full policy summary for the given business, covering all
        configured policy codes. Used by the single-use card request form to
        determine form field requirements.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: businessId
          required: true
          in: path
          description: Business ID to fetch policy summary for
          schema:
            example: CDCAF716DC722
            type: string
        - name: employee_id
          required: true
          in: query
          description: The employee's internal employee_id from the B2B system
          schema:
            example: abcdefghijklmnopqrstuvwxyzabcd
            type: string
      responses:
        '200':
          description: Policy summary returned successfully
        '400':
          description: employee_id query param is required
        '401':
          description: Unauthorized
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:read
      x-boya-access: private-label
  /business-policies/category-policies:
    get:
      operationId: BusinessPoliciesController_getCategoryPolicies
      summary: Get category or subcategory policies
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns all business policies for the given type (SUBCATEGORY or
        CATEGORY). The policy group ID is resolved automatically — no need to
        pass it explicitly. When `type` is omitted, returns the combined
        CATEGORY + SUBCATEGORY policies (empty array if neither group exists —
        no 404 on that path).
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: type
          required: false
          in: query
          description: >-
            Policy type to fetch. Case-insensitive. Omit to return all category
            and subcategory policies.
          schema:
            enum:
              - subcategory
              - category
            type: string
      responses:
        '200':
          description: Policies returned successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BusinessPolicyV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
        '404':
          description: >-
            Policy group not found for the given type (only when `type` is
            provided)
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:read
      x-boya-access: private-label
    put:
      operationId: BusinessPoliciesController_upsertCategoryPolicy
      summary: Create or update a category / subcategory policy
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Upserts a business policy under the SUBCATEGORY or CATEGORY policy
        group.


        - **Without `_id`**: initializes a new policy then applies the full
        payload in one call.

        - **With `_id`**: updates the existing policy directly.


        The policy group is resolved automatically from the `type` query param.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: type
          required: true
          in: query
          description: Policy group to operate under. Case-insensitive.
          schema:
            enum:
              - subcategory
              - category
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpsertCategoryPolicyV1Dto'
      responses:
        '200':
          description: Business policy created or updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessPolicyV1Dto'
        '400':
          description: type query param is required
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
        '404':
          description: Policy group not found for the given type
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:write
      x-boya-access: private-label
  /business-policies/category-policies/{businessPolicyId}:
    put:
      operationId: BusinessPoliciesController_updateCategoryPolicy
      summary: Update a category or subcategory policy
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Updates an existing SUBCATEGORY or CATEGORY business policy. Pass
        status: "DISABLED" or "INACTIVE" to disable (INACTIVE is normalized to
        DISABLED).
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: businessPolicyId
          required: true
          in: path
          description: Business policy document ID
          schema:
            example: 6a3ebb7893bb2649e19cb8a6
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateBusinessPolicyV1Dto'
      responses:
        '200':
          description: Business policy updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessPolicyV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
        '404':
          description: Business policy not found
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:write
      x-boya-access: private-label
    delete:
      operationId: BusinessPoliciesController_deleteCategoryPolicy
      summary: Delete a category or subcategory policy
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Marks the SUBCATEGORY or CATEGORY business policy as DELETED.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: businessPolicyId
          required: true
          in: path
          description: Business policy document ID
          schema:
            example: 6a3ebb7893bb2649e19cb8a6
            type: string
      responses:
        '200':
          description: Business policy deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessPolicyV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
        '404':
          description: Business policy not found
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:write
      x-boya-access: private-label
  /business-policies/workflows:
    get:
      operationId: BusinessPoliciesController_getPolicyWorkflows
      summary: List policy approval workflows for the selected currency
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns POLICY_BASED (action_type 11) approval workflows for the
        business, scoped to the currency indicated by the org_wallet_ref header.
        Used to pick an existing approval workflow when configuring a
        subcategory policy.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Workflows returned successfully
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — required headers missing
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:read
      x-boya-access: private-label
    post:
      operationId: BusinessPoliciesController_createPolicyWorkflow
      summary: Create a policy approval workflow for a currency
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Creates a POLICY_BASED (action_type 11) approval workflow scoped to a
        currency. The wallet reference is resolved from the `currency` field
        when present, otherwise from the org_wallet_ref header.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PolicyWorkflowV1Dto'
      responses:
        '201':
          description: Workflow created successfully
        '400':
          description: No wallet reference found for currency
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — required headers missing
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:write
      x-boya-access: private-label
  /business-policies/create/{policyId}:
    post:
      operationId: BusinessPoliciesController_createBusinessPolicy
      summary: Create a new business policy
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Initializes a new business policy (e.g. SUBCATEGORY or CATEGORY) under
        the given policy group.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: policyId
          required: true
          in: path
          description: Policy group ID
          schema:
            example: 66788b3e2805e9ffbda6dcf7
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateBusinessPolicyV1Dto'
      responses:
        '201':
          description: Business policy created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessPolicyV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:write
      x-boya-access: private-label
  /business-policies/{businessPolicyId}:
    put:
      operationId: BusinessPoliciesController_updateBusinessPolicy
      summary: Update a business policy
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Updates rules, workflow, status, or other fields of an existing business
        policy. Pass status: "DISABLED" to disable the policy.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: businessPolicyId
          required: true
          in: path
          description: Business policy document ID
          schema:
            example: 6a3ebb7893bb2649e19cb8a6
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateBusinessPolicyV1Dto'
      responses:
        '200':
          description: Business policy updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessPolicyV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
        '404':
          description: Business policy not found
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:write
      x-boya-access: private-label
    delete:
      operationId: BusinessPoliciesController_deleteBusinessPolicy
      summary: Delete a business policy
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Marks the business policy as DELETED.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
        - name: businessPolicyId
          required: true
          in: path
          description: Business policy document ID
          schema:
            example: 6a3ebb7893bb2649e19cb8a6
            type: string
      responses:
        '200':
          description: Business policy deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessPolicyV1Dto'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden — business_id header missing
        '404':
          description: Business policy not found
      tags:
        - business-policies
      security:
        - oauth2ClientCredentials:
            - business-policies:write
      x-boya-access: private-label
  /fx/conversion-rate:
    post:
      operationId: FxController_getConversionRate
      summary: Get current FX conversion rate
      description: >-
        Returns the current exchange rate between two currencies, including
        buy/sell markup.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConversionRateRequestV1Dto'
      responses:
        '200':
          description: Conversion rate returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConversionRateResponseV1Dto'
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
      tags:
        - fx
      security:
        - oauth2ClientCredentials:
            - fx:write
  /fx/historic-rate:
    post:
      operationId: FxController_getHistoricRate
      summary: Get historic FX rate
      description: >-
        Returns the exchange rate between two currencies for a specific
        historical date.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HistoricRateRequestV1Dto'
      responses:
        '200':
          description: Historic rate returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConversionRateResponseV1Dto'
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
      tags:
        - fx
      security:
        - oauth2ClientCredentials:
            - fx:write
  /fx/currencies:
    get:
      operationId: FxController_fetchCurrencies
      summary: Fetch available FX currencies
      description: Returns all currencies available for foreign exchange operations.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Currencies returned successfully
        '401':
          description: Unauthorized
      tags:
        - fx
      security:
        - oauth2ClientCredentials:
            - fx:read
  /fx/transfer:
    post:
      operationId: FxController_createFxTransfer
      summary: Execute FX transfer between wallets
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Performs an internal fund transfer between two wallets with FX
        conversion. Auto-generates a reference if not provided.
      parameters:
        - name: business_id
          in: header
          description: Business identifier for the request
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FxTransferRequestV1Dto'
      responses:
        '200':
          description: FX transfer completed successfully
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
      tags:
        - fx
      security:
        - oauth2ClientCredentials:
            - fx:write
      x-boya-access: private-label
  /investments/funds:
    get:
      operationId: InvestmentsController_listFunds
      summary: List fund catalogue
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Returns available funds with yield, minimum, currency, asset manager.
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FundsCatalogueResponseDto'
      tags:
        - investments
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
  /investments/accounts:
    get:
      operationId: InvestmentsController_listAccounts
      summary: List business's investment accounts
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: refresh
          required: true
          in: query
          schema:
            type: string
        - name: management
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListInvestmentAccountsResponseDto'
      tags:
        - investments
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        List business's investment accounts
  /investments/accounts/{fundAccountId}:
    get:
      operationId: InvestmentsController_getAccount
      summary: Single fund account detail (header + KPIs + cash allocation)
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
        - name: refresh
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FundAccountDetailDto'
        '404':
          description: Fund account not found for this business
      tags:
        - investments
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Single fund account detail (header + KPIs + cash allocation)
  /investments/accounts/{fundAccountId}/interest-series:
    get:
      operationId: InvestmentsController_getInterestSeries
      summary: Interest credited series for the account
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
        - name: range
          required: false
          in: query
          schema:
            default: 7D
            enum:
              - 7D
              - 1M
              - 3M
              - ALL
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InterestSeriesResponseDto'
      tags:
        - investments
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Interest credited series for the account
  /investments/accounts/{fundAccountId}/projections:
    get:
      operationId: InvestmentsController_getProjections
      summary: Projected interest at EOM / 3M / 6M / 12M horizons
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
        - name: yield
          required: false
          in: query
          description: >-
            Override annualised yield (percent). Defaults to fund effective
            yield.
          schema:
            minimum: 0
            maximum: 100
            example: 9
            type: number
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectionsResponseDto'
      tags:
        - investments
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Projected interest at EOM / 3M / 6M / 12M horizons
  /investments/accounts/{fundAccountId}/transactions:
    get:
      operationId: InvestmentsController_getTransactions
      summary: Transaction history with type filter + pagination
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
        - name: type
          required: false
          in: query
          schema:
            default: ALL
            enum:
              - ALL
              - MMF-INVESTMENT
              - MMF-INTEREST
              - MMF-WITHDRAWAL
              - MMF-UNKNOWN
            type: string
        - name: page
          required: false
          in: query
          schema:
            default: 1
            type: number
        - name: page_size
          required: false
          in: query
          schema:
            maximum: 100
            default: 25
            type: number
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvestmentTransactionsResponseDto'
      tags:
        - investments
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Transaction history with type filter + pagination
  /investments/opt-in:
    post:
      operationId: InvestmentsController_optIn
      summary: Opt in to a fund
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OptInRequestDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OptInResponseDto'
        '400':
          description: Missing or malformed Idempotency-Key header
        '409':
          description: Concurrent request with the same Idempotency-Key
      tags:
        - investments-movements
      security:
        - oauth2ClientCredentials:
            - investments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Opt in to a fund
  /investments/opt-in/{ref}:
    get:
      operationId: InvestmentsController_getOptInApproval
      summary: Fetch pending MMF opt-in approval request
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: ref
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OptInApprovalResponseDto'
      tags:
        - investments-movements
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Fetch pending MMF opt-in approval request
  /investments/opt-in/{ref}/approve:
    post:
      operationId: InvestmentsController_approveOptIn
      summary: Approve pending MMF opt-in request
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: ref
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OptInApprovalResponseDto'
      tags:
        - investments-movements
      security:
        - oauth2ClientCredentials:
            - investments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Approve pending MMF opt-in request
  /investments/accounts/{fundAccountId}/invest:
    post:
      operationId: InvestmentsController_invest
      summary: Top up an existing fund account
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InvestRequestDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvestResponseDto'
        '400':
          description: Missing or malformed Idempotency-Key header
        '409':
          description: Concurrent request with the same Idempotency-Key
      tags:
        - investments-movements
      security:
        - oauth2ClientCredentials:
            - investments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Top up an existing fund account
  /investments/accounts/{fundAccountId}/top-up:
    post:
      operationId: InvestmentsController_topUp
      summary: Top up an MMF investment wallet from a business wallet
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TopUpRequestDto'
      responses:
        '201':
          description: ''
      tags:
        - investments-movements
      security:
        - oauth2ClientCredentials:
            - investments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Top up an MMF investment wallet from a business wallet
  /investments/accounts/{fundAccountId}/withdraw:
    post:
      operationId: InvestmentsController_withdraw
      summary: Withdraw from a fund account
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WithdrawRequestDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WithdrawResponseDto'
        '400':
          description: Missing or malformed Idempotency-Key header
        '409':
          description: Concurrent request with the same Idempotency-Key
      tags:
        - investments-movements
      security:
        - oauth2ClientCredentials:
            - investments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Withdraw from a fund account
  /investments/accounts/{fundAccountId}/permissions:
    get:
      operationId: InvestmentsController_getPermissions
      summary: Treasury operators allowed to transfer funds from this account
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvestmentAccountPermissionsDto'
        '404':
          description: Fund account not found for this business
      tags:
        - investments-access
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Treasury operators allowed to transfer funds from this account
    put:
      operationId: InvestmentsController_updatePermissions
      summary: Replace the treasury operators for this account
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateInvestmentPermissionsRequestDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvestmentAccountPermissionsDto'
        '403':
          description: Requires APPROVER role
        '404':
          description: Fund account not found for this business
      tags:
        - investments-access
      security:
        - oauth2ClientCredentials:
            - investments:write
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Replace the treasury operators for this account
  /investments/accounts/{fundAccountId}/access:
    get:
      operationId: InvestmentsController_getCurrentAccess
      summary: Current employee's effective MMF access
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: fundAccountId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - investments-access
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Current employee's effective MMF access
  /investments/portfolio:
    get:
      operationId: InvestmentsController_getPortfolio
      summary: Aggregate portfolio across all fund accounts
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: refresh
          required: true
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortfolioResponseDto'
      tags:
        - investments
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Aggregate portfolio across all fund accounts
  /investments/portfolio/performance-by-currency:
    get:
      operationId: InvestmentsController_getPortfolioPerformance
      summary: Portfolio performance grouped by currency
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: range
          required: false
          in: query
          schema:
            default: MTD
            enum:
              - MTD
              - YTD
              - ALL
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortfolioPerformanceResponseDto'
      tags:
        - investments
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Portfolio performance grouped by currency
  /investments/portfolio/activity:
    get:
      operationId: InvestmentsController_getPortfolioActivity
      summary: Unified activity feed across fund accounts
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Required on write endpoints (POST). UUID per submission. Middleware
            dedupes for 24h.
          required: false
          schema:
            type: string
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: range
          required: false
          in: query
          schema:
            default: 7D
            enum:
              - 7D
              - 30D
              - ALL
            type: string
        - name: type
          required: false
          in: query
          schema:
            default: ALL
            enum:
              - ALL
              - INVESTMENT
              - INTEREST
              - WITHDRAWAL
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortfolioActivityResponseDto'
      tags:
        - investments
      security:
        - oauth2ClientCredentials:
            - investments:read
      x-boya-access: private-label
      description: >-
        > 🔒 **Private label — [contact sales](mailto:sales@boyahq.com).**
        Requires a private-label entitlement on your API client.


        Unified activity feed across fund accounts
  /bills:
    get:
      operationId: BillsController_listBills
      summary: List bills
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: status
          required: false
          in: query
          schema:
            enum:
              - draft
              - outstanding
              - paid
              - cancelled
              - refunded
            type: string
        - name: page
          required: false
          in: query
          schema:
            example: 1
            type: number
        - name: limit
          required: false
          in: query
          schema:
            example: 25
            type: number
        - name: search
          required: false
          in: query
          description: Search by invoice, vendor, verifier, or category
          schema:
            type: string
        - name: from
          required: false
          in: query
          description: Start date filter
          schema:
            type: string
        - name: to
          required: false
          in: query
          description: End date filter
          schema:
            type: string
        - name: currency
          required: false
          in: query
          description: Currency code filter
          schema:
            example: KES
            type: string
        - name: partially_paid
          required: false
          in: query
          description: Only return partially paid outstanding bills
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills
      security:
        - oauth2ClientCredentials:
            - bills:read
    post:
      operationId: BillsController_createBill
      summary: Create a bill
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateBillV1Dto'
      responses:
        '201':
          description: ''
      tags:
        - bills
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/create-bulk-bills:
    post:
      operationId: BillsController_bulkCreateBills
      summary: Create multiple bills in one request
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateBillsV1Dto'
      responses:
        '201':
          description: ''
      tags:
        - bills
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/upload:
    post:
      operationId: BillsController_uploadBillFile
      summary: Upload a bill attachment file and get its URL
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UploadBillFileV1Dto'
      responses:
        '201':
          description: ''
      tags:
        - bills-attachments
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/count:
    get:
      operationId: BillsController_getBillsCount
      summary: Get bill counts by status
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills
      security:
        - oauth2ClientCredentials:
            - bills:read
  /bills/payments/{paymentRef}/status:
    get:
      operationId: BillsController_checkPaymentStatus
      summary: Check bill payment status
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: paymentRef
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills-payments
      security:
        - oauth2ClientCredentials:
            - bills:read
  /bills/workflow:
    get:
      operationId: BillsController_getWorkflow
      summary: Get bill approval workflow configuration
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills-workflows
      security:
        - oauth2ClientCredentials:
            - bills:read
    post:
      operationId: BillsController_createWorkflow
      summary: Create bill approval workflow
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BillWorkflowV1Dto'
      responses:
        '201':
          description: ''
      tags:
        - bills-workflows
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/workflow/{workflowId}:
    patch:
      operationId: BillsController_updateWorkflow
      summary: Update bill approval workflow
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: workflowId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BillWorkflowV1Dto'
      responses:
        '200':
          description: ''
      tags:
        - bills-workflows
      security:
        - oauth2ClientCredentials:
            - bills:write
    delete:
      operationId: BillsController_deleteWorkflow
      summary: Delete bill approval workflow
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: workflowId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills-workflows
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/budgets:
    get:
      operationId: BillsController_getBudgets
      summary: Get business budgets for bill assignment
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills-budgets
      security:
        - oauth2ClientCredentials:
            - bills:read
  /bills/budgets/{budgetId}:
    get:
      operationId: BillsController_getBudget
      summary: Get a single budget (with its wallet) for bill assignment
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: budgetId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills-budgets
      security:
        - oauth2ClientCredentials:
            - bills:read
  /bills/{billId}/approvers:
    get:
      operationId: BillsController_getBillApprovers
      summary: Get bill approvers
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills
      security:
        - oauth2ClientCredentials:
            - bills:read
  /bills/{billId}:
    get:
      operationId: BillsController_getBill
      summary: Get bill detail
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills
      security:
        - oauth2ClientCredentials:
            - bills:read
    patch:
      operationId: BillsController_updateBill
      summary: Update a bill
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateBillV1Dto'
      responses:
        '200':
          description: ''
      tags:
        - bills
      security:
        - oauth2ClientCredentials:
            - bills:write
    delete:
      operationId: BillsController_cancelBill
      summary: Cancel a bill
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/vendors/{vendorId}/payment-method:
    post:
      operationId: BillsController_addVendorPaymentMethod
      summary: Add or update vendor payment method
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: vendorId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddVendorPaymentMethodV1Dto'
      responses:
        '201':
          description: ''
      tags:
        - bills-budgets
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/{billId}/attachments:
    post:
      operationId: BillsController_addBillAttachment
      summary: Attach an uploaded file to a bill
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddBillAttachmentV1Dto'
      responses:
        '201':
          description: ''
      tags:
        - bills-attachments
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/{billId}/payments:
    post:
      operationId: BillsController_addPayment
      summary: Add another payment to a bill
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
        - name: Idempotency-Key
          in: header
          description: >-
            Optional idempotency key (8–255 chars). Also accepted as body
            `idempotency_key`; header wins when both are present.
          required: false
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddBillPaymentV1Dto'
      responses:
        '201':
          description: ''
      tags:
        - bills-payments
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/{billId}/payments/{paymentRef}/request-approval:
    patch:
      operationId: BillsController_requestApproval
      summary: Request approval for a bill payment
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
        - name: paymentRef
          required: true
          in: path
          schema:
            type: string
      responses:
        '200':
          description: ''
      tags:
        - bills-payments
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/{billId}/payments/{paymentRef}/approve:
    post:
      operationId: BillsController_approvePayment
      summary: Approve a bill payment
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
        - name: paymentRef
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      tags:
        - bills-payments
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/{billId}/payments/{paymentRef}/reject:
    post:
      operationId: BillsController_rejectPayment
      summary: Reject a bill payment
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
        - name: paymentRef
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RejectBillPaymentV1Dto'
      responses:
        '201':
          description: ''
      tags:
        - bills-payments
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/{billId}/payments/{paymentRef}/withdraw:
    post:
      operationId: BillsController_withdrawApproval
      summary: Withdraw approval request and return bill to draft
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
        - name: paymentRef
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WithdrawBillApprovalV1Dto'
      responses:
        '201':
          description: ''
      tags:
        - bills-payments
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/{billId}/return-to-draft:
    post:
      operationId: BillsController_returnToDraft
      summary: Return a bill to draft
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: billId
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      tags:
        - bills
      security:
        - oauth2ClientCredentials:
            - bills:write
  /bills/payments/{paymentRef}/retry:
    post:
      operationId: BillsController_retryPayment
      summary: Retry a failed bill payment
      parameters:
        - name: org_wallet_ref
          in: header
          required: false
          schema:
            type: string
        - name: business_id
          in: header
          required: true
          schema:
            type: string
        - name: paymentRef
          required: true
          in: path
          schema:
            type: string
      responses:
        '201':
          description: ''
      tags:
        - bills-payments
      security:
        - oauth2ClientCredentials:
            - bills:write
components:
  schemas:
    PaginatedExpenseResponseDto:
      type: object
      properties:
        docs:
          description: Expense documents
          type: array
          items:
            $ref: '#/components/schemas/ExpenseV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    ExportReceiptsDto:
      type: object
      properties:
        fromdate:
          type: string
          description: Export start date in ISO format
          example: '2026-01-01'
        todate:
          type: string
          description: Export end date in ISO format
          example: '2026-12-31'
        accountref:
          type: string
          description: >-
            Optional compatibility field from the dashboard payload. The
            middleware overrides this with the trusted org_wallet_ref header.
          example: '1'
        page:
          type: number
          description: Page number from the dashboard request payload
          example: 1
        limit:
          type: number
          description: Requested export limit
          example: 5000
        order:
          type: string
          description: Sort direction passed by the dashboard
          example: desc
        isExport:
          type: boolean
          description: >-
            Optional compatibility field from the dashboard payload. The
            middleware always forwards isExport=true for this endpoint.
          example: true
        employee:
          type: string
          description: Optional employee filter
          example: employee-123
        team:
          type: string
          description: Optional reviewer/team filter
          example: team-123
        status:
          type: string
          description: Optional expense status filter
          example: pending
        subcategory:
          type: string
          description: Optional subcategory filter
          example: sub-123
        categorySubcategories:
          description: Optional category filter payload
          allOf:
            - $ref: '#/components/schemas/StringArrayFilterDto'
        payment_status:
          type: string
          description: Optional payment status filter
          example: paid
        tags:
          description: Optional tags filter payload
          allOf:
            - $ref: '#/components/schemas/StringArrayFilterDto'
        level:
          type: number
          description: Optional expense level filter
          example: 2
        amount_filter_type:
          type: string
          description: Optional amount filter type
          example: greater_than
        amount_value:
          type: number
          description: Optional amount filter exact value
          example: 1000
        amount_min:
          type: number
          description: Optional minimum amount filter
          example: 100
        amount_max:
          type: number
          description: Optional maximum amount filter
          example: 5000
        customer:
          type: string
          description: Optional customer filter
          example: customer-123
        search:
          type: string
          description: Optional dashboard search query
          example: hotel
    ExpenseV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: MongoDB ID
        amount:
          type: number
          description: Expense amount
        fees:
          type: number
          description: Transaction fees
        charge:
          type: number
          description: Total charge amount
        original_currency:
          type: string
          description: Original currency
        currency:
          type: string
          description: Current currency
        original_amount:
          type: number
          description: Original amount
        transaction_ref:
          type: string
          description: Transaction reference
        provider_ref:
          type: string
          description: Provider reference
        employee_id:
          type: string
          description: Employee ID
        person:
          type: string
          description: Person name
        vendor_ref:
          type: object
          description: Vendor reference
        transaction_date:
          type: string
          description: Transaction date
        MerchantCategoryCode:
          type: string
          description: Merchant category code
        MerchantIdentifier:
          type: string
          description: Merchant identifier
        fx_rate:
          type: number
          description: Foreign exchange rate
        card_vcn:
          type: string
          description: Card VCN
        receiver:
          type: string
          description: Transaction receiver
        accno:
          type: string
          description: Account number
        payment_type:
          type: string
          description: Payment type
        channel:
          type: string
          description: Payment channel
        subcategory:
          description: Subcategory details
          allOf:
            - $ref: '#/components/schemas/SubcategoryDto'
        team:
          description: Team details
          allOf:
            - $ref: '#/components/schemas/TeamDto'
        tag:
          description: Tags array
          type: array
          items:
            $ref: '#/components/schemas/TagDto'
        notes:
          type: string
          description: Transaction notes
        risk:
          type: string
          description: Risk level
        risk_notes:
          type: string
          description: Risk notes
        ip:
          type: string
          description: IP address
        attachments:
          description: Attachment URLs
          type: array
          items:
            type: string
        invoice_attachments:
          description: Invoice attachment URLs
          type: array
          items:
            type: string
        payment_status:
          type: string
          description: Payment status
        status:
          type: string
          description: Expense status
        review_participants:
          description: Review participants
          type: array
          items:
            type: string
        review_mandate:
          type: number
          description: Review mandate
        review_level:
          type: number
          description: Review level
        priority:
          type: number
          description: Priority level
        events:
          description: Events array
          type: array
          items:
            type: string
        exported:
          type: boolean
          description: Exported flag
        tax_compliant:
          type: boolean
          description: Tax compliant flag
        sync_successful:
          type: boolean
          description: Sync successful flag
        org_wallet_ref:
          type: string
          description: Organization wallet reference
        vendor:
          type: string
          description: Vendor name
        customer:
          type: object
          description: Customer info
        subscription_id:
          type: string
          description: Subscription ID
        account_number:
          type: string
          description: Account number
        scan:
          description: Scan results
          type: array
          items:
            $ref: '#/components/schemas/ScanDto'
        batched:
          type: boolean
          description: Batched flag
        line_items:
          description: Line items
          type: array
          items:
            $ref: '#/components/schemas/LineItemDto'
        employee_external_id:
          type: object
          description: Employee external ID
        employee:
          description: Employee details
          allOf:
            - $ref: '#/components/schemas/EmployeeInfoDto'
        reviews:
          description: Reviews array
          type: array
          items:
            $ref: '#/components/schemas/ReviewDto'
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        requisition_reference:
          type: string
          description: Requisition reference
        acknowledged_by_ai:
          type: boolean
          description: AI acknowledged flag
        analysed_by_ai:
          type: boolean
          description: AI analysed flag
        attachments_data:
          description: Attachments data array
          type: array
          items:
            type: string
        deleted_attachments:
          description: Deleted attachments array
          type: array
          items:
            type: string
        ready_for_ai:
          type: boolean
          description: Ready for AI processing flag
        send_to_ai_attempts:
          type: number
          description: Send to AI attempts count
        sent_to_ai:
          type: boolean
          description: Sent to AI flag
        id:
          type: string
          description: Auto-generated ID field
    UpdateExpenseNoteDto:
      type: object
      properties:
        notes:
          type: string
          description: Notes or description for the expense
          example: Updated expense notes
      required:
        - notes
    UpdateExpenseSubcategoryDto:
      type: object
      properties:
        subcategoryId:
          type: string
          description: Subcategory ID to assign to the expense
          example: 64ec5b4bffaef6ff2a28455d
      required:
        - subcategoryId
    ApproveMultipleExpensesDto:
      type: object
      properties:
        expense_ids:
          description: Array of expense IDs to approve
          example:
            - expense1
            - expense2
            - expense3
          type: array
          items:
            type: string
        notes:
          type: string
          description: Optional approval notes
          example: Approved for processing
      required:
        - expense_ids
    ApproveRejectNotesDto:
      type: object
      properties:
        notes:
          type: string
          description: Optional approval/rejection notes
          example: Reviewed and approved
    RejectMultipleExpensesDto:
      type: object
      properties:
        expense_ids:
          description: Array of expense IDs to reject
          example:
            - expense1
            - expense2
            - expense3
          type: array
          items:
            type: string
        notes:
          type: string
          description: Required rejection notes explaining the reason for rejection
          example: Rejected due to insufficient documentation
      required:
        - expense_ids
        - notes
    RequestNotesDTO:
      type: object
      properties:
        notes:
          type: string
          description: Required notes explaining
          example: Rejected due to insufficient documentation
      required:
        - notes
    CategoryReportQueryV1Dto:
      type: object
      properties:
        period:
          type: number
          description: Period for the report
          example: 5
        accountref:
          type: string
          description: Account reference (org_wallet_ref)
          example: 1
        teamcode:
          type: string
          description: Team code for filtering expenses
          example: T0012T
      required:
        - period
    CategoryReportResponseV1Dto:
      type: object
      properties:
        data:
          description: Report data
          allOf:
            - $ref: '#/components/schemas/CategoryReportDataDto'
        status:
          type: number
          description: Status code
          example: 0
        message:
          type: string
          description: Response message
          example: success
      required:
        - data
        - status
        - message
    TeamCategoryReportQueryV1Dto:
      type: object
      properties:
        period:
          description: >-
            Period for the report. Can be a number (1-8) or string name.
            1=TODAY, 2=YESTERDAY, 3=THISWEEK, 4=LASTWEEK, 5=THISMONTH,
            6=LASTMONTH, 7=THISYEAR, 8=LASTYEAR
          example: 5
          oneOf:
            - type: number
              minimum: 1
              maximum: 8
            - type: string
              enum:
                - '1'
                - '2'
                - '3'
                - '4'
                - '5'
                - '6'
                - '7'
                - '8'
                - TODAY
                - YESTERDAY
                - THISWEEK
                - LASTWEEK
                - THISMONTH
                - LASTMONTH
                - THISYEAR
                - LASTYEAR
        accountref:
          type: string
          description: Account reference (org_wallet_ref). Defaults to "1" if not provided.
          example: '1'
        teamcode:
          type: string
          description: >-
            Team code for filtering to a specific team. Use "all" or omit to get
            all teams.
          example: T0012T
        category:
          type: string
          description: >-
            Category name for filtering to a specific category. If not provided,
            returns all categories. Note: Invalid category names are ignored and
            all categories are returned.
          example: Transport
      required:
        - period
    TeamCategoryReportResponseV1Dto:
      type: object
      properties:
        data:
          description: Report data - structure varies based on parameters
          oneOf:
            - $ref: '#/components/schemas/TeamModeDataDto'
            - $ref: '#/components/schemas/CategoryModeDataDto'
            - $ref: '#/components/schemas/SubcategoryModeDataDto'
        status:
          type: number
          description: Status code
          example: 0
        message:
          type: string
          description: Response message
          example: success
      required:
        - data
        - status
        - message
    PaginatedCardResponseDto:
      type: object
      properties:
        docs:
          description: Card documents
          type: array
          items:
            $ref: '#/components/schemas/CardV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    CreateCardV1Dto:
      type: object
      properties:
        employee_id:
          type: string
          description: non mongo Employee id
        currency:
          type: string
          description: Card Currency
          enum:
            - KES
            - USD
          example: KES
        name:
          type: string
          description: Card name
        cardHolder:
          type: string
          description: Cardholder name
        isVirtualCard:
          type: boolean
          description: Is virtual card
        address:
          type: string
          description: >-
            Shipping address for physical card (required when isVirtualCard is
            false or not provided)
          example: 123 Main Street, Nairobi, Kenya
        org_wallet_ref:
          type: number
          description: Business wallet ref
      required:
        - employee_id
        - currency
        - name
        - cardHolder
        - org_wallet_ref
    CardV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Card MongoDB ID
        vcn:
          type: string
          description: Virtual card number (raw)
        ref:
          type: string
          description: Card reference
        last4:
          type: string
          description: Last 4 digits of card
        bin:
          type: string
          description: BIN number
        name:
          type: string
          description: Card name/label
        brand:
          type: string
          description: Card brand (VISA, Mastercard, etc.)
        provider:
          type: string
          description: Card provider/issuer
        employee:
          description: Employee details
          allOf:
            - $ref: '#/components/schemas/EmployeeDto'
        business:
          type: string
          description: Business ID
        account:
          type: string
          description: Account ID
        user:
          type: string
          description: User ID
        exp_month:
          type: string
          description: Expiration month (MM)
        exp_year:
          type: string
          description: Expiration year (YY or YYYY)
        basis_fingerprint:
          type: string
          description: Basis fingerprint for security
        blocked:
          type: boolean
          description: Is card blocked
        retired:
          type: boolean
          description: Is card retired
        dormant:
          type: boolean
          description: Is card dormant
        purged:
          type: boolean
          description: Is card purged
        verified:
          type: boolean
          description: Is card verified
        is_virtual:
          type: boolean
          description: Is virtual card
        is_offline:
          type: boolean
          description: Is offline card
        physical_pin_set:
          type: boolean
          description: Physical PIN is set
        subscription_card:
          type: boolean
          description: Is subscription card
        balance:
          type: number
          description: Current card balance
        currency:
          type: string
          description: Card currency
        tracking_number:
          type: string
          description: Card delivery tracking number
        issued_on:
          type: string
          description: Card issued on timestamp
        issued_by:
          type: string
          description: Card issued by user
        updated_by:
          type: string
          description: Card updated by user
        blocked_by:
          type: string
          description: Blocked by user ID
        frisk:
          type: number
          description: Risk/frisk level
        wallet_type:
          type: string
          description: Wallet type
        works_only_at:
          description: Places where card works only
          type: array
          items:
            type: string
        works_only_at_mid:
          description: MID restrictions for works_only_at
          type: array
          items:
            type: string
        works_everywhere_except:
          description: Places where card is blocked
          type: array
          items:
            type: string
        category_spend_limits:
          description: Category spending limits
          type: array
          items:
            type: object
        events:
          description: Card events history
          type: array
          items:
            type: object
        org_wallet_ref:
          type: number
          description: Organization wallet reference
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        statusDisplay:
          type: string
          description: Card status display name
        typeDisplay:
          type: string
          description: Card type display name
        isActive:
          type: boolean
          description: Is card active
        isExpired:
          type: boolean
          description: Is card expired
        expiryFormatted:
          type: string
          description: Formatted expiry date
        employeeName:
          type: string
          description: Employee name from employee object
        employeeId:
          type: string
          description: Employee ID from employee object
        approval_request:
          description: Approval request object — present only for SINGLE USE PREPAID cards
          allOf:
            - $ref: '#/components/schemas/ApprovalRequestDto'
    RequestSingleUseCardDto:
      type: object
      properties:
        employee_id:
          type: string
          description: Employee ID of the requesting employee
          example: EMP001
        org_wallet_ref:
          type: string
          description: Organization wallet reference
          example: '1'
        amount:
          type: number
          description: >-
            Requested amount. Can be 0 for just_in_time funded cards (amount
            resolved when card is run).
          example: 5000
        currency:
          type: string
          description: Currency code (defaults to "KES")
          example: KES
        notes:
          type: string
          description: Notes / purpose of the card request
          example: Purchase office supplies from vendor
        vendor_id:
          type: string
          description: Vendor / merchant ID
          example: VND_001
        vendor_name:
          type: string
          description: Vendor / merchant display name
          example: Office Supplies Co.
        customer_id:
          type: string
          description: Customer ID (legacy — prefer sending the full `customer` object)
          example: 69dd1e56d2756bba9fa9983b
        customer_name:
          type: string
          description: >-
            Customer display name (legacy — prefer sending the full `customer`
            object)
          example: Giraffe Center
        customer:
          description: >-
            Full customer object from the tenant DB. When provided, the
            downstream service uses this directly instead of fetching by
            customer_id.
          allOf:
            - $ref: '#/components/schemas/CustomerObjectDto'
        subcategory_id:
          type: string
          description: Expense sub-category ID
          example: CAT_OFFICE
        tags:
          description: Array of expense tag objects selected by the user
          example:
            - _id: 68a2de3b73b7e53060aca3df
              tag_group: 68a2de0194af89ac7c37aaa9
              name: Safaricom
              employee:
                customer_id: EAA8F4AF3B1DF2EA8D45
                customer_name: Ivy Ngele ; 00111
          type: array
          items:
            $ref: '#/components/schemas/TagObjectDto'
        attachments:
          description: Array of attachment URLs or file references
          example:
            - https://storage.example.com/receipt.pdf
          type: array
          items:
            type: string
        requisition_reference:
          type: string
          description: Internal requisition reference number
          example: REQ-2024-001
      required:
        - employee_id
    CreateSingleUseCardResponseDto:
      type: object
      properties:
        status:
          type: string
          description: >-
            Outcome of the SUC request. AUTO_APPROVED means the card is issued
            immediately; PENDING_APPROVAL means it is queued for an approver.
          enum:
            - AUTO_APPROVED
            - PENDING_APPROVAL
          example: PENDING_APPROVAL
        ref:
          type: string
          description: Approval / card reference
          example: O-A1B2C3D4
        message:
          type: string
          description: Human-readable result message
          example: Single use card request submitted successfully.
      required:
        - status
        - ref
        - message
    CardBalanceDto:
      type: object
      properties:
        cardId:
          type: string
          description: Card ID
        availableBalance:
          type: number
          description: Available balance
        currentBalance:
          type: number
          description: Current balance
        pendingAmount:
          type: number
          description: Pending transactions amount
        currency:
          type: string
          description: Currency code
        lastUpdated:
          type: string
          description: Last balance update timestamp
    PaginatedPhysicalCardOrderResponseDto:
      type: object
      properties:
        docs:
          type: array
          items:
            $ref: '#/components/schemas/PhysicalCardOrderV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    ApprovePhysicalCardOrdersDto:
      type: object
      properties:
        order_ids:
          description: Array of physical card order IDs to approve
          example:
            - 6737397bcd9b059fff307ada
            - 6734a7a4f52ba5a69f8e722e
          type: array
          items:
            type: string
        notes:
          type: string
          description: Optional approval notes
          example: Approved for production and shipping
      required:
        - order_ids
    RejectPhysicalCardOrdersDto:
      type: object
      properties:
        order_ids:
          description: Array of physical card order IDs to reject
          example:
            - 6737397bcd9b059fff307ada
          type: array
          items:
            type: string
        notes:
          type: string
          description: Required rejection notes explaining the reason
          example: Rejected due to incomplete employee information
      required:
        - order_ids
        - notes
    AuthorizeBTSessionDto:
      type: object
      properties:
        nonce:
          type: string
          description: Nonce value for BT session authorization
          example: abc123def456
        vcn:
          type: string
          description: Virtual Card Number (VCN) for authorization
          example: '4532123456789012'
      required:
        - nonce
        - vcn
    CardFingerprintDto:
      type: object
      properties: {}
    PaginatedApprovalsResponseDto:
      type: object
      properties:
        docs:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalDto'
        page:
          type: number
          example: 1
        limit:
          type: number
          example: 10
      required:
        - docs
        - page
        - limit
    PaginatedApprovalsDigestResponseDto:
      type: object
      properties:
        docs:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalContextDto'
        page:
          type: number
          example: 1
        limit:
          type: number
          example: 100
      required:
        - docs
        - page
        - limit
    ApprovePaymentRequestDto:
      type: object
      properties:
        ref:
          type: string
          description: Payment request reference identifier
          example: Yl280oi1p0g0
      required:
        - ref
    RejectPaymentRequestDto:
      type: object
      properties:
        ref:
          type: string
          description: Payment request reference identifier
          example: bmZbgYGlg116
        reason:
          type: string
          description: Required reason for rejecting the payment request
          example: Insufficient documentation provided
      required:
        - ref
        - reason
    RejectBillPaymentDto:
      type: object
      properties:
        reason:
          type: string
          description: Reason for rejecting the bill payment
          example: test
      required:
        - reason
    PaginatedResponseDto:
      type: object
      properties:
        status:
          type: number
          description: HTTP status code
          example: 200
        data:
          description: Response data
          allOf:
            - $ref: '#/components/schemas/PaginatedDataDto'
        message:
          type: string
          description: Optional response message
          example: Operation completed successfully
        timestamp:
          type: string
          description: Response timestamp in ISO format
          example: '2024-01-01T00:00:00.000Z'
        path:
          type: string
          description: Request path (mainly for error responses)
          example: /api/v1/accounts
      required:
        - status
        - data
        - timestamp
    ErrorResponseDto:
      type: object
      properties:
        status:
          type: number
          description: Error status code
          example: 200
        data:
          type: object
          description: Additional error data
          example: null
        message:
          type: string
          description: Error message
          example: Resource not found
        timestamp:
          type: string
          description: Response timestamp in ISO format
          example: '2024-01-01T00:00:00.000Z'
        path:
          type: string
          description: Request path where error occurred
          example: /api/v1/accounts/123
      required:
        - status
        - data
        - timestamp
    CreateAccountV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Account name
        employeeId:
          type: string
          description: Employee ID
        currency:
          type: string
          description: Currency code
        isPersonal:
          type: boolean
          description: Is personal account
        isDefault:
          type: boolean
          description: Is default account
        businessId:
          type: string
          description: Business ID
        featureFlags:
          description: Feature flags
          type: array
          items:
            type: string
        employeeTopupAllowed:
          type: boolean
          description: Employee topup allowed
      required:
        - name
        - employeeId
    BaseResponseDto:
      type: object
      properties:
        status:
          type: number
          description: HTTP status code
          example: 200
        data:
          type: object
          description: Response data
        message:
          type: string
          description: Optional response message
          example: Operation completed successfully
        timestamp:
          type: string
          description: Response timestamp in ISO format
          example: '2024-01-01T00:00:00.000Z'
        path:
          type: string
          description: Request path (mainly for error responses)
          example: /api/v1/accounts
      required:
        - status
        - data
        - timestamp
    BusinessCurrencyV1Dto:
      type: object
      properties:
        id:
          type: number
          description: Unique identifier for the wallet reference
          example: 1
        currency:
          type: string
          description: Currency code (ISO 4217)
          example: KES
        created_on:
          type: string
          description: ISO 8601 timestamp when the record was created
          example: '2021-07-02T14:15:16.000Z'
        updated_on:
          type: string
          description: ISO 8601 timestamp when the record was last updated
          example: '2021-07-02T14:15:49.000Z'
        created_by:
          type: string
          description: ID of the user who created this record
          example: kwvnakwoppmeuzmitjkkaqcuvqoajv
      required:
        - id
        - currency
        - created_on
        - updated_on
    CreateCurrencyV1Dto:
      type: object
      properties:
        currency:
          type: string
          description: ISO 4217 currency code (uppercase, 3 letters)
          example: USD
      required:
        - currency
    AddAccountV1Dto:
      type: object
      properties:
        currency:
          type: string
          description: ISO 4217 currency code (uppercase, 3 letters)
          example: USD
        walletType:
          type: string
          description: Wallet type to create
          enum:
            - PETTYCASH
            - MAIN
            - SUBSCRIPTION-WALLET
          example: PETTYCASH
        name:
          type: string
          description: Human-readable account name shown to the user
          example: KES Petty Cash
        description:
          type: string
          description: >-
            Optional account description (max 200 characters). Falls back to
            walletType when omitted.
          example: Daily operating expenses
        owners:
          description: Owners list (employee ids) — optional, defaults to empty list
          type: array
          items:
            type: string
      required:
        - currency
        - walletType
        - name
    AddAccountResponseV1Dto:
      type: object
      properties:
        status:
          type: boolean
          description: Whether the operation succeeded
          example: true
        message:
          type: string
          description: Human-readable status message
          example: Account created successfully
        currencyCreated:
          type: boolean
          description: >-
            Whether a new currency record was provisioned as part of this
            request
          example: false
        wallet:
          type: object
          description: Created wallet payload returned by the upstream wallets service
          example:
            _id: 64f1c2a5e2e2a9001f3b8e7c
            walletId: '123456'
            wallet_type: PETTYCASH
            currency: USD
            org_wallet_ref: '2'
            description: Daily operating expenses
      required:
        - status
        - message
        - currencyCreated
        - wallet
    CashflowReportResponseV1Dto:
      type: object
      properties:
        status:
          type: number
          description: HTTP status code
          example: 200
        data:
          description: Cashflow report data
          allOf:
            - $ref: '#/components/schemas/CashflowReportDataDto'
        timestamp:
          type: string
          description: Response timestamp in ISO format
          example: '2026-05-15T10:00:00Z'
      required:
        - status
        - data
        - timestamp
    AccountV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Account MongoDB ID
        org_wallet_ref:
          type: string
          description: Organization wallet reference
        description:
          type: string
          description: Account description
        name:
          type: string
          description: Account name
        walletId:
          type: string
          description: Wallet ID
        boya_accno:
          type: string
          description: Boya account number
        availableBalance:
          type: number
          description: Available balance for spending
        currentBalance:
          type: number
          description: Current account balance
        reservations:
          description: Reserved amounts
          type: array
          items:
            $ref: '#/components/schemas/ReservationDto'
        owners:
          description: Account owners with roles
          type: array
          items:
            $ref: '#/components/schemas/OwnerDto'
        employees_allowed_to_make_payments:
          description: Employees allowed to make payments
          type: array
          items:
            type: string
        alert_contacts:
          description: Alert contacts for account notifications
          type: array
          items:
            $ref: '#/components/schemas/AlertContactDto'
        status:
          type: string
          description: Account status
          enum:
            - ACTIVE
            - INACTIVE
            - SUSPENDED
            - CLOSED
            - BARRED
        wallet_type:
          type: string
          description: Wallet type
          enum:
            - POOLFLOAT
            - REVENUE
            - MAIN
            - SINGLE-WALLET
            - PAYABLES
            - RECEIVABLES
            - PETTYCASH
            - EMPLOYEE-WALLET
            - SUBSCRIPTION-WALLET
            - BUDGET-WALLET
            - TEAM-WALLET
            - OVERDRAFT
            - INVESTMENT-WALLET
            - FIXED-DEPOSIT
            - CREDITLINE
        business_id:
          type: string
          description: Business ID
        employee_id:
          type: string
          description: Employee ID (for employee wallets)
        team:
          type: string
          description: Team ID (for team wallets)
        currency:
          type: string
          description: Account currency (USD/KES)
        is_child:
          type: boolean
          description: Is child account flag
        configuration:
          description: Account configuration settings
          type: array
          items:
            $ref: '#/components/schemas/ConfigurationDto'
        rules:
          description: Business rules applied to account
          type: array
          items:
            $ref: '#/components/schemas/RuleDto'
        outbound_channels:
          description: Available outbound payment channels
          type: array
          items:
            type: string
        isBankAccount:
          type: boolean
          description: Is linked to bank account
        bank:
          description: Bank account details
          allOf:
            - $ref: '#/components/schemas/BankInfoDto'
        depositInstructions:
          description: Deposit instructions for funding this account
          allOf:
            - $ref: '#/components/schemas/DepositInstructionsDto'
        overdraftLimit:
          type: number
          description: Overdraft limit amount
        overdraftWallet:
          type: object
          description: Overdraft wallet reference
        usedOverdraft:
          type: number
          description: Currently used overdraft amount
        overdraftAccessChannel:
          type: string
          description: Overdraft access channel
          enum:
            - BOYA
            - TABB
            - BANK
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        accountNumber:
          type: string
          description: Account number field (legacy)
        computedPermissions:
          description: Policy-computed permission flags for this wallet
          allOf:
            - $ref: '#/components/schemas/ComputedPermissionsDto'
    CreateTransactionV1Dto:
      type: object
      properties:
        amount:
          type: number
          description: Transaction amount
        currency:
          type: string
          description: Currency code (e.g., USD, EUR)
        paymentType:
          type: string
          description: Payment type
        receiverName:
          type: string
          description: Receiver name
        receiver:
          type: string
          description: Receiver
        category:
          type: string
          description: Category
        description:
          type: string
          description: Description
        accountNumber:
          type: string
          description: Account number
        bankCode:
          type: string
          description: Bank code
        note:
          type: string
          description: Notes
        budgetId:
          type: string
          description: Budget ID
        budgetCategoryIds:
          description: Budget category IDs
          type: array
          items:
            type: string
      required:
        - amount
        - currency
        - receiverName
    TransactionDto:
      type: object
      properties:
        id:
          type: number
          description: Local ID
        remoteId:
          type: number
          description: Remote ID
        source:
          type: string
          description: Transaction source
        paymentType:
          type: string
          description: Payment type
        group:
          type: string
          description: Group
        amount:
          type: number
          description: Transaction amount
        fee:
          type: number
          description: Transaction fee
        fees:
          type: number
          description: Transaction fees
        currency:
          type: string
          description: Currency code
        accountNumber:
          type: string
          description: Account number
        note:
          type: string
          description: Notes
        tag:
          type: string
          description: Tag
        tagId:
          type: string
          description: Tag ID
        category:
          type: string
          description: Category
        categoryId:
          type: string
          description: Category ID
        beneficiary:
          type: string
          description: Beneficiary
        team:
          type: string
          description: Team
        email:
          type: string
          description: Email
        phone:
          type: string
          description: Phone
        uid:
          type: string
          description: UID
        customerId:
          type: string
          description: Customer ID
        stripeCustomerId:
          type: string
          description: Stripe customer ID
        ticket:
          type: string
          description: Ticket
        description:
          type: string
          description: Description
        receiverName:
          type: string
          description: Receiver name
        receiver:
          type: string
          description: Receiver
        ref:
          type: string
          description: Reference
        reference:
          type: string
          description: Reference
        txRef:
          type: string
          description: Transaction reference
        bankCode:
          type: string
          description: Bank code
        sms:
          type: string
          description: SMS
        providerRef:
          type: string
          description: Provider reference
        receipt:
          type: string
          description: Physical receipt URL
        otherReceipts:
          type: string
          description: Other receipts URLs
        isPaymentRequest:
          type: boolean
          description: Is payment request
        isInitial:
          type: boolean
          description: Is initial transaction
        timestamp:
          type: string
          description: Timestamp
        createdAt:
          type: string
          description: Created timestamp
        status:
          type: number
          description: Status (0=pending, 1=success, 2=failed, 3=cancelled)
        reviewStatus:
          type: string
          description: Review status
        reviewLevel:
          type: number
          description: Review level
        expenseTags:
          description: Expense tags
          type: array
          items:
            $ref: '#/components/schemas/ExpenseTagDto'
        expenseId:
          type: string
          description: Expense ID
        client:
          type: string
          description: Client
        clientId:
          type: string
          description: Client ID
        vendor:
          type: string
          description: Vendor
        vendorId:
          type: string
          description: Vendor ID
        requisitionReference:
          type: string
          description: Requisition reference
        expiryDate:
          type: string
          description: Expiry date
        walletId:
          type: string
          description: Wallet ID
        budgetId:
          type: string
          description: Budget ID
        budgetName:
          type: string
          description: Budget name
        budgetLineItems:
          description: Budget line items
          type: array
          items:
            type: string
        budgetCategoryIds:
          description: Budget category IDs
          type: array
          items:
            type: string
    MoneyMovementResponseV1Dto:
      type: object
      properties:
        data:
          description: Money movement analytics data
          allOf:
            - $ref: '#/components/schemas/MoneyMovementDataDto'
      required:
        - data
    PaginatedTransactionResponseDto:
      type: object
      properties:
        docs:
          description: Transaction documents
          type: array
          items:
            $ref: '#/components/schemas/TransactionV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    TagTransactionDto:
      type: object
      properties:
        subcategoryId:
          type: string
          description: Subcategory ID to assign (MongoDB ObjectId)
          example: 64ec5b4bffaef6ff2a28455d
      required:
        - subcategoryId
    TransactionV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Transaction MongoDB ID
        currency:
          type: string
          description: Transaction currency (USD/KES)
        org_wallet_ref:
          type: string
          description: Organization wallet reference
        account:
          type: string
          description: Account number
        credit:
          type: number
          description: Credit amount
        counter:
          type: number
          description: Transaction counter
        debit:
          type: number
          description: Debit amount
        description:
          type: string
          description: Transaction description
        ref:
          type: string
          description: Transaction reference
        created_by:
          type: string
          description: Created by user ID
        transaction_type:
          type: string
          description: Transaction type
          enum:
            - IFT
            - EXPENSE
            - TOPUP
            - REFUND
            - INTERNAL TRANSFER
            - OVERDRAFT
            - REPAYMENT
            - BRANCH TRANSFER
        ift:
          description: IFT transaction details
          allOf:
            - $ref: '#/components/schemas/IftDto'
        expense:
          description: Expense transaction details
          allOf:
            - $ref: '#/components/schemas/ExpenseV1Dto'
        topup:
          description: Topup transaction details
          allOf:
            - $ref: '#/components/schemas/TopupDto'
        refund:
          description: Refund transaction details
          allOf:
            - $ref: '#/components/schemas/RefundDto'
        running_balance:
          type: number
          description: Running account balance
        business_running_balance:
          type: number
          description: Business running balance
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        id:
          type: string
          description: Auto-generated ID field
    UploadSupportingDocumentDto:
      type: object
      properties:
        transactionRef:
          type: string
          description: Transaction reference (used in S3 key generation)
          example: M-G2026001234
        transactionId:
          type: string
          description: Transaction ID (MongoDB ObjectId)
          example: 64ec5b4bffaef6ff2a28455d
        contentType:
          type: string
          description: MIME content type of the document
          enum:
            - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            - application/pdf
            - >-
              application/vnd.openxmlformats-officedocument.wordprocessingml.document
            - text/csv
            - image/png
            - image/jpeg
          example: application/pdf
        fileContent:
          type: string
          description: Base64-encoded file content (with or without data URI prefix)
          example: JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC...
      required:
        - contentType
        - fileContent
    UploadSupportingDocumentResponseDto:
      type: object
      properties:
        url:
          type: string
          description: The S3 URL of the uploaded document
          example: >-
            https://supporting-docs-bucket.s3.eu-west-1.amazonaws.com/transactions/64ec5b4bffaef6ff2a28455d/TXN-2026-001234-1705766400000.pdf
        transactionId:
          type: string
          description: The transaction ID the document was uploaded for
          example: 64ec5b4bffaef6ff2a28455d
        transactionRef:
          type: string
          description: The transaction reference
          example: TXN-2026-001234
        contentType:
          type: string
          description: The content type of the uploaded document
          example: application/pdf
      required:
        - url
        - transactionId
        - contentType
    RemoveDocumentDto:
      type: object
      properties:
        transactionId:
          type: string
          description: Transaction ID
        attachment:
          type: string
          description: Attachment URL to remove
      required:
        - attachment
    PaginatedCategoryResponseDto:
      type: object
      properties:
        docs:
          description: Category documents
          type: array
          items:
            $ref: '#/components/schemas/CategoryV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    CreateCategoryV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Category name
          example: Office Expenses
        description:
          type: string
          description: Category description
          example: Office Expenses
      required:
        - name
        - description
    CategoryV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Category MongoDB ID
        groupid:
          type: string
          description: Group ID
        name:
          type: string
          description: Category name
        description:
          type: string
          description: Category description
        subcategories:
          description: Subcategories array
          type: array
          items:
            $ref: '#/components/schemas/SubcategoryV1Dto'
        status:
          type: string
          description: Category status
          enum:
            - ACTIVE
            - ARCHIVED
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
    UpdateCategoryV1Dto:
      type: object
      properties:
        groupid:
          type: string
          description: Group ID
          example: '5'
        name:
          type: string
          description: Category name
          example: Office Expenses
        description:
          type: string
          description: Category description
          example: Office Expenses
    BulkCreateCategoryV1Dto:
      type: object
      properties:
        items:
          description: Array of category/subcategory items to create
          example:
            - category: Office Expenses
              subcategory: Water Bill
              code: '405034'
              description: Water bill
            - category: Office Expenses
              subcategory: Rent
              code: '405035'
              description: HQ RENT
          type: array
          items:
            $ref: '#/components/schemas/BulkCreateCategoryItemV1Dto'
      required:
        - items
    BulkCreateCategoryResponseV1Dto:
      type: object
      properties:
        categories:
          description: Array of created categories with their subcategories
          type: array
          items:
            $ref: '#/components/schemas/CategoryV1Dto'
        totalCategories:
          type: number
          description: Total number of categories created
          example: 2
        totalSubcategories:
          type: number
          description: Total number of subcategories created
          example: 5
        message:
          type: string
          description: Response message
          example: Successfully created 2 categories and 5 subcategories
    PaginatedSubcategoryResponseDto:
      type: object
      properties:
        docs:
          description: Subcategory documents
          type: array
          items:
            $ref: '#/components/schemas/SubcategoryV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    CreateSubcategoryV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Subcategory name
          example: Water Bill
        description:
          type: string
          description: Subcategory description
          example: Water bill expenses
        code:
          type: string
          description: Subcategory code
          example: '405034'
        teams:
          description: Restricted to teams[_ids]
          example: '[team_oid]'
          type: array
          items:
            type: string
      required:
        - name
        - description
    SubcategoryV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Subcategory MongoDB ID
        group_id:
          type: string
          description: Group ID
        category:
          type: string
          description: Parent category ID
        code:
          type: string
          description: Subcategory code
        name:
          type: string
          description: Subcategory name
        description:
          type: string
          description: Subcategory description
        status:
          type: string
          description: Subcategory status
          enum:
            - ACTIVE
            - ARCHIVED
        teams:
          description: Team IDs array
          type: array
          items:
            type: array
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        mapping_id:
          type: string
          description: Mapping ID
        icon:
          type: string
          description: Icon
        __v:
          type: number
          description: Version key
    UpdateSubcategoryV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Subcategory name
          example: Water Bill
        description:
          type: string
          description: Subcategory description
          example: Water bill expenses
        code:
          type: string
          description: Subcategory code
          example: '405034'
        status:
          type: string
          description: Subcategory status
          enum:
            - ACTIVE
            - ARCHIVED
          example: ACTIVE
    PaginatedTeamResponseDto:
      type: object
      properties:
        docs:
          description: Team documents
          type: array
          items:
            type: array
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    CreateTeamV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Team name
        email:
          type: string
          description: Team email
        phone:
          type: string
          description: Team phone
        code:
          type: string
          description: Team code
      required:
        - name
    TeamV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Team MongoDB ID
        name:
          type: string
          description: Team name
        status:
          type: string
          description: Team status (ACTIVE/INACTIVE)
        email:
          type: string
          description: Team email
        phone:
          type: string
          description: Team phone
        reviewers:
          description: Team reviewers
          type: array
          items:
            $ref: '#/components/schemas/TeamReviewerDto'
        code:
          type: string
          description: Team code
        createdAt:
          type: string
          description: Created timestamp
        __v:
          type: number
          description: Version key
        updatedAt:
          type: string
          description: Updated timestamp
        updated_by:
          type: string
          description: Updated by user ID
        alerts:
          description: Alert configurations
          type: array
          items:
            $ref: '#/components/schemas/TeamAlertDto'
        budget:
          description: Budget allocations
          type: array
          items:
            $ref: '#/components/schemas/TeamBudgetDto'
        limit:
          description: Spending limits
          type: array
          items:
            $ref: '#/components/schemas/TeamLimitDto'
        batching_enabled:
          type: boolean
          description: Batching enabled flag
        employee_count:
          type: number
          description: Number of employees in team
        total_balances:
          description: Total balances by currency
          type: array
          items:
            $ref: '#/components/schemas/TeamBalanceDto'
        team_wallets:
          description: Associated team wallets
          type: array
          items:
            $ref: '#/components/schemas/TeamWalletDto'
        employees:
          description: Employees in team
          type: array
          items:
            $ref: '#/components/schemas/EmployeeV1Dto'
        id:
          type: string
          description: Auto-generated ID
    UpdateTeamV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Team name
        email:
          type: string
          description: Team email
        phone:
          type: string
          description: Team phone
        code:
          type: string
          description: Team code
        limit:
          description: Spending limits
          type: array
          items:
            type: string
      required:
        - name
    PaginatedEmployeeResponseDto:
      type: object
      properties:
        docs:
          description: Employee documents
          type: array
          items:
            type: array
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    CreateEmployeeV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Employee name
        organization_email:
          type: string
          description: Organization email
        personal_email:
          type: string
          description: Personal email
        phone:
          type: string
          description: Phone number
        status:
          type: object
          description: Employee status
        role:
          type: object
          description: Employee role
        is_director:
          type: boolean
          description: Is director
        team_code:
          type: string
          description: Team Code
        supervisor:
          type: string
          description: Supervisor ID
        external_id:
          type: string
          description: External ID
        tags:
          description: Employee tags
          type: array
          items:
            type: string
        invited_on:
          type: string
          description: Invited on date
        access_expiry_date:
          type: object
          description: Employee access expiry date
      required:
        - name
        - organization_email
    EmployeeV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Employee MongoDB ID
        name:
          type: string
          description: Employee name
        employee_id:
          type: string
          description: Employee ID
        user:
          type: string
          description: User ID
        wallets:
          description: Employee wallets
          type: array
          items:
            $ref: '#/components/schemas/EmployeeWalletDto'
        business:
          type: string
          description: Business ID
        invited_on:
          type: string
          description: Invited on date
        organization_email:
          type: string
          description: Organization email
        phone:
          type: string
          description: Phone number
        email_verified:
          type: boolean
          description: Email verified flag
        status:
          type: string
          description: Employee status (ACTIVE/INACTIVE)
        role:
          type: string
          description: Employee role
        is_director:
          type: boolean
          description: Is director flag
        consent_pending:
          type: boolean
          description: Consent pending flag
        cards:
          description: Associated cards
          type: array
          items:
            type: string
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        permissions:
          description: Employee permissions
          allOf:
            - $ref: '#/components/schemas/EmployeePermissionsDto'
        last_login_at:
          type: string
          description: Last login timestamp
        team:
          description: Employee team
          allOf:
            - $ref: '#/components/schemas/EmployeeTeamDto'
        notification_preferences:
          description: Notification preferences
          type: array
          items:
            type: string
        tags:
          description: Employee tags
          type: array
          items:
            type: string
        supervisor:
          type: string
          description: Supervisor ID
        external_id:
          type: string
          description: External ID
        id:
          type: string
          description: Auto-generated ID
    EmployeeBalanceDto:
      type: object
      properties:
        walletId:
          type: string
          description: Wallet ID
        accno:
          type: string
          description: Account number
        currency:
          type: string
          description: Currency code
        availableBalance:
          type: number
          description: Available balance
        walletType:
          type: string
          description: Wallet type
    PaginatedStatementResponseDto:
      type: object
      properties:
        docs:
          description: Statement transaction documents
          type: array
          items:
            $ref: '#/components/schemas/StatementItemDto'
        total:
          type: number
          description: Total count
        page:
          type: number
          description: Current page
        limit:
          type: number
          description: Limit per page
        pages:
          type: number
          description: Total pages
      required:
        - docs
        - total
        - page
        - limit
        - pages
    ReviewerManagementV1Dto:
      type: object
      properties:
        teamId:
          type: string
          description: Team ID (MongoDB _id)
          example: 64ec5b57ffaef6ff2a2845b3
        employee_id:
          type: string
          description: Employee ID
          example: 240640D10936B6FECC75A2CC
      required:
        - teamId
        - employee_id
    MoveEmployeeToTeamV1Dto:
      type: object
      properties:
        team_code:
          type: string
          description: Team code to move the employee to
          example: '0003'
        employee_id:
          type: string
          description: Employee ID to be moved
          example: sgggbrfldhqcudjvhhwjpzcdcpcwws
        max_spend_per_period:
          type: string
          description: Maximum spend per period (optional)
          example: '5000'
      required:
        - team_code
        - employee_id
    UpdateProfileV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Employee name
          example: Rob
        employee_id:
          type: string
          description: Employee ID
          example: sgggbrfldhqcudjvhhwjpzcdcpcwws
        email:
          type: string
          description: Employee email
          example: rob@example.com
        phone:
          type: string
          description: Employee phone number (international format)
          example: +1-555-0123
        tags:
          description: Employee tags (array of tag IDs)
          example:
            - 68cbd72f0e3b38101f9e8bfd
          type: array
          items:
            type: string
      required:
        - name
        - employee_id
        - email
        - phone
    ActivateEmployeeV1Dto:
      type: object
      properties:
        employee_id:
          type: string
          description: Employee ID
          example: BEE1209FF82BD720008D8262
      required:
        - employee_id
    TransferOwnershipV1Dto:
      type: object
      properties:
        employee_id:
          type: string
          description: >-
            ID of the existing employee to transfer ownership from. Either
            employee_id or external_id is required.
          example: abc123xyz
        external_id:
          type: string
          description: >-
            External employee ID (alternative identifier). Either employee_id or
            external_id is required.
          example: ext-456
        name:
          type: string
          description: Full name of the new employee taking ownership
          example: John Mwangi
        email:
          type: string
          description: >-
            Email address of the new employee. Must not be in use by any active
            user.
          example: john.mwangi@company.com
        phone:
          type: string
          description: >-
            Phone number of the new employee in international format. Must not
            be in use by any active user.
          example: '+254798765432'
        new_status:
          type: string
          description: >-
            Status to set on the old employee record after the transfer
            completes. Defaults to SUSPENDED.
          example: SUSPENDED
          enum:
            - SUSPENDED
            - DELETED
          default: SUSPENDED
      required:
        - name
        - email
        - phone
    TransferOwnershipResponseV1Dto:
      type: object
      properties:
        new_employee_id:
          type: string
          description: Employee ID of the newly created employee
          example: xyz789abc123
        old_employee_status:
          type: string
          description: Status that was applied to the old employee record
          example: SUSPENDED
          enum:
            - SUSPENDED
            - DELETED
      required:
        - new_employee_id
        - old_employee_status
    AllocateFundsV1Dto:
      type: object
      properties:
        source_wallet:
          type: string
          description: source wallet id
          default: 1
          example: 1
        destination_wallet:
          type: string
          description: source wallet id
          default: 1
          example: 1
        amount:
          type: number
          description: Amount to allocate/remove (in smallest currency unit)
          example: 5000
        description:
          type: string
          description: Transaction description
          example: Monthly allowance allocation
        employee_id:
          type: string
          description: Target employee identifier
          example: sgggbrfldhqcudjvhhwjpzcdcpcwws
      required:
        - source_wallet
        - destination_wallet
        - amount
        - employee_id
    DeductFundsV1Dto:
      type: object
      properties:
        destination_wallet:
          type: string
          description: destination wallet id
          default: 1
          example: 1
        source_wallet:
          type: string
          description: source wallet id
          default: 1
          example: 1
        amount:
          type: number
          description: Amount to deduct (in smallest currency unit)
          example: 5000
        description:
          type: string
          description: Transaction description
          example: Monthly allowance allocation
        employee_id:
          type: string
          description: Target employee identifier
          example: sgggbrfldhqcudjvhhwjpzcdcpcwws
      required:
        - destination_wallet
        - source_wallet
        - amount
        - employee_id
    PermissionResponseV1Dto:
      type: object
      properties:
        status:
          type: number
          description: HTTP status code
          example: 200
        data:
          description: Array of permission role objects
          type: array
          items:
            $ref: '#/components/schemas/PermissionV1Dto'
        timestamp:
          type: string
          description: Response timestamp in ISO format
          example: '2026-01-08T12:07:27.605Z'
      required:
        - status
        - timestamp
    UpdateUserRoleV1Dto:
      type: object
      properties:
        role:
          type: string
          description: User role
          enum:
            - CARD USER
            - APPROVER
            - ADMIN
            - REVIEWER
            - SUPER ADMIN
            - AUDITOR
          example: APPROVER
      required:
        - role
    UpdateUsersRoleResponseV1Dto:
      type: object
      properties:
        status:
          type: number
          description: HTTP status code
          example: 200
        data:
          description: Response data containing database name and permissions
          allOf:
            - $ref: '#/components/schemas/UpdateUsersRoleDataV1Dto'
        timestamp:
          type: string
          description: Response timestamp in ISO format
          example: '2026-01-09T08:18:46.794Z'
      required:
        - status
        - timestamp
    UpdateEmployeePermissionsV1Dto:
      type: object
      properties:
        permissions:
          type: object
          description: >-
            Employee permissions object with permission keys and binary values
            (0=disabled, 1=enabled)
          example:
            ALLOCATIONS_INITIATE: 1
            ALLOCATIONS_APPROVE: 1
            BULK:PAYOUTS_INITIATE: 1
            BUSINESS:BALANCE_VIEW: 1
            CARDS_APPROVE: 1
            EXPENSES_VIEW: 1
      required:
        - permissions
    UpdateRolePermissionsV1Dto:
      type: object
      properties:
        permissions:
          type: object
          description: >-
            Role permissions object with permission keys and binary values
            (0=disabled, 1=enabled)
          example:
            ALLOCATIONS_INITIATE: 1
            ALLOCATIONS_APPROVE: 0
            ALLOCATIONS_VIEW: 1
            BULK:PAYOUTS_INITIATE: 1
            BULK:PAYOUTS_APPROVE: 1
            BULK:PAYOUTS_VIEW: 1
            BUSINESS:STATEMENTS_VIEW: 1
            BUSINESS:BALANCE_VIEW: 1
            BUSINESS:BALANCE_EDIT: 1
            BUSINESS:SETTINGS_VIEW: 1
            BUSINESS:SETTINGS_EDIT: 1
            BUSINESS:TRENDS_VIEW: 1
      required:
        - permissions
    MandateResponseV1Dto:
      type: object
      properties:
        status:
          type: number
          description: HTTP status code
          example: 200
        data:
          description: Response data containing mandate objects
          allOf:
            - $ref: '#/components/schemas/MandateDataV1Dto'
        timestamp:
          type: string
          description: Response timestamp in ISO format
          example: '2026-01-09T11:09:56.314Z'
      required:
        - status
        - timestamp
    UpdateMandateV1Dto:
      type: object
      properties:
        mandateData:
          description: Mandate data containing the minimum approvers configuration
          example:
            minimum_approvers: 2
          allOf:
            - $ref: '#/components/schemas/UpdateMandateDataV1Dto'
      required:
        - mandateData
    UpdateSingleApproverV1Dto:
      type: object
      properties:
        approverData:
          description: Approver data containing level and must_approve configuration
          example:
            level: 1
            must_approve: false
          allOf:
            - $ref: '#/components/schemas/UpdateApproverDataV1Dto'
      required:
        - approverData
    RemoveApproverFromMandateV1Dto:
      type: object
      properties:
        approvers:
          description: Array of approver IDs to be removed from the mandate
          example:
            - 691af15e2c7cead4901adfd2
            - 692af15e2c7cead4901adfd3
          type: array
          items:
            type: string
      required:
        - approvers
    AddApproversToMandateV1Dto:
      type: object
      properties:
        approvers:
          description: Array of approvers to add to the mandate
          example:
            - _id: 68c2cc82272ac8e89e3f930c
              must_approve: false
              level: 1
          type: array
          items:
            $ref: '#/components/schemas/ApproverWithIdDto'
      required:
        - approvers
    PaginatedVendorResponseDto:
      type: object
      properties:
        docs:
          description: Vendor documents
          type: array
          items:
            $ref: '#/components/schemas/VendorV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    CreateVendorV1Dto:
      type: object
      properties:
        phone:
          type: string
          description: Vendor phone number
          example: 712345678
        email:
          type: string
          description: Vendor email address
          example: vendor@example.com
        contact_name:
          type: string
          description: Contact person name
          example: John Doe
        company_name:
          type: string
          description: Company name
          example: Acme Corporation
        address:
          type: string
          description: Company address
          example: P.O. Box 12345, Nairobi
        description:
          type: string
          description: Vendor description
          example: Office supplies vendor
        status:
          type: string
          description: Vendor status
          enum:
            - ACTIVE
            - INACTIVE
            - ARCHIVED
          example: ACTIVE
        payment_instructions:
          description: Payment instructions array (at least one required)
          type: array
          items:
            $ref: '#/components/schemas/CreatePaymentInstructionV1Dto'
        taxID:
          type: string
          description: Tax identification number
          example: P051234567X
        read_only:
          type: boolean
          description: Whether vendor is read-only
          example: false
        externalId:
          type: string
          description: External system ID
          example: '12345'
      required:
        - phone
        - contact_name
        - company_name
        - payment_instructions
    VendorV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Vendor MongoDB ID
        phone:
          type: string
          description: Vendor phone number
        email:
          type: string
          description: Vendor email address
        contact_name:
          type: string
          description: Contact person name
        company_name:
          type: string
          description: Company name
        address:
          type: string
          description: Company address
        description:
          type: string
          description: Vendor description
        status:
          type: string
          description: Vendor status
          enum:
            - ACTIVE
            - INACTIVE
            - ARCHIVED
        payment_instructions:
          description: Payment instructions array
          type: array
          items:
            $ref: '#/components/schemas/PaymentInstructionV1Dto'
        taxID:
          type: string
          description: Tax identification number
        read_only:
          type: boolean
          description: Whether vendor is read-only
        externalId:
          type: string
          description: External system ID
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
    RecentVendorV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Vendor MongoDB ID (only present for existing suppliers)
        vendor:
          type: string
          description: Vendor/Company name
        receiver:
          type: string
          description: Receiver name
        accno:
          type: string
          description: Account number
        vendor_ref:
          type: object
          description: Vendor reference
        channel:
          type: string
          description: Payment channel
          enum:
            - mpesa
            - mtn
            - pochi
            - airtel
            - xentebanktransfer
            - bank
            - rtgs
            - paybill
            - till
            - airtime
            - internal
        phone:
          type: string
          description: Phone number
        company_name:
          type: string
          description: Company name (for existing suppliers)
        contact_name:
          type: string
          description: Contact person name
        email:
          type: string
          description: Email address
        payment_instructions:
          description: Payment instructions (for existing suppliers)
          type: array
          items:
            $ref: '#/components/schemas/PaymentInstructionV1Dto'
    UpdateVendorV1Dto:
      type: object
      properties:
        phone:
          type: string
          description: Vendor phone number
          example: 712345678
        email:
          type: string
          description: Vendor email address
          example: vendor@example.com
        contact_name:
          type: string
          description: Contact person name
          example: John Doe
        company_name:
          type: string
          description: Company name
          example: Acme Corporation
        address:
          type: string
          description: Company address
          example: P.O. Box 12345, Nairobi
        description:
          type: string
          description: Vendor description
          example: Office supplies vendor
        status:
          type: string
          description: Vendor status
          enum:
            - ACTIVE
            - INACTIVE
            - ARCHIVED
          example: ACTIVE
        payment_instructions:
          description: Payment instructions array
          type: array
          items:
            $ref: '#/components/schemas/CreatePaymentInstructionV1Dto'
        taxID:
          type: string
          description: Tax identification number
          example: P051234567X
        read_only:
          type: boolean
          description: Whether vendor is read-only
          example: false
        externalId:
          type: string
          description: External system ID
          example: '12345'
    UpdatePaymentInstructionV1Dto:
      type: object
      properties:
        payment_instruction:
          description: Payment instruction details
          allOf:
            - $ref: '#/components/schemas/PaymentInstructionPayloadDto'
      required:
        - payment_instruction
    AddPaymentInstructionV1Dto:
      type: object
      properties:
        payment_instruction:
          description: Payment instruction details
          allOf:
            - $ref: '#/components/schemas/AddPaymentInstructionPayloadDto'
      required:
        - payment_instruction
    PaymentChannelsResponseV1Dto:
      type: object
      properties:
        status:
          type: boolean
          description: Request status
          example: true
        data:
          description: List of payment channels
          type: array
          items:
            $ref: '#/components/schemas/PaymentChannelV1Dto'
        message:
          type: string
          description: Response message
          example: Country payment channels fetched successfully
      required:
        - status
    PaginatedPaymentsResponseV1Dto:
      type: object
      properties:
        payouts:
          description: List of bulk payment batches
          type: array
          items:
            $ref: '#/components/schemas/BulkPaymentV1Dto'
        paginationData:
          description: Pagination metadata
          allOf:
            - $ref: '#/components/schemas/PaginationDataV1Dto'
    CreateBulkPayoutV1Dto:
      type: object
      properties:
        records:
          description: Array of payout records (at least one required)
          example:
            - name: carol mwangi
              phone: 796725019
              email: ''
              amount: 10
              description: test
              team: DE8832C7
              category_code: P003
              payment_type: mpesa
              bank_code: ''
              receiver: 796725019
              account_no: ''
              idno: ''
              mpesa_number: 796725019
              tags: []
              country: Kenya
              category_name: General Materials
          type: array
          items:
            $ref: '#/components/schemas/PayoutRecordRequestV1Dto'
        description:
          type: string
          description: Batch description
          example: test
        batchno:
          type: string
          description: Unique batch number
          example: K8SpPERUGO9f
        accountref:
          type: number
          description: Account reference (org wallet)
          example: 1
        status:
          type: string
          description: Batch status
          enum:
            - draft
            - pending
          example: draft
        initiator_id:
          type: string
          description: Initiator ID
          example: 28AFC4D3DD4A27BC077E204E
        team_code:
          type: string
          description: Team code
          example: DE8832C7
        team_name:
          type: string
          description: Team name
          example: Petty cash
        attachments:
          description: File attachments
          example: []
          type: array
          items:
            type: string
        allowDuplicates:
          type: boolean
          description: Allow duplicate payments
          example: true
          default: true
        country:
          type: string
          description: Country
          example: Kenya
          default: Kenya
        source:
          type: string
          description: Selected payout source wallet ID
          example: '12007'
        source_name:
          type: string
          description: Selected payout source wallet name
          example: Test Wallet
      required:
        - records
        - description
        - batchno
        - accountref
        - status
        - initiator_id
        - team_code
        - team_name
        - allowDuplicates
        - country
    BulkPaymentV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Bulk payment MongoDB ID
        batch_no:
          type: string
          description: Unique batch number
        type:
          type: number
          description: Payment batch type
        records:
          description: Individual payment records
          type: array
          items:
            $ref: '#/components/schemas/PaymentRecordV1Dto'
        notes:
          type: string
          description: Batch notes
        org_wallet_ref:
          type: string
          description: Organization wallet reference
        currency:
          type: string
          description: Currency code
          example: KES
        mandate_required:
          type: number
          description: Whether mandate is required
        attachments:
          description: File attachments
          type: array
          items:
            type: string
        approvers:
          description: Approvers for this batch
          type: array
          items:
            $ref: '#/components/schemas/ApproverV1Dto'
        initiated_by:
          type: string
          description: Name of person who initiated
        initiated_by_id:
          type: string
          description: ID of person who initiated
        callbackURL:
          type: string
          description: Callback URL for payment processing
        initiated_on:
          type: string
          description: Formatted initiation date
        events:
          description: Activity and approval events
          type: array
          items:
            $ref: '#/components/schemas/EventV1Dto'
        status:
          type: string
          description: Batch status
          enum:
            - pending
            - processed
            - failed
            - cancelled
            - draft
        budget:
          type: object
          description: Associated budget
        collaborators:
          description: Collaborator IDs
          type: array
          items:
            type: string
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        id:
          type: string
          description: Alias for _id
        fees:
          type: number
          description: Total fees
        payout_amount:
          type: number
          description: Total payout amount
        amount:
          type: number
          description: Total amount
        initiated_by_name:
          type: string
          description: Name of initiator (alias)
        summary:
          description: Payment summary by type
          allOf:
            - $ref: '#/components/schemas/PaymentSummaryV1Dto'
        recordsProcessed:
          type: number
          description: Number of records processed
        amountProcessed:
          type: number
          description: Amount processed
        recordsFailed:
          type: number
          description: Number of failed records
        source:
          type: string
          description: Source wallet ID
        source_name:
          type: string
          description: Source wallet name
    BankV1Dto:
      type: object
      properties:
        id:
          type: number
          description: Bank ID
        code:
          type: string
          description: Bank code
          example: '01'
        paybill:
          type: string
          description: Bank paybill number
        name:
          type: string
          description: Bank name
          example: KENYA COMMERCIAL BANK
        country:
          type: string
          description: Country code
          example: KE
        status:
          type: number
          description: Bank status (1 = active)
        swiftcode:
          type: string
          description: SWIFT code
          example: KCBLKENX
        data_json:
          type: object
          description: Additional JSON data
        timestamp:
          type: string
          description: Timestamp
        branchcode:
          type: number
          description: Branch code
    CreatePaymentIntentV1Dto:
      type: object
      properties:
        businessId:
          type: string
          description: Business identifier
          example: 4D7CA841437E366EB38C
        employeeId:
          type: string
          description: Employee identifier
          example: F118CCFA49505BF267361A12
        amount:
          type: number
          description: Payment amount
          example: 11
        currency:
          type: string
          description: Currency code
          example: KES
        source:
          type: string
          description: source
          example: P8756
        receiver:
          type: string
          description: Receiver identifier (phone number)
          example: 790462100
        transactionRef:
          type: string
          description: Transaction reference
          example: M-CF4X4LG8IIW
      required:
        - businessId
        - employeeId
        - amount
        - currency
        - source
        - receiver
        - transactionRef
    PaymentIntentResponseV1Dto:
      type: object
      properties:
        paymentIntentId:
          type: string
          description: Payment intent identifier
          example: 696678f5b1dcd75bfdecd7b6
        intentSecret:
          type: string
          description: Intent secret
          example: 061c46149901df054f8eb5fe3374cdecc911b1c7d0c756e433dc3a21071abe51
        nonce:
          type: string
          description: Nonce for request verification
          example: 4e1885d59b0f1d8d497fed58ea279781
        expiresAt:
          type: string
          description: Intent expiration timestamp (ISO 8601)
          example: '2026-01-13T16:57:17.082Z'
      required:
        - paymentIntentId
        - intentSecret
        - nonce
        - expiresAt
    ConfirmPaymentIntentV1Dto:
      type: object
      properties:
        paymentIntentId:
          type: string
          description: Payment intent identifier from creation step
          example: 69669e16ced2648564b4b2e4
        intentSecret:
          type: string
          description: Intent secret from creation step
          example: 14c417861a5ac32643bf9bafabbc017cda482b26649ee08c34f86e57c896eea8
        nonce:
          type: string
          description: Nonce from creation step
          example: bb2d557b90f189c45daa103a7530782b
        otp:
          type: string
          description: One-time password (6 digits)
          example: '947302'
        transaction:
          description: Complete transaction details
          allOf:
            - $ref: '#/components/schemas/ConfirmPaymentTransactionDto'
      required:
        - paymentIntentId
        - intentSecret
        - nonce
        - otp
        - transaction
    PaymentConfirmationResponseV1Dto:
      type: object
      properties:
        success:
          type: boolean
          description: Payment confirmation status
          example: true
        transactionRef:
          type: string
          description: Transaction reference for confirmed payment
          example: TXN_20260113_ABC123
        message:
          type: string
          description: Confirmation message
          example: Payment processed successfully
        processedAt:
          type: string
          description: Processing timestamp (ISO 8601)
          example: '2026-01-13T14:30:00.000Z'
      required:
        - success
        - transactionRef
        - message
        - processedAt
    RequestMpesaPaymentV1Dto:
      type: object
      properties:
        phoneNumber:
          type: string
          description: M-Pesa phone number
          example: '254712345678'
        amount:
          type: number
          description: Payment amount
          example: 100
        accountNumber:
          type: string
          description: Account reference number
          example: INV001
        note:
          type: string
          description: Payment note/description
          example: Payment for invoice
      required:
        - phoneNumber
        - amount
        - accountNumber
        - note
    MpesaPaymentResponseV1Dto:
      type: object
      properties:
        MerchantRequestID:
          type: string
          description: Merchant request ID
          example: 9a7a-428c-9f96-2533a83f54c22766019
        CheckoutRequestID:
          type: string
          description: Checkout request ID
          example: ws_CO_15012026123947186710702289
        ResponseCode:
          type: string
          description: Response code (0 = success)
          example: '0'
        ResponseDescription:
          type: string
          description: Response description
          example: Success. Request accepted for processing
        CustomerMessage:
          type: string
          description: Customer message
          example: Success. Request accepted for processing
        status:
          type: number
          description: Status (1 = success)
          example: 1
      required:
        - MerchantRequestID
        - CheckoutRequestID
        - ResponseCode
        - ResponseDescription
        - CustomerMessage
        - status
    InitiateBulkPayoutV1Dto:
      type: object
      properties:
        source:
          type: string
          description: Selected payout source wallet ID
          example: T312007
        source_name:
          type: string
          description: Selected payout source wallet name
          example: OCHOA
    RejectPayoutV1Dto:
      type: object
      properties:
        ref:
          type: string
          description: Payout batch reference identifier
          example: vNEYv0YXJ3Lw-rv-rv-rv
        reason:
          type: string
          description: Required reason for rejecting the payout batch
          example: Insufficient documentation provided
      required:
        - ref
        - reason
    PermissionV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Permission MongoDB ID
        name:
          type: string
          description: Permission display name
          example: View Balance
        slug:
          type: string
          description: Permission slug
          example: view-balance
        description:
          type: string
          description: Permission description
          example: See current and available balance
        category:
          type: string
          description: Permission category
          enum:
            - READ
            - TRANSACT
            - ADMIN
        requires_ownership:
          type: boolean
          description: Whether this is an owner-only permission
        createdAt:
          type: string
          description: Creation timestamp
        updatedAt:
          type: string
          description: Last update timestamp
      required:
        - _id
        - name
        - slug
        - description
        - category
        - requires_ownership
    PermissionSyncResultDto:
      type: object
      properties:
        upserted:
          type: number
          description: Number of permissions upserted
        removed:
          type: number
          description: Number of permissions removed
      required:
        - upserted
        - removed
    ComputedPermissionsDto:
      type: object
      properties:
        permissions:
          description: List of permission slugs
          type: array
          items:
            type: string
        canViewBalance:
          type: boolean
          description: Can view wallet balance
        canViewTransactions:
          type: boolean
          description: Can view transaction history
        canExport:
          type: boolean
          description: Can export statements
        canInitiateTransfer:
          type: boolean
          description: Can initiate transfers
        canApprove:
          type: boolean
          description: Can approve transfers/payouts
        canSpend:
          type: boolean
          description: Can spend from wallet
        maskAmounts:
          type: boolean
          description: Whether amounts are masked
        transactionHistoryDays:
          type: number
          description: Maximum transaction history days accessible
        limits:
          type: object
          description: Transaction limits
        thresholds:
          type: object
          description: Approval thresholds
        expiresAt:
          type: object
          description: Policy expiration date
      required:
        - permissions
        - canViewBalance
        - canViewTransactions
        - canExport
        - canInitiateTransfer
        - canApprove
        - canSpend
        - maskAmounts
        - transactionHistoryDays
    CheckAccessV1Dto:
      type: object
      properties:
        employee_id:
          type: string
          description: Employee ID to check access for
        wallet_id:
          type: string
          description: Wallet ID to check access on
        permission:
          type: string
          description: Permission slug to check
          example: initiate-transfer
      required:
        - employee_id
        - wallet_id
        - permission
    AccessCheckResultDto:
      type: object
      properties:
        allowed:
          type: boolean
          description: Whether access is allowed
        policy:
          description: Policy used for the check (if allowed)
          allOf:
            - $ref: '#/components/schemas/PolicyV1Dto'
        reason:
          type: string
          description: Reason for the result
          example: OK
      required:
        - allowed
        - reason
    CheckLimitsV1Dto:
      type: object
      properties:
        employee_id:
          type: string
          description: Employee ID to check limits for
        wallet_id:
          type: string
          description: Wallet ID to check limits on
        amount:
          type: number
          description: Transaction amount to validate
          example: 75000
      required:
        - employee_id
        - wallet_id
        - amount
    LimitsCheckResultDto:
      type: object
      properties:
        allowed:
          type: boolean
          description: Whether transaction is within limits
        reason:
          type: string
          description: Reason for the result
        requires_approval:
          type: boolean
          description: Whether approval is required for this amount
      required:
        - allowed
        - reason
        - requires_approval
    QueryAuditLogsV1Dto:
      type: object
      properties:
        search:
          type: string
          description: Search action, reason, performer, or policy subject
        policy_id:
          type: string
          description: Filter by policy ID
        wallet_id:
          type: string
          description: Filter by wallet ID
        performed_by:
          type: string
          description: Filter by performer employee ID
        action:
          type: string
          description: Filter by action type
          enum:
            - GRANTED
            - MODIFIED
            - SUSPENDED
            - REVOKED
            - EXPIRED
            - REACTIVATED
        from_date:
          type: string
          description: Filter from date
        to_date:
          type: string
          description: Filter to date
        limit:
          type: number
          description: Number of records to return
          default: 50
        offset:
          type: number
          description: Number of records to skip
          default: 0
    PaginatedAuditLogsResponseDto:
      type: object
      properties:
        docs:
          description: List of audit log entries
          type: array
          items:
            $ref: '#/components/schemas/AuditLogEntryDto'
        total:
          type: number
          description: Total count
        page:
          type: number
          description: Current page
        limit:
          type: number
          description: Items per page
        pages:
          type: number
          description: Total pages
      required:
        - docs
        - total
        - page
        - limit
        - pages
    PolicyV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Policy MongoDB ID
        subject_type:
          type: string
          description: Subject type
          enum:
            - EMPLOYEE
            - BUSINESS
            - EXTERNAL
        employee_id:
          type: object
          description: Employee reference (populated)
        business_id:
          type: string
          description: Business ID
        external_ref:
          type: string
          description: External reference
        wallet_id:
          type: string
          description: Wallet ID
        permissions:
          description: Granted permissions
          type: array
          items:
            type: string
        limits:
          description: Transaction limits
          allOf:
            - $ref: '#/components/schemas/PolicyLimitsResponseDto'
        thresholds:
          description: Approval thresholds
          allOf:
            - $ref: '#/components/schemas/PolicyThresholdsResponseDto'
        restrictions:
          description: Display restrictions
          allOf:
            - $ref: '#/components/schemas/PolicyRestrictionsResponseDto'
        status:
          type: string
          description: Policy status
          enum:
            - ACTIVE
            - SUSPENDED
            - EXPIRED
            - REVOKED
        valid_from:
          type: string
          description: Policy start date
        valid_until:
          type: string
          description: Policy expiry date
        granted_by:
          type: object
          description: Granter employee reference
        revoked_by:
          type: string
          description: Revoker employee ID
        revoked_at:
          type: string
          description: Revocation timestamp
        revoke_reason:
          type: string
          description: Revocation reason
        label:
          type: string
          description: Human-friendly label
        notes:
          type: string
          description: Additional notes
        createdAt:
          type: string
          description: Creation timestamp
        updatedAt:
          type: string
          description: Last update timestamp
      required:
        - _id
        - subject_type
        - wallet_id
        - permissions
        - status
        - createdAt
        - updatedAt
    ModifyAccessV1Dto:
      type: object
      properties:
        updates:
          description: Fields to update
          allOf:
            - $ref: '#/components/schemas/PolicyUpdatesDto'
        reason:
          type: string
          description: Reason for modification
        modified_by:
          type: string
          description: Employee ID of the modifier (auto-populated from auth)
      required:
        - updates
    RevokeAccessV1Dto:
      type: object
      properties:
        reason:
          type: string
          description: Reason for revocation
          example: Employee left the company
        revoked_by:
          type: string
          description: Employee ID of the revoker (auto-populated from auth)
    SuspendAccessV1Dto:
      type: object
      properties:
        reason:
          type: string
          description: Reason for suspension
          example: Pending investigation
        suspended_by:
          type: string
          description: Employee ID of the suspender (auto-populated from auth)
    ReactivateAccessV1Dto:
      type: object
      properties:
        reactivated_by:
          type: string
          description: Employee ID of the reactivator (auto-populated from auth)
    GrantAccessV1Dto:
      type: object
      properties:
        subject_type:
          type: string
          description: Subject type
          enum:
            - EMPLOYEE
            - BUSINESS
            - EXTERNAL
          example: EMPLOYEE
        employee_id:
          type: string
          description: Employee ID (required when subject_type is EMPLOYEE)
        business_id:
          type: string
          description: Business ID (required when subject_type is BUSINESS)
        external_ref:
          type: string
          description: External reference (required when subject_type is EXTERNAL)
        wallet_id:
          type: string
          description: Wallet ID to grant access to
        permissions:
          description: Permission slugs to grant
          example:
            - view-balance
            - view-transactions
            - initiate-transfer
          type: array
          items:
            type: string
        limits:
          description: Transaction limits
          allOf:
            - $ref: '#/components/schemas/PolicyLimitsDto'
        thresholds:
          description: Approval thresholds
          allOf:
            - $ref: '#/components/schemas/PolicyThresholdsDto'
        restrictions:
          description: Display restrictions
          allOf:
            - $ref: '#/components/schemas/PolicyRestrictionsDto'
        valid_from:
          type: string
          description: Policy start date (defaults to now)
        valid_until:
          type: string
          description: Policy expiry date (null = no expiry)
        granted_by:
          type: string
          description: Employee ID of the granter (auto-populated from auth)
        label:
          type: string
          description: Human-friendly label
          example: Finance Team Member
        notes:
          type: string
          description: Additional notes
      required:
        - subject_type
        - wallet_id
        - permissions
    PaginatedTaxResponseDto:
      type: object
      properties:
        docs:
          description: Tax documents
          type: array
          items:
            $ref: '#/components/schemas/TaxV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    CreateTaxV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Tax name
          example: Management fee
        type:
          type: string
          description: Tax type
          enum:
            - WITHHOLDING_TAX
            - VAT_WITHHOLDING_TAX
          example: VAT_WITHHOLDING_TAX
        resident_type:
          type: string
          description: Resident type
          enum:
            - Resident
            - Non-Resident
          example: Resident
        nature_of_business:
          type: string
          description: Nature of business
          example: Management, Professional, Training or Consultancy Fees
        rate:
          type: number
          description: Tax rate
          example: 5
      required:
        - name
        - type
        - resident_type
        - rate
    TaxV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Tax MongoDB ID
        name:
          type: string
          description: Tax name
        type:
          type: string
          description: Tax type
          enum:
            - WITHHOLDING_TAX
            - VAT_WITHHOLDING_TAX
        resident_type:
          type: string
          description: Resident type
          enum:
            - Resident
            - Non-Resident
        nature_of_business:
          type: string
          description: Nature of business
        rate:
          type: number
          description: Tax rate
        status:
          type: string
          description: Tax status
          enum:
            - ACTIVE
            - ARCHIVED
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
    UpdateTaxV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Tax name
          example: Management fee
        type:
          type: string
          description: Tax type
          enum:
            - WITHHOLDING_TAX
            - VAT_WITHHOLDING_TAX
          example: VAT_WITHHOLDING_TAX
        resident_type:
          type: string
          description: Resident type
          enum:
            - Resident
            - Non-Resident
          example: Resident
        nature_of_business:
          type: string
          description: Nature of business
          example: Management, Professional, Training or Consultancy Fees
        rate:
          type: number
          description: Tax rate
          example: 5
    TaxTransactionsResponseV1Dto:
      type: object
      properties:
        status:
          type: boolean
          description: Response status
          example: true
        status_code:
          type: number
          description: HTTP status code
          example: 200
        message:
          type: string
          description: Response message
          example: WithHolding Taxes Retrieved
        data:
          description: Tax transactions data
          type: array
          items:
            $ref: '#/components/schemas/TaxTransactionV1Dto'
      required:
        - status
        - status_code
        - message
    PaginatedSubscriptionResponseDto:
      type: object
      properties:
        docs:
          description: Subscription documents
          type: array
          items:
            $ref: '#/components/schemas/SubscriptionV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: object
          description: Limit per page
        page:
          type: object
          description: Current page
        pages:
          type: number
          description: Total pages
    PaginatedExpensesDto:
      type: object
      properties:
        status:
          type: boolean
          description: Status of the operation
          example: true
        message:
          type: string
          description: Response message
          example: Add Susbcription payment
        data:
          description: Paginated expenses data
          allOf:
            - $ref: '#/components/schemas/PaginatedExpensesDataDto'
      required:
        - status
        - message
        - data
    AmountSpentRequestDto:
      type: object
      properties:
        from:
          type: string
          description: Start date in ISO format
          example: '2025-12-31T21:00:00.000+00:00'
        to:
          type: string
          description: End date in ISO format
          example: '2026-01-30T21:00:00.000+00:00'
        currency:
          type: string
          description: Currency code
          example: KES
        business_id:
          type: string
          description: Business ID
          example: 4D7CA841437E366EB38C
        period:
          type: string
          description: Period type
          example: MONTHLY
        subscriptionId:
          type: string
          description: Subscription ID
          example: 67b44aea86c1ccabbe965827
      required:
        - from
        - to
        - currency
        - business_id
        - period
        - subscriptionId
    AmountSpentResponseDto:
      type: object
      properties:
        status:
          type: boolean
          description: Status of the operation
          example: true
        message:
          type: string
          description: Response message
          example: Fetch total amount per period
        data:
          description: Amount spent data
          allOf:
            - $ref: '#/components/schemas/AmountSpentDataDto'
      required:
        - status
        - message
        - data
    CreateSubscriptionRequestDto:
      type: object
      properties:
        name:
          type: string
          description: Merchant/subscription name
          example: DIGITALOCEAN.COM
        limit:
          type: object
          description: Spending limit
          example: '10'
        cards:
          description: Array of card IDs
          example:
            - 683ee0b950009c749ba23312
          type: array
          items:
            type: string
        assignee:
          type: string
          description: Employee ID to assign the subscription to
          example: 67befe9f17f57a814696e291
        status:
          type: string
          description: Subscription status
          example: DRAFT
        frequency_period_unit:
          type: string
          description: Frequency period unit (MONTH, YEAR, etc.)
          example: MONTH
        wallet_name:
          type: string
          description: Wallet display name
          example: xyz - MAIN
        wallet_currency:
          type: string
          description: Wallet currency code
          example: KES
        wallet_id:
          type: string
          description: Wallet identifier
          example: '1271'
        web_url:
          type: string
          description: Merchant website URL
          example: https://www.digitalocean.com
        create_new_merchant:
          type: boolean
          description: Flag to create new merchant
          example: false
        team:
          description: Team assignment
          allOf:
            - $ref: '#/components/schemas/CreateSubscriptionTeamDto'
        subcategory:
          description: Expense category
          allOf:
            - $ref: '#/components/schemas/CreateSubscriptionSubcategoryDto'
        is_request:
          type: boolean
          description: Flag indicating if this is a request
          example: false
        org_wallet_ref:
          type: number
          description: Organization wallet reference
          example: 1
        business_id:
          type: string
          description: Organization business ID
          example: E74490ACDCAF716DC722
        notes:
          type: string
          description: Additional notes
          example: Brian Ryb is requesting creation of a DIGITALOCEAN.COM subscription
      required:
        - name
        - limit
        - cards
        - assignee
        - status
        - frequency_period_unit
        - wallet_name
        - wallet_currency
        - wallet_id
        - team
        - subcategory
        - org_wallet_ref
        - business_id
    SubscriptionV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Subscription ID
        business:
          description: Business information
          allOf:
            - $ref: '#/components/schemas/SubscriptionBusinessDto'
        name:
          type: string
          description: Subscription name
        limit:
          type: number
          description: Subscription limit
        cards:
          description: Associated cards
          type: array
          items:
            $ref: '#/components/schemas/SubscriptionCardDto'
        assignee:
          description: Subscription assignee
          allOf:
            - $ref: '#/components/schemas/SubscriptionAssigneeDto'
        status:
          type: string
          description: Subscription status
          enum:
            - DRAFT
            - ACTIVE
            - PAUSED
            - REJECTED
            - DELETED
            - PENDING
          example: ACTIVE
        wallet_id:
          type: string
          description: Wallet ID
        wallet_currency:
          type: string
          description: Wallet currency
        frequency_period_unit:
          type: string
          description: Frequency period unit
        frequency:
          type: number
          description: Frequency
        icon:
          type: string
          description: Subscription icon URL
        merchant_category_code:
          type: string
          description: Merchant category code
        merchant_receiver_name:
          type: string
          description: Merchant receiver name
        amount_spent:
          type: number
          description: Amount spent
        last_transacted_amount:
          type: number
          description: Last transacted amount
        score:
          type: number
          description: Score
        next_invoice_date:
          type: string
          description: Next invoice date
        createdAt:
          type: string
          description: Created date
        updatedAt:
          type: string
          description: Updated date
        subcategory:
          description: Subcategory information
          allOf:
            - $ref: '#/components/schemas/SubscriptionSubcategoryDto'
        team:
          description: Subcategory information
          allOf:
            - $ref: '#/components/schemas/SubscriptionTeamDto'
    UpdateStatusRequestDto:
      type: object
      properties:
        status:
          type: string
          description: Subscription status
          enum:
            - ACTIVE
            - PAUSED
          example: ACTIVE
      required:
        - status
    UpdateTeamRequestDto:
      type: object
      properties:
        team:
          description: Team information
          allOf:
            - $ref: '#/components/schemas/TeamDto'
        updateExpenses:
          type: boolean
          description: Whether to update existing expenses
          example: false
      required:
        - team
        - updateExpenses
    UpdateLimitsBillingFrequencyRequestDto:
      type: object
      properties:
        limit:
          type: string
          description: Subscription limit
          example: '10'
        frequency_period_unit:
          type: string
          description: Frequency period unit
          example: YEAR
          enum:
            - DAY
            - WEEK
            - MONTH
            - YEAR
        frequency:
          type: number
          description: Frequency value
          example: 1
      required:
        - limit
        - frequency_period_unit
        - frequency
    AssignEmployeeRequestDto:
      type: object
      properties:
        employee_oid:
          type: string
          description: Employee object ID
        card_oid:
          type: string
          description: Card object ID
      required:
        - employee_oid
        - card_oid
    UpdateSubcategoryRequestDto:
      type: object
      properties:
        subcategory:
          description: Subcategory information
          allOf:
            - $ref: '#/components/schemas/SubscriptionSubcategoryDto'
        updateExpenses:
          type: boolean
          description: Whether to update existing expenses
          example: false
      required:
        - subcategory
        - updateExpenses
    AutoGenerateResponseDto:
      type: object
      properties:
        status:
          type: boolean
          description: Status of the operation
          example: true
        data:
          description: Array of generated subscriptions
          example: []
          type: array
          items:
            type: object
        message:
          type: string
          description: Response message
          example: Subscriptions Payload AutoGenerated Successfully
      required:
        - status
        - data
        - message
    PaginatedAuditEventResponseDto:
      type: object
      properties:
        docs:
          description: Audit event documents
          type: array
          items:
            $ref: '#/components/schemas/AuditEventV1Dto'
        total:
          type: number
          description: Total count
        limit:
          type: number
          description: Limit per page
        page:
          type: number
          description: Current page
        pages:
          type: number
          description: Total pages
    AuditDigestResponseDto:
      type: object
      properties:
        groups:
          description: Grouped audit events with insights
          type: array
          items:
            $ref: '#/components/schemas/DigestGroupDto'
        stats:
          description: Aggregate statistics
          allOf:
            - $ref: '#/components/schemas/DigestStatsDto'
      required:
        - groups
        - stats
    CreateCustomerDto:
      type: object
      properties:
        type:
          type: string
          description: >-
            Customer type. "walkIn" auto-sets name to "WalkIn" and nulls all
            other fields. "regular" requires name and taxPin.
          enum:
            - regular
            - walkIn
          example: regular
        name:
          type: string
          description: >-
            Customer name. **Required when `type` is `regular`**; ignored for
            `walkIn` (auto-set to "WalkIn").
          example: Acme Corp
        email:
          type: string
          description: Customer email address (optional).
          example: billing@acme.com
        phone:
          type: string
          description: Customer phone number (optional).
          example: '+254700000000'
        address:
          type: string
          description: Customer physical address.
          example: 123 Main Street, Nairobi
        person:
          description: Array of person identifiers associated with this customer.
          example:
            - person-001
            - person-002
          type: array
          items:
            type: string
        taxPin:
          type: string
          description: KRA Tax PIN.
          example: A123456789Z
      required:
        - type
    UpdateCustomerDto:
      type: object
      properties:
        name:
          type: string
          description: Customer name.
          example: Acme Corp Updated
        email:
          type: string
          description: Customer email address.
          example: billing@acme.com
        phone:
          type: string
          description: Customer phone number.
          example: '+254700000000'
        address:
          type: string
          description: Customer physical address.
          example: 123 Main Street, Nairobi
        person:
          description: Array of person identifiers associated with this customer.
          example:
            - person-001
          type: array
          items:
            type: string
        taxPin:
          type: string
          description: KRA Tax PIN.
          example: A123456789Z
    PolicyGroupV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Policy group MongoDB ObjectId
        description:
          type: string
          description: Description of what this policy group governs
        subject:
          type: string
          description: >-
            Subject area of the policy group (e.g. Employee Spend, Expense
            Review)
        policies:
          description: Policy types within this group
          type: array
          items:
            $ref: '#/components/schemas/PolicySummaryInGroupV1Dto'
        createdAt:
          type: string
          description: ISO 8601 creation timestamp
        updatedAt:
          type: string
          description: ISO 8601 last-updated timestamp
    PolicyGroupWithPoliciesV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Policy group MongoDB ObjectId
        description:
          type: string
          description: Description of what this policy group governs
        subject:
          type: string
          description: >-
            Subject area of the policy group (e.g. Employee Spend, Expense
            Review)
        policies:
          description: >-
            Policy types within this group, each with their business policies
            and rules
          type: array
          items:
            $ref: '#/components/schemas/PolicyWithRulesV1Dto'
        createdAt:
          type: string
          description: ISO 8601 creation timestamp
        updatedAt:
          type: string
          description: ISO 8601 last-updated timestamp
    PolicyWithBusinessPoliciesV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Policy group MongoDB ObjectId
        status:
          type: string
          description: Policy status
          enum:
            - ACTIVE
            - DISABLED
        description:
          type: string
          description: Human-readable description of the policy type
        policy_code:
          type: string
          description: Policy code (e.g. SUBCATEGORY, CHANNELS, VENDORS)
        business_policies:
          description: Business-specific policies configured under this policy type
          type: array
          items:
            $ref: '#/components/schemas/BusinessPolicyV1Dto'
    BusinessPolicyV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Business policy MongoDB ObjectId
        status:
          type: string
          description: Policy status
          enum:
            - ACTIVE
            - DISABLED
            - DELETED
        policy:
          description: >-
            Parent policy group — either a MongoDB ObjectId string or an
            expanded PolicyRefV1Dto object
          allOf:
            - $ref: '#/components/schemas/PolicyRefV1Dto'
        business:
          type: string
          description: Business MongoDB ObjectId this policy belongs to
        policy_type:
          type: string
          description: Policy scope (e.g. business, budget)
        policy_code:
          type: string
          description: Policy code inherited from the parent policy group
        employees:
          description: Employee IDs this policy is scoped to
          type: array
          items:
            type: string
        teams:
          description: Team IDs this policy is scoped to
          type: array
          items:
            type: string
        budgets:
          description: Budget IDs this policy is scoped to
          type: array
          items:
            type: string
        priority:
          type: number
          description: >-
            Priority order among policies of the same type (lower = higher
            priority)
        workflow:
          type: object
          description: >-
            Approval workflow attached to this policy — null when no approval is
            required
          nullable: true
        rules:
          description: Rules defining the conditions and actions of this policy
          type: array
          items:
            $ref: '#/components/schemas/PolicyRuleV1Dto'
        name:
          type: string
          description: Human-readable name for this business policy
        description:
          type: string
          description: Optional description for this business policy
        createdAt:
          type: string
          description: ISO 8601 creation timestamp
        updatedAt:
          type: string
          description: ISO 8601 last-updated timestamp
    UpsertCategoryPolicyV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: >-
            Business policy MongoDB ObjectId. When present the policy is
            updated; omit to create.
          example: 6a3ebb7893bb2649e19cb8a6
        name:
          type: string
          description: Human-readable name for the policy
          example: Company Travel spend limits
        type:
          type: string
          description: 'Target scope of the policy: business | team | employee'
          example: business
        status:
          type: string
          description: Policy status. INACTIVE is accepted as an alias for DISABLED.
          enum:
            - ACTIVE
            - DISABLED
            - INACTIVE
            - DELETED
          example: ACTIVE
        description:
          type: string
          description: Optional description
        priority:
          type: number
          description: Priority order (lower = higher priority)
          example: 1
        workflow:
          type: object
          description: Approval workflow ID or null
          nullable: true
        employees:
          description: Employee IDs scoped to this policy
          type: array
          items:
            type: string
        teams:
          description: Team IDs scoped to this policy
          type: array
          items:
            type: string
        budgets:
          description: Budget IDs scoped to this policy
          type: array
          items:
            type: string
        rules:
          description: Rules defining conditions and actions of this policy
          type: array
          items:
            $ref: '#/components/schemas/PolicyRuleV1Dto'
        require_tax_compliant_receipt:
          type: boolean
          description: Whether tax-compliant receipts are required
      required:
        - name
        - type
    UpdateBusinessPolicyV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Business policy MongoDB ObjectId
          example: 6a3ebb7893bb2649e19cb8a6
        status:
          type: string
          description: Policy status
          enum:
            - ACTIVE
            - DISABLED
            - INACTIVE
            - DELETED
          example: ACTIVE
        policy:
          type: string
          description: Parent policy group ID or object
          example: 66788b3e2805e9ffbda6dcf7
        business:
          type: string
          description: Business MongoDB ObjectId
          example: 631b067a46830ae81217f860
        policy_type:
          type: string
          description: Policy scope type (e.g. business, budget)
          example: business
        employees:
          description: Employee IDs this policy is scoped to
          type: array
          items:
            type: string
        teams:
          description: Team IDs this policy is scoped to
          type: array
          items:
            type: string
        budgets:
          description: Budget IDs this policy is scoped to
          type: array
          items:
            type: string
        priority:
          type: number
          description: Priority order among policies of the same type
          example: 1
        workflow:
          type: object
          description: Approval workflow ID or null when no approval is required
          example: 6a3e6c5387ee44d7d52a3092
          nullable: true
        rules:
          description: Rules defining the conditions and actions of this policy
          type: array
          items:
            $ref: '#/components/schemas/PolicyRuleV1Dto'
        name:
          type: string
          description: Human-readable name for the policy
          example: Test
        description:
          type: string
          description: Optional description for the policy
          example: test
        require_tax_compliant_receipt:
          type: boolean
          description: Whether tax-compliant receipts are required (legacy top-level field)
    PolicyWorkflowV1Dto:
      type: object
      properties:
        name:
          type: string
          example: Travel subcategory approvals
        description:
          type: string
          example: Approval workflow for travel spend
        auto_approval:
          type: boolean
          example: false
        requester_can_approve:
          type: boolean
          example: true
        status:
          type: string
          enum:
            - active
            - inactive
            - archived
        type:
          type: string
          enum:
            - business
            - team
          default: business
          description: Workflow scope type (not policy_type).
        currency:
          type: string
          example: KES
          description: Currency the workflow applies to.
        teams:
          example:
            - 68c1656caa7b2a7f2769a267
          description: Team ObjectIds when type is team.
          type: array
          items:
            type: string
        requester_approval_conditions:
          example: []
          type: array
          items:
            type: string
        steps:
          type: array
          items:
            $ref: '#/components/schemas/PolicyWorkflowStepDto'
      required:
        - steps
    CreateBusinessPolicyV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Human-readable name for the new business policy
          example: testing category
        description:
          type: string
          description: Optional description for the policy
          example: ''
        type:
          type: string
          description: Policy scope type (e.g. business, budget)
          example: business
      required:
        - name
        - type
    ConversionRateRequestV1Dto:
      type: object
      properties:
        from:
          type: string
          example: USD
          description: Source currency code (ISO 4217)
        to:
          type: string
          example: KES
          description: Target currency code (ISO 4217)
      required:
        - from
        - to
    ConversionRateResponseV1Dto:
      type: object
      properties:
        from:
          type: string
          example: USD
        to:
          type: string
          example: KES
        rate:
          type: number
          example: 129.122
        timestamp:
          type: string
          example: '2026-04-23T00:00:00Z'
        markup:
          $ref: '#/components/schemas/FxMarkupDto'
      required:
        - from
        - to
        - rate
        - timestamp
        - markup
    HistoricRateRequestV1Dto:
      type: object
      properties:
        from:
          type: string
          example: USD
          description: Source currency code (ISO 4217)
        to:
          type: string
          example: KES
          description: Target currency code (ISO 4217)
        date:
          type: string
          example: '2024-12-02'
          description: Historical date (YYYY-MM-DD)
      required:
        - from
        - to
        - date
    FxTransferRequestV1Dto:
      type: object
      properties:
        amount:
          type: number
          example: 100
          description: Transfer amount
        description:
          type: string
          example: Internal transfer between accounts
          description: Transfer description
        currency:
          type: string
          example: USD
          description: Currency code (ISO 4217)
        fromWalletId:
          type: string
          example: wallet_1
          description: Source wallet ID
        toWalletId:
          type: string
          example: wallet_2
          description: Destination wallet ID
        reference:
          type: string
          example: FX_a1b2c3d4e5
          description: Reference (auto-generated if not provided)
      required:
        - amount
        - description
        - currency
        - fromWalletId
        - toWalletId
    FundsCatalogueResponseDto:
      type: object
      properties:
        funds:
          type: array
          items:
            $ref: '#/components/schemas/FundCatalogueItemDto'
      required:
        - funds
    ListInvestmentAccountsResponseDto:
      type: object
      properties:
        accounts:
          type: array
          items:
            $ref: '#/components/schemas/FundAccountSummaryDto'
      required:
        - accounts
    FundAccountDetailDto:
      type: object
      properties:
        fund_account_id:
          type: string
          example: fa_01HXYZ...
          description: Customer's fund account ID
        fund_id:
          type: string
          example: fund_britam_kes_mmf
          description: Catalogue fund ID
        fund_name:
          type: string
          example: Britam KES Money Market Fund
        vendor:
          type: string
          example: BRITAM
        product:
          type: string
          example: MONEY_MARKET
        currency:
          type: string
          example: KES
        org_wallet_ref:
          type: string
          example: '1'
          description: Organization wallet reference for this fund account currency.
        account_reference:
          type: string
          example: BA100020873BOYA
          description: External account reference (display-only)
        approval_ref:
          type: string
          example: INV-OPT-123456
          description: Approval request reference for pending opt-in records.
        investment_wallet_id:
          type: string
          example: I622957
          description: >-
            Boya wallet id of the MMF investment account. Used by the dashboard
            as the destination when topping up the investment account from a
            business wallet.
        state:
          type: string
          enum:
            - opt_in_pending
            - active
            - closing
            - opt_in_failed
          example: active
        invested:
          description: Total invested principal (native currency)
          allOf:
            - $ref: '#/components/schemas/MoneyDto'
        wallet_available_balance:
          description: >-
            Available cash in the investment wallet before it is invested with
            the custodian.
          allOf:
            - $ref: '#/components/schemas/MoneyDto'
        opt_in_date:
          type: string
          example: '2024-08-12'
          description: Opt-in date (date-only, ISO 8601)
        treasury_operators:
          example:
            - 64f0a1b2c3d4e5f600112233
            - 64f0a1b2c3d4e5f600445566
          description: >-
            Employee ids permitted to transfer funds from this account (the
            wallet's employees_allowed_to_make_payments). Drives the Treasury
            Operators panel.
          type: array
          items:
            type: string
        investment_permissions:
          type: array
          items:
            $ref: '#/components/schemas/InvestmentPermissionGrantDto'
        available_balance:
          description: Live Britam balance for the account (uncached upstream call).
          allOf:
            - $ref: '#/components/schemas/MoneyDto'
        pending_investment:
          description: Aggregate pending-investment total awaiting custodian confirmation.
          allOf:
            - $ref: '#/components/schemas/MoneyDto'
        native_currency:
          type: string
          description: Currency of the native account totals.
          example: KES
      required:
        - fund_account_id
        - fund_id
        - fund_name
        - vendor
        - product
        - currency
        - state
        - invested
        - native_currency
    InterestSeriesResponseDto:
      type: object
      properties:
        range:
          type: string
          enum:
            - 7D
            - 1M
            - 3M
            - ALL
        currency:
          type: string
          example: KES
        series:
          type: array
          items:
            $ref: '#/components/schemas/InterestSeriesPointDto'
        total_interest:
          type: number
          example: 1284.56
          description: Sum of series.amount within range
      required:
        - range
        - currency
        - series
        - total_interest
    ProjectionsResponseDto:
      type: object
      properties:
        yield_used:
          type: number
          example: 8.2
          description: Annualised yield used for projection (percent)
        yield_unit:
          type: string
          example: percent
        daily_interest:
          type: number
          example: 22.47
          description: Implied daily interest, native currency
        currency:
          type: string
          example: KES
        horizons:
          type: array
          items:
            $ref: '#/components/schemas/ProjectionHorizonDto'
      required:
        - yield_used
        - yield_unit
        - daily_interest
        - currency
        - horizons
    InvestmentTransactionsResponseDto:
      type: object
      properties:
        docs:
          type: array
          items:
            $ref: '#/components/schemas/InvestmentTransactionDto'
        page:
          type: number
          example: 1
        page_size:
          type: number
          example: 25
        total:
          type: number
          example: 142
      required:
        - docs
        - page
        - page_size
        - total
    OptInRequestDto:
      type: object
      properties:
        fund_id:
          type: string
          example: fund_britam_kes_mmf
          description: Catalogue fund id
        amount:
          type: number
          example: 100000
          description: Initial allocation, native currency
        currency:
          type: string
          enum:
            - KES
            - USD
        accepted_terms:
          type: boolean
          example: true
          description: Must be true
      required:
        - fund_id
        - amount
        - currency
        - accepted_terms
    OptInResponseDto:
      type: object
      properties:
        fund_account_id:
          type: string
          example: fa_01HXYZ...
        state:
          type: string
          example: opt_in_pending
        message:
          type: string
          example: opt-in approval requested
      required:
        - fund_account_id
        - state
        - message
    OptInApprovalResponseDto:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/OptInApprovalRequestDto'
        message:
          type: string
          example: Investment opt-in request fetched
      required:
        - data
    InvestRequestDto:
      type: object
      properties:
        amount:
          type: number
          example: 50000
          description: Top-up amount, native currency
      required:
        - amount
    InvestResponseDto:
      type: object
      properties:
        reference:
          type: string
          example: inv_01HXYZ...
        status:
          type: string
          example: PROCESSING
      required:
        - reference
        - status
    TopUpRequestDto:
      type: object
      properties:
        source_wallet_id:
          type: string
          example: W123456
          description: Business wallet to debit
        amount:
          type: number
          example: 10000
          maximum: 1000000000
        currency:
          type: string
          example: KES
        reference:
          type: string
          example: MMF-TOPUP-...
      required:
        - source_wallet_id
        - amount
        - currency
        - reference
    WithdrawRequestDto:
      type: object
      properties:
        amount:
          type: number
          example: 25000
          description: Withdrawal amount, native currency
      required:
        - amount
    WithdrawResponseDto:
      type: object
      properties:
        reference:
          type: string
          example: wd_01HXYZ...
        status:
          type: string
          example: PROCESSING
      required:
        - reference
        - status
    InvestmentAccountPermissionsDto:
      type: object
      properties:
        fund_account_id:
          type: string
          example: fa_01HXYZ...
          description: Customer's fund account ID
        investment_wallet_id:
          type: string
          example: I622957
          description: Boya wallet id backing the investment account.
        treasury_operators:
          example:
            - 64f0a1b2c3d4e5f600112233
            - 64f0a1b2c3d4e5f600445566
          description: >-
            Employee ids permitted to transfer funds from this account (treasury
            operators).
          type: array
          items:
            type: string
        grants:
          type: array
          items:
            $ref: '#/components/schemas/InvestmentPermissionGrantDto'
      required:
        - fund_account_id
        - treasury_operators
        - grants
    UpdateInvestmentPermissionsRequestDto:
      type: object
      properties:
        treasury_operators:
          example:
            - 64f0a1b2c3d4e5f600112233
            - 64f0a1b2c3d4e5f600445566
          description: >-
            Full replacement list of employee ids permitted to transfer funds
            from this account. Sent wholesale — the upstream replaces the wallet
            permission list with exactly these ids.
          type: array
          items:
            type: string
        grants:
          type: array
          items:
            $ref: '#/components/schemas/InvestmentPermissionGrantDto'
      required:
        - treasury_operators
    PortfolioResponseDto:
      type: object
      properties:
        account_count:
          type: number
          example: 2
        accounts:
          type: array
          items:
            $ref: '#/components/schemas/FundAccountDetailDto'
        totals_by_currency:
          type: array
          items:
            $ref: '#/components/schemas/PortfolioCurrencyTotalsDto'
      required:
        - account_count
        - accounts
        - totals_by_currency
    PortfolioPerformanceResponseDto:
      type: object
      properties:
        range:
          type: string
          enum:
            - MTD
            - YTD
            - ALL
        currencies:
          type: array
          items:
            $ref: '#/components/schemas/PortfolioPerformanceCurrencyDto'
      required:
        - range
        - currencies
    PortfolioActivityResponseDto:
      type: object
      properties:
        range:
          type: string
          enum:
            - 7D
            - 30D
            - ALL
        type:
          type: string
          enum:
            - ALL
            - INVESTMENT
            - INTEREST
            - WITHDRAWAL
        docs:
          type: array
          items:
            $ref: '#/components/schemas/InvestmentTransactionDto'
        total:
          type: number
          example: 42
      required:
        - range
        - type
        - docs
        - total
    CreateBillV1Dto:
      type: object
      properties:
        invoice_no:
          type: string
          example: INV-001
        invoice_amount:
          type: number
          example: 12000
        status:
          type: string
          enum:
            - draft
            - outstanding
        supplier:
          type: object
        budget_owner:
          type: object
        team:
          type: object
          description: >-
            Selected team. The middleware derives budget_owner from its
            reviewers/employees before forwarding.
        payments:
          type: array
          items:
            type: string
        attachments:
          type: array
          items:
            type: string
        withholding_taxes:
          type: array
          items:
            type: string
        description:
          type: string
          example: Consulting services - June
        due_date:
          type: string
          example: '2026-06-30'
          description: Due date (YYYY-MM-DD)
        budget:
          description: >-
            Budget ObjectId(s) this bill is assigned to (upstream stores
            `budget: [ObjectId]`)
          type: array
          items:
            type: string
        is_draft:
          type: boolean
          example: true
          description: Whether the bill is saved as a draft
        category:
          type: string
          description: Category name
        category_code:
          type: string
          description: Category / subcategory code
        paid_amount:
          type: number
          description: Amount already paid / to be paid
        send_on:
          type: string
          description: Date the bill payment should be sent (YYYY-MM-DD)
        currency:
          type: string
          enum:
            - KES
            - USD
            - UGX
          description: Bill currency
        wallet_currency:
          type: string
          enum:
            - KES
            - USD
            - UGX
          description: Wallet currency
        original_currency:
          type: string
          enum:
            - KES
            - USD
            - UGX
          description: Original currency
        tags:
          description: Tag ids attached to the bill
          type: array
          items:
            type: string
        fx_rate:
          type: number
          description: FX rate at time of bill creation (original → wallet currency)
          example: 129.5
      required:
        - invoice_no
        - invoice_amount
        - supplier
    BulkCreateBillsV1Dto:
      type: object
      properties:
        bills:
          description: Bills to create
          type: array
          items:
            $ref: '#/components/schemas/CreateBillV1Dto'
      required:
        - bills
    UploadBillFileV1Dto:
      type: object
      properties:
        file:
          type: string
          description: >-
            Base64-encoded file content (no data URI prefix). Maximum supports a
            10MB file.
          maxLength: 14680064
        file_name:
          type: string
          example: invoice.pdf
        content_type:
          type: string
          example: application/pdf
      required:
        - file
        - file_name
        - content_type
    BillWorkflowV1Dto:
      type: object
      properties:
        name:
          type: string
          example: Bill vendor invoice payments
        description:
          type: string
          example: Vendor bill payment approval workflow
        action_type:
          type: number
          example: 5
        auto_approval:
          type: boolean
          example: false
        requester_can_approve:
          type: boolean
          example: true
        status:
          type: string
          enum:
            - active
            - inactive
            - archived
        type:
          type: string
          enum:
            - business
            - team
        business:
          type: string
          example: 699f07c39420ef9b3cb0d667
          description: >-
            Business ObjectId the workflow belongs to. Upstream stores and
            queries workflows by `business`, so it must be forwarded or the
            workflow is saved unattached and never listed.
        currency:
          type: string
          example: KES
        wallet_currency:
          type: string
          example: KES
        original_currency:
          type: string
          example: KES
        currency_code:
          type: string
          example: KES
        teams:
          example: []
          type: array
          items:
            type: string
        requester_approval_conditions:
          example: []
          type: array
          items:
            type: string
        steps:
          type: array
          items:
            $ref: '#/components/schemas/BillWorkflowStepDto'
      required:
        - name
        - steps
    UpdateBillV1Dto:
      type: object
      properties:
        invoice_no:
          type: string
          example: INV-001
        invoice_amount:
          type: number
          example: 12000
        status:
          type: string
          enum:
            - draft
            - outstanding
        supplier:
          type: object
        budget_owner:
          type: object
        team:
          type: object
          description: >-
            Selected team. The middleware derives budget_owner from its
            reviewers/employees before forwarding.
        payments:
          type: array
          items:
            type: string
        attachments:
          type: array
          items:
            type: string
        withholding_taxes:
          type: array
          items:
            type: string
        description:
          type: string
          example: Consulting services - June
        due_date:
          type: string
          example: '2026-06-30'
          description: Due date (YYYY-MM-DD)
        budget:
          description: >-
            Budget ObjectId(s) this bill is assigned to (upstream stores
            `budget: [ObjectId]`)
          type: array
          items:
            type: string
        is_draft:
          type: boolean
          example: true
          description: Whether the bill is saved as a draft
        category:
          type: string
          description: Category name
        category_code:
          type: string
          description: Category / subcategory code
        paid_amount:
          type: number
          description: Amount already paid / to be paid
        send_on:
          type: string
          description: Date the bill payment should be sent (YYYY-MM-DD)
        currency:
          type: string
          enum:
            - KES
            - USD
            - UGX
          description: Bill currency
        wallet_currency:
          type: string
          enum:
            - KES
            - USD
            - UGX
          description: Wallet currency
        original_currency:
          type: string
          enum:
            - KES
            - USD
            - UGX
          description: Original currency
        tags:
          description: Tag ids attached to the bill
          type: array
          items:
            type: string
        fx_rate:
          type: number
          description: FX rate at time of bill creation (original → wallet currency)
          example: 129.5
    AddVendorPaymentMethodV1Dto:
      type: object
      properties:
        channel:
          type: string
          example: bank
          description: Payment channel type
        bank_code:
          type: string
          example: '01'
          description: Bank code
        bankCode:
          type: string
          example: '01'
          description: Bank code alternative field
        bank:
          type: string
          example: Equity Bank
          description: Bank name
        account_number:
          type: string
          example: '1234567890'
          description: Account number
        accno:
          type: string
          example: '1234567890'
          description: Account number alternative field
        phone:
          type: string
          example: 712345678
          description: Phone number for mobile payments
        till:
          type: string
          example: '123456'
          description: Till number
        till_no:
          type: string
          example: '123456'
          description: Till number alternative field
        business_no:
          type: string
          example: '247247'
          description: Paybill business number
        is_default:
          type: boolean
          example: true
          description: Whether this is the default method
      required:
        - channel
    AddBillAttachmentV1Dto:
      type: object
      properties:
        file_name:
          type: string
          example: invoice.pdf
        url:
          type: string
          description: URL returned by the upload endpoint
        content_type:
          type: string
          example: application/pdf
        size:
          type: number
          example: 102400
      required:
        - file_name
        - url
        - content_type
    AddBillPaymentV1Dto:
      type: object
      properties:
        amount:
          type: number
          description: Payment amount
        status:
          type: string
          enum:
            - draft
            - pending
            - outstanding
        is_tax_payment:
          type: boolean
          description: Marks this as a tax remittance payment
        withholding_taxes:
          description: WithHoldingTax ObjectIds linked to this payment
          type: array
          items:
            type: object
        payment_instruction:
          type: object
          description: Selected payment instruction
        source:
          type: string
          description: Source wallet reference/id
        source_name:
          type: string
          description: Source wallet display name
        budget:
          description: >-
            Budget ObjectId(s) funding this payment. Upstream links the budget
            to the payment (schema: `budget: [ObjectId]`).
          type: array
          items:
            type: string
        send_on:
          type: string
          description: Date the bill payment should be sent (YYYY-MM-DD)
        idempotency_key:
          type: string
          description: >-
            Idempotency key making this payment safe to retry. Also accepted as
            the `Idempotency-Key` header; forwarded upstream so a retry is
            deduped instead of double-charging.
    RejectBillPaymentV1Dto:
      type: object
      properties:
        reason:
          type: string
          example: Incorrect invoice details
      required:
        - reason
    WithdrawBillApprovalV1Dto:
      type: object
      properties:
        reason:
          type: string
          example: Withdrawn by initiator
    StringArrayFilterDto:
      type: object
      properties:
        data:
          description: Array of selected filter ids
          example:
            - cat-1
            - cat-2
          type: array
          items:
            type: string
    SubcategoryDto:
      type: object
      properties:
        _id:
          type: string
          description: Subcategory MongoDB ID
        category:
          description: Category details
          allOf:
            - $ref: '#/components/schemas/CategoryDto'
        code:
          type: string
          description: Subcategory code
        name:
          type: string
          description: Subcategory name
    TeamDto:
      type: object
      properties:
        _id:
          type: string
          description: Team MongoDB ID
        name:
          type: string
          description: Team name
        code:
          type: string
          description: Team code
    TagDto:
      type: object
      properties:
        _id:
          type: string
          description: Tag MongoDB ID
        name:
          type: string
          description: Tag name
        tag_group:
          type: string
          description: Tag group ID
        employee:
          description: Employee info
          allOf:
            - $ref: '#/components/schemas/EmployeeInfoDto'
        is_deleted:
          type: boolean
          description: Is deleted flag
        __v:
          type: number
          description: Version key
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        teams:
          description: Associated team IDs
          type: array
          items:
            type: string
    ScanDto:
      type: object
      properties:
        scanId:
          type: string
          description: Scan ID
        total:
          type: object
          description: Total amount from scan
        date:
          type: string
          description: Date from scan
        vendorNames:
          type: string
          description: Vendor names from scan
        taxValidity:
          description: Tax validity info
          allOf:
            - $ref: '#/components/schemas/TaxValidityDto'
        lineItems:
          description: Line items from scan
          type: array
          items:
            $ref: '#/components/schemas/LineItemDto'
        taxCompliant:
          type: boolean
          description: Tax compliant flag
        expenseAmountMatchesTotal:
          type: boolean
          description: Expense amount matches total flag
        validityScore:
          type: number
          description: Validity score
        caption:
          type: string
          description: Validity caption
    LineItemDto:
      type: object
      properties:
        description:
          type: string
          description: Item description
        price:
          type: number
          description: Item price
        quantity:
          type: number
          description: Item quantity
    EmployeeInfoDto:
      type: object
      properties:
        _id:
          type: string
          description: Employee MongoDB ID
        name:
          type: string
          description: Employee name
        organization_email:
          type: string
          description: Employee organization email
        tags:
          description: Employee tags
          type: array
          items:
            type: string
        supervisor:
          type: object
          description: Employee supervisor
        customer_id:
          type: string
          description: Customer ID
        customer_name:
          type: string
          description: Customer name
    ReviewDto:
      type: object
      properties:
        person:
          type: string
          description: Reviewer person name
        notes:
          type: string
          description: Review notes
        employee_id:
          type: string
          description: Reviewer employee ID
        status:
          type: string
          description: Review status
        _id:
          type: string
          description: Review MongoDB ID
        reviewed_on:
          type: string
          description: Review timestamp
    CategoryReportDataDto:
      type: object
      properties:
        labels:
          description: Category labels
          example:
            - Freight & Logistics
            - Test 1
            - B2B Wholesale Sales
          type: array
          items:
            type: string
        data:
          description: Dataset containing data and colors
          type: array
          items:
            $ref: '#/components/schemas/CategoryReportDatasetDto'
        total:
          type: number
          description: Total amount across all categories
          example: 1496
      required:
        - labels
        - data
        - total
    EmployeeDto:
      type: object
      properties:
        _id:
          type: string
          description: Employee MongoDB ID
        name:
          type: string
          description: Employee name
        employee_id:
          type: string
          description: Employee ID
        role:
          type: string
          description: Employee role
    ApprovalRequestDto:
      type: object
      properties:
        ref:
          type: string
          description: Unique approval request reference
        narrative:
          type: string
          description: Approval request narrative
        initiated_by:
          type: string
          description: Employee ObjectId who initiated the request
        initiated_on:
          type: string
          description: Timestamp when request was initiated
        business:
          type: string
          description: Business ObjectId
        status:
          type: number
          description: 'Request status: 0=pending, 1=approved, 2=rejected'
        is_batch:
          type: boolean
          description: Is batch request
        action_type:
          type: number
          description: Action type enum value
        mandate:
          type: number
          description: Mandate — number of approvals required
        participants:
          description: Approval participants
          type: array
          items:
            $ref: '#/components/schemas/ApprovalParticipantDto'
        records:
          description: Associated transaction records
          type: array
          items:
            type: object
        org_wallet_ref:
          type: string
          description: Organization wallet reference
        card:
          type: string
          description: Associated card ObjectId
        auto_approve:
          type: boolean
          description: Auto approve flag
        source:
          type: string
          description: Source of request
        attachments:
          description: Attachment file references
          type: array
          items:
            type: string
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
    CustomerObjectDto:
      type: object
      properties:
        _id:
          type: string
          description: Customer MongoDB ObjectId
          example: 69dd1e56d2756bba9fa9983b
        name:
          type: string
          description: Customer display name
          example: Giraffe Center
        email:
          type: string
          example: giraffe@acme.com
        phone:
          type: string
          example: '+254700000012'
        address:
          type: string
          example: 123 Karen Street, Nairobi
        type:
          type: string
          example: regular
          enum:
            - regular
            - walkIn
        status:
          type: string
          example: active
          enum:
            - active
            - deleted
        person:
          example:
            - '123'
          type: array
          items:
            type: string
        taxPin:
          type: string
          example: A123456789Z
      required:
        - _id
        - name
    TagObjectDto:
      type: object
      properties:
        _id:
          type: string
          description: Tag document ID
          example: 68a2de3b73b7e53060aca3df
        tag_group:
          type: string
          description: Tag group ID this tag belongs to
          example: 68a2de0194af89ac7c37aaa9
        name:
          type: string
          description: Tag display name
          example: Safaricom
        employee:
          description: Employee who owns the tag
          allOf:
            - $ref: '#/components/schemas/TagEmployeeDto'
        teams:
          description: Teams this tag is scoped to
          type: array
          items:
            type: string
        is_deleted:
          type: boolean
          description: Whether the tag is deleted
          example: false
        tag_group_name:
          type: string
          description: Tag group name
          example: Projects
        mapping_id:
          type: string
          description: Mapping ID
          example: bfabdae2-ea2a-41f4-a838-b08494b93674
        createdAt:
          type: string
        updatedAt:
          type: string
        __v:
          type: number
      required:
        - _id
        - tag_group
        - name
    PhysicalCardOrderV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Card MongoDB ID
        vcn:
          type: string
          description: Virtual card number (raw)
        ref:
          type: string
          description: Card reference
        last4:
          type: string
          description: Last 4 digits of card
        bin:
          type: string
          description: BIN number
        name:
          type: string
          description: Card name/label
        brand:
          type: string
          description: Card brand (VISA, Mastercard, etc.)
        provider:
          type: string
          description: Card provider/issuer
        employee:
          description: Employee details
          allOf:
            - $ref: '#/components/schemas/EmployeeDto'
        business:
          type: string
          description: Business ID
        account:
          type: string
          description: Account ID
        user:
          type: string
          description: User ID
        exp_month:
          type: string
          description: Expiration month (MM)
        exp_year:
          type: string
          description: Expiration year (YY or YYYY)
        basis_fingerprint:
          type: string
          description: Basis fingerprint for security
        blocked:
          type: boolean
          description: Is card blocked
        retired:
          type: boolean
          description: Is card retired
        dormant:
          type: boolean
          description: Is card dormant
        purged:
          type: boolean
          description: Is card purged
        verified:
          type: boolean
          description: Is card verified
        is_virtual:
          type: boolean
          description: Is virtual card
        is_offline:
          type: boolean
          description: Is offline card
        physical_pin_set:
          type: boolean
          description: Physical PIN is set
        subscription_card:
          type: boolean
          description: Is subscription card
        balance:
          type: number
          description: Current card balance
        currency:
          type: string
          description: Card currency
        tracking_number:
          type: string
          description: Card delivery tracking number
        issued_on:
          type: string
          description: Card issued on timestamp
        issued_by:
          type: string
          description: Card issued by user
        updated_by:
          type: string
          description: Card updated by user
        blocked_by:
          type: string
          description: Blocked by user ID
        frisk:
          type: number
          description: Risk/frisk level
        wallet_type:
          type: string
          description: Wallet type
        works_only_at:
          description: Places where card works only
          type: array
          items:
            type: string
        works_only_at_mid:
          description: MID restrictions for works_only_at
          type: array
          items:
            type: string
        works_everywhere_except:
          description: Places where card is blocked
          type: array
          items:
            type: string
        category_spend_limits:
          description: Category spending limits
          type: array
          items:
            type: object
        events:
          description: Card events history
          type: array
          items:
            type: object
        org_wallet_ref:
          type: number
          description: Organization wallet reference
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        statusDisplay:
          type: string
          description: Card status display name
        typeDisplay:
          type: string
          description: Card type display name
        isActive:
          type: boolean
          description: Is card active
        isExpired:
          type: boolean
          description: Is card expired
        expiryFormatted:
          type: string
          description: Formatted expiry date
        employeeName:
          type: string
          description: Employee name from employee object
        employeeId:
          type: string
          description: Employee ID from employee object
        approval_request:
          description: Approval request object — present only for SINGLE USE PREPAID cards
          allOf:
            - $ref: '#/components/schemas/ApprovalRequestDto'
        approved_by:
          type: string
          description: Person who approved the order
        invoice_no:
          type: string
          description: Invoice number
        delivery_address:
          type: string
          description: Full delivery address
        wallet_id:
          type: string
          description: Wallet ID
        linked:
          type: boolean
          description: Is linked
        status:
          type: string
          description: Order status
          example: printing
    ApprovalDto:
      type: object
      properties:
        _id:
          type: string
          example: 698eae9e8e02c65ba2c4d0ea
        id:
          type: string
          example: 698eae9e8e02c65ba2c4d0ea
        ref:
          type: string
          example: SUB-84f6ecb209
        narrative:
          type: string
          example: Rob is requesting creation of a Lucidchart subscription
        initiated_by:
          type: string
          example: sgggbrfldhqcudjvhhwjpzcdcpcwws
        business:
          $ref: '#/components/schemas/ApprovalBusinessDto'
        status:
          type: number
          description: 0 = pending, 1 = approved, 2 = rejected
          example: 0
        is_batch:
          type: number
          description: 0 = single, 1 = batch
          example: 0
        action_type:
          type: number
          enum:
            - 1
            - 2
            - 3
            - 4
            - 5
            - 6
            - 7
            - 8
            - 9
            - 10
            - 11
            - 12
          example: 12
        mandate:
          type: number
          example: 1
        participants:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalParticipantDto'
        records:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalRecordDto'
        callback_url:
          type: string
          example: https://api.boyahq.com/subscription/process-subscription-request
        org_wallet_ref:
          type: string
          example: '5'
        is_expenses_batch:
          type: boolean
          example: false
        auto_approve:
          type: boolean
          example: false
        isPolicyrequest:
          type: boolean
          example: false
        budget:
          type: object
        initiated_on:
          type: string
          example: '2026-02-13T04:54:54.492Z'
        createdAt:
          type: string
          example: '2026-02-13T04:54:54.493Z'
        updatedAt:
          type: string
          example: '2026-02-13T04:55:35.967Z'
        attachments:
          type: array
          items:
            type: string
        events:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalEventDto'
        request_status:
          type: number
          example: 0
        initiatedByName:
          type: string
          example: Rob
        business_id:
          type: string
          example: zyatjjbfhwwrzzmpgrpsbkcpnldfge
        email:
          type: string
          example: rob@boyahq.com
        phone:
          type: string
          example: '+254710702289'
        requested_on:
          type: string
          example: '2026-02-13T14:26:47Z'
        updated_on:
          type: string
          example: '2026-02-13T07:55:35Z'
      required:
        - _id
        - id
        - ref
        - narrative
        - initiated_by
        - business
        - status
        - is_batch
        - action_type
        - mandate
        - participants
        - records
        - org_wallet_ref
        - is_expenses_batch
        - auto_approve
        - isPolicyrequest
        - initiated_on
        - createdAt
        - updatedAt
        - request_status
        - initiatedByName
        - business_id
        - requested_on
        - updated_on
    ApprovalContextDto:
      type: object
      properties:
        id:
          type: string
          example: 698eae9e8e02c65ba2c4d0ea
        ref:
          type: string
          example: SUB-84f6ecb209
        approvalType:
          type: number
          enum:
            - 1
            - 2
            - 3
            - 4
            - 5
            - 6
            - 7
            - 8
            - 9
            - 10
            - 11
            - 12
          example: 12
        approvalTypeLabel:
          type: string
          example: Subscription
        icon:
          type: string
          example: autorenew
        color:
          type: string
          example: '#06b6d4'
        title:
          type: string
          example: Subscription - KES 5,000
        narrative:
          type: string
          example: Rob is requesting creation of a Lucidchart subscription
        amount:
          type: number
          example: 5000
        currency:
          type: string
          example: KES
        requester:
          $ref: '#/components/schemas/RequesterDto'
        approvalChain:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalStepDto'
        currentApprover:
          $ref: '#/components/schemas/ApprovalStepDto'
        pendingApprovers:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalStepDto'
        completedApprovers:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalStepDto'
        riskScore:
          type: string
          enum:
            - low
            - medium
            - high
            - critical
          example: medium
        riskFactors:
          example:
            - 'High value: KES 50,000'
            - After-hours submission
          type: array
          items:
            type: string
        tags:
          example:
            - Subscription
            - Urgent
            - High Value
          type: array
          items:
            type: string
        requestedAt:
          format: date-time
          type: string
          example: '2026-02-13T04:54:54.492Z'
        timeSinceRequest:
          type: string
          example: 2d ago
        lastActionAt:
          format: date-time
          type: string
          example: '2026-02-13T04:55:35.810Z'
        isUrgent:
          type: boolean
          example: true
        isOverdue:
          type: boolean
          example: false
        status:
          type: number
          description: 0=pending, 1=approved, 2=rejected
          example: 0
        statusLabel:
          type: string
          example: Pending Approval
        progress:
          $ref: '#/components/schemas/ApprovalProgressDto'
        isBatch:
          type: boolean
          example: false
        batchSize:
          type: number
          example: 5
        isPolicyBased:
          type: boolean
          example: false
        isAutoApproveEligible:
          type: boolean
          example: false
        records:
          type: array
          items:
            type: object
        payout:
          type: object
          description: Payout summary for PAYOUT approval types
        invoice:
          type: object
          description: Invoice details for INVOICE approval types
        events:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalEventDigestDto'
        availableActions:
          example:
            - approve
            - reject
            - view_details
          type: array
          items:
            type: string
        recommendedAction:
          type: string
          enum:
            - approve
            - review
            - reject
            - request_info
          example: review
      required:
        - id
        - ref
        - approvalType
        - approvalTypeLabel
        - icon
        - color
        - title
        - narrative
        - requester
        - approvalChain
        - pendingApprovers
        - completedApprovers
        - riskScore
        - riskFactors
        - tags
        - requestedAt
        - timeSinceRequest
        - isUrgent
        - isOverdue
        - status
        - statusLabel
        - progress
        - isBatch
        - isPolicyBased
        - isAutoApproveEligible
        - records
        - events
        - availableActions
    PaginatedDataDto:
      type: object
      properties:
        total:
          type: number
          description: Total number of items
          example: 100
        pages:
          type: number
          description: Total number of pages
          example: 10
        page:
          type: number
          description: Current page number
          example: 1
        limit:
          type: number
          description: Number of items per page
          example: 10
        docs:
          type: array
          description: Array of items
      required:
        - total
        - pages
        - page
        - limit
        - docs
    CashflowReportDataDto:
      type: object
      properties:
        accounts:
          description: Array of account cashflow details
          type: array
          items:
            $ref: '#/components/schemas/CashflowAccountDto'
        summary:
          description: Summary totals
          allOf:
            - $ref: '#/components/schemas/CashflowSummaryDto'
        period:
          description: Report period
          allOf:
            - $ref: '#/components/schemas/CashflowPeriodDto'
      required:
        - accounts
        - summary
        - period
    ReservationDto:
      type: object
      properties:
        _id:
          type: string
          description: Reservation ID
        amount:
          type: number
          description: Reserved amount
        purpose:
          type: string
          description: Reservation purpose
        employee_id:
          type: string
          description: Employee ID who made reservation
        status:
          type: string
          description: Reservation status
        createdAt:
          type: string
          description: Created timestamp
        expiresAt:
          type: string
          description: Expiry timestamp
    OwnerDto:
      type: object
      properties:
        name:
          type: string
          description: Employee name
        role:
          type: string
          description: Owner role (OWNER, ADMIN, etc.)
        _id:
          type: string
          description: Owner record ID
    AlertContactDto:
      type: object
      properties:
        name:
          type: string
          description: Contact name
        email:
          type: string
          description: Contact email
        phone:
          type: string
          description: Contact phone number
    ConfigurationDto:
      type: object
      properties:
        key:
          type: string
          description: Configuration key
        value:
          type: object
          description: Configuration value
        description:
          type: string
          description: Configuration description
        is_active:
          type: boolean
          description: Is active flag
    RuleDto:
      type: object
      properties:
        _id:
          type: string
          description: Rule ID
        operation:
          type: string
          description: Rule operation
        enabled:
          type: boolean
          description: Is enabled flag
    BankInfoDto:
      type: object
      properties:
        name:
          type: string
          description: Bank name
        accountNumber:
          type: string
          description: Bank account number
        accountName:
          type: string
          description: Bank account name
        branchName:
          type: string
          description: Bank branch name
        swiftCode:
          type: string
          description: SWIFT code
        bankCode:
          type: string
          description: Bank code
        businessNumber:
          type: string
          description: Mpesa Paybill Business number
        country:
          type: string
          description: Country code
        bank_logo_url:
          type: string
          description: Bank logo
    DepositInstructionsDto:
      type: object
      properties:
        bank:
          description: Bank wire transfer instructions
          allOf:
            - $ref: '#/components/schemas/BankDepositInstructionsDto'
        mpesa:
          description: M-Pesa Pay Bill instructions (KES only)
          allOf:
            - $ref: '#/components/schemas/MpesaDepositInstructionsDto'
    ExpenseTagDto:
      type: object
      properties:
        id:
          type: string
          description: Tag ID
        tagGroupId:
          type: string
          description: Tag group ID
        name:
          type: string
          description: Tag name
        employee:
          type: object
          description: Employee
      required:
        - id
        - tagGroupId
        - name
    MoneyMovementDataDto:
      type: object
      properties:
        moneyIn:
          description: Money in details
          allOf:
            - $ref: '#/components/schemas/MoneyInDto'
        moneyOut:
          description: Money out details
          allOf:
            - $ref: '#/components/schemas/MoneyOutDto'
      required:
        - moneyIn
        - moneyOut
    IftDto:
      type: object
      properties:
        _id:
          type: string
          description: IFT MongoDB ID
        ref:
          type: string
          description: Reference number
        amount:
          type: number
          description: Transaction amount (negative for debits)
        description:
          type: string
          description: Transaction description
        account:
          type: string
          description: Account number
        person:
          type: string
          description: Person name
        org_wallet_ref:
          type: string
          description: Organization wallet reference
        currency:
          type: string
          description: Currency code
        created_by:
          type: string
          description: Created by user ID
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
    TopupDto:
      type: object
      properties:
        _id:
          type: string
          description: Topup MongoDB ID
        ref:
          type: string
          description: Reference number
        description:
          type: string
          description: Topup description
        amount:
          type: number
          description: Topup amount
        account:
          type: string
          description: Account number
        channel:
          type: string
          description: Payment channel (MPESA, etc.)
        is_employee_topup:
          type: boolean
          description: Employee topup flag
        exported:
          type: boolean
          description: Exported flag
        sync_successful:
          type: boolean
          description: Sync successful flag
        created_by:
          type: string
          description: Created by user ID
        status:
          type: string
          description: Topup status
        subcategory:
          description: Subcategory details
          allOf:
            - $ref: '#/components/schemas/SubcategoryDto'
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        attachments:
          description: Attachment URLs
          type: array
          items:
            type: string
    RefundDto:
      type: object
      properties:
        _id:
          type: string
          description: Refund MongoDB ID
        ref:
          type: string
          description: Reference number
        transaction_ref:
          type: string
          description: Transaction reference
        description:
          type: string
          description: Refund description
        amount:
          type: number
          description: Refund amount
        account:
          type: string
          description: Account number
        employee_id:
          type: string
          description: Employee ID
        status:
          type: string
          description: Refund status
        vendor:
          type: string
          description: Refund vendor
        org_wallet_ref:
          type: string
          description: Organization wallet reference
        currency:
          type: string
          description: Currency code
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
    BulkCreateCategoryItemV1Dto:
      type: object
      properties:
        category:
          type: string
          description: Category name (will be used as group)
          example: Office Expenses
        subcategory:
          type: string
          description: Subcategory name
          example: Water Bill
        code:
          type: string
          description: Subcategory code
          example: '405034'
        description:
          type: string
          description: Subcategory description
          example: Water bill
      required:
        - category
        - subcategory
        - description
    TeamReviewerDto:
      type: object
      properties:
        employee_id:
          type: string
          description: Employee ID
        name:
          type: string
          description: Reviewer name
        read_only:
          type: boolean
          description: Read-only access flag
        added_by:
          type: string
          description: Added by user
        _id:
          type: string
          description: Reviewer MongoDB ID
        added_on:
          type: string
          description: Date added
    TeamAlertDto:
      type: object
      properties:
        employee_id:
          type: string
          description: Employee ID
        phone:
          type: string
          description: Phone number
        name:
          type: string
          description: Name
        currency:
          description: Currencies
          type: array
          items:
            type: string
        _id:
          type: string
          description: Alert MongoDB ID
    TeamBudgetDto:
      type: object
      properties:
        currency:
          type: string
          description: Currency code
        amount:
          type: number
          description: Budget amount
        _id:
          type: string
          description: Budget MongoDB ID
    TeamLimitDto:
      type: object
      properties:
        currency:
          type: string
          description: Currency code
        amount:
          type: number
          description: Limit amount
        _id:
          type: string
          description: Limit MongoDB ID
    TeamBalanceDto:
      type: object
      properties:
        currency:
          type: string
          description: Currency code
        balance:
          type: number
          description: Current balance
    TeamWalletDto:
      type: object
      properties:
        walletId:
          type: string
          description: Wallet ID
        accountNumber:
          type: string
          description: Account number
        availableBalance:
          type: number
          description: Available balance
        name:
          type: string
          description: Wallet name
    EmployeeWalletDto:
      type: object
      properties:
        boya_accno:
          type: string
          description: Boya account number
        walletId:
          type: string
          description: Wallet ID
        currency:
          type: string
          description: Currency code
        availableBalance:
          type: number
          description: Available balance
        wallet_type:
          type: string
          description: Wallet type
    EmployeePermissionsDto:
      type: object
      properties:
        ALLOCATIONS_INITIATE:
          type: number
          description: Allocations initiate permission
        ALLOCATIONS_VIEW:
          type: number
          description: Allocations view permission
        BULK:PAYOUTS_INITIATE:
          type: number
          description: Bulk payouts initiate permission
        BULK:PAYOUTS_VIEW:
          type: number
          description: Bulk payouts view permission
        BUSINESS:STATEMENTS_VIEW:
          type: number
          description: Business statements view permission
        BUSINESS:BALANCE_VIEW:
          type: number
          description: Business balance view permission
        BUSINESS:BALANCE_EDIT:
          type: number
          description: Business balance edit permission
        BUSINESS:TRENDS_VIEW:
          type: number
          description: Business trends view permission
        BUSINESS:SETTINGS_VIEW:
          type: number
          description: Business settings view permission
        BUSINESS:SETTINGS_EDIT:
          type: number
          description: Business settings edit permission
        CARDS_VIEW:
          type: number
          description: Cards view permission
        CARDS_EDIT:
          type: number
          description: Cards edit permission
        EMPLOYEES:BALANCE_VIEW:
          type: number
          description: Employees balance view permission
        PAYROLL_INITIATE:
          type: number
          description: Payroll initiate permission
        PAYROLL_VIEW:
          type: number
          description: Payroll view permission
        PAYABLES_INITIATE:
          type: number
          description: Payables initiate permission
        PAYABLES_VIEW:
          type: number
          description: Payables view permission
        PEOPLE_VIEW:
          type: number
          description: People view permission
        PEOPLE_EDIT:
          type: number
          description: People edit permission
        PEOPLE_ARCHIVE:
          type: number
          description: People archive permission
        PEOPLE_ALLOCATE:
          type: number
          description: People allocate permission
        EXPENSES_VIEW:
          type: number
          description: Expenses view permission
        EXPENSES_EXPORT:
          type: number
          description: Expenses export permission
        EXPENSES_REVIEW:
          type: number
          description: Expenses review permission
        SETTINGS:CATEGORY_VIEW:
          type: number
          description: Settings category view permission
        SETTINGS:CATEGORY_EDIT:
          type: number
          description: Settings category edit permission
        SETTINGS:INTEGRATIONS_VIEW:
          type: number
          description: Settings integrations view permission
        SETTINGS:INTEGRATIONS_EDIT:
          type: number
          description: Settings integrations edit permission
        SETTINGS:ROLES_VIEW:
          type: number
          description: Settings roles view permission
        SETTINGS:REPRESENTATIVES_VIEW:
          type: number
          description: Settings representatives view permission
        SETTINGS:REPRESENTATIVES_EDIT:
          type: number
          description: Settings representatives edit permission
        INVOICE_VIEW:
          type: number
          description: Invoice view permission
        INVOICE_EDIT:
          type: number
          description: Invoice edit permission
        SUPPLIER_VIEW:
          type: number
          description: Supplier view permission
        SUPPLIER_EDIT:
          type: number
          description: Supplier edit permission
        SUB:ACCOUNTS_VIEW:
          type: number
          description: Sub-accounts view permission
        SUB:ACCOUNTS_EDIT:
          type: number
          description: Sub-accounts edit permission
        SUB:ACCOUNTS_ALLOCATE:
          type: number
          description: Sub-accounts allocate permission
        BUDGETS_CREATE:
          type: number
          description: Budgets create permission
        SUBSCRIPTIONS_VIEW:
          type: number
          description: Subscriptions view permission
        EXPENSES:RECEIPT_EDIT:
          type: number
          description: Expenses receipt edit permission
    EmployeeTeamDto:
      type: object
      properties:
        code:
          type: string
          description: Team code
        name:
          type: string
          description: Team name
        _id:
          type: string
          description: Team MongoDB ID
        status:
          type: string
          description: Team status
    StatementItemDto:
      type: object
      properties:
        _id:
          type: string
          description: Transaction MongoDB ID
        currency:
          type: string
          description: Transaction currency (USD/KES)
        org_wallet_ref:
          type: string
          description: Organization wallet reference
        account:
          type: string
          description: Account number
        credit:
          type: number
          description: Credit amount
        debit:
          type: number
          description: Debit amount
        description:
          type: string
          description: Transaction description
        ref:
          type: string
          description: Transaction reference
        created_by:
          type: string
          description: Created by user ID
        transaction_type:
          type: string
          description: Transaction type
          enum:
            - IFT
            - EXPENSE
            - TOPUP
            - REFUND
            - INTERNAL TRANSFER
            - OVERDRAFT
            - REPAYMENT
            - BRANCH TRANSFER
        running_balance:
          type: number
          description: Running account balance
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        id:
          type: string
          description: Auto-generated ID field
    UpdateUsersRoleDataV1Dto:
      type: object
      properties:
        databaseName:
          type: string
          description: Business database identifier
          example: biz_4badab471100
        data:
          type: object
          description: >-
            Permission object with dynamic categories and actions. Each category
            contains action keys with binary values (0=disabled, 1=enabled).
          additionalProperties:
            type: object
            additionalProperties:
              type: number
              enum:
                - 0
                - 1
          example:
            ALLOCATIONS:
              INITIATE: 1
              VIEW: 1
            BULK:PAYOUTS:
              INITIATE: 1
              VIEW: 1
            BUSINESS:STATEMENTS:
              VIEW: 1
    MandateDataV1Dto:
      type: object
      properties:
        data:
          description: Array of mandate objects
          type: array
          items:
            $ref: '#/components/schemas/MandateV1Dto'
    UpdateMandateDataV1Dto:
      type: object
      properties:
        minimum_approvers:
          type: number
          description: Minimum number of approvers required for this mandate
          example: 2
          minimum: 1
      required:
        - minimum_approvers
    UpdateApproverDataV1Dto:
      type: object
      properties:
        level:
          type: number
          description: Approval level/tier in the approval hierarchy
          example: 1
          minimum: 1
        must_approve:
          type: boolean
          description: Whether this approver must approve (mandatory approval)
          example: false
      required:
        - level
        - must_approve
    ApproverWithIdDto:
      type: object
      properties:
        level:
          type: number
          description: Approval level/tier in the approval hierarchy
          example: 1
          minimum: 1
        must_approve:
          type: boolean
          description: Whether this approver must approve (mandatory approval)
          example: false
        _id:
          type: string
          description: Employee object id
          example: 68c2cc82272ac8e89e3f930c
      required:
        - level
        - must_approve
        - _id
    CreatePaymentInstructionV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Payment instruction MongoDB ID (for updates)
        channel:
          type: string
          description: Payment channel type
          enum:
            - mpesa
            - mtn
            - pochi
            - airtel
            - xentebanktransfer
            - bank
            - rtgs
            - paybill
            - till
            - airtime
            - internal
          example: bank
        phone:
          type: string
          description: Phone number for mpesa payments
          example: 712345678
        accno:
          type: string
          description: Account number for bank payments
          example: '1234567890'
        bank:
          type: string
          description: Bank name
          example: BANK OF AFRICA K LTD
        bank_code:
          type: string
          description: Bank code
          example: '19'
        bankCode:
          type: string
          description: Bank code (alternative field)
          example: '19'
        till:
          type: string
          description: Till number for till payments
          example: '123456'
        till_no:
          type: string
          description: Till number (alternative field)
          example: '123456'
        business_no:
          type: string
          description: Business number for paybill payments
          example: '247247'
        is_default:
          type: boolean
          description: Whether this is the default payment method
          example: true
      required:
        - channel
    PaymentInstructionV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Payment instruction MongoDB ID
        channel:
          type: string
          description: Payment channel type
          enum:
            - mpesa
            - mtn
            - pochi
            - airtel
            - xentebanktransfer
            - bank
            - rtgs
            - paybill
            - till
            - airtime
            - internal
        phone:
          type: string
          description: Phone number for mpesa payments
        accno:
          type: string
          description: Account number for bank payments
        bank:
          type: string
          description: Bank name
        bank_code:
          type: string
          description: Bank code
        bankCode:
          type: string
          description: Bank code (alternative field)
        till:
          type: string
          description: Till number for till payments
        business_no:
          type: string
          description: Business number for paybill payments
        is_default:
          type: boolean
          description: Whether this is the default payment method
    PaymentInstructionPayloadDto:
      type: object
      properties:
        _id:
          type: string
          description: Payment instruction MongoDB ID
        channel:
          type: string
          description: Payment channel type
          example: bank
        phone:
          type: string
          description: Phone number for mobile payments
        accno:
          type: string
          description: Account number for bank payments
        bank:
          type: string
          description: Bank name
        till:
          type: string
          description: Till number
        business_no:
          type: string
          description: Business number for paybill payments
        till_no:
          type: string
          description: Till number (alternative field)
        bankCode:
          type: string
          description: Bank code
        bank_code:
          type: string
          description: Bank code (alternative field)
    AddPaymentInstructionPayloadDto:
      type: object
      properties:
        channel:
          type: string
          description: Payment channel type
          example: bank
        phone:
          type: string
          description: Phone number for mobile payments
        accno:
          type: string
          description: Account number for bank payments
        bank:
          type: string
          description: Bank name
        till:
          type: string
          description: Till number
        business_no:
          type: string
          description: Business number for paybill payments
        till_no:
          type: string
          description: Till number (alternative field)
        bankCode:
          type: string
          description: Bank code
        bank_code:
          type: string
          description: Bank code (alternative field)
    PaymentChannelV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Payment channel MongoDB ID
        method:
          type: string
          description: Payment method identifier
          example: mpesa
        name:
          type: string
          description: Display name for the payment channel
          example: Send Money
        currency:
          type: string
          description: Currency code
          example: KES
        country:
          type: string
          description: Country code
          example: KENYA
        status:
          type: string
          description: Channel status
          enum:
            - ACTIVE
            - INACTIVE
          example: ACTIVE
        type:
          type: string
          description: Payment type
          example: SENDMONEY
        provider:
          type: string
          description: Payment provider
          example: SAFARICOM
        beneficiary:
          type: string
          description: Beneficiary type
          example: phone
        validation:
          description: Validation rules for the payment channel
          allOf:
            - $ref: '#/components/schemas/PaymentChannelValidationV1Dto'
        gateway:
          type: string
          description: Payment gateway identifier
        group:
          type: string
          description: Payment channel group
          example: mpesa
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
    PaginationDataV1Dto:
      type: object
      properties:
        total:
          type: number
          description: Total number of records
        perPage:
          type: object
          description: Records per page
        currentPage:
          type: object
          description: Current page number
        totalPages:
          type: number
          description: Total number of pages
    PayoutRecordRequestV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Recipient name
          example: carol mwangi
        phone:
          type: string
          description: Phone number (required)
          example: 796725019
        email:
          type: string
          description: Email address
          example: carol@example.com
        amount:
          type: number
          description: Payment amount (must be positive)
          example: 10
        description:
          type: string
          description: Payment description
          example: test
        team:
          type: string
          description: Team code
          example: DE8832C7
        category_code:
          type: string
          description: Category code
          example: P003
        payment_type:
          type: string
          description: Payment type
          enum:
            - mpesa
            - airtel
            - mtn
            - xente
            - pochi
            - paybill
            - till
            - bank
            - rtgs
          example: mpesa
        bank_code:
          type: string
          description: Bank code (required for bank and RTGS payments)
          example: '01'
        receiver:
          type: string
          description: >-
            Receiver identifier (required for mpesa, airtel, mtn, xente, pochi,
            paybill)
          example: 796725019
        account_no:
          type: string
          description: Account number (required for paybill, bank, and RTGS payments)
          example: ''
        idno:
          type: string
          description: ID number
          example: ''
        mpesa_number:
          type: string
          description: M-Pesa number
          example: 796725019
        tags:
          description: Tags associated with payment
          example: []
          type: array
          items:
            type: string
        country:
          type: string
          description: Country
          example: Kenya
          default: Kenya
        category_name:
          type: string
          description: Category name
          example: General Materials
        branch_code:
          type: string
          description: Branch code (required for RTGS payments)
          example: '001'
        swift_code:
          type: string
          description: SWIFT/BIC code (required for RTGS payments)
          example: ABCDKENA
      required:
        - name
        - phone
        - amount
        - description
        - team
        - category_code
        - payment_type
        - country
        - category_name
    PaymentRecordV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Payment record MongoDB ID
        batch:
          type: string
          description: Batch ID reference
        batch_no:
          type: string
          description: Batch number
        mpesa_number:
          type: string
          description: M-Pesa phone number
        payment_type:
          type: string
          description: Payment type
          example: mpesa
        receiver:
          type: string
          description: Receiver identifier
        bank_name:
          type: string
          description: Bank name
        bank_code:
          type: string
          description: Bank code
        branch_code:
          type: string
          description: Branch code
        swift_code:
          type: string
          description: SWIFT code
        account_no:
          type: string
          description: Account number
        name:
          type: string
          description: Recipient name
        phone:
          type: string
          description: Phone number
        email:
          type: string
          description: Email address
        idno:
          type: string
          description: ID number
        description:
          type: string
          description: Payment description
        amount:
          type: number
          description: Payment amount
        fees:
          type: number
          description: Transaction fees
        status:
          type: string
          description: Payment status
          enum:
            - pending
            - processed
            - failed
            - cancelled
        transaction_ref:
          type: string
          description: Internal transaction reference
        category_name:
          type: string
          description: Category name
        category_code:
          type: string
          description: Category code
        team_code:
          type: string
          description: Team code
        noOfRetries:
          type: number
          description: Number of retry attempts
        send_on:
          type: string
          description: Scheduled send date
        is_duplicate:
          type: boolean
          description: Whether record is a duplicate
        tags:
          description: Tags associated with the payment
          type: array
          items:
            $ref: '#/components/schemas/TagV1Dto'
        error_message:
          type: string
          description: Error message if payment failed
        external_ref:
          type: string
          description: External reference from payment provider
        __v:
          type: number
          description: Version key
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
    ApproverV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Approver name
        email:
          type: string
          description: Approver email
        phone:
          type: string
          description: Approver phone
        employee_id:
          type: string
          description: Employee ID
        notes:
          type: string
          description: Approval notes
        mandatory:
          type: boolean
          description: Whether approval is mandatory
        level:
          type: number
          description: Approval level
        status:
          type: string
          description: Approval status
          enum:
            - pending
            - approved
            - cancelled
        _id:
          type: string
          description: Approver record ID
    EventV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Event ID
        record:
          type: string
          description: Related record ID
        recordType:
          type: string
          description: Record type
          enum:
            - ACTIVITY
            - APPROVAL
        description:
          type: string
          description: Event description
        person:
          type: string
          description: Person who performed the action
        item:
          type: string
          description: Item type
        recordIds:
          description: Related record IDs
          type: array
          items:
            type: string
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
    PaymentSummaryV1Dto:
      type: object
      properties:
        mpesa:
          type: number
          description: M-Pesa total
        pochi:
          type: number
          description: Pochi La Biashara total
        boya:
          type: number
          description: Boya total
        bank:
          type: number
          description: Bank transfer total
        rtgs:
          type: number
          description: RTGS total
        till:
          type: number
          description: Till number total
        airtime:
          type: number
          description: Airtime total
        paybill:
          type: number
          description: Paybill total
        xente:
          type: number
          description: Xente total
        mtn:
          type: number
          description: MTN total
        airtel:
          type: number
          description: Airtel total
    ConfirmPaymentTransactionDto:
      type: object
      properties:
        source:
          type: string
          description: Payment source (card token or identifier)
          example: 82622342945EE8C0-DUMMY
        payment_type:
          type: string
          description: Payment type
          example: CARD
        group:
          type: string
          description: Payment group/channel
          example: mpesa
        amount:
          type: number
          description: Transaction amount
          example: 10
        currency:
          type: string
          description: Currency code
          example: KES
        accno:
          type: string
          description: Account number
          example: 693345001
        notes:
          type: string
          description: Transaction notes
          example: Test a Payment via intents flow.
        categoryid:
          type: string
          description: Category ID
          example: 123XYZ
        description:
          type: string
          description: Transaction description
          example: Pay Biwott
        receivername:
          type: string
          description: Receiver name
          example: Biwott
        receiver:
          type: string
          description: Receiver identifier (phone/account)
          example: 790462100
        ref:
          type: string
          description: Transaction reference
          example: M-CF4X4LG8IIE
        txRef:
          type: string
          description: Transaction reference (duplicate of ref)
          example: M-CF4X4LG8IIE
        bank:
          $ref: '#/components/schemas/BankDetailsDto'
        physical_receipt:
          type: string
        other_receipts:
          type: string
        is_a_request:
          type: boolean
        initial:
          type: boolean
          description: Indicates if this is an initial transaction
          example: false
        timestamp:
          type: string
        expense_tags:
          type: array
          items:
            type: string
        expense_id:
          type: string
        vendor:
          type: string
        vendor_id:
          type: string
        wallet_id:
          type: string
          description: Wallet identifier
          example: P8756
        requisition_reference:
          type: string
        sms:
          type: string
          description: SMS notification content or reference
          example: ''
        checksum:
          type: string
          description: Data integrity verification checksum
          example: ''
      required:
        - source
        - payment_type
        - group
        - amount
        - currency
        - description
        - receiver
        - ref
        - txRef
        - initial
        - sms
        - checksum
    AuditLogEntryDto:
      type: object
      properties:
        _id:
          type: string
          description: Audit log MongoDB ID
        policy_id:
          type: string
          description: Policy ID
        wallet_id:
          type: string
          description: Wallet ID
        action:
          type: string
          description: Action performed
          enum:
            - GRANTED
            - MODIFIED
            - SUSPENDED
            - REVOKED
            - EXPIRED
            - REACTIVATED
        performed_by:
          type: object
          description: Employee who performed the action
        changes:
          type: object
          description: Changes made
        reason:
          type: string
          description: Reason for the action
        ip_address:
          type: string
          description: IP address of the request
        user_agent:
          type: string
          description: User agent of the request
        createdAt:
          type: string
          description: Timestamp of the action
        updatedAt:
          type: string
          description: Last update timestamp
      required:
        - _id
        - policy_id
        - wallet_id
        - action
        - createdAt
    PolicyLimitsResponseDto:
      type: object
      properties:
        per_transaction:
          type: object
          description: Per-transaction limit
        daily_total:
          type: object
          description: Daily total limit
        monthly_total:
          type: object
          description: Monthly total limit
        currency:
          type: string
          description: Currency code
    PolicyThresholdsResponseDto:
      type: object
      properties:
        approval_required_above:
          type: object
          description: Amount above which approval is required
        auto_flag_above:
          type: object
          description: Amount above which transaction is auto-flagged
    PolicyRestrictionsResponseDto:
      type: object
      properties:
        mask_balance:
          type: boolean
          description: Whether balance is masked
        mask_transaction_amounts:
          type: boolean
          description: Whether transaction amounts are masked
        max_transaction_history_days:
          type: number
          description: Maximum transaction history days accessible
    PolicyUpdatesDto:
      type: object
      properties:
        permissions:
          description: Updated permission slugs
          example:
            - view-balance
            - view-transactions
            - export-statements
          type: array
          items:
            type: string
        limits:
          description: Updated transaction limits
          allOf:
            - $ref: '#/components/schemas/PolicyLimitsDto'
        thresholds:
          description: Updated approval thresholds
          allOf:
            - $ref: '#/components/schemas/PolicyThresholdsDto'
        restrictions:
          description: Updated display restrictions
          allOf:
            - $ref: '#/components/schemas/PolicyRestrictionsDto'
        valid_until:
          type: string
          description: Updated expiry date
        label:
          type: string
          description: Updated label
    PolicyLimitsDto:
      type: object
      properties:
        per_transaction:
          type: object
          description: Per-transaction limit (null = no limit)
          example: 100000
        daily_total:
          type: object
          description: Daily total limit (null = no limit)
          example: 500000
        monthly_total:
          type: object
          description: Monthly total limit (null = no limit)
          example: 2000000
        currency:
          type: string
          description: Currency code
          example: KES
          default: KES
    PolicyThresholdsDto:
      type: object
      properties:
        approval_required_above:
          type: object
          description: Amount above which approval is required
          example: 50000
        auto_flag_above:
          type: object
          description: Amount above which transaction is auto-flagged
          example: 200000
    PolicyRestrictionsDto:
      type: object
      properties:
        mask_balance:
          type: boolean
          description: Whether to mask balance display
          default: false
        mask_transaction_amounts:
          type: boolean
          description: Whether to mask transaction amounts
          default: false
        max_transaction_history_days:
          type: number
          description: Maximum transaction history days accessible
          default: 90
    TaxTransactionV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Tax transaction ID
        name:
          type: string
          description: Transaction name
          example: Witholding Tax - emm3m44
        status:
          type: string
          description: Transaction status
          enum:
            - OUTSTANDING
            - PROCESSING
            - FAILED
        bill:
          description: Associated bill details
          allOf:
            - $ref: '#/components/schemas/BillV1Dto'
        tax:
          description: Tax rate details
          allOf:
            - $ref: '#/components/schemas/TaxDetailsV1Dto'
        base_amount:
          type: number
          description: Base amount
        withheld_amount:
          type: number
          description: Withheld amount
        source:
          type: string
          description: Source
        source_name:
          type: string
          description: Source name
        source_account_number:
          type: string
          description: Source account number
        __v:
          type: number
          description: Version key
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        tax_prn:
          type: string
          description: Tax PRN (Payment Reference Number)
    PaginatedExpensesDataDto:
      type: object
      properties:
        docs:
          description: Array of expense documents
          example: []
          type: array
          items:
            type: object
        total:
          type: number
          description: Total number of expenses
          example: 0
        limit:
          type: number
          description: Number of items per page
          example: 4
        page:
          type: number
          description: Current page number
          example: 1
        pages:
          type: number
          description: Total number of pages
          example: 1
      required:
        - docs
        - total
        - limit
        - page
        - pages
    AmountSpentDataDto:
      type: object
      properties:
        amountSpent:
          description: Array of amounts spent
          example: []
          type: array
          items:
            type: object
        periodBreakdown:
          description: Breakdown by period
          type: array
          items:
            $ref: '#/components/schemas/PeriodBreakdownDto'
      required:
        - amountSpent
        - periodBreakdown
    CreateSubscriptionTeamDto:
      type: object
      properties:
        _id:
          type: string
          description: Team ID
          example: 688877881b49af84b1aa11d9
        code:
          type: string
          description: Team code
          example: 74CAAEEA
        name:
          type: string
          description: Team name
          example: AAR Bamburi
      required:
        - _id
        - code
        - name
    CreateSubscriptionSubcategoryDto:
      type: object
      properties:
        _id:
          type: string
          description: Subcategory ID
          example: 64f04ea40aac0abfb44b3bb7
        code:
          type: string
          description: Subcategory code
          example: P003
        name:
          type: string
          description: Subcategory name
          example: General Materials
      required:
        - _id
        - code
        - name
    SubscriptionBusinessDto:
      type: object
      properties:
        _id:
          type: string
          description: Business ID
        name:
          type: string
          description: Business name
        email:
          type: string
          description: Business email
        phone:
          type: string
          description: Business phone
        country:
          type: string
          description: Business country
    SubscriptionCardDto:
      type: object
      properties:
        _id:
          type: string
          description: Card ID
        exp_month:
          type: string
          description: Card expiration month
        exp_year:
          type: string
          description: Card expiration year
        brand:
          type: string
          description: Card brand
        last4:
          type: string
          description: Last 4 digits of card
        bin:
          type: string
          description: Card BIN
        blocked:
          type: boolean
          description: Card blocked status
        retired:
          type: boolean
          description: Card retired status
        issued_on:
          type: string
          description: Card issued date
        provider:
          type: string
          description: Card provider
        currency:
          type: string
          description: Card currency
        tracking_number:
          type: string
          description: Card tracking number
        is_virtual:
          type: boolean
          description: Is virtual card
        is_offline:
          type: boolean
          description: Is offline card
        dormant:
          type: boolean
          description: Card dormant status
        purged:
          type: boolean
          description: Card purged status
    SubscriptionAssigneeDto:
      type: object
      properties:
        _id:
          type: string
          description: Assignee ID
        name:
          type: string
          description: Assignee name
        employee_id:
          type: string
          description: Employee ID
        team_code:
          type: string
          description: Team code
    SubscriptionSubcategoryDto:
      type: object
      properties:
        _id:
          type: string
          description: Subcategory ID
        code:
          type: string
          description: Subcategory Code
        name:
          type: string
          description: Subcategory Name
    SubscriptionTeamDto:
      type: object
      properties:
        code:
          type: string
          description: Team Code
        name:
          type: string
          description: Team Name
    AuditEventV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Audit event MongoDB ID
        id:
          type: string
          description: Audit event ID
        business:
          type: string
          description: Business ID
        recordType:
          type: string
          description: Record type
          enum:
            - ACTIVITY
            - MODIFICATION
            - CREATION
            - DELETION
        description:
          type: string
          description: Event description
        person:
          type: string
          description: Person who performed the action
        item:
          type: string
          description: Item type affected
          enum:
            - LOGIN
            - SUBSCRIPTION
            - INVESTMENT
            - EXPENSE
            - TRANSACTION
            - EMPLOYEE
            - VENDOR
        ip_address:
          type: string
          description: IP address of the request
        location:
          type: string
          description: Location country code
        recordIds:
          description: Related record IDs
          type: array
          items:
            type: string
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
    DigestGroupDto:
      type: object
      properties:
        id:
          type: string
          description: Unique group identifier
          example: group-0
        type:
          type: string
          description: Group type
          enum:
            - insight
            - session
            - activity
          example: insight
        priority:
          type: string
          description: Priority level
          enum:
            - high
            - normal
            - low
          example: high
        title:
          type: string
          description: Brief title describing what happened
          example: Multiple Login Attempts
        summary:
          type: string
          description: One-sentence summary for executives
          example: Faith logged in 4 times within 8 minutes
        timestamp:
          type: string
          description: ISO timestamp of most recent event
          example: '2026-02-05T14:30:45.000Z'
        insight:
          type: string
          description: Natural language explanation with context and assessment
          example: >-
            This pattern may indicate connection issues or automated testing. No
            security concerns detected - same IP and location.
        confidence:
          type: number
          description: Confidence score (0-1)
          example: 0.85
        actors:
          description: Actors involved in this group
          example:
            - Faith
            - Rob
          type: array
          items:
            type: string
        location:
          type: string
          description: Location (human-readable)
          example: Kenya
        events:
          description: Events in this group
          type: array
          items:
            $ref: '#/components/schemas/DigestEventDto'
      required:
        - id
        - type
        - priority
        - title
        - summary
        - timestamp
        - insight
        - confidence
        - actors
        - events
    DigestStatsDto:
      type: object
      properties:
        totalEvents:
          type: number
          description: Total events in digest
          example: 15
        uniqueUsers:
          type: number
          description: Number of unique users
          example: 3
        topAction:
          type: string
          description: Most common action type
          example: Investment queries
        timeSpan:
          type: string
          description: Time span covered
          example: 24 hours
        byType:
          description: Event counts by record type
          allOf:
            - $ref: '#/components/schemas/DigestStatsByTypeDto'
        byPerson:
          type: object
          description: Event counts by person
          example:
            Rob: 8
            Faith: 5
      required:
        - totalEvents
        - uniqueUsers
        - topAction
        - timeSpan
        - byType
        - byPerson
    PolicySummaryInGroupV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Policy type MongoDB ObjectId
        status:
          type: string
          description: Policy status
          enum:
            - ACTIVE
            - DISABLED
        description:
          type: string
          description: Human-readable description of the policy type
        policy_code:
          type: string
          description: Policy code (e.g. CHANNELS, SUBCATEGORY, TAGS)
        rules:
          description: Default rules for this policy type
          type: array
          items:
            $ref: '#/components/schemas/PolicyRuleV1Dto'
        business_policy_id:
          type: string
          description: ID of the active business policy under this type, if any
    PolicyWithRulesV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Policy type MongoDB ObjectId
        status:
          type: string
          description: Policy status
          enum:
            - ACTIVE
            - DISABLED
        description:
          type: string
          description: Human-readable description of the policy type
        policy_code:
          type: string
          description: Policy code (e.g. CHANNELS, SUBCATEGORY, VENDORS)
        business_policies:
          description: Business-specific policies under this type
          type: array
          items:
            $ref: '#/components/schemas/BusinessPolicyV1Dto'
        rules:
          description: Default rules for this policy type
          type: array
          items:
            $ref: '#/components/schemas/PolicyRuleV1Dto'
    PolicyRefV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Policy group MongoDB ObjectId
        status:
          type: string
          description: Policy status
          enum:
            - ACTIVE
            - DISABLED
            - DELETED
        description:
          type: string
          description: Human-readable description of the policy type
        policy_code:
          type: string
          description: Policy code identifier (e.g. SUBCATEGORY, CHANNELS, VENDORS)
    PolicyRuleV1Dto:
      type: object
      properties:
        conditions:
          description: Conditions that must be met for this rule to apply
          type: array
          items:
            $ref: '#/components/schemas/PolicyConditionV1Dto'
        action:
          type: string
          description: >-
            Action to take when conditions are met (e.g. allow, block,
            request_approval, require_receipt)
        period_unit:
          type: string
          description: >-
            Time unit for the spending period. TRANSACTION = per-payment limit;
            HOUR/DAY/WEEK/MONTH/YEAR = cumulative window
          enum:
            - TRANSACTION
            - HOUR
            - DAY
            - WEEK
            - MONTH
            - YEAR
          example: TRANSACTION
        period:
          type: number
          description: >-
            Number of period units for the spending limit window. Use 0 when
            period_unit is TRANSACTION
          example: 0
        kick_off_date:
          type: string
          description: ISO 8601 date when the rule becomes active
        target:
          type: string
          description: Who this rule targets (e.g. everyone)
        target_employees:
          description: Specific employee IDs this rule targets
          type: array
          items:
            type: string
        exempt_employees:
          description: Employee IDs exempt from this rule
          type: array
          items:
            type: string
        target_teams:
          description: Team IDs this rule targets
          type: array
          items:
            type: string
        exempt_teams:
          description: Team IDs exempt from this rule
          type: array
          items:
            type: string
        target_sub_categories:
          description: Subcategories this rule targets
          type: array
          items:
            type: string
        exempt_sub_categories:
          description: Subcategories exempt from this rule
          type: array
          items:
            type: string
        target_channels:
          description: Payment channels this rule targets (e.g. mpesa, bills, tills)
          type: array
          items:
            type: string
        target_roles:
          description: Employee roles this rule targets
          type: array
          items:
            type: string
        require_tax_compliant_receipt:
          type: boolean
          description: Whether a tax-compliant receipt is required
        funding_source_strategy:
          type: string
          description: Funding source strategy (e.g. business_wallet, initiator_wallet)
        exempt_wallet_types:
          description: Wallet types exempt from this rule
          type: array
          items:
            type: string
    PolicyWorkflowStepDto:
      type: object
      properties:
        approval_mandate:
          type: string
          enum:
            - all
            - any_of
          default: all
        minimum_approvers:
          type: number
          example: 1
        is_auto_approval:
          type: boolean
          example: false
        daily_limit:
          type: object
          example: 1000000
          description: >-
            Per-day approval limit. Optional — the gateway fills a per-currency
            default when omitted.
        transaction_limit:
          type: object
          example: 500000
          description: >-
            Per-transaction approval limit. Optional — the gateway fills a
            per-currency default when omitted.
        amount_approval_condition:
          $ref: '#/components/schemas/PolicyWorkflowAmountConditionDto'
        approvers:
          type: array
          items:
            $ref: '#/components/schemas/PolicyWorkflowApproverDto'
      required:
        - minimum_approvers
        - approvers
    FxMarkupDto:
      type: object
      properties:
        buy:
          type: number
          example: 2
        sell:
          type: number
          example: 2
      required:
        - buy
        - sell
    FundCatalogueItemDto:
      type: object
      properties:
        fund_id:
          type: string
          example: fund_britam_mmf_kes
        fund_name:
          type: string
          example: Britam Money Market Fund (KES)
        vendor:
          type: string
          example: BRITAM
        asset_manager:
          type: string
          example: Britam Asset Managers
        product:
          type: string
          example: MONEY_MARKET
        currency:
          type: string
          example: KES
        min_initial_investment:
          $ref: '#/components/schemas/MoneyDto'
        effective_yield:
          description: Current effective annual yield assumption.
          allOf:
            - $ref: '#/components/schemas/YieldDto'
        interest_frequency:
          type: string
          example: Daily
        risk_level:
          type: string
          example: Low
        withdrawals_allowed:
          type: boolean
          example: true
      required:
        - fund_id
        - fund_name
        - vendor
        - asset_manager
        - product
        - currency
        - min_initial_investment
        - effective_yield
        - interest_frequency
        - risk_level
        - withdrawals_allowed
    FundAccountSummaryDto:
      type: object
      properties:
        fund_account_id:
          type: string
          example: fa_01HXYZ...
          description: Customer's fund account ID
        fund_id:
          type: string
          example: fund_britam_kes_mmf
          description: Catalogue fund ID
        fund_name:
          type: string
          example: Britam KES Money Market Fund
        vendor:
          type: string
          example: BRITAM
        product:
          type: string
          example: MONEY_MARKET
        currency:
          type: string
          example: KES
        org_wallet_ref:
          type: string
          example: '1'
          description: Organization wallet reference for this fund account currency.
        account_reference:
          type: string
          example: BA100020873BOYA
          description: External account reference (display-only)
        approval_ref:
          type: string
          example: INV-OPT-123456
          description: Approval request reference for pending opt-in records.
        investment_wallet_id:
          type: string
          example: I622957
          description: >-
            Boya wallet id of the MMF investment account. Used by the dashboard
            as the destination when topping up the investment account from a
            business wallet.
        state:
          type: string
          enum:
            - opt_in_pending
            - active
            - closing
            - opt_in_failed
          example: active
        invested:
          description: Total invested principal (native currency)
          allOf:
            - $ref: '#/components/schemas/MoneyDto'
        wallet_available_balance:
          description: >-
            Available cash in the investment wallet before it is invested with
            the custodian.
          allOf:
            - $ref: '#/components/schemas/MoneyDto'
        opt_in_date:
          type: string
          example: '2024-08-12'
          description: Opt-in date (date-only, ISO 8601)
        treasury_operators:
          example:
            - 64f0a1b2c3d4e5f600112233
            - 64f0a1b2c3d4e5f600445566
          description: >-
            Employee ids permitted to transfer funds from this account (the
            wallet's employees_allowed_to_make_payments). Drives the Treasury
            Operators panel.
          type: array
          items:
            type: string
        investment_permissions:
          type: array
          items:
            $ref: '#/components/schemas/InvestmentPermissionGrantDto'
      required:
        - fund_account_id
        - fund_id
        - fund_name
        - vendor
        - product
        - currency
        - state
        - invested
    MoneyDto:
      type: object
      properties:
        amount:
          type: number
          example: 125000.5
          description: Numeric amount
        currency:
          type: string
          example: KES
          description: ISO 4217 currency code
      required:
        - amount
        - currency
    InvestmentPermissionGrantDto:
      type: object
      properties:
        employee_id:
          type: string
          example: 64f0a1b2c3d4e5f600112233
        actions:
          type: array
          items:
            type: string
            enum:
              - VIEW
              - TOP_UP
              - INVEST
              - WITHDRAW
              - MANAGE
      required:
        - employee_id
        - actions
    InterestSeriesPointDto:
      type: object
      properties:
        date:
          type: string
          example: '2024-08-12'
          description: Date-only, ISO 8601
        amount:
          type: number
          example: 12.34
          description: Interest credited on this date, native currency
        currency:
          type: string
          example: KES
      required:
        - date
        - amount
        - currency
    ProjectionHorizonDto:
      type: object
      properties:
        horizon:
          type: string
          enum:
            - EOM
            - 3M
            - 6M
            - 12M
        projected_interest:
          type: number
          example: 4200.5
          description: Projected interest at horizon, native currency
        currency:
          type: string
          example: KES
      required:
        - horizon
        - projected_interest
        - currency
    InvestmentTransactionDto:
      type: object
      properties:
        id:
          type: string
          example: txn_01HXYZ...
        occurred_at:
          type: string
          example: '2024-08-12T09:14:00.000Z'
          description: ISO 8601 timestamp
        type:
          type: string
          enum:
            - ALL
            - MMF-INVESTMENT
            - MMF-INTEREST
            - MMF-WITHDRAWAL
            - MMF-UNKNOWN
        amount:
          type: number
          example: 50000
          description: 'Signed amount: credit positive, debit negative'
        currency:
          type: string
          example: KES
        status:
          type: string
          example: SUCCESS
        description:
          type: string
          example: Britam KES MMF interest
        reference:
          type: string
          example: MMF-D4B58C018D
          description: Internal Boya reference
        external_reference:
          type: string
          example: '132210551'
          description: Custodian (Britam) provider reference
        credit:
          type: number
          example: 42.28
          description: Raw credit amount from the ledger
        debit:
          type: number
          example: 0
          description: Raw debit amount from the ledger
      required:
        - id
        - occurred_at
        - type
        - amount
        - currency
    OptInApprovalRequestDto:
      type: object
      properties:
        _id:
          type: string
          example: 64f1f77bc6d4f24b75a0c101
        ref:
          type: string
          example: INV-OPT-123456
        status:
          type: string
          example: PENDING
        participants:
          type: array
          items:
            type: object
        records:
          type: array
          items:
            type: object
    PortfolioCurrencyTotalsDto:
      type: object
      properties:
        currency:
          type: string
          example: KES
        total_invested:
          $ref: '#/components/schemas/MoneyDto'
        available_balance:
          $ref: '#/components/schemas/MoneyDto'
        account_count:
          type: number
          example: 1
      required:
        - currency
        - total_invested
        - available_balance
        - account_count
    PortfolioPerformanceCurrencyDto:
      type: object
      properties:
        currency:
          type: string
          example: KES
        total_interest:
          $ref: '#/components/schemas/MoneyDto'
        series:
          type: array
          items:
            $ref: '#/components/schemas/InterestSeriesPointDto'
      required:
        - currency
        - total_interest
        - series
    BillWorkflowStepDto:
      type: object
      properties:
        approval_mandate:
          type: string
          enum:
            - all
            - any_of
          default: any_of
        minimum_approvers:
          type: number
          example: 1
        is_auto_approval:
          type: boolean
          example: false
        daily_limit:
          type: object
          example: 200
        transaction_limit:
          type: object
          example: 5000
        amount_approval_condition:
          $ref: '#/components/schemas/BillWorkflowAmountConditionDto'
        approvers:
          type: array
          items:
            $ref: '#/components/schemas/BillWorkflowApproverDto'
      required:
        - minimum_approvers
        - approvers
    CategoryDto:
      type: object
      properties:
        _id:
          type: string
          description: Category MongoDB ID
        groupid:
          type: string
          description: Category group ID
        name:
          type: string
          description: Category name
    TaxValidityDto:
      type: object
      properties:
        pin:
          type: string
          description: PIN number
        cu:
          type: object
          description: CU details
        invoice:
          type: object
          description: Invoice details
        tax:
          type: object
          description: Tax details
    CategoryReportDatasetDto:
      type: object
      properties:
        data:
          description: Data values for each category
          example:
            - 1013
            - 78
            - 10
            - 240
            - 58
          type: array
          items:
            type: number
        backgroundColor:
          description: Background colors for each category
          example:
            - '#EA088B'
            - '#662F8E'
            - '#191970'
          type: array
          items:
            type: string
        hoverBackgroundColor:
          description: Hover background colors for each category
          example:
            - '#EA088B'
            - '#662F8E'
            - '#191970'
          type: array
          items:
            type: string
      required:
        - data
        - backgroundColor
        - hoverBackgroundColor
    ApprovalParticipantDto:
      type: object
      properties:
        employee:
          type: string
          description: Participant employee ObjectId
        id:
          type: string
          description: Employee identifier string
        status:
          type: number
          description: 'Participant status: 1=pending, 0=approved, 2=rejected'
        reason:
          type: string
          description: Reason for decision
        approval_type:
          type: number
          description: 'Approval type: 1=mandatory, 0=optional'
        requested_on:
          type: string
          description: Requested on timestamp
        actioned_on:
          type: string
          description: Actioned on timestamp
        level:
          type: number
          description: Approval hierarchy level
    TagEmployeeDto:
      type: object
      properties:
        customer_id:
          type: string
          description: Customer ID of the tag owner
          example: EAA8F4AF3B1DF2EA8D45
        customer_name:
          type: string
          description: Customer name of the tag owner
          example: Ivy Ngele ; 00111
    ApprovalBusinessDto:
      type: object
      properties:
        _id:
          type: string
          example: 631b067a46830ae81217f860
        business_id:
          type: string
          example: zyatjjbfhwwrzzmpgrpsbkcpnldfge
        name:
          type: string
          example: Boya Limited
      required:
        - _id
        - business_id
        - name
    ApprovalRecordDto:
      type: object
      properties:
        _id:
          type: string
          example: 698eae9e8e02c65ba2c4d0ea
        ref:
          type: string
          example: SUB-3e70cd6484
        amount:
          type: number
          example: 100
        currency:
          type: string
          example: USD
        description:
          type: string
          example: Mpesa transaction
        notes:
          type: string
          example: Rob is requesting creation of a subscription
        receiver_name:
          type: string
          example: Lucidchart
        fees:
          type: number
          example: 0
        transaction_ref:
          type: string
          example: D-UGUKVSPHMJGFE
        team:
          $ref: '#/components/schemas/ApprovalTeamDto'
        payment_instruction:
          $ref: '#/components/schemas/PaymentInstructionDto'
        status:
          type: string
          example: pending
    ApprovalEventDto:
      type: object
      properties:
        _id:
          type: string
          example: 698eaec7c3e3ddd24c2dfa47
        recordType:
          type: string
          example: APPROVAL
        description:
          type: string
          example: 'Approved request: #SUB-84f6ecb209'
        person:
          type: string
          example: Rob
        createdAt:
          type: string
          example: '2026-02-13T04:55:35.850Z'
      required:
        - _id
        - recordType
        - description
        - person
        - createdAt
    RequesterDto:
      type: object
      properties:
        id:
          type: string
          example: sgggbrfldhqcudjvhhwjpzcdcpcwws
        name:
          type: string
          example: Rob
        email:
          type: string
          example: rob@boyahq.com
        phone:
          type: string
          example: '+254710702289'
      required:
        - id
        - name
        - email
        - phone
    ApprovalStepDto:
      type: object
      properties:
        id:
          type: string
          example: sgggbrfldhqcudjvhhwjpzcdcpcwws
        name:
          type: string
          example: Rob
        employeeId:
          type: string
          example: sgggbrfldhqcudjvhhwjpzcdcpcwws
        level:
          type: number
          example: 1
        status:
          type: string
          enum:
            - completed
            - pending
            - rejected
            - awaiting
          example: pending
        statusLabel:
          type: string
          example: Pending Review
        requestedAt:
          format: date-time
          type: string
          example: '2026-02-13T04:54:54.492Z'
        actionedAt:
          format: date-time
          type: string
          example: '2026-02-13T04:55:35.810Z'
        reason:
          type: string
          example: ''
        duration:
          type: string
          example: 1h 30m
        isCurrentUser:
          type: boolean
          example: true
      required:
        - id
        - name
        - employeeId
        - level
        - status
        - statusLabel
        - requestedAt
    ApprovalProgressDto:
      type: object
      properties:
        completed:
          type: number
          example: 1
        total:
          type: number
          example: 2
        percentage:
          type: number
          example: 50
      required:
        - completed
        - total
        - percentage
    ApprovalEventDigestDto:
      type: object
      properties:
        type:
          type: string
          example: APPROVAL
        description:
          type: string
          example: 'Approved request: #SUB-84f6ecb209'
        person:
          type: string
          example: Rob
        timestamp:
          format: date-time
          type: string
          example: '2026-02-13T04:55:35.850Z'
      required:
        - type
        - description
        - person
        - timestamp
    CashflowAccountDto:
      type: object
      properties:
        accountId:
          type: string
          description: Account identifier
          example: acc-1
        accountName:
          type: string
          description: Account name
          example: Main Account
        accountType:
          type: string
          description: Account type
          example: BUSINESS_WALLET
        currency:
          type: string
          description: Account currency
          example: KES
        openingBalance:
          type: number
          description: Opening balance at start of period
          example: 100000
        expense:
          type: number
          description: Total expenses during period
          example: 0
        moneyIn:
          type: number
          description: Total money received during period
          example: 0
        iftIn:
          type: number
          description: Internal fund transfers in
          example: 0
        iftOut:
          type: number
          description: Internal fund transfers out
          example: 0
        closingBalance:
          type: number
          description: Closing balance at end of period
          example: 120000
      required:
        - accountId
        - accountName
        - accountType
        - currency
        - openingBalance
        - expense
        - moneyIn
        - iftIn
        - iftOut
        - closingBalance
    CashflowSummaryDto:
      type: object
      properties:
        openingBalance:
          type: object
          description: Opening balance totals by currency
          example:
            KES: 2217.32
            total: 2217.32
        closingBalance:
          type: object
          description: Closing balance totals by currency
          example:
            KES: 2037.32
            total: 2037.32
        currency:
          type: string
          description: Primary currency for the report
          example: KES
      required:
        - openingBalance
        - closingBalance
        - currency
    CashflowPeriodDto:
      type: object
      properties:
        startDate:
          type: string
          description: Period start date
          example: '2026-05-01'
        endDate:
          type: string
          description: Period end date
          example: '2026-05-15'
      required:
        - startDate
        - endDate
    BankDepositInstructionsDto:
      type: object
      properties:
        bank:
          type: string
          description: Bank name for wire transfer
        bankCode:
          type: string
          description: Bank code
        branchCode:
          type: string
          description: Branch code
        accountNumber:
          type: string
          description: Account number for deposit
        bankBranch:
          type: string
          description: Bank branch name
        swiftCode:
          type: string
          description: SWIFT code for international transfers
        reference:
          type: string
          description: Payment reference (use this in transfer description)
        currency:
          type: string
          description: Currency for this deposit account
    MpesaDepositInstructionsDto:
      type: object
      properties:
        type:
          type: string
          description: Payment type
        businessNumber:
          type: string
          description: M-Pesa Paybill business number
        accountNumber:
          type: string
          description: Account number to use when paying
    MoneyInDto:
      type: object
      properties:
        totalAmount:
          type: number
          description: Total money in for the requested period
          example: 139.26
        topSources:
          description: Top 5 sources of income (payment channels)
          example:
            - id: '1'
              name: MPESA
              amount: 139.26
              avatar: M
          type: array
          items:
            $ref: '#/components/schemas/TopSourceDto'
        last3MonthsAverage:
          type: number
          description: Average money in over the last 3 months
          example: 125.5
        last3MonthsData:
          description: Money in data for the last 3 months
          example:
            - month: Oct
              year: 2025
              amount: 120
            - month: Nov
              year: 2025
              amount: 130.5
            - month: Dec
              year: 2025
              amount: 126
          type: array
          items:
            $ref: '#/components/schemas/MonthlyDataDto'
      required:
        - totalAmount
        - topSources
        - last3MonthsAverage
        - last3MonthsData
    MoneyOutDto:
      type: object
      properties:
        totalAmount:
          type: number
          description: Total money out for the requested period
          example: 65
        topSpends:
          description: Top 5 spending destinations (vendors/merchants)
          example:
            - id: '1'
              name: Boya Limited
              amount: 50
              avatar: B
          type: array
          items:
            $ref: '#/components/schemas/TopSpendDto'
        last3MonthsAverage:
          type: number
          description: Average money out over the last 3 months
          example: 60.25
        last3MonthsData:
          description: Money out data for the last 3 months
          example:
            - month: Oct
              year: 2025
              amount: 55
            - month: Nov
              year: 2025
              amount: 62.5
            - month: Dec
              year: 2025
              amount: 63.25
          type: array
          items:
            $ref: '#/components/schemas/MonthlyDataDto'
      required:
        - totalAmount
        - topSpends
        - last3MonthsAverage
        - last3MonthsData
    MandateV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Mandate MongoDB ID
          example: 64f04e9f0aac0abfb44b3b6b
        type:
          type: string
          description: Type of mandate (PAYABLES, PAYROLL, etc.)
          enum:
            - PAYABLES
            - PAYROLL
          example: PAYABLES
        approvers:
          description: Array of approvers for this mandate
          type: array
          items:
            $ref: '#/components/schemas/MandateApproverV1Dto'
        minimum_approvers:
          type: number
          description: Minimum number of approvers required for this mandate
          example: 1
    PaymentChannelValidationV1Dto:
      type: object
      properties:
        required:
          description: Required fields for this payment channel
          example:
            - phone
          type: array
          items:
            type: string
        minimum_amount:
          type: number
          description: Minimum transaction amount
          example: 10
        maximum_amount:
          type: number
          description: Maximum transaction amount
          example: 150000
    TagV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Tag ID
        name:
          type: string
          description: Tag name
        tag_group:
          description: Tag group details
          allOf:
            - $ref: '#/components/schemas/TagGroupV1Dto'
        employee:
          description: Employee associated with the tag
          allOf:
            - $ref: '#/components/schemas/TagEmployeeV1Dto'
        is_deleted:
          type: boolean
          description: Whether tag is deleted
        __v:
          type: number
          description: Version key
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        teams:
          description: Team IDs associated with tag
          type: array
          items:
            type: string
    BankDetailsDto:
      type: object
      properties:
        BANKNAME:
          type: string
        BANKCODE:
          type: string
        ACCOUNTNAME:
          type: string
        SWIFTBIC:
          type: string
        BANKCITY:
          type: string
        BANKCOUNTRY:
          type: string
    BillV1Dto:
      type: object
      properties:
        budget_owner:
          description: Budget owner details
          allOf:
            - $ref: '#/components/schemas/BudgetOwnerV1Dto'
        _id:
          type: string
          description: Bill ID
        invoice_no:
          type: string
          description: Invoice number
        org_wallet_ref:
          type: string
          description: Organization wallet reference
        description:
          type: string
          description: Bill description
        category:
          type: string
          description: Category
        category_code:
          type: string
          description: Category code
        attachments:
          description: Attachments
          type: array
          items:
            $ref: '#/components/schemas/AttachmentV1Dto'
        invoice_amount:
          type: number
          description: Invoice amount
        due_date:
          type: string
          description: Due date
        created_by:
          type: string
          description: Created by
        invoice_date:
          type: string
          description: Invoice date
        received_from:
          type: string
          description: Received from
        events:
          description: Event IDs
          type: array
          items:
            type: string
        status:
          type: string
          description: Bill status
          enum:
            - outstanding
            - cancelled
            - draft
            - paid
        supplier:
          description: Supplier details
          allOf:
            - $ref: '#/components/schemas/SupplierV1Dto'
        auto_approve_repeat_payments:
          type: boolean
          description: Auto approve repeat payments
        repeat_frequency:
          type: string
          description: Repeat frequency
          enum:
            - none
            - daily
            - weekly
            - monthly
        no_of_repeats:
          type: number
          description: Number of repeats
        items:
          description: Items
          type: array
          items:
            type: string
        payments:
          description: Payments
          type: array
          items:
            $ref: '#/components/schemas/PaymentV1Dto'
        read_only:
          type: boolean
          description: Read only flag
        tags:
          description: Tags
          type: array
          items:
            type: string
        initiated_by_id:
          type: string
          description: Initiated by ID
        initiated_by_name:
          type: string
          description: Initiated by name
        original_currency:
          type: string
          description: Original currency
        original_currency_amount:
          type: number
          description: Original currency amount
        wallet_currency:
          type: string
          description: Wallet currency
        fx_rate:
          type: number
          description: FX rate
        withholding_taxes:
          description: Withholding taxes
          type: array
          items:
            type: string
        is_withholding_taxable:
          type: boolean
          description: Is withholding taxable
        approvers:
          description: Approvers
          type: array
          items:
            type: string
        budget:
          type: object
          description: Budget
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        updated_by:
          type: string
          description: Updated by
    TaxDetailsV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Tax ID
        name:
          type: string
          description: Tax name
        type:
          type: string
          description: Tax type
          enum:
            - PROFFESSIONAL_WITHHOLDING_TAX
            - VAT_WITHHOLDING_TAX
        rate:
          type: number
          description: Tax rate
        status:
          type: string
          description: Tax status
          enum:
            - ACTIVE
            - ARCHIVED
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
        nature_of_business:
          type: string
          description: Nature of business
        resident_type:
          type: string
          description: Resident type
          enum:
            - Resident
            - Non-Resident
    PeriodBreakdownDto:
      type: object
      properties:
        period:
          type: string
          description: Period identifier
          example: 2025-05
        periodStart:
          type: string
          description: Period start date
          example: '2025-05-31T21:00:00.000Z'
        periodEnd:
          type: string
          description: Period end date
          example: '2025-06-30T20:59:59.999Z'
        total:
          type: number
          description: Total amount spent in this period
          example: 0
      required:
        - period
        - periodStart
        - periodEnd
        - total
    DigestEventDto:
      type: object
      properties:
        time:
          type: string
          description: Event time (HH:MM:SS format)
          example: '14:30:45'
        action:
          type: string
          description: Human-readable action description
          example: Logged in to the dashboard
        ip:
          type: string
          description: IP address
          example: 129.222.187.88
        subscription:
          type: string
          description: Subscription ID
          example: sub_123
        investment:
          type: string
          description: Investment ID
          example: inv_456
        details:
          type: string
          description: Additional details
          example: 'Amount: KES 5,000'
        note:
          type: string
          description: Warning or observation note
          example: Different IP from previous login
        count:
          type: number
          description: Event count for grouped actions
          example: 2
      required:
        - time
        - action
    DigestStatsByTypeDto:
      type: object
      properties:
        ACTIVITY:
          type: number
          description: Activity event count
        MODIFICATION:
          type: number
          description: Modification event count
        CREATION:
          type: number
          description: Creation event count
        DELETION:
          type: number
          description: Deletion event count
    PolicyConditionV1Dto:
      type: object
      properties:
        field:
          type: string
          description: Field the condition applies to (e.g. amount, channel, subcategory)
        operator:
          type: string
          description: Comparison operator (e.g. greater_than, equal, less_than)
        value:
          type: object
          description: Value to compare against
        value_id:
          type: string
          description: MongoDB ObjectId of the referenced value (e.g. subcategory ID)
    PolicyWorkflowAmountConditionDto:
      type: object
      properties:
        type:
          type: string
          enum:
            - under
            - between
            - over_or_equal_to
            - any_amount
        amount:
          type: number
          example: 250000
        amount_range:
          example:
            - 1
            - 250000
          type: array
          items:
            type: string
        values:
          example: []
          type: array
          items:
            type: string
      required:
        - type
    PolicyWorkflowApproverDto:
      type: object
      properties:
        employee:
          type: string
          example: 65fbf2f42a5d67f03a764111
        level:
          type: number
          example: 1
        must_approve:
          type: boolean
          example: false
        amount_approval_condition:
          $ref: '#/components/schemas/PolicyWorkflowAmountConditionDto'
        non_amount_approval_conditions:
          type: array
          items:
            type: string
      required:
        - employee
    YieldDto:
      type: object
      properties:
        value:
          type: number
          example: 8.2
          description: Yield value as a number; see unit
        unit:
          type: string
          example: percent
          enum:
            - percent
      required:
        - value
        - unit
    BillWorkflowAmountConditionDto:
      type: object
      properties:
        type:
          type: string
          enum:
            - under
            - between
            - over_or_equal_to
            - any_amount
        amount:
          type: number
          example: 250000
        amount_range:
          example:
            - 1
            - 250000
          type: array
          items:
            type: string
        values:
          example: []
          type: array
          items:
            type: string
      required:
        - type
    BillWorkflowApproverDto:
      type: object
      properties:
        employee:
          type: string
          example: 65fbf2f42a5d67f03a764111
        level:
          type: number
          example: 1
        must_approve:
          type: boolean
          example: false
        amount_approval_condition:
          $ref: '#/components/schemas/BillWorkflowAmountConditionDto'
        non_amount_approval_conditions:
          type: array
          items:
            type: string
      required:
        - employee
    ApprovalTeamDto:
      type: object
      properties:
        _id:
          type: string
          example: 64ec5b57ffaef6ff2a2845b3
        code:
          type: string
          example: '0003'
        name:
          type: string
          example: Tech
      required:
        - _id
        - code
        - name
    PaymentInstructionDto:
      type: object
      properties:
        _id:
          type: string
          example: 6808e7c3b7a3aab7e41fbe7f
        channel:
          type: string
          example: bank
        phone:
          type: string
          example: ''
        accno:
          type: string
          example: '1400284063131'
        bank:
          type: string
          example: EQUITY BANK LTD
        bank_code:
          type: string
          example: '68'
        till:
          type: string
          example: ''
        business_no:
          type: string
          example: ''
      required:
        - _id
        - channel
    TopSourceDto:
      type: object
      properties:
        id:
          type: string
          description: Source ID
          example: '1'
        name:
          type: string
          description: Source name (e.g., MPESA, BANK, CARD)
          example: MPESA
        amount:
          type: number
          description: Total amount from this source
          example: 139.26
        avatar:
          type: string
          description: Avatar/initial for the source
          example: M
      required:
        - id
        - name
        - amount
        - avatar
    MonthlyDataDto:
      type: object
      properties:
        month:
          type: string
          description: Month abbreviation (Jan, Feb, Mar, etc.)
          example: Oct
        year:
          type: number
          description: Year
          example: 2025
        amount:
          type: number
          description: Total amount for this month
          example: 120
      required:
        - month
        - year
        - amount
    TopSpendDto:
      type: object
      properties:
        id:
          type: string
          description: Vendor ID
          example: '1'
        name:
          type: string
          description: Vendor name
          example: Boya Limited
        amount:
          type: number
          description: Total amount spent with this vendor
          example: 50
        avatar:
          type: string
          description: Avatar/initial for the vendor
          example: B
      required:
        - id
        - name
        - amount
        - avatar
    MandateApproverV1Dto:
      type: object
      properties:
        employee:
          description: Employee information for the approver
          allOf:
            - $ref: '#/components/schemas/MandateEmployeeV1Dto'
        level:
          type: number
          description: Approval level/tier in the approval hierarchy
          example: 1
        _id:
          type: string
          description: Approver identifier (typically same as employee._id)
          example: 691af15e2c7cead4901adfd2
    TagGroupV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Tag group ID
        name:
          type: string
          description: Tag group name
        tags:
          description: Tag IDs in this group
          type: array
          items:
            type: string
        is_deleted:
          type: boolean
          description: Whether tag group is deleted
        __v:
          type: number
          description: Version key
    TagEmployeeV1Dto:
      type: object
      properties:
        customer_id:
          type: string
          description: Customer ID
        customer_name:
          type: string
          description: Customer name
    BudgetOwnerV1Dto:
      type: object
      properties:
        name:
          type: string
          description: Budget owner name
        approved:
          type: boolean
          description: Approval status
        employee_id:
          type: string
          description: Employee ID
    AttachmentV1Dto:
      type: object
      properties:
        url:
          type: string
          description: Attachment URL
        file_name:
          type: string
          description: File name
        content_type:
          type: string
          description: Content type
    SupplierV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Supplier ID
        phone:
          type: string
          description: Phone number
        email:
          type: string
          description: Email address
        contact_name:
          type: string
          description: Contact name
        company_name:
          type: string
          description: Company name
        address:
          type: string
          description: Address
        description:
          type: string
          description: Description
        status:
          type: string
          description: Supplier status
          enum:
            - ACTIVE
            - INACTIVE
        payment_instructions:
          description: Payment instructions
          type: array
          items:
            type: string
        taxID:
          type: string
          description: Tax ID
        read_only:
          type: boolean
          description: Read only flag
        mapping_id:
          type: string
          description: Mapping ID
        createdAt:
          type: string
          description: Created timestamp
        updatedAt:
          type: string
          description: Updated timestamp
        __v:
          type: number
          description: Version key
    PaymentV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Payment ID
        transaction_ref:
          type: string
          description: Transaction reference
        amount:
          type: number
          description: Payment amount
        send_on:
          type: string
          description: Send on date
        initiated_on:
          type: string
          description: Initiated on date
        approved:
          type: boolean
          description: Approval status
        payment_instruction:
          description: Payment instruction details
          allOf:
            - $ref: '#/components/schemas/PaymentInstructionV1Dto'
        error_message:
          type: string
          description: Error message
        status:
          type: string
          description: Payment status
          enum:
            - scheduled
            - successful
            - cancelled
            - failed
        approvers:
          description: Approvers list
          type: array
          items:
            type: string
        completed_on:
          type: string
          description: Completed on date
        external_ref:
          type: string
          description: External reference
    MandateEmployeeV1Dto:
      type: object
      properties:
        _id:
          type: string
          description: Employee MongoDB ID
          example: 691af15e2c7cead4901adfd2
        name:
          type: string
          description: Employee full name
          example: Joan Wangare
    TeamModeDataDto:
      type: object
      title: TeamModeDataDto
      additionalProperties: true
      description: Object shape not yet published by the upstream spec.
      example: {}
    CategoryModeDataDto:
      type: object
      title: CategoryModeDataDto
      additionalProperties: true
      description: Object shape not yet published by the upstream spec.
      example: {}
    SubcategoryModeDataDto:
      type: object
      title: SubcategoryModeDataDto
      additionalProperties: true
      description: Object shape not yet published by the upstream spec.
      example: {}
  securitySchemes:
    oauth2ClientCredentials:
      type: oauth2
      description: >-
        Exchange your client_id and client_secret for a short-lived (5 minute)
        bearer access token, then send it as `Authorization: Bearer <token>`.
      flows:
        clientCredentials:
          tokenUrl: https://api.boyahq.com/v2/oauth/token
          scopes:
            accounts:read: Read accounts
            accounts:write: Write accounts
            approvals:read: Read approvals (private label)
            approvals:write: Write approvals (private label)
            audit-trail:read: Read audit trail (private label)
            bills:read: Read bills
            bills:write: Write bills
            business-policies:read: Read business policies (private label)
            business-policies:write: Write business policies (private label)
            cards:read: Read cards (private label)
            cards:write: Write cards (private label)
            categories:read: Read categories
            categories:write: Write categories
            customers:read: Read customers
            customers:write: Write customers
            employees:read: Read employees
            employees:write: Write employees
            expenses:read: Read expenses
            expenses:write: Write expenses
            fx:read: Read fx
            fx:write: Write fx (private label)
            investments:read: Read investments (private label)
            investments:write: Write investments (private label)
            payments:read: Read payments (private label)
            payments:write: Write payments (private label)
            roles:read: Read roles (private label)
            roles:write: Write roles (private label)
            subscriptions:read: Read subscriptions
            subscriptions:write: Write subscriptions
            tags:read: Read tags
            taxes:read: Read taxes
            taxes:write: Write taxes
            teams:read: Read teams
            teams:write: Write teams
            transactions:read: Read transactions
            transactions:write: Write transactions
            vendors:read: Read vendors
            vendors:write: Write vendors
            wallet-policies:read: Read wallet policies (private label)
            wallet-policies:write: Write wallet policies (private label)
