openapi: 3.0.3
info:
  title: mibudge API
  version: 1.0.0
  description: |-
    REST API for the mibudge personal budgeting service.

    ## Authentication

    All endpoints require JWT authentication via `Authorization: Bearer <token>` header. Obtain tokens through the login flow; refresh via `POST /api/token/refresh/` (httpOnly cookie).

    ## Permissions

    - **Banks**: read-only, any authenticated user.
    - **Users**: list/retrieve/update restricted to staff; `/api/v1/users/me/` available to all authenticated users.
    - **All other resources** (bank accounts, budgets, transactions, allocations, internal transactions): scoped to bank account ownership. Only users in an account's `owners` M2M can access that account and its related objects. Staff and superuser status does not bypass ownership checks.

    ## Money fields

    Monetary values are represented as a decimal amount paired with an ISO 4217 currency code (e.g. `amount` + `amount_currency`). Currency defaults to the account's currency if not specified.
paths:
  /api/token/:
    post:
      operationId: api_token_create
      description: |-
        JWT obtain endpoint that stores the refresh token in an httpOnly
        cookie and returns only the access token in the response body.

        This is the browser-SPA login flow: JS receives the short-lived
        access token (kept in memory); the refresh token is a
        Secure/HttpOnly/SameSite=Strict cookie that JS cannot read,
        and that the browser sends automatically to /api/token/refresh/.
      tags:
      - api
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenObtainPairRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TokenObtainPairRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TokenObtainPairRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenObtainPair'
          description: ''
  /api/token/refresh/:
    post:
      operationId: api_token_refresh_create
      description: |-
        JWT refresh endpoint that reads the refresh token from the httpOnly
        cookie rather than the request body.

        On success, returns {"access": "<new_access_token>"} in JSON.
        When token rotation is enabled, also rotates the refresh cookie so
        the 14-day sliding window resets with each use.
      tags:
      - api
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRefreshRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TokenRefreshRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TokenRefreshRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenRefresh'
          description: ''
  /api/v1/allocations/:
    get:
      operationId: allocations_list
      description: Return allocations belonging to the authenticated user's transactions.
        Filterable by transaction, budget, and category. Orderable by created_at.
      summary: List transaction allocations
      parameters:
      - in: query
        name: bank_account
        schema:
          type: string
          format: uuid
      - in: query
        name: budget
        schema:
          type: string
          format: uuid
      - in: query
        name: category
        schema:
          type: string
      - name: ordering
        required: false
        in: query
        description: Which field to use when ordering the results.
        schema:
          type: string
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      - in: query
        name: transaction
        schema:
          type: string
          format: uuid
      tags:
      - allocations
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTransactionAllocationList'
          description: ''
  /api/v1/allocations/{id}/:
    get:
      operationId: allocations_retrieve
      description: Return a single transaction allocation by UUID.
      summary: Get allocation details
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - allocations
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionAllocation'
          description: ''
  /api/v1/bank-accounts/:
    get:
      operationId: bank_accounts_list
      description: Return bank accounts owned by the authenticated user. Filterable
        by account_type. Orderable by name or created_at.
      summary: List bank accounts
      parameters:
      - in: query
        name: account_type
        schema:
          type: string
          enum:
          - C
          - S
          - X
        description: |-
          * `C` - Checking
          * `S` - Savings
          * `X` - Credit Card
      - name: ordering
        required: false
        in: query
        description: Which field to use when ordering the results.
        schema:
          type: string
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      tags:
      - bank-accounts
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedBankAccountList'
          description: ''
    post:
      operationId: bank_accounts_create
      description: Create a new bank account. The authenticated user is automatically
        added as an owner. An 'Unallocated' budget is auto-created by a post_save
        signal. Optionally set initial posted_balance, available_balance, and currency
        (all immutable after creation).
      summary: Create a bank account
      tags:
      - bank-accounts
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BankAccountRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/BankAccountRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/BankAccountRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BankAccount'
          description: ''
  /api/v1/bank-accounts/{id}/:
    get:
      operationId: bank_accounts_retrieve
      description: Return a single bank account by UUID.
      summary: Get bank account details
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - bank-accounts
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BankAccount'
          description: ''
    put:
      operationId: bank_accounts_update
      description: Full update of a bank account. Only 'name' is mutable after creation
        -- bank, account_type, currency, and balances are rejected if changed.
      summary: Update a bank account
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - bank-accounts
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BankAccountRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/BankAccountRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/BankAccountRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BankAccount'
          description: ''
    patch:
      operationId: bank_accounts_partial_update
      description: Partial update of a bank account. Only 'name' is mutable after
        creation.
      summary: Partially update a bank account
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - bank-accounts
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedBankAccountRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedBankAccountRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedBankAccountRequest'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BankAccount'
          description: ''
    delete:
      operationId: bank_accounts_destroy
      description: Delete a bank account and all associated budgets, transactions,
        and allocations.
      summary: Delete a bank account
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - bank-accounts
      security:
      - jwtAuth: []
      responses:
        '204':
          description: No response body
  /api/v1/bank-accounts/{id}/funding-summary/:
    get:
      operationId: bank_accounts_funding_summary_retrieve
      description: Return the total amounts that will be automatically funded at the
        next event for each distinct funding schedule on this account.  Only active,
        schedulable budgets are included -- paused, archived, completed goals, and
        RECURRING budgets that delegate to a fill-up goal are excluded.  Results are
        grouped by funding schedule (RRULE string) and sorted by next event date.
      summary: Funding summary
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - bank-accounts
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                properties:
                  schedules:
                    type: array
                    items:
                      type: object
                      properties:
                        schedule:
                          type: string
                        next_date:
                          type: string
                          format: date
                        total_amount:
                          type: string
                        currency:
                          type: string
                        budget_count:
                          type: integer
                  total_amount:
                    type: string
                  currency:
                    type: string
          description: Per-schedule funding totals.
  /api/v1/bank-accounts/{id}/mark-imported/:
    post:
      operationId: bank_accounts_mark_imported_create
      description: 'Record that a transaction import has been completed for this account.  Sets
        last_imported_at to now and advances last_posted_through to the supplied date
        (never regresses an existing value).  Body: {"last_posted_through": "YYYY-MM-DD"}.'
      summary: Mark import complete
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - bank-accounts
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                last_posted_through:
                  type: string
                  format: date
              required:
              - last_posted_through
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BankAccount'
          description: ''
  /api/v1/banks/:
    get:
      operationId: banks_list
      description: Return all banks in the system. Banks are shared reference data
        managed through the admin -- any authenticated user can list and retrieve
        them.
      summary: List banks
      parameters:
      - name: ordering
        required: false
        in: query
        description: Which field to use when ordering the results.
        schema:
          type: string
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      tags:
      - banks
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedBankList'
          description: ''
  /api/v1/banks/{id}/:
    get:
      operationId: banks_retrieve
      description: Return a single bank by UUID.
      summary: Get bank details
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - banks
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Bank'
          description: ''
  /api/v1/budgets/:
    get:
      operationId: budgets_list
      description: Return budgets belonging to the authenticated user's accounts.
        Filterable by bank_account, budget_type, archived, and paused. Searchable
        by name. Orderable by name, created_at, or balance.
      summary: List budgets
      parameters:
      - in: query
        name: archived
        schema:
          type: boolean
      - in: query
        name: bank_account
        schema:
          type: string
          format: uuid
      - in: query
        name: budget_type
        schema:
          type: string
          enum:
          - A
          - C
          - G
          - R
        description: |-
          * `G` - Goal
          * `R` - Recurring
          * `A` - Associated Fill-up Goal
          * `C` - Capped
      - name: ordering
        required: false
        in: query
        description: Which field to use when ordering the results.
        schema:
          type: string
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      - in: query
        name: paused
        schema:
          type: boolean
      - name: search
        required: false
        in: query
        description: A search term.
        schema:
          type: string
      tags:
      - budgets
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedBudgetList'
          description: ''
    post:
      operationId: budgets_create
      description: 'Create a new budget under a bank account. Required: name, bank_account
        (UUID), budget_type, funding_type, and target_balance. The bank_account and
        budget_type are immutable after creation. Balance is managed by signals and
        is always read-only.'
      summary: Create a budget
      tags:
      - budgets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BudgetRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/BudgetRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/BudgetRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Budget'
          description: ''
  /api/v1/budgets/{id}/:
    get:
      operationId: budgets_retrieve
      description: Return a single budget by UUID.
      summary: Get budget details
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - budgets
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Budget'
          description: ''
    put:
      operationId: budgets_update
      description: Full update of a budget. bank_account and budget_type are immutable.
        The unallocated budget cannot be renamed.
      summary: Update a budget
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - budgets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BudgetRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/BudgetRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/BudgetRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Budget'
          description: ''
    patch:
      operationId: budgets_partial_update
      description: Partial update of a budget. bank_account and budget_type are immutable.
        The unallocated budget cannot be renamed.
      summary: Partially update a budget
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - budgets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedBudgetRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedBudgetRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedBudgetRequest'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Budget'
          description: ''
    delete:
      operationId: budgets_destroy
      description: Delete a budget. The unallocated budget cannot be deleted (403).
        A budget with existing transaction allocations cannot be deleted (400) --
        archive it instead.
      summary: Delete a budget
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - budgets
      security:
      - jwtAuth: []
      responses:
        '204':
          description: No response body
  /api/v1/budgets/{id}/archive/:
    post:
      operationId: budgets_archive_create
      description: Archive a budget. Any remaining balance is transferred to the account's
        unallocated budget. If the budget has an associated fill-up goal, that budget
        is also archived and its balance moved to unallocated. The unallocated budget
        cannot be archived.
      summary: Archive a budget
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - budgets
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BudgetRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/BudgetRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/BudgetRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Budget'
          description: ''
  /api/v1/currencies/:
    get:
      operationId: currencies_retrieve
      description: Return all ISO 4217 currency codes supported by the system, sorted
        by code. Each entry includes the code, English name, and numeric ISO 4217
        code. Requires authentication.
      summary: List supported currencies
      tags:
      - currencies
      security:
      - jwtAuth: []
      responses:
        '200':
          description: List of supported currencies.
  /api/v1/internal-transactions/:
    get:
      operationId: internal_transactions_list
      description: Return budget-to-budget transfers belonging to the authenticated
        user's accounts. Filterable by bank_account, src_budget, dst_budget, and date
        range (date_from/date_to). Orderable by created_at.
      summary: List internal transactions
      parameters:
      - in: query
        name: bank_account
        schema:
          type: string
          format: uuid
      - in: query
        name: budget
        schema:
          type: string
          format: uuid
      - in: query
        name: date_from
        schema:
          type: string
          format: date-time
      - in: query
        name: date_to
        schema:
          type: string
          format: date-time
      - in: query
        name: dst_budget
        schema:
          type: string
          format: uuid
      - name: ordering
        required: false
        in: query
        description: Which field to use when ordering the results.
        schema:
          type: string
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      - in: query
        name: src_budget
        schema:
          type: string
          format: uuid
      tags:
      - internal-transactions
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedInternalTransactionList'
          description: ''
    post:
      operationId: internal_transactions_create
      description: 'Transfer money between two budgets in the same bank account. Required:
        bank_account (UUID), amount, src_budget (UUID), and dst_budget (UUID). The
        authenticated user is recorded as the actor. Internal transactions are write-once
        -- to reverse a transfer, create a new one with src and dst swapped.'
      summary: Create an internal transaction
      tags:
      - internal-transactions
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InternalTransactionRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/InternalTransactionRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/InternalTransactionRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalTransaction'
          description: ''
  /api/v1/internal-transactions/{id}/:
    get:
      operationId: internal_transactions_retrieve
      description: Return a single internal transaction by UUID.
      summary: Get internal transaction details
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - internal-transactions
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalTransaction'
          description: ''
  /api/v1/transactions/:
    get:
      operationId: transactions_list
      description: Return transactions belonging to the authenticated user's accounts.
        Filterable by bank_account, pending status, transaction_type, and date range
        (date_from/date_to). Searchable by description, raw_description, and party.
        Orderable by transaction_date, amount, or created_at.
      summary: List transactions
      parameters:
      - in: query
        name: bank_account
        schema:
          type: string
          format: uuid
      - in: query
        name: date_from
        schema:
          type: string
          format: date-time
      - in: query
        name: date_to
        schema:
          type: string
          format: date-time
      - name: ordering
        required: false
        in: query
        description: Which field to use when ordering the results.
        schema:
          type: string
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      - in: query
        name: pending
        schema:
          type: boolean
      - in: query
        name: posted_date_from
        schema:
          type: string
          format: date-time
      - in: query
        name: posted_date_to
        schema:
          type: string
          format: date-time
      - name: search
        required: false
        in: query
        description: A search term.
        schema:
          type: string
      - in: query
        name: transaction_type
        schema:
          type: string
          enum:
          - ''
          - ach
          - ach_reversal
          - adjustment
          - atm_withdrawal
          - balance_sweep
          - bank_generated_credit
          - bill_payment
          - c2c
          - check
          - check_deposit
          - courtesy_credit
          - fee
          - fx_order
          - interest_credit
          - migration_interbank_transfer
          - pin_purchase
          - protected_goal_account_transfer
          - round-up_transfer
          - shared_transfer
          - signature_credit
          - signature_purchase
          - signature_return
          - wire_transfer
        description: |-
          * `signature_purchase` - Signature Purchase
          * `ach` - ACH
          * `round-up_transfer` - Round-up Transfer
          * `protected_goal_account_transfer` - Protected Goal Account Transfer
          * `fee` - Fee
          * `pin_purchase` - Pin Purchase
          * `signature_credit` - Signature Credit
          * `interest_credit` - Interest Credit
          * `shared_transfer` - Shared Transfer
          * `courtesy_credit` - Courtesy Credit
          * `atm_withdrawal` - ATM Withdrawal
          * `bill_payment` - Bill Payment
          * `bank_generated_credit` - Bank Generated Credit
          * `wire_transfer` - Wire Transfer
          * `check_deposit` - Check Deposit
          * `check` - Check
          * `c2c` - c2c
          * `migration_interbank_transfer` - Migration Interbank Transfer
          * `balance_sweep` - Balance Sweep
          * `ach_reversal` - ACH Reversal
          * `adjustment` - Adjustment
          * `signature_return` - Signature return
          * `fx_order` - FX Order
          * `` - --------
      tags:
      - transactions
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTransactionList'
          description: ''
    post:
      operationId: transactions_create
      description: 'Create a new bank transaction. Required: bank_account (UUID),
        amount, transaction_date, transaction_type, and raw_description. A default
        TransactionAllocation to the bank account''s unallocated budget is auto-created.
        After creation, only transaction_type, memo, and description are updatable.'
      summary: Create a transaction
      tags:
      - transactions
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransactionRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TransactionRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TransactionRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transaction'
          description: ''
  /api/v1/transactions/{id}/:
    get:
      operationId: transactions_retrieve
      description: Return a single transaction by UUID.
      summary: Get transaction details
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - transactions
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transaction'
          description: ''
    put:
      operationId: transactions_update
      description: Full update of a transaction. Only transaction_type, memo, and
        description are mutable after creation.
      summary: Update a transaction
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - transactions
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransactionRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TransactionRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TransactionRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transaction'
          description: ''
    patch:
      operationId: transactions_partial_update
      description: Partial update of a transaction. Only transaction_type, memo, and
        description are mutable after creation.
      summary: Partially update a transaction
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - transactions
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedTransactionRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedTransactionRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedTransactionRequest'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transaction'
          description: ''
    delete:
      operationId: transactions_destroy
      description: Delete a transaction. Balance changes are reversed by the pre_delete
        signal. Associated allocations are cascade-deleted.
      summary: Delete a transaction
      parameters:
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      tags:
      - transactions
      security:
      - jwtAuth: []
      responses:
        '204':
          description: No response body
  /api/v1/transactions/{id}/splits/:
    post:
      operationId: transactions_splits_create
      description: 'Declaratively set how a transaction''s amount is split across
        budgets. All referenced budgets must belong to the same bank account as the
        transaction. The backend reconciles existing allocations to match: creating,
        updating, or deleting as needed. Any unallocated remainder gets an allocation
        to the account''s unallocated budget. Returns all allocations for this transaction
        after reconciliation.'
      summary: Declare transaction splits
      parameters:
      - in: query
        name: bank_account
        schema:
          type: string
          format: uuid
      - in: query
        name: date_from
        schema:
          type: string
          format: date-time
      - in: query
        name: date_to
        schema:
          type: string
          format: date-time
      - in: path
        name: id
        schema:
          type: string
          format: uuid
        required: true
      - name: ordering
        required: false
        in: query
        description: Which field to use when ordering the results.
        schema:
          type: string
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      - in: query
        name: pending
        schema:
          type: boolean
      - in: query
        name: posted_date_from
        schema:
          type: string
          format: date-time
      - in: query
        name: posted_date_to
        schema:
          type: string
          format: date-time
      - name: search
        required: false
        in: query
        description: A search term.
        schema:
          type: string
      - in: query
        name: transaction_type
        schema:
          type: string
          enum:
          - ''
          - ach
          - ach_reversal
          - adjustment
          - atm_withdrawal
          - balance_sweep
          - bank_generated_credit
          - bill_payment
          - c2c
          - check
          - check_deposit
          - courtesy_credit
          - fee
          - fx_order
          - interest_credit
          - migration_interbank_transfer
          - pin_purchase
          - protected_goal_account_transfer
          - round-up_transfer
          - shared_transfer
          - signature_credit
          - signature_purchase
          - signature_return
          - wire_transfer
        description: |-
          * `signature_purchase` - Signature Purchase
          * `ach` - ACH
          * `round-up_transfer` - Round-up Transfer
          * `protected_goal_account_transfer` - Protected Goal Account Transfer
          * `fee` - Fee
          * `pin_purchase` - Pin Purchase
          * `signature_credit` - Signature Credit
          * `interest_credit` - Interest Credit
          * `shared_transfer` - Shared Transfer
          * `courtesy_credit` - Courtesy Credit
          * `atm_withdrawal` - ATM Withdrawal
          * `bill_payment` - Bill Payment
          * `bank_generated_credit` - Bank Generated Credit
          * `wire_transfer` - Wire Transfer
          * `check_deposit` - Check Deposit
          * `check` - Check
          * `c2c` - c2c
          * `migration_interbank_transfer` - Migration Interbank Transfer
          * `balance_sweep` - Balance Sweep
          * `ach_reversal` - ACH Reversal
          * `adjustment` - Adjustment
          * `signature_return` - Signature return
          * `fx_order` - FX Order
          * `` - --------
      tags:
      - transactions
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransactionSplitsRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TransactionSplitsRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TransactionSplitsRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTransactionAllocationList'
          description: ''
  /api/v1/users/:
    get:
      operationId: users_list
      description: Return all users. Restricted to staff/admin users.
      summary: List users (staff only)
      parameters:
      - name: ordering
        required: false
        in: query
        description: Which field to use when ordering the results.
        schema:
          type: string
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      - name: page_size
        required: false
        in: query
        description: Number of results to return per page.
        schema:
          type: integer
      tags:
      - users
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedUserList'
          description: ''
  /api/v1/users/{username}/:
    get:
      operationId: users_retrieve
      description: Return a single user by username. Restricted to staff/admin users.
      summary: Get user details (staff only)
      parameters:
      - in: path
        name: username
        schema:
          type: string
          description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
            only.
        required: true
      tags:
      - users
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
    put:
      operationId: users_update
      description: Full update of a user profile. Restricted to staff/admin users.
      summary: Update a user (staff only)
      parameters:
      - in: path
        name: username
        schema:
          type: string
          description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
            only.
        required: true
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/UserRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/UserRequest'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
    patch:
      operationId: users_partial_update
      description: Partial update of a user profile. Restricted to staff/admin users.
      summary: Partially update a user (staff only)
      parameters:
      - in: path
        name: username
        schema:
          type: string
          description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
            only.
        required: true
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedUserRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedUserRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedUserRequest'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
  /api/v1/users/me/:
    get:
      operationId: users_me_retrieve
      description: GET returns the authenticated user's own profile. PATCH allows
        updating the name field. Available to any authenticated user (not restricted
        to staff).
      summary: Get or update current user profile
      tags:
      - users
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
    patch:
      operationId: users_me_partial_update
      description: GET returns the authenticated user's own profile. PATCH allows
        updating the name field. Available to any authenticated user (not restricted
        to staff).
      summary: Get or update current user profile
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedUserRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedUserRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedUserRequest'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
components:
  schemas:
    AccountTypeEnum:
      enum:
      - C
      - S
      - X
      type: string
      description: |-
        * `C` - Checking
        * `S` - Savings
        * `X` - Credit Card
    Bank:
      type: object
      description: |-
        Read-only serializer for banks.

        Banks are shared reference data managed only through the admin.
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        name:
          type: string
          readOnly: true
        routing_number:
          type: string
          readOnly: true
          nullable: true
        default_currency:
          type: string
          readOnly: true
          description: ISO 4217 currency code (e.g. USD, EUR, GBP).
        created_at:
          type: string
          format: date-time
          readOnly: true
        modified_at:
          type: string
          format: date-time
          readOnly: true
      required:
      - created_at
      - default_currency
      - id
      - modified_at
      - name
      - routing_number
    BankAccount:
      type: object
      description: |-
        Serializer for bank accounts.

        On create the caller supplies name, bank (UUID), account_type,
        account_number, and optionally currency and initial balances.
        The view routes creation through BankAccountService which adds
        the requesting user as owner and seeds the Unallocated budget.

        After creation, name and account_number are updatable.  Currency,
        account_type, bank, and balances are immutable once the account
        exists.

        Group assignment is not yet supported via the API.
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        name:
          type: string
          maxLength: 200
        bank:
          type: string
          format: uuid
        owners:
          type: array
          items:
            type: string
            description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
              only.
          readOnly: true
        account_type:
          $ref: '#/components/schemas/AccountTypeEnum'
        account_number:
          type: string
          nullable: true
          maxLength: 32
        currency:
          type: string
          description: ISO 4217 currency code (e.g. USD, EUR, GBP).
          maxLength: 3
        posted_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        posted_balance_currency:
          type: string
          readOnly: true
        available_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        available_balance_currency:
          type: string
          readOnly: true
        unallocated_budget:
          type: string
          format: uuid
          readOnly: true
          nullable: true
        last_imported_at:
          type: string
          format: date-time
          readOnly: true
          nullable: true
          description: Wall-clock time of the most recent completed import for this
            account.
        last_posted_through:
          type: string
          format: date
          readOnly: true
          nullable: true
          description: Latest posted_date seen in the most recent import batch. The
            funding engine will not process events dated after this value.
        created_at:
          type: string
          format: date-time
          readOnly: true
        modified_at:
          type: string
          format: date-time
          readOnly: true
      required:
      - available_balance_currency
      - bank
      - created_at
      - id
      - last_imported_at
      - last_posted_through
      - modified_at
      - name
      - owners
      - posted_balance_currency
      - unallocated_budget
    BankAccountRequest:
      type: object
      description: |-
        Serializer for bank accounts.

        On create the caller supplies name, bank (UUID), account_type,
        account_number, and optionally currency and initial balances.
        The view routes creation through BankAccountService which adds
        the requesting user as owner and seeds the Unallocated budget.

        After creation, name and account_number are updatable.  Currency,
        account_type, bank, and balances are immutable once the account
        exists.

        Group assignment is not yet supported via the API.
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
        bank:
          type: string
          format: uuid
        account_type:
          $ref: '#/components/schemas/AccountTypeEnum'
        account_number:
          type: string
          nullable: true
          maxLength: 32
        currency:
          type: string
          minLength: 1
          description: ISO 4217 currency code (e.g. USD, EUR, GBP).
          maxLength: 3
        posted_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        available_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
      required:
      - bank
      - name
    BlankEnum:
      enum:
      - ''
    Budget:
      type: object
      description: |-
        Serializer for budgets.

        On create the caller supplies bank_account (UUID) and budget
        properties.  After creation, bank_account and budget_type are
        immutable.  Balance is managed by signals and is always read-only.
        The unallocated budget's name cannot be changed.

        Currency is inherited from the bank account via the pre_save
        signal and is not accepted from the client.
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        name:
          type: string
          maxLength: 200
        bank_account:
          type: string
          format: uuid
        balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          readOnly: true
        balance_currency:
          type: string
          readOnly: true
        target_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        target_balance_currency:
          type: string
          readOnly: true
        funding_amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          nullable: true
        funding_amount_currency:
          type: string
          readOnly: true
          nullable: true
        budget_type:
          $ref: '#/components/schemas/BudgetTypeEnum'
        funding_type:
          $ref: '#/components/schemas/FundingTypeEnum'
        target_date:
          type: string
          format: date
          nullable: true
        with_fillup_goal:
          type: boolean
        fillup_goal:
          type: string
          format: uuid
          nullable: true
        archived:
          type: boolean
          readOnly: true
        archived_at:
          type: string
          format: date-time
          readOnly: true
          nullable: true
        complete:
          type: boolean
          readOnly: true
          description: True when this budget has reached its target and should not
            be funded further.  Managed by signals and funding tasks; do not set manually.
        paused:
          type: boolean
          description: A paused budget does not get automatically funded on its schedule.
        funding_schedule:
          type: string
        recurrance_schedule:
          type: string
          nullable: true
        memo:
          type: string
          nullable: true
          maxLength: 512
        auto_spend: {}
        next_funding:
          type: object
          additionalProperties: {}
          nullable: true
          description: |-
            Return the next scheduled funding event for this budget, or null.

            Args:
                obj: The Budget instance being serialized.

            Returns:
                Dict with 'date', 'amount', 'amount_currency', 'deferred', or None.
          readOnly: true
        created_at:
          type: string
          format: date-time
          readOnly: true
        modified_at:
          type: string
          format: date-time
          readOnly: true
      required:
      - archived
      - archived_at
      - balance
      - balance_currency
      - bank_account
      - complete
      - created_at
      - funding_amount_currency
      - id
      - modified_at
      - name
      - next_funding
      - target_balance
      - target_balance_currency
    BudgetRequest:
      type: object
      description: |-
        Serializer for budgets.

        On create the caller supplies bank_account (UUID) and budget
        properties.  After creation, bank_account and budget_type are
        immutable.  Balance is managed by signals and is always read-only.
        The unallocated budget's name cannot be changed.

        Currency is inherited from the bank account via the pre_save
        signal and is not accepted from the client.
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
        bank_account:
          type: string
          format: uuid
        target_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        funding_amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          nullable: true
        budget_type:
          $ref: '#/components/schemas/BudgetTypeEnum'
        funding_type:
          $ref: '#/components/schemas/FundingTypeEnum'
        target_date:
          type: string
          format: date
          nullable: true
        with_fillup_goal:
          type: boolean
        fillup_goal:
          type: string
          format: uuid
          nullable: true
        paused:
          type: boolean
          description: A paused budget does not get automatically funded on its schedule.
        funding_schedule:
          type: string
        recurrance_schedule:
          type: string
          nullable: true
        memo:
          type: string
          nullable: true
          maxLength: 512
        auto_spend: {}
      required:
      - bank_account
      - name
      - target_balance
    BudgetTypeEnum:
      enum:
      - G
      - R
      - A
      - C
      type: string
      description: |-
        * `G` - Goal
        * `R` - Recurring
        * `A` - Associated Fill-up Goal
        * `C` - Capped
    CategoryEnum:
      enum:
      - Business:Business Clothing
      - Business:Business Services
      - Business:Business Supplies
      - Business:Meals
      - Business:Travel
      - Children:Activities
      - Children:Allowance
      - Children:Baby Supplies
      - Children:Childcare
      - Children:Kids Clothing
      - Children:Kids Education
      - Children:Toys
      - Culture:Art
      - Culture:Books
      - Culture:Dance
      - Culture:Games
      - Culture:Movies
      - Culture:Music
      - Culture:News
      - Culture:Random Fun
      - Culture:TV
      - Education:Books & Supplies
      - Education:Room & Board
      - Education:Student Loans
      - 'Education: Tuition & Fees'
      - Fees:ATM Fees
      - Fees:Investment Fees
      - Fees:Other Fees
      - Financial:Accounting
      - Financial:Credit Card Payment
      - Financial:Financial Advice
      - Financial:Life Insurance
      - Financial:Loan
      - Financial:Loan Payment
      - Financial:Money Transfers
      - Financial:Other Financial
      - Financial:Tax Preparation
      - Financial:Taxes, Federal
      - Financial:Taxes, Other
      - Financial:Taxes, State
      - Food & Drink:Alcohol & Bars
      - Food & Drink:Coffee & Tea
      - Food & Drink:Dessert
      - Food & Drink:Fast Food
      - Food & Drink:Groceries
      - Food & Drink:Other Food & Drink
      - Food & Drink:Restaurants
      - Food & Drink:Snacks
      - Food & Drink:Tobacco & Like
      - Gifts & Donations:Charities
      - Gifts & Donations:Gifts
      - Health & Medical:Care Facilities
      - Health & Medical:Dentist
      - Health & Medical:Doctor
      - Health & Medical:Equipment
      - Health & Medical:Eyes
      - Health & Medical:Health Insurance
      - Health & Medical:Other Health & Medical
      - Health & Medical:Pharmacies
      - Health & Medical:Prescriptions
      - Home:Furnishings
      - Home:Home Insurance
      - Home:Home Purchase
      - Home:Home Services
      - Home:Home Supplies
      - Home:Lawn & Garden
      - Home:Mortgage
      - Home:Moving
      - Home:Other Home
      - Home:Property Tax
      - Home:Rent
      - Home:Renter's Insurance
      - Income:Bonus
      - Income:Commission
      - Income:Interest
      - Income:Other Income
      - Income:Paycheck
      - Income:Reimbursement
      - Income:Rental Income
      - Investment:Education Investment
      - Investment:Other Investments
      - Investment:Retirement
      - Investment:Stocks & Mutual Funds
      - Legal:Legal Fees
      - Legal:Legal Services
      - Legal:Other Legal Costs
      - Office:Equipment
      - Office:Office Supplies
      - Office:Other Office
      - Office:Postage & Shipping
      - Personal:Accessories
      - Personal:Beauty
      - Personal:Body Enhancement
      - Personal:Clothing
      - Personal:Counseling
      - Personal:Hair
      - Personal:Hobbies
      - Personal:Jewelry
      - Personal:Laundry
      - Personal:Other Personal
      - Personal:Religion
      - Personal:Shoes
      - Pets:Pet Food
      - Pets:Pet Grooming
      - Pets:Pet Medicine
      - Pets:Pet Supplies
      - Pets:Veterinarian
      - Sports & Fitness:Camping
      - Sports & Fitness:Fitness Gear
      - Sports & Fitness:Golf
      - Sports & Fitness:Memberships
      - Sports & Fitness:Other Sports & Fitness
      - Sports & Fitness:Sporting Events
      - Sports & Fitness:Sporting Goods
      - Technology:Domains & Hosting
      - Technology:Hardware
      - Technology:Online Services
      - Technology:Software
      - Transportation:Auto Insurance
      - Transportation:Auto Payment
      - Transportation:Auto Services
      - Transportation:Auto Supplies
      - Transportation:Bicycle
      - Transportation:Boats & Marine
      - Transportation:Gas
      - Transportation:Other Transportation
      - Transportation:Parking & Tolls
      - Transportation:Parking Tickets
      - Transportation:Public Transit
      - Transportation:Shipping
      - Transportation:Taxies
      - Travel:Car Rental
      - Travel:Flights
      - Travel:Hotels
      - Travel:Tours & Cruises
      - Travel:Train
      - Travel:Travel Buses
      - Travel:Travel Dining
      - Travel:Travel Entertainment
      - Uncategorized:Cash
      - Uncategorized:Other Shopping
      - Uncategorized:Unknown
      - Uncategorized:Unassigned
      - Utilities:Cable
      - Utilities:Electricity
      - Utilities:Gas & Fuel
      - Utilities:Internet
      - Utilities:Other Utilities
      - Utilities:Phone
      - Utilities:Trash
      - Utilities:Water & Sewer
      type: string
      description: |-
        * `Business:Business Clothing` - Business Clothing
        * `Business:Business Services` - Business Services
        * `Business:Business Supplies` - Business Supplies
        * `Business:Meals` - Meals
        * `Business:Travel` - Travel
        * `Children:Activities` - Activities
        * `Children:Allowance` - Allowance
        * `Children:Baby Supplies` - Baby Supplies
        * `Children:Childcare` - Childcare
        * `Children:Kids Clothing` - Kids Clothing
        * `Children:Kids Education` - Kids Education
        * `Children:Toys` - Toys
        * `Culture:Art` - Art
        * `Culture:Books` - Books
        * `Culture:Dance` - Dance
        * `Culture:Games` - Games
        * `Culture:Movies` - Movies
        * `Culture:Music` - Music
        * `Culture:News` - News
        * `Culture:Random Fun` - Random Fun
        * `Culture:TV` - TV
        * `Education:Books & Supplies` - Books & Supplies
        * `Education:Room & Board` - Room & Board
        * `Education:Student Loans` - Student Loans
        * `Education: Tuition & Fees` -  Tuition & Fees
        * `Fees:ATM Fees` - ATM Fees
        * `Fees:Investment Fees` - Investment Fees
        * `Fees:Other Fees` - Other Fees
        * `Financial:Accounting` - Accounting
        * `Financial:Credit Card Payment` - Credit Card Payment
        * `Financial:Financial Advice` - Financial Advice
        * `Financial:Life Insurance` - Life Insurance
        * `Financial:Loan` - Loan
        * `Financial:Loan Payment` - Loan Payment
        * `Financial:Money Transfers` - Money Transfers
        * `Financial:Other Financial` - Other Financial
        * `Financial:Tax Preparation` - Tax Preparation
        * `Financial:Taxes, Federal` - Taxes, Federal
        * `Financial:Taxes, Other` - Taxes, Other
        * `Financial:Taxes, State` - Taxes, State
        * `Food & Drink:Alcohol & Bars` - Alcohol & Bars
        * `Food & Drink:Coffee & Tea` - Coffee & Tea
        * `Food & Drink:Dessert` - Dessert
        * `Food & Drink:Fast Food` - Fast Food
        * `Food & Drink:Groceries` - Groceries
        * `Food & Drink:Other Food & Drink` - Other Food & Drink
        * `Food & Drink:Restaurants` - Restaurants
        * `Food & Drink:Snacks` - Snacks
        * `Food & Drink:Tobacco & Like` - Tobacco & Like
        * `Gifts & Donations:Charities` - Charities
        * `Gifts & Donations:Gifts` - Gifts
        * `Health & Medical:Care Facilities` - Care Facilities
        * `Health & Medical:Dentist` - Dentist
        * `Health & Medical:Doctor` - Doctor
        * `Health & Medical:Equipment` - Equipment
        * `Health & Medical:Eyes` - Eyes
        * `Health & Medical:Health Insurance` - Health Insurance
        * `Health & Medical:Other Health & Medical` - Other Health & Medical
        * `Health & Medical:Pharmacies` - Pharmacies
        * `Health & Medical:Prescriptions` - Prescriptions
        * `Home:Furnishings` - Furnishings
        * `Home:Home Insurance` - Home Insurance
        * `Home:Home Purchase` - Home Purchase
        * `Home:Home Services` - Home Services
        * `Home:Home Supplies` - Home Supplies
        * `Home:Lawn & Garden` - Lawn & Garden
        * `Home:Mortgage` - Mortgage
        * `Home:Moving` - Moving
        * `Home:Other Home` - Other Home
        * `Home:Property Tax` - Property Tax
        * `Home:Rent` - Rent
        * `Home:Renter's Insurance` - Renter's Insurance
        * `Income:Bonus` - Bonus
        * `Income:Commission` - Commission
        * `Income:Interest` - Interest
        * `Income:Other Income` - Other Income
        * `Income:Paycheck` - Paycheck
        * `Income:Reimbursement` - Reimbursement
        * `Income:Rental Income` - Rental Income
        * `Investment:Education Investment` - Education Investment
        * `Investment:Other Investments` - Other Investments
        * `Investment:Retirement` - Retirement
        * `Investment:Stocks & Mutual Funds` - Stocks & Mutual Funds
        * `Legal:Legal Fees` - Legal Fees
        * `Legal:Legal Services` - Legal Services
        * `Legal:Other Legal Costs` - Other Legal Costs
        * `Office:Equipment` - Equipment
        * `Office:Office Supplies` - Office Supplies
        * `Office:Other Office` - Other Office
        * `Office:Postage & Shipping` - Postage & Shipping
        * `Personal:Accessories` - Accessories
        * `Personal:Beauty` - Beauty
        * `Personal:Body Enhancement` - Body Enhancement
        * `Personal:Clothing` - Clothing
        * `Personal:Counseling` - Counseling
        * `Personal:Hair` - Hair
        * `Personal:Hobbies` - Hobbies
        * `Personal:Jewelry` - Jewelry
        * `Personal:Laundry` - Laundry
        * `Personal:Other Personal` - Other Personal
        * `Personal:Religion` - Religion
        * `Personal:Shoes` - Shoes
        * `Pets:Pet Food` - Pet Food
        * `Pets:Pet Grooming` - Pet Grooming
        * `Pets:Pet Medicine` - Pet Medicine
        * `Pets:Pet Supplies` - Pet Supplies
        * `Pets:Veterinarian` - Veterinarian
        * `Sports & Fitness:Camping` - Camping
        * `Sports & Fitness:Fitness Gear` - Fitness Gear
        * `Sports & Fitness:Golf` - Golf
        * `Sports & Fitness:Memberships` - Memberships
        * `Sports & Fitness:Other Sports & Fitness` - Other Sports & Fitness
        * `Sports & Fitness:Sporting Events` - Sporting Events
        * `Sports & Fitness:Sporting Goods` - Sporting Goods
        * `Technology:Domains & Hosting` - Domains & Hosting
        * `Technology:Hardware` - Hardware
        * `Technology:Online Services` - Online Services
        * `Technology:Software` - Software
        * `Transportation:Auto Insurance` - Auto Insurance
        * `Transportation:Auto Payment` - Auto Payment
        * `Transportation:Auto Services` - Auto Services
        * `Transportation:Auto Supplies` - Auto Supplies
        * `Transportation:Bicycle` - Bicycle
        * `Transportation:Boats & Marine` - Boats & Marine
        * `Transportation:Gas` - Gas
        * `Transportation:Other Transportation` - Other Transportation
        * `Transportation:Parking & Tolls` - Parking & Tolls
        * `Transportation:Parking Tickets` - Parking Tickets
        * `Transportation:Public Transit` - Public Transit
        * `Transportation:Shipping` - Shipping
        * `Transportation:Taxies` - Taxies
        * `Travel:Car Rental` - Car Rental
        * `Travel:Flights` - Flights
        * `Travel:Hotels` - Hotels
        * `Travel:Tours & Cruises` - Tours & Cruises
        * `Travel:Train` - Train
        * `Travel:Travel Buses` - Travel Buses
        * `Travel:Travel Dining` - Travel Dining
        * `Travel:Travel Entertainment` - Travel Entertainment
        * `Uncategorized:Cash` - Cash
        * `Uncategorized:Other Shopping` - Other Shopping
        * `Uncategorized:Unknown` - Unknown
        * `Uncategorized:Unassigned` - -------
        * `Utilities:Cable` - Cable
        * `Utilities:Electricity` - Electricity
        * `Utilities:Gas & Fuel` - Gas & Fuel
        * `Utilities:Internet` - Internet
        * `Utilities:Other Utilities` - Other Utilities
        * `Utilities:Phone` - Phone
        * `Utilities:Trash` - Trash
        * `Utilities:Water & Sewer` - Water & Sewer
    FundingTypeEnum:
      enum:
      - D
      - F
      type: string
      description: |-
        * `D` - Target Date
        * `F` - Fixed Amount
    InternalTransaction:
      type: object
      description: |-
        Serializer for internal transactions (budget-to-budget transfers).

        Internal transactions are write-once: the API supports create and
        read but not update or delete.  To reverse a transfer, create a
        new internal transaction with the src and dst budgets swapped.

        On create the caller supplies bank_account, amount, src_budget,
        and dst_budget.  The view sets the actor to the requesting user.

        The ``amount_currency`` is read from raw request data by
        djmoney's ``MoneyField.get_value()`` -- no explicit currency
        field declaration is needed.
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        bank_account:
          type: string
          format: uuid
        amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        amount_currency:
          type: string
          readOnly: true
        src_budget:
          type: string
          format: uuid
        dst_budget:
          type: string
          format: uuid
        actor:
          type: integer
          readOnly: true
        effective_date:
          type: string
          format: date-time
        src_budget_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          readOnly: true
        src_budget_balance_currency:
          type: string
          readOnly: true
        dst_budget_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          readOnly: true
        dst_budget_balance_currency:
          type: string
          readOnly: true
        created_at:
          type: string
          format: date-time
          readOnly: true
        modified_at:
          type: string
          format: date-time
          readOnly: true
      required:
      - actor
      - amount
      - amount_currency
      - bank_account
      - created_at
      - dst_budget
      - dst_budget_balance
      - dst_budget_balance_currency
      - id
      - modified_at
      - src_budget
      - src_budget_balance
      - src_budget_balance_currency
    InternalTransactionRequest:
      type: object
      description: |-
        Serializer for internal transactions (budget-to-budget transfers).

        Internal transactions are write-once: the API supports create and
        read but not update or delete.  To reverse a transfer, create a
        new internal transaction with the src and dst budgets swapped.

        On create the caller supplies bank_account, amount, src_budget,
        and dst_budget.  The view sets the actor to the requesting user.

        The ``amount_currency`` is read from raw request data by
        djmoney's ``MoneyField.get_value()`` -- no explicit currency
        field declaration is needed.
      properties:
        bank_account:
          type: string
          format: uuid
        amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        src_budget:
          type: string
          format: uuid
        dst_budget:
          type: string
          format: uuid
        effective_date:
          type: string
          format: date-time
      required:
      - amount
      - bank_account
      - dst_budget
      - src_budget
    PaginatedBankAccountList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/BankAccount'
    PaginatedBankList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/Bank'
    PaginatedBudgetList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/Budget'
    PaginatedInternalTransactionList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/InternalTransaction'
    PaginatedTransactionAllocationList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/TransactionAllocation'
    PaginatedTransactionList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/Transaction'
    PaginatedUserList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/User'
    PatchedBankAccountRequest:
      type: object
      description: |-
        Serializer for bank accounts.

        On create the caller supplies name, bank (UUID), account_type,
        account_number, and optionally currency and initial balances.
        The view routes creation through BankAccountService which adds
        the requesting user as owner and seeds the Unallocated budget.

        After creation, name and account_number are updatable.  Currency,
        account_type, bank, and balances are immutable once the account
        exists.

        Group assignment is not yet supported via the API.
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
        bank:
          type: string
          format: uuid
        account_type:
          $ref: '#/components/schemas/AccountTypeEnum'
        account_number:
          type: string
          nullable: true
          maxLength: 32
        currency:
          type: string
          minLength: 1
          description: ISO 4217 currency code (e.g. USD, EUR, GBP).
          maxLength: 3
        posted_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        available_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
    PatchedBudgetRequest:
      type: object
      description: |-
        Serializer for budgets.

        On create the caller supplies bank_account (UUID) and budget
        properties.  After creation, bank_account and budget_type are
        immutable.  Balance is managed by signals and is always read-only.
        The unallocated budget's name cannot be changed.

        Currency is inherited from the bank account via the pre_save
        signal and is not accepted from the client.
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
        bank_account:
          type: string
          format: uuid
        target_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        funding_amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          nullable: true
        budget_type:
          $ref: '#/components/schemas/BudgetTypeEnum'
        funding_type:
          $ref: '#/components/schemas/FundingTypeEnum'
        target_date:
          type: string
          format: date
          nullable: true
        with_fillup_goal:
          type: boolean
        fillup_goal:
          type: string
          format: uuid
          nullable: true
        paused:
          type: boolean
          description: A paused budget does not get automatically funded on its schedule.
        funding_schedule:
          type: string
        recurrance_schedule:
          type: string
          nullable: true
        memo:
          type: string
          nullable: true
          maxLength: 512
        auto_spend: {}
    PatchedTransactionRequest:
      type: object
      description: |-
        Serializer for bank transactions.

        On create the caller supplies bank_account, amount,
        transaction_date, transaction_type, raw_description, and
        optionally pending, memo, and description.

        After creation only transaction_type, memo, and description are
        updatable.  The view is responsible for creating the default
        TransactionAllocation to the unallocated budget on create.

        The ``amount_currency`` is read from raw request data by
        djmoney's ``MoneyField.get_value()`` -- no explicit currency
        field declaration is needed.
      properties:
        bank_account:
          type: string
          format: uuid
        amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        posted_date:
          type: string
          format: date-time
        transaction_date:
          type: string
          format: date-time
          nullable: true
        transaction_type:
          oneOf:
          - $ref: '#/components/schemas/TransactionTypeEnum'
          - $ref: '#/components/schemas/BlankEnum'
        pending:
          type: boolean
          default: false
        memo:
          type: string
          nullable: true
          maxLength: 512
        raw_description:
          type: string
          minLength: 1
          maxLength: 512
        description:
          type: string
          maxLength: 512
        image:
          type: string
          format: binary
          nullable: true
        document:
          type: string
          format: binary
          nullable: true
    PatchedUserRequest:
      type: object
      description: |-
        Serializer for user profiles.

        The ``default_bank_account`` field is writable but constrained:
        the bank account must be owned by the user being updated.  On
        output it returns the UUID string (or null).
      properties:
        name:
          type: string
          title: Name of User
          maxLength: 255
        default_bank_account:
          type: string
          format: uuid
          nullable: true
        timezone:
          type: string
          minLength: 1
          maxLength: 100
    TokenObtainPair:
      type: object
      properties:
        access:
          type: string
          readOnly: true
        refresh:
          type: string
          readOnly: true
      required:
      - access
      - refresh
    TokenObtainPairRequest:
      type: object
      properties:
        username:
          type: string
          writeOnly: true
          minLength: 1
        password:
          type: string
          writeOnly: true
          minLength: 1
      required:
      - password
      - username
    TokenRefresh:
      type: object
      properties:
        access:
          type: string
          readOnly: true
        refresh:
          type: string
      required:
      - access
      - refresh
    TokenRefreshRequest:
      type: object
      properties:
        refresh:
          type: string
          minLength: 1
      required:
      - refresh
    Transaction:
      type: object
      description: |-
        Serializer for bank transactions.

        On create the caller supplies bank_account, amount,
        transaction_date, transaction_type, raw_description, and
        optionally pending, memo, and description.

        After creation only transaction_type, memo, and description are
        updatable.  The view is responsible for creating the default
        TransactionAllocation to the unallocated budget on create.

        The ``amount_currency`` is read from raw request data by
        djmoney's ``MoneyField.get_value()`` -- no explicit currency
        field declaration is needed.
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        bank_account:
          type: string
          format: uuid
        amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        amount_currency:
          type: string
          readOnly: true
        party:
          type: string
          readOnly: true
          nullable: true
        posted_date:
          type: string
          format: date-time
        transaction_date:
          type: string
          format: date-time
          nullable: true
        transaction_type:
          oneOf:
          - $ref: '#/components/schemas/TransactionTypeEnum'
          - $ref: '#/components/schemas/BlankEnum'
        pending:
          type: boolean
          default: false
        memo:
          type: string
          nullable: true
          maxLength: 512
        raw_description:
          type: string
          maxLength: 512
        description:
          type: string
          maxLength: 512
        linked_transaction:
          type: string
          format: uuid
          readOnly: true
        bank_account_posted_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          readOnly: true
          description: Posted Balance does not include pending debits.
        bank_account_posted_balance_currency:
          type: string
          readOnly: true
        bank_account_available_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          readOnly: true
          description: Available Balance has pending debits deducted.
        bank_account_available_balance_currency:
          type: string
          readOnly: true
        image:
          type: string
          format: uri
          nullable: true
        document:
          type: string
          format: uri
          nullable: true
        created_at:
          type: string
          format: date-time
          readOnly: true
        modified_at:
          type: string
          format: date-time
          readOnly: true
      required:
      - amount
      - amount_currency
      - bank_account
      - bank_account_available_balance
      - bank_account_available_balance_currency
      - bank_account_posted_balance
      - bank_account_posted_balance_currency
      - created_at
      - id
      - linked_transaction
      - modified_at
      - party
      - posted_date
      - raw_description
      - transaction_type
    TransactionAllocation:
      type: object
      description: |-
        Serializer for transaction allocations.

        An allocation maps a portion of a transaction's amount to a budget.
        On create the caller supplies transaction, amount, and optionally
        budget (defaults to unallocated) and category.  After creation,
        budget, category, and memo are updatable.

        The serializer enforces two key constraints:

        1. **Same-account restriction** -- the budget must belong to the
           same bank account as the transaction.  Cross-account allocations
           are rejected with a 400 error.
        2. **Sum constraint** -- the total allocated amount across all
           allocations for a transaction must not exceed the transaction
           amount.

        The ``amount_currency`` is read from raw request data by
        djmoney's ``MoneyField.get_value()`` -- no explicit currency
        field declaration is needed.
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        transaction:
          type: string
          format: uuid
        budget:
          type: string
          format: uuid
          nullable: true
        amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        amount_currency:
          type: string
          readOnly: true
        budget_balance:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          readOnly: true
        budget_balance_currency:
          type: string
          readOnly: true
        category:
          $ref: '#/components/schemas/CategoryEnum'
        memo:
          type: string
          nullable: true
          maxLength: 512
        created_at:
          type: string
          format: date-time
          readOnly: true
        modified_at:
          type: string
          format: date-time
          readOnly: true
      required:
      - amount
      - amount_currency
      - budget_balance
      - budget_balance_currency
      - created_at
      - id
      - modified_at
      - transaction
    TransactionRequest:
      type: object
      description: |-
        Serializer for bank transactions.

        On create the caller supplies bank_account, amount,
        transaction_date, transaction_type, raw_description, and
        optionally pending, memo, and description.

        After creation only transaction_type, memo, and description are
        updatable.  The view is responsible for creating the default
        TransactionAllocation to the unallocated budget on create.

        The ``amount_currency`` is read from raw request data by
        djmoney's ``MoneyField.get_value()`` -- no explicit currency
        field declaration is needed.
      properties:
        bank_account:
          type: string
          format: uuid
        amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
        posted_date:
          type: string
          format: date-time
        transaction_date:
          type: string
          format: date-time
          nullable: true
        transaction_type:
          oneOf:
          - $ref: '#/components/schemas/TransactionTypeEnum'
          - $ref: '#/components/schemas/BlankEnum'
        pending:
          type: boolean
          default: false
        memo:
          type: string
          nullable: true
          maxLength: 512
        raw_description:
          type: string
          minLength: 1
          maxLength: 512
        description:
          type: string
          maxLength: 512
        image:
          type: string
          format: binary
          nullable: true
        document:
          type: string
          format: binary
          nullable: true
      required:
      - amount
      - bank_account
      - posted_date
      - raw_description
      - transaction_type
    TransactionSplitsRequest:
      type: object
      description: |-
        Serializer for the declarative splits endpoint.

        Accepts a dict mapping budget UUIDs to amounts.  The backend
        reconciles existing allocations to match the declared state.
        Any remainder goes to the unallocated budget.

        All budgets must belong to the same bank account as the
        transaction.  Cross-account budget references are rejected
        with a 400 error.
      properties:
        splits:
          type: object
          additionalProperties:
            type: string
            format: decimal
            pattern: ^-?\d{0,12}(?:\.\d{0,2})?$
          description: Map of budget UUID → amount.  Amounts must not exceed the transaction
            total.  Omitted remainder is assigned to the unallocated budget.
      required:
      - splits
    TransactionTypeEnum:
      enum:
      - signature_purchase
      - ach
      - round-up_transfer
      - protected_goal_account_transfer
      - fee
      - pin_purchase
      - signature_credit
      - interest_credit
      - shared_transfer
      - courtesy_credit
      - atm_withdrawal
      - bill_payment
      - bank_generated_credit
      - wire_transfer
      - check_deposit
      - check
      - c2c
      - migration_interbank_transfer
      - balance_sweep
      - ach_reversal
      - adjustment
      - signature_return
      - fx_order
      type: string
      description: |-
        * `signature_purchase` - Signature Purchase
        * `ach` - ACH
        * `round-up_transfer` - Round-up Transfer
        * `protected_goal_account_transfer` - Protected Goal Account Transfer
        * `fee` - Fee
        * `pin_purchase` - Pin Purchase
        * `signature_credit` - Signature Credit
        * `interest_credit` - Interest Credit
        * `shared_transfer` - Shared Transfer
        * `courtesy_credit` - Courtesy Credit
        * `atm_withdrawal` - ATM Withdrawal
        * `bill_payment` - Bill Payment
        * `bank_generated_credit` - Bank Generated Credit
        * `wire_transfer` - Wire Transfer
        * `check_deposit` - Check Deposit
        * `check` - Check
        * `c2c` - c2c
        * `migration_interbank_transfer` - Migration Interbank Transfer
        * `balance_sweep` - Balance Sweep
        * `ach_reversal` - ACH Reversal
        * `adjustment` - Adjustment
        * `signature_return` - Signature return
        * `fx_order` - FX Order
        * `` - --------
    User:
      type: object
      description: |-
        Serializer for user profiles.

        The ``default_bank_account`` field is writable but constrained:
        the bank account must be owned by the user being updated.  On
        output it returns the UUID string (or null).
      properties:
        username:
          type: string
          readOnly: true
          description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
            only.
        name:
          type: string
          title: Name of User
          maxLength: 255
        url:
          type: string
          format: uri
          readOnly: true
        default_bank_account:
          type: string
          format: uuid
          nullable: true
        timezone:
          type: string
          maxLength: 100
      required:
      - url
      - username
    UserRequest:
      type: object
      description: |-
        Serializer for user profiles.

        The ``default_bank_account`` field is writable but constrained:
        the bank account must be owned by the user being updated.  On
        output it returns the UUID string (or null).
      properties:
        name:
          type: string
          title: Name of User
          maxLength: 255
        default_bank_account:
          type: string
          format: uuid
          nullable: true
        timezone:
          type: string
          minLength: 1
          maxLength: 100
  securitySchemes:
    jwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
