openapi: 3.1.0
info:
  title: Bujeti Public API
  version: 1.2.1
  description: |
    Read & create company data for ERP integrations (QuickBooks, Odoo, Xero, Sage, Zoho).

    **Auth:** `Authorization: Bearer <32-char-key>` — Dashboard → Settings → Developers (paying plans).

    **Rules:** `code` ids only · amounts in minor units · no PAN/CVV/PIN or bank secrets · light nests (`code` + name).
    Envelope: `{ message, status, error, data }`.

    | Scope | Access |
    |-------|--------|
    | `transactions.read` | Transactions |
    | `categories.read` / `.write` | Categories |
    | `vendors.read` / `.write` | Vendors |
    | `beneficiaries.read` | Beneficiaries |
    | `assets.read` | Assets (+ txn attachment URLs) |
    | `invoices.read` / `.write` | Invoices |
    | `quotes.read` / `.write` | Quotes |
    | `budgets.read` / `.write` | Budgets (+ group) |
    | `balances.read` | Balances |
    | `cards.read` | Cards |
    | `requests.read` / `.write` | Fund requests |
    | `card-requests.read` / `.write` | Card requests |
  contact:
    name: Bujeti Support
    url: https://bujeti.com
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary

servers:
  - url: https://api.bujeti.com/v1
    description: Production
  - url: https://staging-api.bujeti.com/v1
    description: Staging

security:
  - ApiKeyAuth: []

tags:
  - name: Transactions
    description: Payments & expenses
  - name: Categories
    description: Expense categories
  - name: Vendors
    description: Suppliers / payees
  - name: Beneficiaries
    description: Employee payees
  - name: Assets
    description: Attachments (signed URLs)
  - name: Invoices
    description: Customer invoices
  - name: Quotes
    description: Quotes / estimates
  - name: Budgets
    description: Spend budgets
  - name: Balances
    description: Company balances
  - name: Cards
    description: Cards (last_4 only)
  - name: Requests
    description: Fund requests
  - name: Card Requests
    description: Card issuance requests

paths:
  /transactions:
    get:
      operationId: listTransactions
      summary: List transactions
      tags: [Transactions]
      security:
        - ApiKeyAuth: [transactions.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            oneOf:
              - type: string
              - type: array
                items:
                  type: string
        - name: category
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^ctg_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^ctg_.{17}$"
        - name: vendor
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^vdr_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^vdr_.{17}$"
        - name: payer
          in: query
          schema:
            type: array
            items:
              type: string
              pattern: "^usr_.{17}$"
        - name: budget
          in: query
          schema:
            type: array
            items:
              type: string
              pattern: "^bdg_.{17}$"
        - name: card
          in: query
          schema:
            type: array
            items:
              type: string
              pattern: "^crd_.{17}$"
        - name: currency
          in: query
          schema:
            type: array
            items:
              type: string
              enum: [NGN, USD]
        - name: min_amount
          in: query
          schema:
            type: number
        - name: max_amount
          in: query
          schema:
            type: number
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
        - name: search
          in: query
          schema:
            type: string
        - name: team
          in: query
          schema:
            type: string
            pattern: "^tms_.{17}$"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          transactions:
                            type: array
                            items:
                              $ref: "#/components/schemas/Transaction"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /transactions/{code}:
    get:
      operationId: getTransaction
      summary: Get a transaction
      tags: [Transactions]
      security:
        - ApiKeyAuth: [transactions.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^trx_.{17}$"
          example: trx_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/Transaction"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /transactions/{code}/assets:
    get:
      operationId: listTransactionAssets
      summary: List transaction assets
      tags: [Transactions]
      security:
        - ApiKeyAuth: [assets.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^trx_[a-zA-Z0-9]{17}$"
          example: trx_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          assets:
                            type: array
                            items:
                              $ref: "#/components/schemas/Asset"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /categories:
    get:
      operationId: listCategories
      summary: List categories
      tags: [Categories]
      security:
        - ApiKeyAuth: [categories.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            type: string
        - name: parent
          in: query
          schema:
            type: string
            pattern: "^ctg_.{17}$"
        - name: search
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          categories:
                            type: array
                            items:
                              $ref: "#/components/schemas/Category"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

    post:
      operationId: createCategory
      summary: Create a category
      tags: [Categories]
      security:
        - ApiKeyAuth: [categories.write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateCategory"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          category:
                            $ref: "#/components/schemas/Category"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /categories/{code}:
    get:
      operationId: getCategory
      summary: Get a category
      tags: [Categories]
      security:
        - ApiKeyAuth: [categories.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^ctg_.{17}$"
          example: ctg_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          category:
                            $ref: "#/components/schemas/Category"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /vendors:
    get:
      operationId: listVendors
      summary: List vendors
      tags: [Vendors]
      security:
        - ApiKeyAuth: [vendors.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            type: string
        - name: name
          in: query
          schema:
            type: string
        - name: search
          in: query
          schema:
            type: string
        - name: currency
          in: query
          schema:
            type: string
        - name: categories
          in: query
          schema:
            type: array
            items:
              type: string
              pattern: "^ctg_.{17}$"
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          vendors:
                            type: array
                            items:
                              $ref: "#/components/schemas/Vendor"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

    post:
      operationId: createVendor
      summary: Create a vendor
      tags: [Vendors]
      security:
        - ApiKeyAuth: [vendors.write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateVendor"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          vendor:
                            $ref: "#/components/schemas/Vendor"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /beneficiaries:
    get:
      operationId: listBeneficiaries
      summary: List beneficiaries
      tags: [Beneficiaries]
      security:
        - ApiKeyAuth: [beneficiaries.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: search
          in: query
          schema:
            type: string
        - name: status
          in: query
          schema:
            type: array
            items:
              type: string
        - name: role
          in: query
          schema:
            type: array
            items:
              type: string
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          beneficiaries:
                            type: array
                            items:
                              $ref: "#/components/schemas/Beneficiary"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /assets:
    get:
      operationId: listAssets
      summary: Get assets by codes
      tags: [Assets]
      security:
        - ApiKeyAuth: [assets.read]
      parameters:
        - name: codes
          in: query
          required: true
          style: form
          explode: true
          schema:
            type: array
            items:
              type: string
              pattern: "^ast_[a-zA-Z0-9]{17}$"
            minItems: 1
            maxItems: 50
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          assets:
                            type: array
                            items:
                              $ref: "#/components/schemas/Asset"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /assets/{code}:
    get:
      operationId: getAsset
      summary: Get asset
      tags: [Assets]
      security:
        - ApiKeyAuth: [assets.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^ast_[a-zA-Z0-9]{17}$"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          asset:
                            $ref: "#/components/schemas/Asset"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /invoices:
    get:
      operationId: listInvoices
      summary: List invoices
      tags: [Invoices]
      security:
        - ApiKeyAuth: [invoices.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            oneOf:
              - type: string
              - type: array
                items:
                  type: string
        - name: currency
          in: query
          schema:
            type: array
            items:
              type: string
        - name: customer
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^cus_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^cus_.{17}$"
        - name: budget
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^bdg_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^bdg_.{17}$"
        - name: search
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          invoices:
                            type: array
                            items:
                              $ref: "#/components/schemas/Invoice"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

    post:
      operationId: createInvoice
      summary: Create an invoice
      tags: [Invoices]
      security:
        - ApiKeyAuth: [invoices.write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateInvoice"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          invoice:
                            $ref: "#/components/schemas/Invoice"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /invoices/{code}:
    get:
      operationId: getInvoice
      summary: Get an invoice
      tags: [Invoices]
      security:
        - ApiKeyAuth: [invoices.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^inv_.{17}$"
          example: inv_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          invoice:
                            $ref: "#/components/schemas/Invoice"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /quotes:
    get:
      operationId: listQuotes
      summary: List quotes
      tags: [Quotes]
      security:
        - ApiKeyAuth: [quotes.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            oneOf:
              - type: string
              - type: array
                items:
                  type: string
        - name: currency
          in: query
          schema:
            type: array
            items:
              type: string
        - name: customer
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^cus_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^cus_.{17}$"
        - name: budget
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^bdg_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^bdg_.{17}$"
        - name: search
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          quotes:
                            type: array
                            items:
                              $ref: "#/components/schemas/Quote"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

    post:
      operationId: createQuote
      summary: Create a quote
      tags: [Quotes]
      security:
        - ApiKeyAuth: [quotes.write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateQuote"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          quote:
                            $ref: "#/components/schemas/Quote"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /quotes/{code}:
    get:
      operationId: getQuote
      summary: Get a quote
      tags: [Quotes]
      security:
        - ApiKeyAuth: [quotes.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^qte_.{17}$"
          example: qte_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          quote:
                            $ref: "#/components/schemas/Quote"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /budgets:
    get:
      operationId: listBudgets
      summary: List budgets
      tags: [Budgets]
      security:
        - ApiKeyAuth: [budgets.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            oneOf:
              - type: string
              - type: array
                items:
                  type: string
        - name: currency
          in: query
          schema:
            type: array
            items:
              type: string
        - name: parent
          in: query
          schema:
            type: string
            pattern: "^bdg_.{17}$"
        - name: search
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          budgets:
                            type: array
                            items:
                              $ref: "#/components/schemas/Budget"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

    post:
      operationId: createBudget
      summary: Create a budget
      tags: [Budgets]
      security:
        - ApiKeyAuth: [budgets.write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateBudget"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          budget:
                            $ref: "#/components/schemas/Budget"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /budgets/group:
    post:
      operationId: createBudgetGroup
      summary: Create budget group
      tags: [Budgets]
      security:
        - ApiKeyAuth: [budgets.write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateBudgetGroup"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          budget:
                            allOf:
                              - $ref: "#/components/schemas/Budget"
                              - type: object
                                properties:
                                  subBudgets:
                                    type: array
                                    items:
                                      $ref: "#/components/schemas/Budget"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /budgets/{code}:
    get:
      operationId: getBudget
      summary: Get a budget
      tags: [Budgets]
      security:
        - ApiKeyAuth: [budgets.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^bdg_.{17}$"
          example: bdg_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          budget:
                            $ref: "#/components/schemas/Budget"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /balances:
    get:
      operationId: listBalances
      summary: List balances
      tags: [Balances]
      security:
        - ApiKeyAuth: [balances.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            oneOf:
              - type: string
              - type: array
                items:
                  type: string
        - name: currency
          in: query
          schema:
            type: array
            items:
              type: string
        - name: purpose
          in: query
          schema:
            type: string
        - name: search
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          balances:
                            type: array
                            items:
                              $ref: "#/components/schemas/Balance"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /balances/{code}:
    get:
      operationId: getBalance
      summary: Get a balance
      tags: [Balances]
      security:
        - ApiKeyAuth: [balances.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^blc_.{17}$"
          example: blc_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          balance:
                            $ref: "#/components/schemas/Balance"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /cards:
    get:
      operationId: listCards
      summary: List cards
      tags: [Cards]
      security:
        - ApiKeyAuth: [cards.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            oneOf:
              - type: string
              - type: array
                items:
                  type: string
        - name: currency
          in: query
          schema:
            type: array
            items:
              type: string
        - name: type
          in: query
          schema:
            type: string
            enum: [virtual, physical, flash]
        - name: user
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^usr_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^usr_.{17}$"
        - name: budget
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^bdg_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^bdg_.{17}$"
        - name: balance
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^blc_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^blc_.{17}$"
        - name: search
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          cards:
                            type: array
                            items:
                              $ref: "#/components/schemas/Card"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /cards/{code}:
    get:
      operationId: getCard
      summary: Get a card
      tags: [Cards]
      security:
        - ApiKeyAuth: [cards.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^crd_.{17}$"
          example: crd_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          card:
                            $ref: "#/components/schemas/Card"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /requests:
    get:
      operationId: listRequests
      summary: List fund requests
      tags: [Requests]
      security:
        - ApiKeyAuth: [requests.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            oneOf:
              - type: string
              - type: array
                items:
                  type: string
        - name: currency
          in: query
          schema:
            type: array
            items:
              type: string
        - name: type
          in: query
          schema:
            type: string
            enum: [budget, payment, top_up, telecom]
        - name: user
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^usr_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^usr_.{17}$"
        - name: vendor
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^vdr_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^vdr_.{17}$"
        - name: budget
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^bdg_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^bdg_.{17}$"
        - name: category
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^ctg_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^ctg_.{17}$"
        - name: search
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          requests:
                            type: array
                            items:
                              $ref: "#/components/schemas/FundRequest"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"
    post:
      operationId: createRequest
      summary: Create a fund request
      tags: [Requests]
      security:
        - ApiKeyAuth: [requests.write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateFundRequest"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          request:
                            $ref: "#/components/schemas/FundRequest"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /requests/{code}:
    get:
      operationId: getRequest
      summary: Get a fund request
      tags: [Requests]
      security:
        - ApiKeyAuth: [requests.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^frq_.{17}$"
          example: frq_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          request:
                            $ref: "#/components/schemas/FundRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

  /card-requests:
    get:
      operationId: listCardRequests
      summary: List card requests
      tags: [Card Requests]
      security:
        - ApiKeyAuth: [card-requests.read]
      parameters:
        - $ref: "#/components/parameters/Page"
        - $ref: "#/components/parameters/PerPage"
        - name: status
          in: query
          schema:
            oneOf:
              - type: string
              - type: array
                items:
                  type: string
        - name: owner
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^usr_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^usr_.{17}$"
        - name: budget
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^bdg_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^bdg_.{17}$"
        - name: balance
          in: query
          schema:
            oneOf:
              - type: string
                pattern: "^blc_.{17}$"
              - type: array
                items:
                  type: string
                  pattern: "^blc_.{17}$"
        - name: search
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          cardRequests:
                            type: array
                            items:
                              $ref: "#/components/schemas/CardRequest"
                          meta:
                            $ref: "#/components/schemas/PaginationMeta"
        "401":
          $ref: "#/components/responses/Unauthorized"
    post:
      operationId: createCardRequest
      summary: Create a card request
      tags: [Card Requests]
      security:
        - ApiKeyAuth: [card-requests.write]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateCardRequest"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          cardRequest:
                            $ref: "#/components/schemas/CardRequest"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorEnvelope"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /card-requests/{code}:
    get:
      operationId: getCardRequest
      summary: Get a card request
      tags: [Card Requests]
      security:
        - ApiKeyAuth: [card-requests.read]
      parameters:
        - name: code
          in: path
          required: true
          schema:
            type: string
            pattern: "^car_.{17}$"
          example: car_a1B2c3D4e5F6g7H8i
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/SuccessEnvelope"
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          cardRequest:
                            $ref: "#/components/schemas/CardRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"

components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: 32-char API key. Paying customers only.

  parameters:
    Page:
      name: page
      in: query
      schema:
        type: integer
        minimum: 1
        default: 1
    PerPage:
      name: perPage
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 1000
        default: 50

  responses:
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"
    NotFound:
      description: Not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorEnvelope"

  schemas:
    SuccessEnvelope:
      type: object
      required: [message, status, error]
      properties:
        message:
          type: string
        status:
          type: boolean
          example: true
        error:
          type: boolean
          example: false

    ErrorEnvelope:
      type: object
      required: [message, status, error]
      properties:
        message:
          type: string
        status:
          type: boolean
          example: false
        error:
          type: boolean
          example: true

    PaginationMeta:
      type: object
      properties:
        page:
          type: integer
        perPage:
          type: integer
        total:
          type: integer
        hasMore:
          type: boolean
        nextPage:
          type: ["integer", "null"]

    User:
      type: object
      properties:
        code:
          type: string
          pattern: "^usr_.{17}$"
        firstName:
          type: string
        lastName:
          type: string
        middleName:
          type: ["string", "null"]
        email:
          type: string
          format: email
        name:
          type: string
          description: Display name
        status:
          type: string
        role:
          type: ["string", "null"]

    Category:
      type: object
      description: Expense category
      properties:
        code:
          type: string
          pattern: "^ctg_.{17}$"
        name:
          type: string
        description:
          type: ["string", "null"]
        slug:
          type: ["string", "null"]
        status:
          type: string
        isSubCategory:
          type: boolean
        parent:
          oneOf:
            - $ref: "#/components/schemas/Category"
            - type: "null"
        children:
          type: array
          items:
            $ref: "#/components/schemas/Category"

    Vendor:
      type: object
      description: Supplier / payee
      properties:
        code:
          type: string
          pattern: "^vdr_.{17}$"
        name:
          type: string
        email:
          type: ["string", "null"]
          format: email
        description:
          type: ["string", "null"]
        type:
          oneOf:
            - type: string
              enum: [business, individual]
            - type: "null"
        status:
          type: string
        categories:
          type: array
          items:
            $ref: "#/components/schemas/Category"

    Beneficiary:
      type: object
      properties:
        code:
          type: string
          pattern: "^bnf_.{17}$"
        status:
          type: string
        user:
          $ref: "#/components/schemas/User"

    Transaction:
      type: object
      description: Payment or expense
      properties:
        code:
          type: string
          pattern: "^trx_.{17}$"
        amount:
          type: integer
          description: Minor units
        currency:
          type: string
        narration:
          type: ["string", "null"]
        description:
          type: ["string", "null"]
        status:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        category:
          oneOf:
            - $ref: "#/components/schemas/Category"
            - type: "null"
        recipient:
          oneOf:
            - $ref: "#/components/schemas/Vendor"
            - $ref: "#/components/schemas/User"
            - type: "null"
        payer:
          oneOf:
            - $ref: "#/components/schemas/User"
            - type: "null"
        initiator:
          oneOf:
            - $ref: "#/components/schemas/User"
            - type: "null"
        integrationSync:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/IntegrationSyncState"
          description: Sync state
        fee:
          type: ["number", "null"]
        assets:
          type: array
          items:
            $ref: "#/components/schemas/Asset"
          description: Present if key has `assets.read`

    Asset:
      type: object
      description: Attachment (signed URL)
      properties:
        code:
          type: string
          pattern: "^ast_[a-zA-Z0-9]{17}$"
          example: ast_AbCdEf01234567890
        name:
          type: ["string", "null"]
          description: Filename
        created_at:
          type: string
          format: date-time
        url:
          type: string
          format: uri
          description: Short-lived signed URL (do not cache)

    IntegrationSyncState:
      type: object
      properties:
        platform:
          type: string
          example: odoo
        entity:
          type: string
        syncStatus:
          type: ["string", "null"]
        externalIdentifier:
          type: ["string", "null"]
          description: External ID
        lastSyncAt:
          type: ["string", "null"]
          format: date-time
        lastError:
          type: ["string", "null"]

    CodeRef:
      type: object
      description: code + name
      properties:
        code:
          type: string
        name:
          type: string

    Customer:
      type: object
      properties:
        code:
          type: string
          pattern: "^cus_.{17}$"
        name:
          type: string
        email:
          type: ["string", "null"]
          format: email
        type:
          type: ["string", "null"]
        status:
          type: string

    Invoice:
      type: object
      description: Customer invoice
      properties:
        code:
          type: string
          pattern: "^inv_.{17}$"
        invoiceId:
          type: ["string", "null"]
        title:
          type: ["string", "null"]
        description:
          type: ["string", "null"]
        amount:
          type: integer
          description: Minor units
        currency:
          type: string
        status:
          type: string
        due_date:
          type: ["string", "null"]
          format: date-time
        paidOn:
          type: ["string", "null"]
          format: date-time
        sent_at:
          type: ["string", "null"]
          format: date-time
        vat:
          type: ["number", "null"]
        vatAmount:
          type: ["integer", "null"]
        discount:
          type: ["integer", "null"]
        discount_type:
          type: ["string", "null"]
        customer:
          oneOf:
            - $ref: "#/components/schemas/Customer"
            - type: "null"
        budget:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    Quote:
      type: object
      description: Quote
      properties:
        code:
          type: string
          pattern: "^qte_.{17}$"
        quoteId:
          type: ["string", "null"]
        title:
          type: ["string", "null"]
        description:
          type: ["string", "null"]
        amount:
          type: integer
          description: Minor units
        currency:
          type: string
        status:
          type: string
        revision:
          type: integer
        notes:
          type: ["string", "null"]
        vat:
          type: ["number", "null"]
        vatAmount:
          type: ["integer", "null"]
        discount:
          type: ["integer", "null"]
        discount_type:
          type: ["string", "null"]
        customer:
          oneOf:
            - $ref: "#/components/schemas/Customer"
            - type: "null"
        budget:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    Budget:
      type: object
      description: Spend budget
      properties:
        code:
          type: string
          pattern: "^bdg_.{17}$"
        name:
          type: string
        currency:
          type: string
        amount:
          type: integer
          description: Minor units
        available:
          type: integer
        spent:
          type: integer
        status:
          type: string
        type:
          type: ["string", "integer", "null"]
        level:
          type: integer
          description: "1 root · 2 sub · 3 period"
        isFunded:
          type: boolean
        allowOverdraft:
          type: boolean
        rolloverFunds:
          type: boolean
        parent:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        balance:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    Balance:
      type: object
      description: Company balance
      properties:
        code:
          type: string
          pattern: "^blc_.{17}$"
        name:
          type: string
        amount:
          type: integer
          description: Minor units
        currency:
          type: string
        purpose:
          type: string
        type:
          type: string
          description: linked | direct-debit | internal
        status:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    Card:
      type: object
      description: Card (last_4 only)
      properties:
        code:
          type: string
          pattern: "^crd_.{17}$"
        name:
          type: string
        brand:
          type: ["string", "null"]
        last_4:
          type: ["string", "null"]
        currency:
          type: string
        type:
          type: string
          enum: [virtual, physical, flash]
        status:
          type: string
        amount:
          type: integer
        spent:
          type: integer
        available:
          type: integer
        atmWithdrawals:
          type: boolean
        posTransaction:
          type: boolean
        onlineTransaction:
          type: boolean
        contactlessTransaction:
          type: boolean
        user:
          oneOf:
            - $ref: "#/components/schemas/User"
            - type: "null"
        budget:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        balance:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    FundRequest:
      type: object
      description: Fund request
      properties:
        code:
          type: string
          pattern: "^frq_.{17}$"
        amount:
          type: integer
          description: Minor units
        currency:
          type: string
        description:
          type: ["string", "null"]
        note:
          type: ["string", "null"]
        type:
          type: string
          enum: [budget, payment, top_up, telecom]
        status:
          type: string
        channel:
          type: ["string", "null"]
        platform:
          type: ["string", "null"]
        user:
          oneOf:
            - $ref: "#/components/schemas/User"
            - type: "null"
        vendor:
          oneOf:
            - $ref: "#/components/schemas/Vendor"
            - type: "null"
        budget:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        sourceBudget:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        balance:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        card:
          oneOf:
            - type: object
              properties:
                code:
                  type: string
                  pattern: "^crd_.{17}$"
                name:
                  type: string
                last_4:
                  type: ["string", "null"]
            - type: "null"
        category:
          oneOf:
            - $ref: "#/components/schemas/Category"
            - type: "null"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    CreateFundRequest:
      type: object
      required: [amount, currency, description]
      properties:
        amount:
          type: integer
          description: Minor units
        currency:
          type: string
          example: NGN
        description:
          type: string
        note:
          type: string
        type:
          type: string
          enum: [budget, payment, top_up, telecom]
        vendor:
          type: string
          pattern: "^vdr_.{17}$"
        budget:
          type: string
          pattern: "^bdg_.{17}$"
        sourceBudget:
          type: string
          pattern: "^bdg_.{17}$"
        balance:
          type: string
          pattern: "^blc_.{17}$"
        card:
          type: string
          pattern: "^crd_.{17}$"
        category:
          type: string
          pattern: "^ctg_.{17}$"

    CardRequest:
      type: object
      description: Card request
      properties:
        code:
          type: string
          pattern: "^car_.{17}$"
        status:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        owner:
          oneOf:
            - $ref: "#/components/schemas/User"
            - type: "null"
        requestedBy:
          oneOf:
            - $ref: "#/components/schemas/User"
            - type: "null"
        budget:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        balance:
          oneOf:
            - $ref: "#/components/schemas/CodeRef"
            - type: "null"
        atmWithdrawals:
          type: boolean
        posTransaction:
          type: boolean
        onlineTransaction:
          type: boolean
        contactlessTransaction:
          type: boolean
        city:
          type: ["string", "null"]
        state:
          type: ["string", "null"]
        postalCode:
          type: ["string", "null"]
        country:
          type: ["string", "null"]
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    CreateCardRequest:
      type: object
      required: [firstName, lastName]
      properties:
        firstName:
          type: string
        lastName:
          type: string
        owner:
          type: string
          pattern: "^usr_.{17}$"
        budget:
          type: string
          pattern: "^bdg_.{17}$"
        balance:
          type: string
          pattern: "^blc_.{17}$"
        atmWithdrawals:
          type: boolean
          default: true
        posTransaction:
          type: boolean
          default: true
        onlineTransaction:
          type: boolean
          default: true
        contactlessTransaction:
          type: boolean
          default: true
        city:
          type: string
        state:
          type: string
        postalCode:
          type: string
        country:
          type: string
          description: ISO country

    LineItem:
      type: object
      required: [name, quantity, unitPrice]
      properties:
        name:
          type: string
        quantity:
          type: number
          minimum: 1
        unitPrice:
          type: integer
          description: Minor units
        currency:
          type: string
        description:
          type: ["string", "null"]
        discount:
          type: ["number", "null"]
        discount_type:
          type: ["string", "null"]
          enum: [amount, percentage]

    InlineCustomer:
      type: object
      description: Inline customer
      properties:
        name:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        email:
          type: string
          format: email
        type:
          type: string
          enum: [business, individual]

    CreateCategory:
      type: object
      required: [name]
      properties:
        name:
          type: string
        slug:
          type: string
        description:
          type: string
        parent:
          type: string
          pattern: "^ctg_.{17}$"

    CreateVendor:
      type: object
      required: [name]
      properties:
        name:
          type: string
        email:
          type: string
          format: email
        description:
          type: string
        type:
          type: string
          enum: [business, individual]
        categories:
          type: array
          items:
            type: string
            pattern: "^ctg_.{17}$"

    CreateInvoice:
      type: object
      required: [customer, products]
      properties:
        customer:
          oneOf:
            - type: string
              pattern: "^cus_.{17}$"
            - $ref: "#/components/schemas/InlineCustomer"
        title:
          type: string
          maxLength: 100
        description:
          type: ["string", "null"]
          maxLength: 100
        currency:
          type: string
        terms:
          oneOf:
            - type: integer
            - type: string
              enum: [30days, 60days, 90days, 90_plus_days, installments, 3_plus_installments]
            - type: "null"
        due_date:
          type: string
          format: date-time
        products:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/LineItem"
        vat:
          type: ["number", "null"]
        discount:
          type: ["number", "null"]
        discount_type:
          type: ["string", "null"]
          enum: [amount, percentage]
        budget:
          type: string
          pattern: "^bdg_.{17}$"
        isDraft:
          type: boolean
          default: false
        invoiceId:
          type: string
          maxLength: 100

    CreateQuote:
      type: object
      required: [customer, products]
      properties:
        customer:
          oneOf:
            - type: string
              pattern: "^cus_.{17}$"
            - $ref: "#/components/schemas/InlineCustomer"
        title:
          type: ["string", "null"]
          maxLength: 100
        description:
          type: ["string", "null"]
        currency:
          type: string
          default: NGN
        terms:
          oneOf:
            - type: integer
            - type: string
              enum: [30days, 60days, 90days, 90_plus_days]
            - type: "null"
        expiryDate:
          type: ["string", "null"]
          format: date-time
        products:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/LineItem"
        vat:
          type: ["number", "null"]
        discount:
          type: ["number", "null"]
        discount_type:
          type: ["string", "null"]
          enum: [amount, percentage]
        notes:
          type: ["string", "null"]
        budget:
          type: string
          pattern: "^bdg_.{17}$"
        isDraft:
          type: boolean
          default: true

    CreateBudget:
      type: object
      required: [name, amount, currency, type]
      properties:
        name:
          type: string
          minLength: 3
        amount:
          type: integer
          description: Minor units
          minimum: 0
        currency:
          type: string
          minLength: 3
          maxLength: 3
        type:
          type: integer
          minimum: 1
        parent:
          type: ["string", "null"]
          pattern: "^bdg_.{17}$"
        balance:
          type: string
          pattern: "^blc_.{17}$"
        isFunded:
          type: boolean
        allowOverdraft:
          type: boolean
        rolloverFunds:
          type: boolean
          default: false
        budgetCategory:
          type: string
          enum: [expenses, revenues, mixed]
          default: expenses
        frequency:
          type: string
          enum: [weekly, bi-weekly, monthly, quarterly, yearly, on-time]
        startDate:
          type: string
          format: date-time
        endDate:
          type: string
          format: date-time

    CreateBudgetSubBudget:
      allOf:
        - $ref: "#/components/schemas/CreateBudget"
      description: Sub-budget

    CreateBudgetGroup:
      allOf:
        - $ref: "#/components/schemas/CreateBudget"
        - type: object
          required: [subBudgets]
          properties:
            subBudgets:
              type: array
              minItems: 1
              items:
                $ref: "#/components/schemas/CreateBudgetSubBudget"
