openapi: 3.0.2
info:
  title: Lunch Money API - v2
  description: |-
    Welcome to the Lunch Money v2 API reference. This is the **v2.11.0** spec. It includes previews of the proposed `/crypto` and `/balance_history` endpoints. Only the mock service works with these endpoints.<br><br>
    The most recent stable version of the API is v2.9.4 and is available at:
    `https://api.lunchmoney.dev/v2`

    ------------------------------------------------------------------------------------------------

    ### Introduction

    The API is available at `https://api.lunchmoney.dev/v2`. Get your access token from the [Lunch Money developers page](https://my.lunchmoney.app/developers).

    <span class="red-text"><strong>The v2 API is in open alpha and is still subject to change. Use the mock server or a test budget when getting started.</strong></span>

    **Static Mock Server**

    Explore the API without an access token or risk to real data. Select **"Static Mock v2 Lunch Money API Server"** from the Server dropdown, then set your Bearer token to any string with 11 or more characters.

    **Client Libraries & SDKs**

    An official TypeScript SDK is available on [NPM](https://www.npmjs.com/package/@lunch-money/v2-api-spec) and [GitHub](https://github.com/lunch-money/lunch-money-js-v2). For Python or other languages, see [lunchmoney-clients](https://github.com/juftin/lunchmoney-clients) or generate a client from this OpenAPI spec.

    **Migrating from v1**

    The v2 API is not backwards compatible with v1. See the [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide) for details.

    **Useful links**
    - [Developer Portal](https://alpha.lunchmoney.dev/v2/introduction)
    - [Getting Started Guide](https://alpha.lunchmoney.dev/v2/getting-started)
    - [v2 API Overview](https://alpha.lunchmoney.dev/v2/overview)
    - [Version History](https://alpha.lunchmoney.dev/v2/version-history)
    - [Migration Guide](https://alpha.lunchmoney.dev/v2/migration-guide)
    - [Rate Limits](https://alpha.lunchmoney.dev/v2/rate-limits)
  termsOfService: https://lunchmoney.dev/#current-status
  contact:
    email: devsupport@lunchmoney.app
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 2.11.0

servers:
  - url: https://api.lunchmoney.dev/v2
    description: v2 Lunch Money API Server - changes will affect real data!
#  - url: https://mock.lunchmoney.dev/v2
  - url: https://lm-v2-api-next-a7fabcab8e9a.herokuapp.com/v2/
    description: Static mock version of the v2 Lunch Money API Server

tags:
  - name: me
    description: View details and settings for the current user and account
  - name: categories
    description: Work with categories
    externalDocs:
      description: Learn more about categories
      url: https://support.lunchmoney.app/setup/categories
  - name: manual_accounts
    description: Work with manually managed accounts (formerly called assets)
    externalDocs:
      description: Learn more about manual accounts
      url: https://support.lunchmoney.app/setup/linked-accounts#how-are-manually-managed-account-balances-updated
  - name: plaid_accounts
    description: Work with accounts synced through Plaid
    externalDocs:
      description: Learn more about synced accounts
      url: https://support.lunchmoney.app/setup/linked-accounts#how-often-should-i-expect-new-transactions-to-get-imported
  - name: crypto-manual
    description: Work with manually managed crypto assets
    externalDocs:
      description: Learn more about crypto assets
      url: https://support.lunchmoney.app/setup/crypto
  - name: crypto-synced
    description: Read and refresh synced crypto assets and balances. Creating and managing connections with synced crypto providers is done exclusively in the Lunch Money web app.
    externalDocs:
      description: Learn more about crypto assets
      url: https://support.lunchmoney.app/setup/crypto
  - name: balance_history
    description: View and update historical account balances. Balance history is what drives the [Net Worth](https://my.lunchmoney.app/net-worth) views in the Lunch Money app. Balance history is generated for each account's balance on the first day of each month and can be edited in the Lunch Money app or via the API.
  - name: recurring_items
    description: Work with recurring items
    externalDocs:
      url: https://support.lunchmoney.app/finances/recurring-items
  - name: tags
    description: Work with tags
    externalDocs:
      description: Learn more about tags
      url: https://support.lunchmoney.app/setup/tags
  - name: transactions
    description: Work with transactions
    externalDocs:
      description: Learn more about transactions
      url: https://support.lunchmoney.app/finances/transactions
  - name: transactions (bulk)
    description: Perform bulk actions on transactions
    externalDocs:
      description: Learn more about transactions
      url: https://support.lunchmoney.app/finances/transactions
  - name: transactions (group)
    description: Group or ungroup transactions
    externalDocs:
      description: Learn more about transactions
      url: https://support.lunchmoney.app/finances/transactions
  - name: transactions (split)
    description: Split or unsplit transactions
    externalDocs:
      description: Learn more about transactions
      url: https://support.lunchmoney.app/finances/transactions
  - name: transactions (files)
    description: Manage files attached to transactions
    externalDocs:
      description: Learn more about transactions
      url: https://support.lunchmoney.app/finances/transactions
  - name: budgets
    description: View settings and modify budget amounts.<p> Use the
      [/summary](#tag/summary) endpoint to view the budget details performance.
    externalDocs:
      description: Learn more about budgets
      url: https://support.lunchmoney.app/finances/budgets
  - name: summary
    description: View a summary of the user's budget

components:
  schemas:

    userObject:
      type: object
      title: user object (returned by /me)
      additionalProperties: false
      properties: 
        name:
          type: string
          description: The user's name
        email:
          type: string
          description: The user's email
        id:
          type: integer
          format: int32
          description: Unique ID for the user
        account_id:
          type: integer
          format: int64
          description: Unique ID for the linked budgeting account
        budget_name:
          type: string
          description: Name of the linked budgeting account
        primary_currency:
          description: Primary currency set in the user's settings
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
        api_key_label:
          type: string
          nullable: true
          description: Label assigned by the user to the API key being used.
            Returns null if no label is set
      required:
        - name
        - email
        - id
        - account_id
        - budget_name
        - primary_currency
        - api_key_label

    categoryObject:
          type: object
          title: category object
          additionalProperties: false
          properties:
            id:
              type: integer
              format: int32
              nullable: false
              description: System defined unique ID for the category
            name:
              type: string
              nullable: false
              description: Name of the category
              minLength: 1
              maxLength: 100
            description:
              type: string
              nullable: true
              description: Category description, or `null` if none is set
              maxLength: 200
            is_income:
              type: boolean
              nullable: false
              description: 'If `true`, transactions in this category are treated
                as income. (See [Category
                Properties](https://support.lunchmoney.app/setup/categories/category-properties)
                for details)'
            exclude_from_budget:
              type: boolean
              nullable: false
              description: 'If `true`, transactions in this category are
                excluded from the budget. (See [Category
                Properties](https://support.lunchmoney.app/setup/categories/category-properties)
                for details)'
            exclude_from_totals:
              type: boolean
              nullable: false
              description: 'If `true`, transactions in this category are
                excluded from totals. (See [Category
                Properties](https://support.lunchmoney.app/setup/categories/category-properties)
                for details)'
            updated_at:
              type: string
              format: date-time
              nullable: false
              description: Date and time the category was last updated (in the
                ISO 8601 extended format).
            created_at:
              type: string
              format: date-time
              nullable: false
              description: Date and time of when the category was created (ISO
                8601 extended format).
            group_id:
              type: integer
              format: int64
              nullable: true
              description: ID of the category group this category belongs to, or
                `null` if it does not belong to a group, or is itself a group.
            is_group:
              type: boolean
              description: If `true`, this category is created as a category
                group
            children:
              type: array
              items:
                $ref: "#/components/schemas/childCategoryObject"
              description: For category groups, contains details about the
                categories in the group. These objects are similar to Category
                Objects but the `is_group` property will always be `false`, and
                there will be no `children` attribute.
            archived:
              type: boolean
              description: If true, the category is archived and hidden in
                relevant areas of the Lunch Money app.
            archived_at:
              type: string
              format: date-time
              nullable: true
              description: Date and time the category was last archived ( ISO
                8601 extended format).
            order:
              type: integer
              nullable: true
              default: null
              description: "Position of the category on the categories page in
                the Lunch Money app. For grouped categories, the order is
                relative to others in the same group.<br>
                Categories with `order: null` are shown alphabetically before ordered categories"
            collapsed:
              type: boolean
              nullable: false
              default: false
              description: If `true`, the category appears collapsed in the
                Lunch Money app
          required:
            - id
            - name
            - description
            - is_income
            - exclude_from_budget
            - exclude_from_totals
            - updated_at
            - created_at
            - group_id
            - is_group
            - archived
            - archived_at
            - order
            - collapsed

    # The childCategoryObject is a categoryObject without a 
    # `children` attribute. This ensures that only non-group categories
    # are added to a category group
    childCategoryObject:
      type: object
      x-internal: true # Don't display in schemas section of docs
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int32
          nullable: false
          description: System defined unique ID for the category
        name:
          type: string
          nullable: false
          description: The name of the category
          minLength: 1
          maxLength: 100
        description:
          type: string
          nullable: true
          description: Category description, or `null` if none is set
          maxLength: 200
        is_income:
          type: boolean
          nullable: false
          description: If true, transactions in this category are treated as
            income. (Inherited from the Category Group).
        exclude_from_budget:
          type: boolean
          nullable: false
          description: If true, transactions in this category are excluded from
            the budget. (Inherited from Category Group).
        exclude_from_totals:
          type: boolean
          nullable: false
          description: If true, transactions in this category are excluded from
            totals. (Inherited from Category Group).
        updated_at:
          type: string
          format: date-time
          nullable: false
          description: Date and time the category was last updated (ISO 8601
            extended format).
        created_at:
          type: string
          format: date-time
          nullable: false
          description: Date and time the category was created (ISO 8601 extended
            format).
        group_id:
          type: integer
          format: int64
          nullable: true
          description: ID of the category group this category belongs to, or
            `null` if it does not belong to a group, or is itself a group.
        is_group:
          type: boolean
          enum:
            - false
          description: Always false for categories that belong to a category
            group
        archived:
          type: boolean
          description: If true, the category is archived and hidden in relevant
            areas of the Lunch Money app.
        archived_at:
          type: string
          format: date-time
          nullable: true
          description: Date and time the category was last archived ( ISO 8601
            extended format).
        order:
          type: integer
          nullable: true
          description: Position of the category on the categories page in the
            Lunch Money app. For grouped categories, the order is relative to
            the others in the same group.
        collapsed:
          type: boolean
          nullable: false
          description: Always `false` for a child category. Child categories
            cannot be collapsed.
      required:
        - id
        - name
        - description
        - is_income
        - exclude_from_budget
        - exclude_from_totals
        - updated_at
        - created_at
        - group_id
        - is_group
        - archived
        - archived_at
        - order
        - collapsed

     # The request object for POST /categories
    # Prevent user from submitting any system created fields in a POST request
    createCategoryRequestObject:
      type: object
      additionalProperties: false
      x-internal: true
      properties:
        name:
          type: string
          nullable: false
          description: >-
            Name of the new category. Must be between 1 and 100 characters.

            The name must not match the name of any existing categories or category
            groups.
          minLength: 1
          maxLength: 100
        description:
          type: string
          nullable: true
          default: null
          description: Description of the category. Maximum length is 200
            characters.
          minLength: 0 # Allow empty strings
          maxLength: 200
        is_income:
          type: boolean
          nullable: false
          default: false
          description: If `true`, transactions in this category are treated as
            income. (See [Category
            Properties](https://support.lunchmoney.app/setup/categories/category-properties)
            for details)
        exclude_from_budget:
          type: boolean
          nullable: false
          default: false
          description: If `true`, transactions in this category are excluded
            from the budget. (See [Category
            Properties](https://support.lunchmoney.app/setup/categories/category-properties)
            for details)
        exclude_from_totals:
          type: boolean
          nullable: false
          default: false
          description: If `true`, transactions in this category are excluded
            from totals. (See [Category
            Properties](https://support.lunchmoney.app/setup/categories/category-properties)
            for details)
        is_group:
          type: boolean
          nullable: false
          default: false
          description: If `true`, this category will be created as a category
            group.
        group_id:
          type: integer
          format: int64
          nullable: true
          default: null
          description: If set to the ID of an existing category group, the new
            category will be added to that group. Cannot be used if `is_group`
            is true.
        archived:
          type: boolean
          default: false
          description: If `true`, the category is archived and in relevant areas
            of the Lunch Money app.
        children:
          type: array
          nullable: false
          description: List of categories to include in the new category group.
            This field should only be set if `is_group` is also set to true.<br>
            You may provide existing category objects, existing category IDs, or
            names for new categories to add to the group. Categories or IDs must
            already exist and cannot be category groups. Categories that already
            belong to another group will be moved. If strings are provided, they
            will be used as names for new categories added to the group. The
            request will fail if any provided name already exists.<br> You may
            mix category objects, IDs, and new category names in the same
            request.
          items:
            oneOf:
              - type: integer
                description: "ID of an existing category."
              - type: string
                description: "Name of a new child category to be created."
                maxLength: 100
              - $ref: "#/components/schemas/categoryObject"
        order:
          type: integer
          nullable: true
          description: Position of the category on the categories page in the
            Lunch Money app. For grouped categories, the order is relative to
            other categories in the same group.<br>While this property can be
            set via the API, it is usually managed by the user in the Lunch
            Money app.
        collapsed:
          type: boolean
          nullable: true
          description: If `true`, the category group appears collapsed in the
            Lunch Money app. Can only be set to `true` for category
            groups.<br>While this property can be set via the API, it is usually
            managed by the user in the Lunch Money app.
      required:
        - name


    # Request object for a PUT /categories/:id request
    # Tolerates a request object that includes system created fields from a
    # previous GET request, but these are essentially ignored
    updateCategoryRequestObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: false
          description: If set, updates the category name. Must be between 1 and
            100 characters.
          minLength: 1
          maxLength: 100
          x-updatable: true
        description:
          type: string
          nullable: true
          description: If set, updates the category description. Must not exceed
            200 characters.
          minLength: 0 # Allow empty strings
          maxLength: 200
          x-updatable: true
        is_income:
          type: boolean
          nullable: false
          description: If set, determines whether transactions in this category
            are treated as income. (See [Category
            Properties](https://support.lunchmoney.app/setup/categories/category-properties)
            for details)
          x-updatable: true
        exclude_from_budget:
          type: boolean
          nullable: false
          description: If set, determines whether transactions in this category
            are excluded from budgets. (See [Category
            Properties](https://support.lunchmoney.app/setup/categories/category-properties)
            for details)
          x-updatable: true
        exclude_from_totals:
          type: boolean
          nullable: false
          description: If set, determines whether transactions in this category
            are excluded from totals. (See [Category
            Properties](https://support.lunchmoney.app/setup/categories/category-properties)
            for details)
          x-updatable: true
        archived:
          type: boolean
          description: If set, determines whether this category is archived.
          x-updatable: true
        group_id:
          type: integer
          format: int64
          nullable: true
          description: If set to the ID of an existing category group, and this
            category is not itself a category group, this category will be
            assigned to that group.
          x-updatable: true
        is_group:
          type: boolean
          nullable: true
          default: false
          description: This property is tolerated but cannot be changed. This
            API cannot be used to convert a category into a category group or
            vice versa.
        children:
          type: array
          nullable: false
          description: List of existing category objects, existing category IDs,
            or names of new categories to add to the category group. This
            attribute should only be set when modifying an existing category
            group.<br> Categories or IDs must already exist and must not already
            belong to a category group. Categories that already belong to
            another category group will be moved. If strings are specified, they
            will be used as names for new categories added to the group. The
            request will fail if any provided name matches an existing category
            name.<br> You may mix full category objects, IDs, and new category
            names in the same request.
          x-updatable: true
          items:
            oneOf:
              - type: integer
                description: "ID of an existing category."
              - type: string
                description: "Name of a new child category to be created."
                maxLength: 100
              - $ref: "#/components/schemas/categoryObject"
        order:
          type: integer
          nullable: true
          description: Position of the category on the categories page in the
            Lunch Money app. For categories within a category group, the order
            is relative to the other categories in the group.<br>While this
            property can be set via the API, it is generally managed by the user
            in the Lunch Money app.
          x-updatable: true
        collapsed:
          type: boolean
          nullable: true
          description: If `true`, the category is collapsed in the Lunch Money
            app.<br>While this property can be set via the API it is generally
            set by the user in the Lunch Money app.
          x-updatable: true
        id:
          type: integer
          format: int64
          description: System defined unique identifier for the category.
            Ignored if set.
          x-updatable: false
        archived_at:
          type: string
          format: date-time
          nullable: true
          description: System set date and time of when the category was last
            archived (in the ISO 8601 extended format). Provide an ISO 8601
            extended datetime or `null` to clear it.
          x-updatable: true
        updated_at:
          type: string
          format: date-time
          nullable: false
          description: System set date and time of when the category was last
            updated (in the ISO 8601 extended format). Ignored if set.
          x-updatable: false
        created_at:
          type: string
          format: date-time
          nullable: false
          description: System set date and time of when the category was created
            (in the ISO 8601 extended format). Ignored if set.
          x-updatable: false

    # The response object for a DELETE /category request with dependencies
    deleteCategoryResponseWithDependencies:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        category_name:
          type: string
          description: The name of the category
        dependents:
          type: object
          properties:
            budget:
              type: integer
              description: The number of budgets depending on the category
            category_rules:
              type: integer
              description: The number of category rules depending on the
                category
            transactions:
              type: integer
              description: The number of transactions depending on the category
            children:
              type: integer
              description: The number of child categories in the category group
            recurring:
              type: integer
              description: The number of recurring transactions depending on the
                category
            plaid_cats:
              type: integer
              description: The number of auto created categories based on Plaid
                categories
          required:
            - budget
            - category_rules
            - transactions
            - children
            - recurring
            - plaid_cats
      required:
        - category_name
        - dependents

    # Manual crypto balance object
    cryptoManualObject:
      type: object
      title: manual crypto object
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int32
          description: System defined unique ID for the manual crypto balance
        name:
          type: string
          minLength: 1
          maxLength: 45
          description: User-defined name for the crypto asset
        display_name:
          type: string
          nullable: true
          description: Optional display name for the crypto asset. If `null`,
            clients may derive a display name from `institution_name` + `name`.
        institution_name:
          type: string
          nullable: true
          minLength: 1
          maxLength: 50
          description: Institution or wallet provider display name
        balance:
          type: string
          pattern: ^-?\d+(\.\d{1,18})?$
          description: Current balance in numeric format to 18 decimal places
        symbol:
          type: string
          minLength: 1
          maxLength: 25
          description: Cryptocurrency symbol
        coingecko_id:
          type: string
          nullable: true
          minLength: 1
          maxLength: 100
          description: CoinGecko identifier associated with this balance
        to_base:
          type: number
          nullable: true
          description: Balance converted to the user's primary currency. May be null if no conversion was available.
        balance_as_of:
          type: string
          format: date-time
          nullable: true
          description: Date/time the manual balance record was last updated in
            ISO 8601 extended format. This is currently based on the manual
            crypto record's updated_at timestamp.
        exchange_rate_as_of:
          type: string
          format: date-time
          nullable: true
          description: Date/time the exchange rate used to calculate to_base was
            last updated in ISO 8601 extended format. Null when no exchange rate was
            used or no conversion was available.
        created_by_name:
          type: string
          nullable: true
          description: Name of the user who created the crypto asset
        created_at:
          type: string
          format: date-time
          description: Date/time the crypto asset was created in ISO 8601
            extended format
        updated_at:
          type: string
          format: date-time
          description: Date/time the crypto asset was last updated in ISO 8601
            extended format
      required:
        - id
        - name
        - display_name
        - institution_name
        - balance
        - symbol
        - coingecko_id
        - to_base
        - balance_as_of
        - exchange_rate_as_of
        - created_by_name
        - created_at
        - updated_at

    # Synced per-symbol balance nested under a synced crypto account
    cryptoSyncedBalance:
      type: object
      title: synced crypto balance object
      additionalProperties: false
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 45
          description: The name of the crypto asset
        balance:
          type: string
          pattern: ^-?\d+(\.\d{1,18})?$
          description: Current balance in numeric format to 18 decimal places
        symbol:
          type: string
          minLength: 1
          maxLength: 25
          description: Symbol of the currency held in the synced account
        coingecko_id:
          type: string
          nullable: true
          minLength: 1
          maxLength: 100
          description: CoinGecko identifier associated with this balance
        to_base:
          type: number
          nullable: true
          description: Balance converted to the user's primary currency. May be null if no conversion was available.
        balance_as_of:
          type: string
          format: date-time
          nullable: true
          description: Date/time the balance was last updated in ISO 8601
            extended format.
        exchange_rate_as_of:
          type: string
          format: date-time
          nullable: true
          description: Date/time the exchange rate used to calculate to_base was
            last updated in ISO 8601 extended format. Null when no exchange rate was
            used or no conversion was available.
        updated_at:
          type: string
          format: date-time
          description: Date/time the crypto asset was last updated in ISO 8601
            extended format
      required:
        - name
        - balance
        - symbol
        - coingecko_id
        - to_base
        - balance_as_of
        - exchange_rate_as_of
        - updated_at

    syncedCryptoAccount:
      type: object
      title: synced crypto account
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int32
          description: System defined unique ID for the synced crypto connection
        provider:
          type: string
          description: Provider used for the synced crypto connection
          enum:
            - kraken
            - coinbase
            - ethereum
        status:
          type: string
          description: Status of the synced crypto account. If not `active`,
            see the [Knowledge
            Base](https://support.lunchmoney.app/setup/crypto#why-is-my-synced-crypto-account-showing-not-supported)
            for details.
          enum:
            - active
            - unsupported
            - relink
            - initializing
        created_by_name:
          type: string
          nullable: true
          description: Name of the user who created the crypto connection
        created_at:
          type: string
          format: date-time
          description: Date/time the synced crypto connection was created in ISO
            8601 extended format
        updated_at:
          type: string
          format: date-time
          description: Date/time the synced crypto connection was last updated
            in ISO 8601 extended format
        last_import:
          type: string
          format: date-time
          nullable: true
          description: System defined timestamp in ISO 8601 extended format of
            the last successful import.
        display_name:
          type: string
          nullable: true
          description: Optional display name for the synced crypto connection
        balances:
          type: array
          items:
            $ref: "#/components/schemas/cryptoSyncedBalance"
          description: Balances currently held in the synced crypto connection
      required:
        - id
        - provider
        - status
        - created_by_name
        - created_at
        - updated_at
        - display_name
        - balances

    # Response object returned by GET /crypto/manual
    cryptoManualListResponseObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        crypto_manual:
          type: array
          items:
            $ref: "#/components/schemas/cryptoManualObject"
      required:
        - crypto_manual

    # Response object returned by GET /crypto/synced
    cryptoSyncedListResponseObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        crypto_synced:
          type: array
          items:
            $ref: "#/components/schemas/syncedCryptoAccount"
      required:
        - crypto_synced

    cryptoCurrencyObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int32
          description: System-defined unique identifier for this
            cryptocurrency in Lunch Money.
        coingecko_id:
          type: string
          minLength: 1
          maxLength: 100
          description: System-defined CoinGecko identifier used to fetch
            the USD-based prices for this cryptocurrency.
        symbol:
          type: string
          minLength: 1
          maxLength: 25
          description: Lowercase currency symbol that must be used as
            `symbol` when creating a manual crypto balance.
        full_name:
          type: string
          minLength: 1
          maxLength: 200
          description: Human-readable name of the cryptocurrency.
      required:
        - id
        - coingecko_id
        - symbol
        - full_name

    # Response object returned by GET /cryptocurrencies
    cryptoCurrencyResponseObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        cryptocurrencies:
          type: array
          description: List of cryptocurrencies currently supported for manual
            tracking.
          items:
            $ref: "#/components/schemas/cryptoCurrencyObject"
      required:
        - cryptocurrencies

    createCryptocurrencyRequestObject:
      type: object
      additionalProperties: false
      x-internal: true
      properties:
        coingecko_url:
          type: string
          minLength: 1
          maxLength: 200
          description: CoinGecko coin-page URL in the form
            `https://www.coingecko.com/{locale}/coins/{id}`
          example: https://www.coingecko.com/en/coins/cardano
      required:
        - coingecko_url

    # The object that may be submitted to POST /crypto/manual
    createCryptoManualRequestObject:
      type: object
      additionalProperties: false
      x-internal: true
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 45
          description: User-defined name for the manual crypto asset
          example: Cold Wallet BTC
        display_name:
          type: string
          minLength: 1
          maxLength: 45
          description: Optional display name for the manual crypto asset. If
            omitted, clients may derive one from `institution_name` + `name`.
          example: Cold Storage
        institution_name:
          type: string
          minLength: 1
          maxLength: 50
          description: Optional institution or wallet provider display name
          example: Ledger
        balance:
          oneOf:
            - type: number
              format: double
            - type: string
              pattern: ^-?\d+(\.\d{1,18})?$
          description: Numeric value of the balance, up to 18 decimal places
          example: "0.523400000000000000"
        symbol:
          type: string
          minLength: 1
          maxLength: 25
          description: Cryptocurrency symbol to track. Must match the `symbol`
            of one of the supported cryptocurrencies returned by `GET
            /cryptocurrencies`.
          example: btc
      required:
        - name
        - balance
        - symbol

    # The object that may be submitted to PUT /crypto/manual/{id}
    updateCryptoManualRequestObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int32
          description: System defined unique ID for the manual crypto asset.
            Ignored if set
          x-updatable: false
        name:
          type: string
          nullable: true
          minLength: 1
          maxLength: 45
          description: If set, the new name of the manual crypto asset
          x-updatable: true
        display_name:
          type: string
          nullable: true
          minLength: 1
          maxLength: 45
          description: If set, the new display name for the manual crypto asset
          x-updatable: true
        institution_name:
          type: string
          nullable: true
          minLength: 1
          maxLength: 50
          description: If set, the new institution or wallet provider display
            name
          x-updatable: true
        balance:
          oneOf:
            - type: number
              format: double
            - type: string
              pattern: ^-?\d+(\.\d{1,18})?$
          description: If set, the new balance value up to 18 decimal places
          example: "1.050000000000000000"
          x-updatable: true
        symbol:
          type: string
          minLength: 1
          maxLength: 25
          description: Existing cryptocurrency symbol. Ignored if set.
          x-updatable: false
        coingecko_id:
          type: string
          nullable: true
          minLength: 1
          maxLength: 100
          description: System-defined CoinGecko identifier for this symbol.
            Ignored if set.
          x-updatable: false
        to_base:
          type: number
          description: System defined balance converted to the user's primary
            currency. Ignored if set
          x-updatable: false
        balance_as_of:
          type: string
          format: date-time
          nullable: true
          description: System defined date/time the manual balance record was
            last updated in ISO 8601 extended format. Ignored if set
          x-updatable: false
        exchange_rate_as_of:
          type: string
          format: date-time
          nullable: true
          description: System defined date/time the exchange rate used to
            calculate to_base was observed in ISO 8601 extended format. Ignored
            if set
          x-updatable: false
        created_by_name:
          type: string
          nullable: true
          description: System defined name of the user who created the crypto
            asset. Ignored if set
          x-updatable: false
        created_at:
          type: string
          format: date-time
          description: System defined date/time the crypto asset was created in
            ISO 8601 extended format. Ignored if set
          x-updatable: false
        updated_at:
          type: string
          format: date-time
          description: System defined date/time the crypto asset was last
            updated in ISO 8601 extended format. Ignored if set
          x-updatable: false
      description: Update a manual crypto balance. System-defined properties are
        accepted when resubmitting a `GET /crypto/manual/{id}` response body.


    # The object containing information about a manual account
    manualAccountObject:
      type: object
      title: manual account object
      additionalProperties: false
      description: An object containing information about a manual account
      properties:
        id:
          type: integer
          format: int32
          description: The unique identifier of this account
        name:
          type: string
          description: Name of the account
          minLength: 1
          maxLength: 45
        institution_name:
          type: string
          nullable: true
          minLength: 1
          maxLength: 50
          description: Name of institution holding the account
        display_name:
          type: string
          nullable: true
          description: Optional display name for the account as set by the user
            or derived from the `institution_name` and `name` if not explicitly
            set.
        type:
          description: Primary type of the account
          allOf:
            - $ref: "#/components/schemas/accountTypeEnum"
        subtype:
          type: string
          nullable: true
          description: Optional account subtype. Examples include<br> -
            retirement - checking - savings - prepaid credit card
          minLength: 1
          maxLength: 100
        balance:
          type: string
          pattern: ^-?\d+(\.\d{1,4})?$
          description: Current balance of the account in numeric format to 4
            decimal places
        currency:
          type: string
          minLength: 3
          maxLength: 3
          description: Three-letter lowercase currency code of the account
            balance
        to_base:
          type: number
          description: The balance converted to the user's primary currency
        balance_as_of:
          type: string
          format: date-time
          description: Date balance was last updated in ISO 8601 extended
            format, can be in date or date-time format
        status:
          type: string
          description: The status of the account
          enum:
            - active
            - closed
        closed_on:
          type: string
          format: date
          nullable: true
          description: The date this account was closed in YYYY-MM-DD format.
            Will be null if the account has not been marked as closed.
        external_id:
          type: string
          nullable: true
          minLength: 0
          maxLength: 75
          description: An optional external_id that may be set or updated via
            the API
        custom_metadata:
          type: object
          nullable: true
          description: User defined JSON data that can be set or cleared via the
            API
          additionalProperties: true
        exclude_from_transactions:
          type: boolean
          default: false
          description: If true, this account will not show up as an option for
            assignment when creating transactions manually
        created_by_name:
          type: string
          description: The name of the user who created the account
        created_at:
          type: string
          format: date-time
          description: Date/time the account was created in ISO 8601 extended
            format
        updated_at:
          type: string
          format: date-time
          description: Date/time the account was last updated in ISO 8601
            extended format
      required:
        - id
        - name
        - type
        - subtype
        - display_name
        - balance
        - currency
        - to_base
        - balance_as_of
        - closed_on
        - institution_name
        - external_id
        - exclude_from_transactions
        - created_by_name
        - created_at
        - updated_at
        - status

    # The object that may be submitted to POST /manual_accounts
    createManualAccountRequestObject:
      type: object
      additionalProperties: false
      x-internal: true
      properties:
        name:
          type: string
          description: Name of the manual account
          minLength: 1
          maxLength: 45
          example: My Savings Account
        institution_name:
          type: string
          example: Bank of the West
          description: Name of institution holding the manual account
          minLength: 1
          maxLength: 50
        display_name:
          type: string
          description: Display name of the manual account as set by user or
            derived from the `institution_name` and `name` if not explicitly
            set.<br> This must be unique for the budgeting account.
          example: Savings
        type:
          description: The type of manual account
          allOf:
            - $ref: "#/components/schemas/accountTypeEnum"
        subtype:
          type: string
          description: An optional manual account subtype. Examples include<br>
            - retirement - checking - savings - prepaid credit card
          minLength: 1
          maxLength: 100
          example: prepaid credit card
        balance:
          oneOf:
            - type: number
              format: double
            - type: string
              pattern: ^-?\d+(\.\d{1,4})?$
          example: "195.50"
          description: Numeric value of the current balance, up to four decimal
            places, of the account as a number or string. Do not include any
            special characters aside from a decimal point.
        balance_as_of:
          type: string
          oneOf:
            - format: date-time
            - format: date
          example: "2024-09-15"
          description: Date/time the balance of the manual account was last
            updated in ISO 8601 extended format
        currency:
          description: Three-letter lowercase currency code of the transaction
            in ISO 4217 format
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
        status: 
          type: string
          description: The status of the account
          enum:
            - active
            - closed
          default: active
        closed_on:
          oneOf:
            - type: string
              format: date
            - type: string
              format: date-time
          nullable: true
          example: "2024-10-01"
          description: The date this manual account was closed in YYYY-MM-DD
            format. If set, `status` must also be set to `closed`.
        external_id:
          type: string
          nullable: true
          minLength: 0
          maxLength: 75
          description: An optional user-defined ID for the manual account
        custom_metadata:
          type: object
          nullable: true
          description: An optional JSON object that includes additional data
            related to this account. This must be a valid JSON object and, when
            stringified, must not exceed 4096 characters.
          additionalProperties: true
        exclude_from_transactions:
          type: boolean
          description: If `true`, transactions may not be assigned to this
            manual account
          default: false
      required:
        - name
        - type
        - balance

    # The object that may be submitted to PUT /manual_accounts/:id
    updateManualAccountRequestObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int32
          description: System defined unique identifier of this account. Ignored
            if set
          x-updatable: false
        name:
          type: string
          description: If set, the new name of the manual account
          minLength: 1
          maxLength: 45
          x-updatable: true
        institution_name:
          type: string
          nullable: true
          description: If set, the name of the institution holding the account
          minLength: 1
          maxLength: 50
          x-updatable: true
        display_name:
          type: string
          nullable: true
          description: If set, the new display name for the manual account.<br>
            This must be unique for the user.
          x-updatable: true
        type:
          description: If set, the new type of the manual account
          x-updatable: true
          allOf:
            - $ref: "#/components/schemas/accountTypeEnum"
        subtype:
          type: string
          description: If set, an optional account subtype. Examples include<br>
            - retirement - checking - savings - prepaid credit card
          minLength: 1
          maxLength: 100
          x-updatable: true
        balance:
          oneOf:
            - type: number
              format: double
            - type: string
              pattern: ^-?\d+(\.\d{1,4})?$
          example: "195.50"
          description: Numeric value of the current balance, up to four decimal
            places, of the manual account as a number or string. Do not include
            any special characters aside from a decimal point.
          x-updatable: true
        currency:
          description: If set, the new three-letter lowercase currency code of
            the manual account balance.
          x-updatable: true
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
        balance_as_of:
          type: string
          oneOf:
            - format: date-time
            - format: date
          description: "If set, updates the `balance_as_of` value. May be
            provided as a date in YYYY-MM-DD format or as a date-time string in
            ISO 8601 extended format. This property is ignored unless `balance`
            is also set. If `balance` is set and this property is not set, the
            current time is used."
          x-updatable: true
        status:
          type: string
          description: If set, updates the status of the manual account. If set
            to `closed`, `closed_on` will be set to the current date unless it
            is also set.
          enum:
            - active
            - closed
          x-updatable: true
        closed_on:
          nullable: true
          oneOf:
            - type: string
              format: date
            - type: string
              format: date-time
          description: If set, the date this manual account was closed in
            YYYY-MM-DD format. If updating an account that is not already
            closed, `status` must also be set to `closed`.
          x-updatable: true
        external_id:
          type: string
          nullable: true
          minLength: 0
          maxLength: 75
          description: An optional user-defined ID for the manual account
          x-updatable: true
        custom_metadata:
          type: object
          nullable: true
          description: An optional JSON object that includes additional data
            related to this account. This must be a valid JSON object and, when
            stringified, must not exceed 4096 characters.
          additionalProperties: true
          x-updatable: true
        exclude_from_transactions:
          type: boolean
          description: If set, transactions may not be assigned to this manual
            account
          x-updatable: true
        to_base:
          type: number
          description: System defined balance converted to the user's primary
            currency. Ignored if set. Use `balance` to update the balance in the
            account
          x-updatable: false
        created_at:
          type: string
          format: date-time
          description: System defined date/time the account was created in ISO
            8601 extended format. Ignored if set.
          x-updatable: false
        updated_at:
          type: string
          format: date-time
          description: System defined date/time the account was last updated in
            ISO 8601 extended format. Ignored if set.
          x-updatable: false
        created_by_name:
          type: string
          description: System defined name of the user who created the account.
            Ignored if set
          x-updatable: false

    # The object containing information about a Plaid account
    plaidAccountObject:
      type: object
      title: plaid account object
      additionalProperties: false
      description: An object containing information about an account synced via
        Plaid
      properties:
        id:
          type: integer
          format: int32
          description: The unique identifier of this account
        plaid_item_id:
          type: string
          nullable: true
          minLength: 0
          maxLength: 255
          description: The unique identifier of the Plaid connection that this
            account belongs to. Accounts with the same plaid_item_id usually
            belong to the same institution.
        date_linked:
          type: string
          format: date
          description: Date account was first linked in ISO 8601 format
        linked_by_name:
          type: string
          nullable: false
          description: The name of the user who linked the account
        name:
          type: string
          description: Name of the account. This field is set by Plaid and
            cannot be altered.
        display_name:
          type: string
          nullable: true
          description: Optional display name for the account set by the user. If
            not set, it will return a concatenated string of institution and
            account name.
        type:
          type: string
          description: Primary type of the account, such as `credit`,
            `depository`, etc. This field is set by Plaid and cannot be altered.
        subtype:
          type: string
          description: Optional account subtype. This field is set by Plaid and
            cannot be altered.
        mask:
          type: string
          description: Mask (last 3 to 4 digits of account) of account. This
            field is set by Plaid and cannot be altered.
        institution_name:
          type: string
          description: Name of institution holding the account. This field is
            set by Plaid and cannot be altered.
        status:
          type: string
          description: "Denotes the current status of the account within Lunch
            Money. Must be one of<br>
            - active: Account is actively syncing transactions and/or balance<br>
            - inactive: Account marked inactive from user. Transaction imports and balance updates will not occur for this account.<br>
            - closed: Account is marked as closed<br>
            - deactivated: Account is marked deactivated during setup. The user must click `Add/Remove Accounts From This Bank` and manually re-select this account to activate it.'<br>
            - not found: Account was once linked but can no longer be found with Plaid.<br>
            - not supported: Account is not supported by Plaid.<br>
            - relink: Account (and others with the same connection) need to be relinked with Plaid.<br>
            - syncing: Account is awaiting the first import of transactions.<br>
            - revoked: Account connection has been revoked by Plaid and syncing is no longer possible. A new connection needs to be set up again.<br>
            - error: Account (and others with the same connection) is in error with Plaid and requires intervention to re-activate it.<br>"
          enum:
            - active
            - inactive
            - closed
            - deactivated
            - not found
            - not supported
            - relink
            - syncing
            - revoked
            - error
        allow_transaction_modifications:
          type: boolean
          description: If `false`, transactions imported for this synced account
            can have their properties (such as amount and account) be modified
            by the user. This option is managed in the Lunch Money app.
        limit:
          type: number
          nullable: true
          description: Optional credit limit of the account. This field is set
            by Plaid and cannot be altered
        balance:
          type: string
          description: Current balance of the account in numeric format to 4
            decimal places. This field is set by Plaid and cannot be altered.
        currency:
          type: string
          minLength: 3
          maxLength: 3
          description: Three-letter lowercase currency code of the account
            balance
        to_base:
          type: number
          description: The account balance converted to the user's primary
            currency
        balance_last_update:
          type: string
          format: date-time
          nullable: true
          description: Date balance was last updated in ISO 8601 extended
            format. This field is set by Plaid and cannot be altered.
        import_start_date:
          type: string
          format: date
          nullable: true
          description: Date of earliest date allowed for importing transactions.
            Transactions earlier than this date are not imported.
        last_import:
          type: string
          format: date-time
          nullable: true
          description: Timestamp in ISO 8601 extended format of the last time
            Lunch Money imported new data from Plaid for this account.
        last_fetch:
          type: string
          format: date-time
          nullable: true
          description: Timestamp in ISO 8601 extended format of the last
            successful request from Lunch Money for updated data or timestamps
            from Plaid in ISO 8601 extended format (not necessarily date of last
            successful import)
        plaid_last_successful_update:
          type: string
          format: date-time
          nullable: true
          description: Timestamp in ISO 8601 extended format of the last time
            Plaid successfully connected with institution for new transaction
            updates, regardless of whether any new data was available in the
            update.
      required:
        - id
        - plaid_item_id
        - date_linked
        - linked_by_name
        - name
        - display_name
        - type
        - subtype
        - mask
        - institution_name
        - status
        - allow_transaction_modifications
        - limit
        - balance
        - currency
        - to_base
        - balance_last_update
        - import_start_date
        - last_import
        - last_fetch
        - plaid_last_successful_update

    balanceHistorySourceManual:
      type: object
      description: Source information for a manual account balance history entry.
      additionalProperties: false
      x-internal: true
      properties:
        type:
          type: string
          enum: [manual]
          description: Identifies this entry as belonging to a manually-managed account.
        manual_account_id:
          type: integer
          format: int32
          description: ID of the manual account associated with this entry.
      required:
        - type
        - manual_account_id

    balanceHistorySourcePlaid:
      type: object
      description: Source information for a Plaid-synced account balance history entry.
      additionalProperties: false
      x-internal: true
      properties:
        type:
          type: string
          enum: [plaid]
          description: Identifies this entry as belonging to a Plaid-synced account.
        plaid_account_id:
          type: integer
          format: int32
          description: ID of the Plaid account associated with this entry.
      required:
        - type
        - plaid_account_id

    balanceHistorySourceCryptoManual:
      type: object
      description: Source information for a manually-tracked cryptocurrency balance history entry.
      additionalProperties: false
      x-internal: true
      properties:
        type:
          type: string
          enum: [crypto_manual]
          description: Identifies this entry as belonging to a manually-tracked crypto account.
        crypto_manual_id:
          type: integer
          format: int32
          description: ID of the manual crypto account associated with this entry.
        symbol:
          type: string
          nullable: true
          minLength: 1
          maxLength: 25
          description: Crypto symbol associated with the manual crypto account, when available.
      required:
        - type
        - crypto_manual_id

    balanceHistorySourceCryptoSynced:
      type: object
      x-internal: true
      description: Source information for a synced cryptocurrency balance history entry.
      additionalProperties: false
      properties:
        type:
          type: string
          enum: [crypto_synced]
          description: Identifies this entry as belonging to a synced crypto connection.
        crypto_synced_id:
          type: integer
          format: int32
          description: ID of the synced crypto connection associated with this entry.
        symbol:
          type: string
          minLength: 1
          maxLength: 25
          description: Crypto symbol (e.g. `eth`, `btc`) identifying the specific currency within the synced account.
      required:
        - type
        - crypto_synced_id
        - symbol

    balanceHistorySourceDeleted:
      type: object
      x-internal: true
      description: >
        Source information for a balance history entry whose account has since been deleted.
        Historical balances are preserved when a user chooses to keep history on account deletion.
        This object contains details that can be used to display the deleted account in the UI.
        The `deleted_account_id` can be passed to `PUT /v2/balance_history/deleted/{account_id}/details`
        to update the archived source metadata.
      additionalProperties: false
      properties:
        type:
          type: string
          enum: [deleted]
          description: Identifies this entry as belonging to an account that has since been deleted.
        deleted_account_id:
          type: integer
          format: int32
          description: Identifier for the deleted account history source
        name:
          type: string
          nullable: true
          description: Archived account `name` for the deleted account source
        institution_name:
          type: string
          nullable: true
          description: Archived `institution_name` for the deleted account source
        display_name:
          type: string
          nullable: true
          description: Archived `display_name` of the deleted account
        account_type:
          type: string
          nullable: true
          description: Archived `type` of the deleted account source
        subtype:
          type: string
          nullable: true
          description: Archived `subtype`` of the deleted account source
        mask:
          type: string
          nullable: true
          description: Archived account `mask` for a deleted plaid account source
        symbol:
          type: string
          nullable: true
          minLength: 1
          maxLength: 25
          description: Archived `symbol` for a deleted crypto account source
      required:
        - type
        - deleted_account_id
        - name
        - institution_name
        - display_name
        - account_type
        - subtype
        - mask
        - symbol

    balanceHistoryAccountObject:
      type: object
      title: balance history for an account object
      additionalProperties: false
      description: Historical balance entries grouped under a single account source.
      properties:
        source:
          description: >
            Identifies the account this balance entry belongs to. The shape varies by
            `source.type`. Use `source.type` to determine which account id field is present.
          oneOf:
            - $ref: "#/components/schemas/balanceHistorySourceManual"
            - $ref: "#/components/schemas/balanceHistorySourcePlaid"
            - $ref: "#/components/schemas/balanceHistorySourceCryptoManual"
            - $ref: "#/components/schemas/balanceHistorySourceCryptoSynced"
            - $ref: "#/components/schemas/balanceHistorySourceDeleted"
          discriminator:
            propertyName: type
            mapping:
              manual: "#/components/schemas/balanceHistorySourceManual"
              plaid: "#/components/schemas/balanceHistorySourcePlaid"
              crypto_manual: "#/components/schemas/balanceHistorySourceCryptoManual"
              crypto_synced: "#/components/schemas/balanceHistorySourceCryptoSynced"
              deleted: "#/components/schemas/balanceHistorySourceDeleted"
        balances:
          type: array
          description: One or more monthly balance history entries for the source account.
          items:
            $ref: "#/components/schemas/balanceHistoryObject"
      required:
        - source
        - balances

    balanceHistoryObject:
      type: object
      title: balance history entry object
      additionalProperties: false
      x-internal: true
      description: A historical balance entry for a single account on a single date.
      properties:
        id:
          type: integer
          format: int32
          description: Unique identifier of this historical balance entry.
        date:
          type: string
          format: date
          description: Date of this historical balance entry in YYYY-MM-DD format. This is always the first day of a month.
        balance:
          type: string
          pattern: ^-?\d+(\.\d{1,4})?$
          description: Historical balance stored for this entry. For manual and Plaid accounts this is in the account currency. For crypto accounts this is in the user's primary currency.
        currency:
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
          description: Currency of the stored `balance`. For crypto entries this is the user's primary currency.
        to_base:
          type: number
          format: double
          description: Historical balance converted to the user's primary currency. When the entry currency is the user's primary currency, this is the numeric value of `balance`.
        crypto_balance:
          type: string
          nullable: true
          pattern: ^-?\d+(\.\d{1,18})?$
          description: Crypto quantity stored for this balance entry, when available. This may be present for crypto or deleted-account entries and is `null` otherwise.
      required:
        - id
        - date
        - balance
        - currency
        - to_base
        - crypto_balance

    balanceHistoryListResponseObject:
      type: object
      additionalProperties: false
      x-internal: true
      properties:
        balance_history:
          type: array
          items:
            $ref: "#/components/schemas/balanceHistoryAccountObject"
      required:
        - balance_history

    balanceHistoryUpdateItemObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int32
          description: System-defined balance history entry id. Ignored if set.
          x-updatable: false
        date:
          type: string
          format: date
          description: Month to update, in YYYY-MM-DD format. This must be the first day of a month and must not be in the future.
        balance:
          oneOf:
            - type: number
              format: double
            - type: string
              pattern: ^-?\d+(\.\d{1,4})?$
          description: Numeric value of the historical balance, up to four decimal places, as a number or string. For manual and Plaid accounts this is typically in the account currency. For crypto and deleted accounts this is typically in the user's primary currency. Do not include any special characters aside from a decimal point.
        symbol:
          type: string
          nullable: true
          minLength: 1
          maxLength: 25
          description: Optional for crypto balances, but if set it must match the account's symbol.
            Tolerated for deleted-account balances. Do not provide this for manual or Plaid balances.
            If provided when using the synced crypto path-based endpoint, this must match the symbol in the path.
          x-updatable: true
        crypto_balance:
          type: string
          nullable: true
          pattern: ^-?\d+(\.\d{1,18})?$
          description: Optional crypto quantity for crypto_manual, crypto_synced, and deleted balances. Do not provide this for manual or Plaid balances.
          x-updatable: true
        currency:
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
          description: Optional currency for this balance entry. If omitted, it defaults to the account currency for manual/Plaid accounts, or the user's primary currency for crypto/deleted accounts.
          x-updatable: true
        to_base:
          type: number
          format: double
          description: System-defined historical balance converted to the user's primary currency. Ignored if set. Use `balance` to update the stored historical balance.
          x-updatable: false
      required:
        - date
        - balance

    upsertBalanceHistoryRequestObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        balances:
          type: array
          minItems: 1
          description: One or more monthly balance history entries to upsert
          items:
            $ref: "#/components/schemas/balanceHistoryUpdateItemObject"
      required:
        - balances

    updateBalanceHistoryDetailsRequestObject:
      type: object
      x-internal: true
      additionalProperties: false
      minProperties: 1
      properties:
        name:
          type: string
          nullable: true
          description: New archived account name for the deleted account source.
        institution_name:
          type: string
          nullable: true
          description: New archived institution name for the deleted account source.
        display_name:
          type: string
          nullable: true
          description: New display name for the deleted account source.
        account_type:
          type: string
          nullable: true
          description: New archived account type for the deleted account source.
        subtype:
          type: string
          nullable: true
          description: New archived subtype for the deleted account source.
        mask:
          type: string
          nullable: true
          description: New archived account mask for the deleted account source.

    updateBalanceHistoryDetailsResponseObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: true
        institution_name:
          type: string
          nullable: true
        display_name:
          type: string
          nullable: true
        account_type:
          type: string
          nullable: true
        subtype:
          type: string
          nullable: true
        mask:
          type: string
          nullable: true
      required:
        - name
        - institution_name
        - display_name
        - account_type
        - subtype
        - mask

    # The object containing information about a recurring item
    recurringObject:
      type: object
      title: recurring item object
      properties:
        id:
          type: integer
          format: int32
          description: The unique identifier of this recurring item
        description:
          type: string
          nullable: true
          description: An optional description of this recurring item.
        status:
          type: string
          description: The status of this recurring item. `suggested` recurring
            items are generated by Lunch Money, but only `reviewed` recurring
            items will be applied to matching transactions.
          enum:
            - suggested
            - reviewed
        transaction_criteria:
          type: object
          description: The set of properties used to identify matching
            transactions.
          properties:
            start_date:
              type: string
              format: date
              nullable: true
              description: The beginning of the date range for matching
                transactions. If `null`, any transactions before end_date may be
                considered.
            end_date:
              type: string
              format: date
              nullable: true
              description: The end of the date range for matching transactions.
                If `null`, any transactions after start_date may be considered.
            granularity:
              type: string
              description: The unit of time used to define the cadence of the
                recurring item.
              enum:
                - day
                - week
                - month
                - year
            quantity:
              type: integer
              description: The number of granularity units between each
                recurrence.
            anchor_date:
              type: string
              format: date
              nullable: false
              description: The date used in conjunction with the `quantity` and
                `granularity` properties to calculate expected occurrences of
                recurring transactions.
            payee:
              type: string
              nullable: true
              description: If set, specifies the original transaction payee name
                that triggered this recurring item's creation.
            amount:
              type: string
              pattern: ^-?\d+(\.\d{1,4})?$
              description: The expected amount for a transaction that will match
                this recurring item. For recurring items that have a flexible
                amount this is the average of the specified min and max amounts.
            to_base:
              type: number
              description: The amount converted to the user's primary currency
            currency:
              type: string
              nullable: false
              description: Three-letter lowercase currency code of the recurring
                item.
            plaid_account_id:
              type: integer
              format: int64
              nullable: true
              description: The Plaid account ID associated with the recurring
                item, if any.
            manual_account_id:
              type: integer
              format: int64
              nullable: true
              description: The manual account ID associated with the recurring
                item, if any.
          required:
            - start_date
            - end_date
            - granularity
            - quantity
            - anchor_date
            - payee
            - amount
            - to_base
            - currency
            - plaid_account_id
            - manual_account_id
        overrides:
          type: object
          description: The values that will be applied to matching transactions.
          properties:
            payee:
              type: string
              nullable: false
              description: If present, the payee name that will be displayed for
                any matching transactions.
            notes:
              type: string
              nullable: false
              description: If present, the notes that will be displayed for any
                matching transactions.
            category_id:
              type: integer
              nullable: false
              description: If present, the ID of the category that matching
                transactions will be assigned to.
        matches:
          type: object
          nullable: true
          description: Details on expected, found and missing transactions for
            the specified range. This will be `null` for recurring items with a
            `status` of `suggested`.
          properties:
            request_start_date:
              type: string
              format: date
              description: The beginning of the date range that this request
                used to find matching transactions.
            request_end_date:
              type: string
              format: date
              description: The beginning of the date range that this request
                used to find matching transactions.
            expected_occurrence_dates:
              type: array
              items:
                type: string
                format: date
              description: A list of dates within the specified range where a
                recurring transactions is expected.
            found_transactions:
              type: array
              description: A list with the dates and IDs of matching
                transactions.
              items:
                type: object
                properties:
                  date:
                    type: string
                    format: date
                    description: The date for a matching transaction within the
                      specified range.
                  transaction_id:
                    type: integer
                    description: The ID of a matching transaction within the
                      specified range.
            missing_transaction_dates:
              type: array
              items:
                type: string
                format: date
              description: A list of dates within the range of where a recurring
                transaction was expected but none was found.
        created_by:
          type: integer
          nullable: false
          description: The ID of the user who created the recurring item.
        created_at:
          type: string
          format: date-time
          nullable: false
          description: Date/time the recurring item was created in ISO 8601
            extended format.
        updated_at:
          type: string
          format: date-time
          nullable: false
          description: Date/time the recurring item was updated in ISO 8601
            extended format.
        source:
          type: string
          description: >
            This can be one of four values:

            - `manual`: User created this recurring item manually from the
            Recurring Items page

            - `transaction`: User created this by converting a transaction from
            the Transactions page

            - `system`: Recurring item was created by the system on transaction
            import

            - `null`: Some older recurring items may not have a source.
          enum:
            - manual
            - transaction
            - system
      required:
        - id
        - description
        - status
        - transaction_criteria
        - overrides
        - matches
        - created_by
        - created_at
        - updated_at
        - source

    # The object containing information about a tag
    tagObject:
      type: object
      title: tag object
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int32
          description: Unique identifier for the tag.
        name:
          type: string
          description: Name of the tag.
        description:
          type: string
          nullable: true
          description: Description of the tag.
        text_color:
          type: string
          nullable: true
          description: The text color of the tag.
        background_color:
          type: string
          nullable: true
          description: The background color of the tag.
        updated_at:
          type: string
          format: date-time
          nullable: false
          description: The date and time of when the tag was last updated (in
            the ISO 8601 extended format).
        created_at:
          type: string
          format: date-time
          nullable: false
          description: The date and time of when the tag was created (in the ISO
            8601 extended format).
        archived:
          type: boolean
          description: If `true`, the tag will not show up when creating or
            updating transactions in the Lunch Money app.
        archived_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time of when the tag was last archived or
            `null` if not archived
      required:
        - id
        - name
        - description
        - text_color
        - background_color
        - created_at
        - updated_at
        - archived
        - archived_at

    # The object that may be submitted to POST /tags
    createTagRequestObject:
      type: object
      additionalProperties: false
      x-internal: true
      properties:
        name:
          type: string
          nullable: false
          description: |-
            The name of the new tag. Must be between 1 and 100 characters.
            Must not match the name of any existing tags.
          minLength: 1
          maxLength: 100
        description:
          type: string
          nullable: true
          default: null
          description: The description of the tag. Must not exceed 200
            characters.
          maxLength: 200
        text_color:
          type: string
          nullable: true
          description: The text color of the tag.
        background_color:
          type: string
          nullable: true
          description: The background color of the tag.
        archived:
          type: boolean
          default: false
          description: If `true`, the tag is archived and not displayed in
            relevant areas of the Lunch Money app.
      required:
        - name

    # The object that may be submitted to PUT /tags/:id
    updateTagRequestObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: false
          description: If set, the new name of the tag. Must be between 1 and
            100. characters.
          minLength: 1
          maxLength: 100
          x-updatable: true
        description:
          type: string
          nullable: true
          description: If set, the new description of the tag. Must not exceed
            200. characters.
          maxLength: 200
          x-updatable: true
        text_color:
          type: string
          nullable: true
          description: The text color of the tag.
          x-updatable: true
        background_color:
          type: string
          nullable: true
          description: The background color of the tag.
          x-updatable: true
        archived:
          type: boolean
          description: If set, determines whether this tag is archived.
          x-updatable: true
        id:
          type: integer
          format: int32
          description: System-defined unique identifier for the tag. Ignored if
            set.
          x-updatable: false
        updated_at:
          type: string
          format: date-time
          nullable: false
          description: System-set time the tag was last updated. Ignored if set
          x-updatable: false
        created_at:
          type: string
          format: date-time
          nullable: false
          description: System-set time the tag was created. Ignored if set.
          x-updatable: false
        archived_at:
          type: string
          format: date-time
          nullable: true
          description: If set, updates the archived timestamp for the tag.
            Provide an ISO 8601 extended datetime or `null` to clear it.
          x-updatable: true

    # The object returned when a DELETE /tag/:id request 
    # has an id for a tag that has dependencies  
    deleteTagResponseWithDependencies:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        tag_name:
          type: string
          description: The name of the tag
        dependents:
          type: object
          properties:
            rules:
              type: integer
              description: The number of rules depending on the tag
            transactions:
              type: integer
              description: The number of transactions with the tag
          required:
            - rules
            - transactions
      required:
        - tag_name
        - dependents

    # The primary object that represents a transaction
    transactionObject:
      type: object
      title: transaction object
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int64
          description: System-created unique identifier for the transaction
        date:
          type: string
          format: date
          description: Transaction date in ISO 8601 format
        amount:
          type: string
          description: Amount of the transaction in numeric format to 4 decimal
            places. Positive values indicate a debit transaction, negative
            values indicate a credit transaction.
        currency:
          description: Three-letter lowercase currency code of the transaction
            in ISO 4217 format.
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
        to_base:
          type: number
          format: double
          description: The amount converted to the user's primary currency. If
            the multi-currency feature is not being used, to_base and amount
            will be the same. Positive values indicate a debit transaction,
            negative values indicate a credit transaction.
        recurring_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the associated recurring item
            that this transaction matched.
        payee:
          type: string
          description: |
            Name of payee set by the user, the financial institution, or by 
            a matched recurring item. This will match the value 
            displayed in payee field on the transactions page in the Lunch Money app.
        original_name:
          type: string
          nullable: true
          description: Original payee name from the source (financial
            institution, CSV, etc.). For Plaid transactions, this is the raw
            name before normalization. For manual/API transactions, this
            typically matches `payee`. May be null for older transactions.
        category_id:
          type: integer
          format: int32
          nullable: true
          description: Unique identifier of associated category set by the user
            or by a matched recurring_item.<br> Category details can be obtained
            by passing the value of this property to the [Get A Single
            Category](../operations/getCategoryById) API
        plaid_account_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the plaid account associated
            with this transaction. This will always be null if this transaction
            is associated with a manual account or if this transaction has no
            associated account and appears as a "Cash Transaction" in the Lunch
            Money app.
        manual_account_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the manual account associated
            with this transaction. This will always be null if this transaction
            is associated with a synced account or if this transaction has no
            associated account and appears as a "Cash Transaction" in the Lunch
            Money app.
        external_id:
          type: string
          nullable: true
          description: A user-defined external ID for any transaction that was
            added via csv import, `POST /transactions` API call, or manually
            added via the Lunch Money app. No external ID exists for
            transactions associated with synced accounts, and they cannot be
            added. For transactions associated with manual accounts, the
            external ID must be unique as attempts to add a subsequent
            transaction with the same external_id and manual_account_id will be
            flagged as duplicates and fail.
          minLength: 0
          maxLength: 75
        tag_ids:
          type: array
          nullable: false
          description: A list of tag_ids for the tags associated with this
            transaction. If the transaction has no tags this will be an empty
            list.<br> Tag details can be obtained by passing the value of this
            attribute as the `ids` query parameter to the [List
            Tags](../operations/getTags) API
          items:
            type: integer
            format: int32
        notes:
          type: string
          nullable: true
          description: |
            Any transaction notes set by the user or by 
            a matched recurring item. This will match the value 
            displayed in notes field on the transactions page in the Lunch Money app.
        status:
          type: string
          # description: >
          #   Status of the transaction.  Will be one of the following values:
          # x-enumDescriptions:
          #   reviewed: User has reviewed the transaction, or it was automatically marked as reviewed due to reviewed recurring_item logic
          #   unreviewed: User has not reviewed the transaction and it does not match any reviewed recurring_items.
          #   delete_pending: The synced account deleted this transaction after it was updated by the user. Requires manual intervention.
          description: >
            Status of the transaction:

            - `reviewed`: User has reviewed the transaction, or it was
            automatically marked as reviewed due to reviewed recurring_item
            logic

            - `unreviewed`: User has not reviewed the transaction and it does
            not match any reviewed recurring_items. Note that any transactions 
            where `is_pending` is true will be returned with a status of unreviewed.

            - `delete_pending`: The synced account deleted this transaction
            after it was updated by the user. Requires manual intervention.

          enum:
            - reviewed
            - unreviewed
            - delete_pending
        is_pending:
          type: boolean
          description: Denotes if the transaction is pending (not posted).
            Applies only to transactions in synced accounts and will always be
            false for transactions associated with manual accounts.
        created_at:
          type: string
          format: date-time
          description: The date and time of when the transaction was created (in
            the ISO 8601 extended format).
        updated_at:
          type: string
          format: date-time
          description: The date and time of when the transaction was last
            updated (in the ISO 8601 extended format).
        is_split_parent:
          type: boolean
          description: If `true`, this transaction has been split into two or
            more other transactions. By default, parent transactions are not
            returned in call to `GET /transactions` but they can be queried
            directly by their ID.
        split_parent_id:
          type: integer
          format: int64
          nullable: true
          description: A transaction ID if this is a split transaction. Denotes
            the transaction ID of the original, or parent, transaction. Is null
            if this is not a split transaction
        is_group_parent:
          type: boolean
          description: "`true` if this transaction represents a group of
            transactions. If so, amount and currency represent the totalled
            amount of transactions bearing this transaction's id as their
            group_parent_id. Amount is calculated based on the user's primary
            currency."
        group_parent_id:
          type: integer
          format: int64
          nullable: true
          description: If set, this transaction is part of a group. Denotes the
            ID of the grouped transaction that it is included in. By default,
            the transactions that were grouped are not returned in a call to
            `GET /transactions` but they can be queried directly by calling the
            `GET /transactions/group/{id}`, where the id passed is associated
            with a transaction where the `is_group_parent` attribute is true.
        children:
          type: array
          nullable: false
          items:
            $ref: "#/components/schemas/childTransactionObject"
          description: Exists only for transactions which are the parent of a
            split transaction or for transaction groups. It will not exist in
            the response unless the `include_children` query parameter is set to
            `true`.<br> For parents of split transactions, it contains a list of
            the associated transactions that it was split into. For transaction
            groups, it contains the transactions that were grouped together.
            Examine the `is_split_parent` and `is_group_parent` properties to
            determine which of these it is.
        plaid_metadata:
          type: object
          nullable: true
          description: If requested, the transaction's plaid_metadata that came
            when this transaction was obtained. This will be a JSON object, but
            the schema is variable. This is only present when the
            `include_metadata` query parameter is set to true.
        custom_metadata:
          type: object
          nullable: true
          description: If requested, the transaction's custom_metadata that was
            included when the transaction was inserted via the API. This will be
            a JSON object, but the schema is variable. This is only present when
            the `include_metadata` query parameter is set to true.
        files:
          type: array
          nullable: false
          description: A list of objects that describe any attachments to the
            transaction. This is only present when the `include_files` query
            parameter is set to true.
          items:
            $ref: "#/components/schemas/transactionAttachmentObject"
        source:
          type: string
          nullable: true
          description: >
            Source of the transaction:

            - `api`: Transaction was added by a call to the [POST
            /transactions](../operations/createTransaction) API

            - `csv`: Transaction was added via a CSV Import

            - `manual`: Transaction was created via the "Add to Cash" button on
            the Transactions page

            - `merge`: Transactions were originally in an account that was
            merged into another account

            - `plaid`: Transaction came from a Financial Institution synced via
            Plaid

            - `recurring`: Transaction was created from the Recurring page 

            - `rule`: Transaction was created by a rule to split a transaction

            - `split`: Transaction was created by splitting another
            transaction

            - `user`: This is a legacy value and is replaced by either csv or
            manual
          enum:
            - api
            - csv
            - manual
            - merge
            - plaid
            - recurring
            - rule
            - split
            - user
      required:
        - id
        - date
        - amount
        - currency
        - to_base
        - recurring_id
        - payee
        - category_id
        - notes
        - status
        - is_pending
        - created_at
        - updated_at
        - split_parent_id
        - is_group_parent
        - group_parent_id
        - manual_account_id
        - plaid_account_id
        - tag_ids
        - source
        - external_id

    # The childTransactionObject is basically a transactionObject that has no
    # `children` attribute which should not be present on grouped or split 
    # transactions.
    childTransactionObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int64
          description: System-created unique identifier for the transaction
        date:
          type: string
          format: date
          description: Transaction date in ISO 8601 format
        amount:
          type: string
          description: Amount of the transaction in numeric format to 4 decimal
            places. Positive values indicate a debit transaction, negative
            values indicate a credit transaction.
        currency:
          description: Three-letter lowercase currency code of the transaction
            in ISO 4217 format
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
        to_base:
          type: number
          format: double
          description: The amount converted to the user's primary currency. If
            the transaction currency is the same as the user's primary currency,
            to_base and amount will be the same. Positive values indicate a
            debit transaction, negative values indicate a credit transaction.
        recurring_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the associated recurring item
            that this transaction matched.
        payee:
          type: string
          description: |
            Name of payee set by the user, the financial institution, or by 
            a matched recurring item. This will match the value 
            displayed in payee field on the transactions page in the Lunch Money app.
        original_name:
          type: string
          nullable: true
          description: Original payee name from the source (financial
            institution, CSV, etc.). For Plaid transactions, this is the raw
            name before normalization. For manual/API transactions, this
            typically matches `payee`. May be null for older transactions.
        category_id:
          type: integer
          format: int32
          nullable: true
          description: Unique identifier of associated category set by the user
            or by a matched recurring item.<br> Category details can be obtained
            by passing the value of this property to the [Get A Single
            Category](../operations/getCategoryById) API
        notes:
          type: string
          nullable: true
          description: |
            Any transaction notes set by the user or by 
            a matched recurring item. This will match the value 
            displayed in notes field on the transactions page in the Lunch Money app.
        status:
          type: string
          description: >
            Status of the transaction.  Will be one of the following values:
          x-enumDescriptions:
            reviewed: User has reviewed the transaction, or it was automatically marked as reviewed due to reviewed recurring item logic
            unreviewed: User has not reviewed the transaction and it does not match any reviewed recurring_items. Note that any transactions where `is_pending` is true will be returned with a status of unreviewed.
            delete_pending: The synced account deleted this transaction after it was updated by the user. Requires manual intervention.
          # description: >
          #   Status of the transaction:

          #   - `reviewed`: User has reviewed the transaction, or it was
          #   automatically marked as reviewed due to reviewed recurring_item
          #   logic

          #   - `unreviewed`: User has not reviewed the transaction and it does
          #   not match any reviewed recurring_items.

          #   - `delete_pending`: The synced account deleted this transaction
          #   after it was updated by the user. Requires manual intervention.

          enum:
            - reviewed
            - unreviewed
            - delete_pending
        is_pending:
          type: boolean
          description: Denotes if the transaction is pending (not posted).
            Applies only to transactions in synced accounts and will always be
            false for transactions associated with manual accounts.
        created_at:
          type: string
          format: date-time
          description: The date and time of when the transaction was created (in
            the ISO 8601 extended format).
        updated_at:
          type: string
          format: date-time
          description: The date and time of when the transaction was last
            updated (in the ISO 8601 extended format).
        is_split_parent:
          type: boolean
          description: If `true`, this transaction has been split into two or
            more other transactions. By default, parent transactions are not
            returned in call to `GET /transactions` but they can be queried
            directly by their ID.
        split_parent_id:
          type: integer
          format: int64
          nullable: true
          description: A transaction ID if this is a split transaction. Denotes
            the transaction ID of the original, or parent, transaction. Is null
            if this is not a split transaction
        is_group_parent:
          type: boolean
          description: True if this transaction represents a group of
            transactions. If so, amount and currency represent the totalled
            amount of transactions bearing this transaction's id as their
            group_parent_id. Amount is calculated based on the user's primary
            currency.
        group_parent_id:
          type: integer
          format: int64
          nullable: true
          description: If set, this transaction is part of a group. Denotes the
            ID of the grouped transaction that it is included in. By default,
            the transactions that were grouped are not returned in a call to
            `GET /transactions` but they can be queried directly by calling the
            `GET /transactions/group/{id}`, where the id passed is associated
            with a transaction where the `is_group_parent` attribute is true.
        manual_account_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the manual account associated
            with this transaction. This will always be null if this transaction
            is associated with a synced account or if this transaction has no
            associated account and appears as a "Cash Transaction" in the Lunch
            Money app.
        plaid_account_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the plaid account associated
            with this transaction. This will always be null if this transaction
            is associated with a manual account or if this transaction has no
            associated account and appears as a "Cash Transaction" in the Lunch
            Money app.
        tag_ids:
          type: array
          nullable: false
          description: A list of tag_ids for the tags associated with this
            transaction. If the transaction has no tags this will be an empty
            list.<br> Tag details can be obtained by passing the value of this
            attribute as the `ids` query parameter to the [List
            Tags](../operations/getTags) API
          items:
            type: integer
            format: int32
        source:
          type: string
          nullable: true
          description: >
            Source of the transaction:

            - `api`: Transaction was added by a call to the [POST
            /transactions](../operations/createTransaction) API

            - `csv`: Transaction was added via a CSV Import

            - `manual`: Transaction was created via the "Add to Cash" button on
            the Transactions page

            - `merge`: Transactions were originally in an account that was
            merged into another account

            - `plaid`: Transaction came from a Financial Institution synced via
            Plaid

            - `recurring`: Transaction was created from the Recurring page 

            - `rule`: Transaction was created by a rule to split a transaction

            - `split`: This is a transaction created by splitting another
            transaction

            - `user`: This is a legacy value and is replaced by either csv or
            manual
          enum:
            - api
            - csv
            - manual
            - merge
            - plaid
            - recurring
            - rule
            - split
            - user
        external_id:
          type: string
          nullable: true
          description: A user-defined external ID for any transaction that was
            added via csv import, `POST /transactions` API call, or manually
            added via the Lunch Money app. No external ID exists for
            transactions associated with synced accounts, and they cannot be
            added. For transactions associated with manual accounts, the
            external ID must be unique as attempts to add a subsequent
            transaction with the same external_id and manual_account_id will be
            flagged as duplicates and fail.
          minLength: 0
          maxLength: 75
        plaid_metadata:
          type: object
          nullable: true
          description: If requested, the transaction's plaid_metadata that came
            when this transaction was obtained. This will be a JSON object, but
            the schema is variable. This will only be present for transactions
            associated with a plaid account.
        custom_metadata:
          type: object
          nullable: true
          description: If requested, the transaction's custom_metadata that was
            included when the transaction was inserted via the API. This will be
            a JSON object, but the schema is variable.
        files:
          type: array
          nullable: false
          description: A list of objects that describe any attachments to the
            transaction
          items:
            $ref: "#/components/schemas/transactionAttachmentObject"
      required:
        - id
        - date
        - amount
        - currency
        - to_base
        - recurring_id
        - payee
        - category_id
        - notes
        - status
        - is_pending
        - created_at
        - updated_at
        - split_parent_id
        - is_group_parent
        - group_parent_id
        - manual_account_id
        - plaid_account_id
        - tag_ids
        - source
        - external_id
    
    # The request object for a POST /transactions request 
    # It contains only user settable properties.
    insertTransactionObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        date:
          type: string
          format: date
          description: Transaction date in ISO 8601 format
        amount:
          oneOf:
            - type: number
              format: double
            - type: string
              pattern: ^-?\d+(\.\d{1,4})?$
          description: Numeric value of the amount without a currency symbol.
            For example, $4.25 should be provided as 4.25. May be a string or a
            number in double format. Positive values indicate a debit
            transaction, negative values indicate a credit transaction.
        currency:
          description: Three-letter lowercase currency code of the transaction
            in ISO 4217 format. Must match one of the [supported
            currencies](https://lm-v2-api-next-a7fabcab8e9a.herokuapp.com/v2/currencies). If not set
            defaults to the user account's primary currency.
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
        payee:
          type: string
          description: Name of payee for the transaction
        original_name:
          type: string
          nullable: true
          description: Original payee name. If not provided, defaults to `payee`
            value.
        category_id:
          type: integer
          format: int32
          nullable: true
          description: The ID of the category associated with the transaction.
            If set, the category ID must exist for the user's account and it
            cannot be a category group.
        notes:
          type: string
          nullable: true
          description: |
            Any transaction notes set by the user or by 
            a matched recurring item. This will match the value 
            displayed in notes field on the transactions page in the Lunch Money app.
        manual_account_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the associated manual account.
            If set, this must match an existing manual account id associated
            with the user's account. If not set, and `plaid_account_id` is also
            not set, no account is associated with the transaction and it will
            appear as a "Cash Transaction" in the Lunch Money app. It is an
            error if this and `plaid_account_id` are both set on the same
            transaction.
        plaid_account_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the associated Plaid account. If
            set, this must match an existing plaid account id associated with
            the user's account. If not set, and `manual_account_id` is also not
            set, no account is associated with the transaction and it will
            appear as a "Cash Transaction" in the Lunch Money app. It is an
            error if this and `manual_account_id` are both set on the same
            transaction. In addition the specified plaid account must have the
            "Allow Modifications To Transactions" property set (which is enabled
            by default), or the insert will fail.
        recurring_id:
          type: integer
          format: int32
          nullable: true
          description: Unique identifier for associated recurring item.
            Recurring item must be associated with the same account.
        status:
          type: string
          description: If set, must be either `reviewed` or `unreviewed`. If not
            set, defaults to `unreviewed`.
          enum:
            - reviewed
            - unreviewed
        tag_ids:
          type: array
          nullable: false
          description: A list of IDs for the tags associated with this
            transaction. Each ID must match an existing tag associated with the
            user's account. If not set, no tags will be associated with the
            created transaction.
          items:
            type: integer
            format: int32
        external_id:
          type: string
          nullable: true
          description: A user-defined external ID for the transaction. If set,
            and `manual_account_id` is set, the creation of the new transaction
            will fail if a transaction with this id already exists for the
            specified manual account.
          minLength: 0
          maxLength: 75
        custom_metadata:
          type: object
          nullable: true
          description: An optional JSON object that includes additional data
            related to this transaction. This must be a valid JSON object and,
            when stringified, must not exceed 4096 characters. This data may be
            available in the future for processing by rules.
          additionalProperties: true
      required:
        - date
        - amount

    # The object that may be submitted to PUT /transactions/:id
    # System set properties such as id and created_at are tolerated but ignored
    updateTransactionObject:
      type: object
      x-internal: true
      additionalProperties: false
      properties:
        id:
          type: integer
          format: int64
          description: System defined unique identifier of this transaction.
            Ignored if set.
          x-updatable: false
        date:
          type: string
          format: date
          description: Transaction date in ISO 8601 format
          x-updatable: true
        amount:
          oneOf:
            - type: number
              format: double
            - type: string
              pattern: ^-?\d+(\.\d{1,4})?$
          description: Numeric value of the amount without a currency symbol.
            For example, $4.25 should be provided as 4.25. May be a string or a
            number in double format. Positive values indicate a debit
            transaction, negative values indicate a credit transaction. <br> May
            not be updated on transactions that belong to a synced account with
            the "Allow Modifications to Transactions" property disabled.
          x-updatable: true
        currency:
          description: Three-letter lowercase currency code of the transaction
            in ISO 4217 format.<br> May not be updated on transactions that
            belong to a synced account with the "Allow Modifications to
            Transactions" property disabled.
          x-updatable: true
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
        recurring_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the associated recurring item
            that this transaction matches.
          x-updatable: true
        payee:
          type: string
          description: |
            The new payee for the transaction.
          minLength: 0
        original_name:
          type: string
          nullable: true
          description: Original payee name. Cannot be changed. Ignored if set.
          x-updatable: false
        category_id:
          type: integer
          format: int32
          nullable: true
          description: Unique identifier of the category for this transaction.
            Set this to null to clear the transaction's category.
          x-updatable: true
        notes:
          type: string
          nullable: true
          description: >
            New notes for the transaction. Set this to an empty string to clear
            the existing notes.
          x-updatable: true
        manual_account_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the manual account associated
            with this transaction. Set this to null to disassociate the
            transaction with an account. If set, `plaid_account_id` may not also
            be set to a non null value. Moving an existing transaction to
            another account will not work if the transaction belongs to a synced
            account whose "Allow Modifications to Transactions" property is not
            set.
          x-updatable: true
        plaid_account_id:
          type: integer
          format: int32
          nullable: true
          description: The unique identifier of the Plaid account associated
            with this transaction. If set, `manual_account_id` may not also be
            set to a non null value. Attempting to modify this on a transaction
            associated with a Plaid account will not work if the account's
            "Allow Modifications to Transactions" property is not set.
            Similarly, this cannot be set to an id associated with this type of
            locked Plaid account.
          x-updatable: true
        tag_ids:
          type: array
          nullable: false
          description: A list of tag_ids for the tags associated with this
            transaction. If set, this property will overwrite any existing tags.
            Use `additional_tag_ids` to add tags to the existing transaction's
            tags. Set this to an empty array to remove all tags from a
            transaction. If set `additional_tag_ids` may not be set.
          x-updatable: true
          items:
            type: integer
            format: int32
        additional_tag_ids:
          type: array
          nullable: false
          description: A list of tag_ids for the tags associated with this
            transaction. If set, the tags listed in this property will be added
            to any existing transaction tags. Use `tag_ids` to overwrite or
            clear transaction tags. If set, `tag_ids` may not be set.
          x-updatable: true
          items:
            type: integer
            format: int32
        external_id:
          type: string
          nullable: true
          description: A user-defined external ID for the transaction. The
            update will fail if the transaction does not also have a
            `manual_account_id` or if there is already an existing transaction
            with the same `manual_account_id`/`external_id` combination.
          minLength: 0
          maxLength: 75
          x-updatable: true
        custom_metadata:
          type: object
          nullable: true
          description: User defined JSON data that can be set or cleared via the
            API.
          x-updatable: true
        status:
          type: string
          description: >
            Status of the transaction, may be one of:

            - `reviewed`: User has reviewed the transaction, or it was
            automatically marked as reviewed due to reviewed recurring_item
            logic

            - `unreviewed`: User has not reviewed the transaction and it does
            not match any reviewed recurring_items.
          enum:
            - reviewed
            - unreviewed
          x-updatable: true
        to_base:
          type: number
          format: double
          description: System defined amount of this transaction in the user's
            primary currency. Ignored if set. Use `amount` to update the amount
            in the transaction.
          x-updatable: false
        is_pending:
          type: boolean
          description: System defined flag set for pending transactions. Ignored
            if set.
          x-updatable: false
        plaid_metadata:
          type: object
          nullable: true
          description: System set metadata from a Plaid account sync. Ignored if
            set.
          x-updatable: false
        created_at:
          type: string
          format: date-time
          description: System defined date and time of when the transaction was
            created. Ignored if set.
          x-updatable: false
        updated_at:
          type: string
          format: date-time
          description: System defined date and time of when the transaction was
            last updated. Ignored if set.
          x-updatable: false
        is_split_parent:
          type: boolean
          description: System defined boolean indicating if this transaction was
            split. To split or unsplit a transaction use the
            `/transactions/split` endpoint. Ignored if set.
          x-updatable: false 
        children:
          type: array
          nullable: false
          items:
            $ref: "#/components/schemas/childTransactionObject"
          description: An array of child transactions present when a transaction
            has been split or when the transaction is a group. Split and grouped
            transactions may not be modified using this API. Ignored if set.
          x-updatable: false
        split_parent_id:
          type: integer
          format: int64
          nullable: true
          description: A transaction ID if this is a split transaction. Split
            transactions may not be modified this API. Use the
            `transactions/split` endpoint instead. Ignored if set.
          x-updatable: false
        is_group_parent:
          type: boolean
          description: System defined boolean indicating if this transaction
            represents a group of transactions. Grouped transactions may not be
            modified with this API. Use the `transactions/group` endpoint
            instead. Ignored if set.
          x-updatable: false
        group_parent_id:
          type: integer
          format: int64
          nullable: true
          description: A transaction group ID if this transaction is part of a
            group. Grouped transactions may not be modified with this API. Use
            the `transactions/group` endpoint instead. Ignored if set.
          x-updatable: false
        source:
          type: string
          nullable: true
          description: |
            System defined original source of the transaction. Ignored if set.
          x-updatable: false
          enum:
            - api
            - csv
            - manual
            - merge
            - plaid
            - recurring
            - rule
            - split
            - user

    # The object that may be submitted to PUT /transactions/split
    splitTransactionObject:
      type: object
      additionalProperties: false
      x-internal: true
      description: The object representing a split transaction
      properties:
        amount:
          oneOf:
            - type: number
              format: double
            - type: string
              pattern: ^-?\d+(\.\d{1,4})?$
          description: Individual amount of split. Currency will inherit from
            parent transaction. All amounts must sum up to parent transaction
            amount.
        payee:
          type: string
          minLength: 0
          description: The payee for the child transaction. Will inherit the
            original payee from the parent if not defined.
        date:
          type: string
          format: date
          description: Must be in ISO 8601 format (YYYY-MM-DD). Will inherit
            from the parent if not defined.
        category_id:
          type: integer
          format: int32
          description: Unique identifier for associated category_id. Category
            must already exist for the account. Will inherit category from the
            parent if not defined.
        tag_ids:
          type: array
          description: The IDs of any tags to apply to this split child
            transaction. Each ID must match an existing tag.
          items:
            type: integer
            format: int32
        notes:
          type: string
          description: Will inherit notes from parent if not defined.
      required:
        - amount

    # The object returned when a new transaction duplicates one that
    # already exists
    skippedExistingExternalIdObject:
      type: object
      x-internal: true
      additionalProperties: false
      description: The object returned when a new transaction has an external_id
        that already exists
      properties:
        reason:
          type: string
          description: >
            The reason the transaction was skipped, may be one of:

            - `duplicate_external_id`: The transaction has the same
            `manual_account_id` and `external_id` as an existing transaction

            - `duplicate_payee_amount_date`: The `skip_duplicates` request body
            property was set to `true` and the transaction has the same
            `amount`, `payee`, and `date` as an existing
            transaction associated with the same account.
          enum:
            - duplicate_external_id
            - duplicate_payee_amount_date
        request_transactions_index:
          type: integer
          format: int64
          description: The index of the transaction in the request body's
            transactions array that was skipped.
        existing_transaction_id:
          type: integer
          format: int64
          description: The id of the existing transactions that the requested
            transaction duplicates.
        request_transaction:
          type: object
          description: The requested transaction that was skipped.
          allOf:
            - $ref: "#/components/schemas/insertTransactionObject"

    # The object returned from a successful POST /transactions request
    insertTransactionsResponseObject:
      type: object
      x-internal: true
      additionalProperties: false
      description: The object returned from a successful POST /transactions
        request
      properties:
        transactions:
          description: An array of the inserted transactions.
          items:
            $ref: "#/components/schemas/transactionObject"
          type: array
        skipped_duplicates:
          description: An array of the requested transactions that were
            duplicates of existing transactions and were not inserted.
          items:
            $ref: "#/components/schemas/skippedExistingExternalIdObject"
          type: array
      required:
        - transactions
        - skipped_duplicates

    # The object containing information about a file attached to a transaction
    transactionAttachmentObject:
      type: object
      title: transaction attachment object
      additionalProperties: false
      # description: An object containing information about a file attached to a transaction
      properties:
        id:
          type: integer
          format: int32
          description: The unique identifier of the attachment
        uploaded_by:
          type: integer
          format: int64
          description: The id of the user who uploaded the attachment
        name:
          type: string
          description: The name of the file
        type:
          type: string
          description: The MIME type of the file
        size:
          type: integer
          description: The size of the file in kilobytes
        notes:
          type: string
          nullable: true
          description: Optional notes about the attachment
        created_at:
          type: string
          format: date-time
          description: The date and time when the attachment was created in ISO
            8601 format

    # Object that describes a budget's amount, category and start_date
    budgetObject:
      type: object
      title: budget object
      additionalProperties: false
      description: "A budget object represents a budgeted amount for a specific
        category and budget period. Each budget entry is tied to a specific time
        period defined by its `start_date`. The budget object includes
        information about the budget amount, currency, period settings, and how
        future periods will be automatically calculated."
      properties:
        id:
          type: integer
          format: int64
          description: System-created unique identifier for the budget entry.
        category_id:
          type: integer
          format: int32
          description: The ID of the category this budget applies to.
        amount:
          type: number
          format: double
          description: The budgeted amount for this period.
        currency:
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
          description: The currency of the budgeted amount in ISO 4217 format.
        start_date:
          type: string
          format: date
          description: The start date of the budget period in ISO 8601 format
            (YYYY-MM-DD). This represents the beginning of the period for which
            this budget applies.
        next_start_date:
          type: string
          format: date
          readOnly: true
          description: The calculated start date of the next budget period based
            on the category's period settings (granularity, quantity, and
            anchor_date). This is useful for determining when the next budget
            period begins.
        notes:
          type: string
          nullable: true
          description: Optional notes associated with this budget period.
        auto_budget_type:
          type: string
          readOnly: true
          enum:
            - nothing
            - fixed
            - spend
            - budget
          description: "The budget preset type that determines how future
            periods will be automatically calculated. `nothing` means no
            automatic calculation (budgets must be set manually for each
            period). `fixed` uses a fixed amount for all future periods. `spend`
            uses the previous period's spending amount. `budget` uses the
            previous period's budgeted amount."
        auto_budget_amount:
          type: number
          format: double
          nullable: true
          readOnly: true
          description: "If `auto_budget_type` is `fixed`, this is the fixed
            amount that will be used for future periods."
        auto_budget_currency:
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
          nullable: true
          readOnly: true
          description: "If `auto_budget_type` is `fixed`, this is the currency
            of the fixed amount."
        rollover_option:
          type: string
          nullable: true
          readOnly: true
          enum:
            - same category
            - available funds
          description: "The rollover setting for this category. `same category`
            means unspent funds roll over to the next period for this category.
            `available funds` means unspent funds are added to the available
            funds pool. `null` means rollover is disabled."
        granularity:
          type: string
          readOnly: true
          enum:
            - month
            - week
            - twice a month
          description: "The granularity of the budget period (e.g., monthly,
            weekly, twice a month). This is determined by the category's custom
            budget settings or the account's default budget period settings."
        quantity:
          type: integer
          format: int32
          readOnly: true
          description: "The quantity of granularity units that make up each
            budget period. For example, if granularity is `week` and quantity is
            `2`, each budget period is 2 weeks."
        is_group:
          type: boolean
          readOnly: true
          description: "Whether the category is a category group. Category
            groups can have their own budgets that apply to all subcategories,
            or subcategories can have individual budgets."
        group_id:
          type: integer
          format: int32
          nullable: true
          readOnly: true
          description: "If this budget is for a subcategory, this is the ID of
            the parent category group. `null` if this is not a subcategory."
        created_at:
          type: string
          format: date-time
          description: The date and time when this budget entry was created (in
            ISO 8601 extended format).
        updated_at:
          type: string
          format: date-time
          description: The date and time when this budget entry was last updated
            (in ISO 8601 extended format).
      required:
        - id
        - category_id
        - amount
        - currency
        - start_date
        - next_start_date
        - auto_budget_type
        - granularity
        - quantity
        - is_group
        - created_at
        - updated_at

    # Request body for PUT /budgets (upsert)
    upsertBudgetRequestObject:
      x-internal: true
      type: object
      additionalProperties: false
      properties:
        start_date:
          type: string
          format: date
          description: Start date of the budget period in ISO 8601 date format
            (YYYY-MM-DD). Must be a valid budget period start for the account.
        category_id:
          type: integer
          format: int32
          description: Category ID for the budget
        amount:
          oneOf:
            - type: number
              format: double
            - type: string
              pattern: ^-?\d+(\.\d{1,4})?$
          description: Budget amount. May be a string or a number in double
            format.
        currency:
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
          description: Three-letter currency code. If omitted, the primary
            currency for the user's account is used.
        notes:
          type: string
          nullable: true
          description: Optional notes for the budget period
          minLength: 0
          maxLength: 350
      required:
        - start_date
        - category_id
        - amount

    # Response body for PUT /budgets (200)
    budgetUpsertResponseObject:
      x-internal: true
      type: object
      properties:
        category_id:
          type: integer
          format: int32
          description: Category ID
        start_date:
          type: string
          format: date
          description: Start date of the budget period
        amount:
          type: string
          description: Budget amount in the stored currency (string for
            consistency with other amount fields in the API).
        currency:
          type: string
          description: Currency code for the budget
        to_base:
          type: number
          format: float
          description: Amount converted to the user's primary currency
        notes:
          type: string
          nullable: true
          description: Notes for the budget period

    # Response body for GET /budgets/settings (200)
    budgetSettingsResponseObject:
      x-internal: true
      type: object
      additionalProperties: false
      description: Budget period and display settings
      properties:
        budget_period_granularity:
          type: string
          enum:
          - day
          - week
          - month
          - year
          - twice a month
          description: Budget period granularity
        budget_period_quantity:
          type: number
          format: double
          description: The number of `granularity` units that make up a single
            budgeting period.
        budget_period_anchor_date:
          type: string
          format: date
          description: The date from which the budgeting period is calculated.
            All future (and past) periods are derived by applying `quantity` ×
            `granularity` forward and backward from this date.
        budget_hide_no_activity:
          type: boolean
          default: false
          description: Display preference for hiding categories in budget view
            that have no activity and no budgeted value
        budget_use_last_day_of_month:
          type: boolean
          default: false
          description: Display preference for using the last day of the month as
            the period end for monthly periods
        budget_income_option:
          type: string
          enum:
            - max
            - budgeted
            - activity
          description: Determines which income value is used as the base when
            calculating available funds for a budgeting period
        budget_rollover_left_to_budget:
          type: boolean
          default: false
          description: Determines whether the remaining unallocated funds (“Left
            to Budget”) at the end of a budgeting period are carried forward to
            the next period
      required:
        - budget_hide_no_activity
        - budget_period_quantity
        - budget_period_granularity
        - budget_period_anchor_date
        - budget_use_last_day_of_month
        - budget_income_option
        - budget_rollover_left_to_budget

    # Summary endpoint response schemas
    summaryResponseObject:
      type: object
      title: summary object
      additionalProperties: false
      description: Budget summary for the requested range
      properties:
        aligned:
          type: boolean
          description: "`true` if start_date and end_date are aligned with the
            user's budget period setting; `false` otherwise.<p> When the
            response is not aligned, category `totals` will not include values
            for the `budgeted` and `available` properties, so aligned responses
            are usually preferred.<p> If unsure how to set an aligned date
            range, set a range of at least one month and set the
            `include_occurrences` parameter to `true`. Then examine the objects
            in the `occurrences` array for the first category to find start and
            end dates that will produce aligned responses.  Setting
            `include_past_budget_dates` to `true` will add the three budget
            periods prior to the range in the `occurrences` array."
        categories:
          type: array
          items:
            $ref: "#/components/schemas/summaryCategoryObject"
        totals:
          $ref: "#/components/schemas/summaryTotalsObject"
        rollover_pool:
          nullable: true
          $ref: "#/components/schemas/summaryRolloverPoolObject"
      required:
        - aligned
        - categories

    summaryTotalsObject:
      x-internal: true
      type: object
      additionalProperties: false
      description: Total inflow and outflow for the given date range. This
        object is returned when the query parameter `include_totals` is set to
        `true`.
      properties:
        inflow:
          $ref: "#/components/schemas/summaryTotalsBreakdownObject"
        outflow:
          $ref: "#/components/schemas/summaryTotalsBreakdownObject"

    summaryTotalsBreakdownObject:
      type: object
      additionalProperties: false
      x-internal: true # Don't display in schemas section of docs
      properties:
        other_activity:
          description: Total amount, in the user's default currency, of
            non-recurring activity for the given date range
          type: number
        recurring_activity:
          description: Total amount, in the user's default currency, of
            recurring activity that has occurred for the given date range
          type: number
        recurring_remaining:
          description: Total amount, in the user's default currency, of expected
            recurring activity that has not yet occurred
          type: number
        recurring_expected:
          description: Total amount, in the user's default currency, of expected
            recurring activity for the given date range
          type: number
        uncategorized:
          description: Total amount, in the user's default currency, of
            non-recurring activity coming from uncategorized transactions
          type: number
        uncategorized_count:
          description: Number of uncategorized transactions for the given date
            range
          type: integer
        uncategorized_recurring:
          description: "Total amount, in the user's default currency, of
            recurring activity coming from uncategorized transactions."
          type: number

    summaryCategoryObject:
      x-internal: true
      type: object
      additionalProperties: false
      description: "List of each category's budget configuration and activity
        for the date range."
      properties:
        category_id:
          description: "ID of the category associated with the totals."
          type: integer
        totals:
          $ref: "#/components/schemas/summaryCategoryTotalsObject"
        occurrences:
          description: A list of objects describing the budget activity for each
            period within the range. This property is only present when
            `include_occurrences` is true.<p> For aligned ranges, there is one
            occurrence for each budget period in the range; for non-aligned,
            only periods fully contained in the range are included.<p> If
            `include_past_budget_dates` is also `true`, the three budget periods
            prior to the range are also included.
          type: array
          items:
            $ref: "#/components/schemas/summaryCategoryOccurrenceObject"
      required:
        - category_id
        - totals
    
    summaryRolloverPoolAdjustmentObject:
      type: object
      additionalProperties: false
      x-internal: true # Don't display in schemas section of docs
      description: "The date and adjusted balance of the rollover pool at the
        time of the adjustment."
      properties:
        in_range:
          description: "`true` if this rollover pool adjustment is for a budget
            period that falls within the given date range."
          type: boolean
        date:
          description: "Date the adjustment was made."
          type: string
          format: date
        amount:
          description: "Amount of the rollover pool, in the budget's currency,
            at the time of the adjustment."
          type: string
        currency:
          description: "Currency of the rollover pool at the time of the
            adjustment."
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
        to_base:
          description: "Amount of the rollover pool, in the user's default
            currency, at the time of the adjustment."
          type: number
      required:
        - in_range
        - date
        - amount
        - currency
        - to_base

    summaryCategoryTotalsObject:
      type: object
      additionalProperties: false
      x-internal: true # Don't display in schemas section of docs
      description: "Total activity for the given category within the given date
        range when it is aligned with the budget period setting."
      properties:
        other_activity:
          description: Total non-recurring activity, in the user's default
            currency, for the category within the given date range.<br> The
            total activity for the category is the sum of this and the
            recurring_activity.
          type: number
        recurring_activity:
          description: Total recurring activity, in the user's default currency,
            for the category within the given date range.<br> The total activity
            for the category is the sum of this and the other_activity.
          type: number
        budgeted:
          description: "Total budgeted amount, in the user's default currency,
            for the category within the given date range or null if the category
            is not budgeted. This property will not be present in a non-aligned
            response."
          type: number
          nullable: true
        available:
          description: "Total amount of funds available, in the user's default
            currency, for the category within the given date range. This
            property will not be present in a non-aligned response."
          type: number
          nullable: true
        recurring_remaining:
          description: "Total expected recurring activity, in the user's default
            currency, that has not yet occurred for the category within the
            given date range."
          type: number
        recurring_expected:
          description: "Total expected recurring activity for the category
            within the given date range."
          type: number
      required:
        - other_activity
        - recurring_activity
        - recurring_remaining
        - recurring_expected

    summaryCategoryOccurrenceObject:
      type: object
      additionalProperties: false
      x-internal: true # Don't display in schemas section of docs
      description: ""
      properties:
        in_range:
          description: "`true` if this occurrence is within the given date
            range, `false` if it was included because the
            `include_past_budget_periods` parameter was set to `true`."
          type: boolean
        start_date:
          description: The start date of the budget period
          type: string
          format: date
        end_date:
          description: The end date of the budget period
          type: string
          format: date
        other_activity:
          description: Total non-recurring activity, in the user's default
            currency, for the budget period. The total activity for this
            category in the period is the sum of this and the
            recurring_activity.
          type: number
        recurring_activity:
          description: Total recurring activity, in the user's default currency,
            for the budget period. The total activity for this category in the
            budget period is the sum of this and the other_activity.
          type: number
        budgeted:
          description: "Total budgeted amount, in the user's primary currency,
            for the period, or `null` if no budget was set."
          type: number
          nullable: true
        budgeted_amount:
          description: Total budgeted amount, in the budgeted currency, for the
            category within the period, or `null` if no budget was set.
          type: string
          nullable: true
        budgeted_currency:
          description: Currency of the budgeted amount
          nullable: true
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
        notes:
          description: "Any notes set for the budget period."
          type: string
          nullable: true
      required:
        - in_range
        - start_date
        - end_date
        - other_activity
        - recurring_activity
        - budgeted
        - budgeted_amount
        - budgeted_currency
        - notes

    summaryRecurringTransactionObject:
      type: object
      additionalProperties: false
      x-internal: true # Don't display in schemas section of docs
      description: "A single transaction associated with a recurring item."
      properties:
        date:
          type: string
          format: date
        category_id:
          type: integer
        payee:
          type: string
        to_base:
          type: number
        amount:
          type: string
        currency:
          allOf:
            - $ref: "#/components/schemas/currencyEnum"
      required:
        - date
        - category_id
        - payee
        - to_base
        - amount
        - currency

    summaryRolloverPoolObject:
      type: object
      additionalProperties: false
      x-internal: true # Don't display in schemas section of docs
      description: "Summary of the current rollover pool balance and all
        previous adjustments.<br> Only present if the `include_rollover_pool`
        query parameter is set to `true`."
      properties:
        budgeted_to_base:
          description: "Amount of funds, in the user's default currency,
            currently available to rollover."
          type: number
        all_adjustments:
          description: List of previous adjustments to the rollover pool
          type: array
          items:
            $ref: "#/components/schemas/summaryRolloverPoolAdjustmentObject"
      required:
        - budgeted_to_base
        - all_adjustments
    
    # The schema for an object returned when an error occurs
    errorResponseObject:
      type: object
      title: error response object
      description: The object returned with any 4XX error response. Each
        response is guaranteed to have a `message` and at least one `error`
        object.
      properties:
        message:
          type: string
          description: "High level error type, for example 'Not Found' or
            'Request Validation Failure'"
        errors:
          description: A list of objects that describe the errors encountered
            while processing the request.<br> If multiple errors were
            encountered, the list will contain multiple objects.<br> Each
            `error` object is guaranteed to have an `errMsg`, but it may also
            contain other error specific properties.
          type: array
          items:
            type: object
            properties:
              errMsg:
                type: string
                description: A message to help the developer determine the
                  problem with the request.
            required:
              - errMsg
            additionalProperties: true
      required:
        - message
        - errors

    # Error response when start_date is not a valid budget period start (PUT /budgets 400)
    budgetInvalidPeriodErrorObject:
      x-internal: true
      type: object
      additionalProperties: false
      description: Returned when the requested start_date is not a valid budget
        period start for the account.
      properties:
        message:
          type: string
          description: Overall error message (e.g. Invalid Request)
        requested_start_date:
          type: string
          format: date
          description: The start_date value that was rejected
        previous_valid_start_date:
          type: string
          format: date
          nullable: true
          description: The previous valid budget period start date before the
            requested date
        next_valid_start_date:
          type: string
          format: date
          nullable: true
          description: The next valid budget period start date after the
            requested date
        errMsg:
          type: string
          description: Human-readable error message
      required:
        - message
        - requested_start_date
        - errMsg

    # Enums shared by multiple schemas
    # Define the allowed types for a manual account
    accountTypeEnum:
      type: string
      title: manual account type enum
      enum:
        - cash
        - credit
        - cryptocurrency
        - employee compensation
        - investment
        - loan
        - other liability
        - other asset
        - real estate
        - vehicle

    # Define the allowed types for the 3 letter currency codes
    # CSpell: disable
    # TODO see if we can avoid having the long doc string show up in the
    # docs for the models like userObject and transactionObject that reference
    # this. Ideally if users want to see the details we can offer a link instead.
    currencyEnum:
      type: string
      title: currency enum
      # Comment out this documentation until I can figure out how to override it
      # in the docs that include this schema.
      # description: |
      #   Supported Currency codes:
      #   - `aed`: United Arab Emirates Dirham
      #   - `afn`: Afghan Afghani
      #   - `all`: Albanian Lek
      #   - `amd`: Armenian Dram
      #   - `ang`: Netherlands Antillean Guilder
      #   - `aoa`: Angolan Kwanza
      #   - `ars`: Argentine Peso
      #   - `aud`: Australian Dollar
      #   - `awg`: Aruban Florin
      #   - `azn`: Azerbaijani Manat
      #   - `bam`: Bosnia-Herzegovina Convertible Mark
      #   - `bbd`: Barbadian Dollar
      #   - `bdt`: Bangladeshi Taka
      #   - `bgn`: Bulgarian Lev
      #   - `bhd`: Bahraini Dinar
      #   - `bif`: Burundian Franc
      #   - `bmd`: Bermudian Dollar
      #   - `bnd`: Brunei Dollar
      #   - `bob`: Bolivian Boliviano
      #   - `brl`: Brazilian Real
      #   - `bsd`: Bahamian Dollar
      #   - `btc`: Bitcoin
      #   - `btn`: Bhutanese Ngultrum
      #   - `bwp`: Botswanan Pula
      #   - `byn`: Belarusian Ruble
      #   - `bzd`: Belize Dollar
      #   - `cad`: Canadian Dollar
      #   - `cdf`: Congolese Franc
      #   - `chf`: Swiss Franc
      #   - `clf`: Chilean Unit of Account (UF)
      #   - `clp`: Chilean Peso
      #   - `cny`: Chinese Yuan
      #   - `cop`: Colombian Peso
      #   - `crc`: Costa Rican Colón
      #   - `cuc`: Cuban Convertible Peso
      #   - `cup`: Cuban Peso
      #   - `cve`: Cape Verdean Escudo
      #   - `czk`: Czech Republic Koruna
      #   - `djf`: Djiboutian Franc
      #   - `dkk`: Danish Krone
      #   - `dop`: Dominican Peso
      #   - `dzd`: Algerian Dinar
      #   - `egp`: Egyptian Pound
      #   - `ern`: Eritrean Nakfa
      #   - `etb`: Ethiopian Birr
      #   - `eth`: Ethereum
      #   - `eur`: Euro
      #   - `fjd`: Fijian Dollar
      #   - `fkp`: Falkland Islands Pound
      #   - `gbp`: British Pound Sterling
      #   - `gel`: Georgian Lari
      #   - `ggp`: Guernsey Pound
      #   - `ghs`: Ghanaian Cedi
      #   - `gip`: Gibraltar Pound
      #   - `gmd`: Gambian Dalasi
      #   - `gnf`: Guinean Franc
      #   - `gtq`: Guatemalan Quetzal
      #   - `gyd`: Guyanaese Dollar
      #   - `hkd`: Hong Kong Dollar
      #   - `hnl`: Honduran Lempira
      #   - `hrk`: Croatian Kuna
      #   - `htg`: Haitian Gourde
      #   - `huf`: Hungarian Forint
      #   - `idr`: Indonesian Rupiah
      #   - `ils`: Israeli New Sheqel
      #   - `imp`: Isle of Man Pound
      #   - `inr`: Indian Rupee
      #   - `iqd`: Iraqi Dinar
      #   - `irr`: Iranian Rial
      #   - `isk`: Icelandic Króna
      #   - `jep`: Jersey Pound
      #   - `jmd`: Jamaican Dollar
      #   - `jod`: Jordanian Dinar
      #   - `jpy`: Japanese Yen
      #   - `kes`: Kenyan Shilling
      #   - `kgs`: Kyrgystani Som
      #   - `khr`: Cambodian Riel
      #   - `kmf`: Comorian Franc
      #   - `kpw`: North Korean Won
      #   - `krw`: South Korean Won
      #   - `kwd`: Kuwaiti Dinar
      #   - `kyd`: Cayman Islands Dollar
      #   - `kzt`: Kazakhstani Tenge
      #   - `lak`: Laotian Kip
      #   - `lbp`: Lebanese Pound
      #   - `lkr`: Sri Lankan Rupee
      #   - `lrd`: Liberian Dollar
      #   - `lsl`: Lesotho Loti
      #   - `ltl`: Lithuanian Litas
      #   - `lvl`: Latvian Lats
      #   - `lyd`: Libyan Dinar
      #   - `mad`: Moroccan Dirham
      #   - `mdl`: Moldovan Leu
      #   - `mga`: Malagasy Ariary
      #   - `mkd`: Macedonian Denar
      #   - `mmk`: Myanma Kyat
      #   - `mnt`: Mongolian Tugrik
      #   - `mop`: Macanese Pataca
      #   - `mro`: Mauritanian Ouguiya
      #   - `mur`: Mauritian Rupee
      #   - `mvr`: Maldivian Rufiyaa
      #   - `mwk`: Malawian Kwacha
      #   - `mxn`: Mexican Peso
      #   - `myr`: Malaysian Ringgit
      #   - `mzn`: Mozambican Metical
      #   - `nad`: Namibian Dollar
      #   - `ngn`: Nigerian Naira
      #   - `nio`: Nicaraguan Córdoba
      #   - `nok`: Norwegian Krone
      #   - `npr`: Nepalese Rupee
      #   - `nzd`: New Zealand Dollar
      #   - `omr`: Omani Rial
      #   - `pab`: Panamanian Balboa
      #   - `pen`: Peruvian Nuevo Sol
      #   - `pgk`: Papua New Guinean Kina
      #   - `php`: Philippine Peso
      #   - `pkr`: Pakistani Rupee
      #   - `pln`: Polish Zloty
      #   - `pyg`: Paraguayan Guarani
      #   - `qar`: Qatari Rial
      #   - `ron`: Romanian Leu
      #   - `rsd`: Serbian Dinar
      #   - `rub`: Russian Ruble
      #   - `rwf`: Rwandan Franc
      #   - `sar`: Saudi Riyal
      #   - `sbd`: Solomon Islands Dollar
      #   - `scr`: Seychellois Rupee
      #   - `sdg`: Sudanese Pound
      #   - `sek`: Swedish Krona
      #   - `sgd`: Singapore Dollar
      #   - `shp`: Saint Helena Pound
      #   - `sll`: Sierra Leonean Leone
      #   - `sos`: Somali Shilling
      #   - `srd`: Surinamese Dollar
      #   - `std`: São Tomé and Príncipe Dobra
      #   - `svc`: Salvadoran Colón
      #   - `syp`: Syrian Pound
      #   - `szl`: Swazi Lilangeni
      #   - `thb`: Thai Baht
      #   - `tjs`: Tajikistani Somoni
      #   - `tmt`: Turkmenistani Manat
      #   - `tnd`: Tunisian Dinar
      #   - `top`: Tongan Paʻanga
      #   - `try`: Turkish Lira
      #   - `ttd`: Trinidad and Tobago Dollar
      #   - `twd`: New Taiwan Dollar
      #   - `tzs`: Tanzanian Shilling
      #   - `uah`: Ukrainian Hryvnia
      #   - `ugx`: Ugandan Shilling
      #   - `usd`: United States Dollar
      #   - `uyu`: Uruguayan Peso
      #   - `uzs`: Uzbekistan Som
      #   - `vef`: Venezuelan Bolívar
      #   - `ves`: Venezuelan Bolívar Sotiemas
      #   - `vnd`: Vietnamese Dong
      #   - `vuv`: Vanuatu Vatu
      #   - `wst`: Samoan Tala
      #   - `xaf`: CFA Franc BEAC
      #   - `xag`: Silver (troy ounce)
      #   - `xau`: Gold (troy ounce)
      #   - `xcd`: East Caribbean Dollar
      #   - `xof`: CFA Franc BCEAO
      #   - `xpf`: CFP Franc
      #   - `yer`: Yemeni Rial
      #   - `zar`: South African Rand
      #   - `zmw`: Zambian Kwacha
      #   - `zwl`: Zimbabwean Dollar
      enum:
        - aed
        - afn
        - all
        - amd
        - ang
        - aoa
        - ars
        - aud
        - awg
        - azn
        - bam
        - bbd
        - bdt
        - bgn
        - bhd
        - bif
        - bmd
        - bnd
        - bob
        - brl
        - bsd
        - btc
        - btn
        - bwp
        - byn
        - bzd
        - cad
        - cdf
        - chf
        - clf
        - clp
        - cny
        - cop
        - crc
        - cuc
        - cup
        - cve
        - czk
        - djf
        - dkk
        - dop
        - dzd
        - egp
        - ern
        - etb
        - eth
        - eur
        - fjd
        - fkp
        - gbp
        - gel
        - ggp
        - ghs
        - gip
        - gmd
        - gnf
        - gtq
        - gyd
        - hkd
        - hnl
        - hrk
        - htg
        - huf
        - idr
        - ils
        - imp
        - inr
        - iqd
        - irr
        - isk
        - jep
        - jmd
        - jod
        - jpy
        - kes
        - kgs
        - khr
        - kmf
        - kpw
        - krw
        - kwd
        - kyd
        - kzt
        - lak
        - lbp
        - lkr
        - lrd
        - lsl
        - ltl
        - lvl
        - lyd
        - mad
        - mdl
        - mga
        - mkd
        - mmk
        - mnt
        - mop
        - mro
        - mur
        - mvr
        - mwk
        - mxn
        - myr
        - mzn
        - nad
        - ngn
        - nio
        - nok
        - npr
        - nzd
        - omr
        - pab
        - pen
        - pgk
        - php
        - pkr
        - pln
        - pyg
        - qar
        - ron
        - rsd
        - rub
        - rwf
        - sar
        - sbd
        - scr
        - sdg
        - sek
        - sgd
        - shp
        - sll
        - sos
        - srd
        - std
        - svc
        - syp
        - szl
        - thb
        - tjs
        - tmt
        - tnd
        - top
        - try
        - ttd
        - twd
        - tzs
        - uah
        - ugx
        - usd
        - uyu
        - uzs
        - vef
        - ves
        - vnd
        - vuv
        - wst
        - xaf
        - xag
        - xau
        - xcd
        - xof
        - xpf
        - yer
        - zar
        - zmw
        - zwl
    # CSpell: enable





  # These responses are defined primarily to provide examples in the docs
  responses:
    unauthorizedToken:
      description: Unauthorized. This error occurs when an invalid API token is
        passed to the request.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/errorResponseObject"
          example:
            message: Unauthorized
            errors:
              - errMsg: Access token does not exist.
    rateLimited:
      description: Too Many Requests. Retry your request after the number of
        seconds specified in the retry-after header.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/errorResponseObject"
          example:
            message: Too Many Requests
            errors:
              - errMsg: Too many requests, please try again later.
    serverError:
      description: Internal Server Error. Contact support.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/errorResponseObject"
          example:
            message: Internal Server Error
            errors:
              - errMsg: Currently in maintenance mode. Please try again in a few minutes.
  
  securitySchemes:
    bearerSecurity:
      type: http
      # TODO Make this shorter?
      # description: The Lunch Money API uses API keys to authenticate requests. To use
      #   the v1 API you can view and manage your API keys on the [developers page
      #   in the Lunch Money app](https://my.lunchmoney.app/developers). <p> To
      #   interact with the Static Mock Server simply enter an API key of 11
      #   characters or more. <p> To interact with the v2 service implemented on
      #   top of the v1 API paste in a real API token associated with a Lunch
      #   Money Budget.
      description: To interact with the Static Mock Server simply enter an API
        key of 11 characters or more.
      scheme: bearer
      bearerFormat: JWT
    cookieAuth:
      type: apiKey
      in: cookie
      name: _lm_access_token

paths:
  /me:
    get:
      tags:
        - me
      summary: Get current user
      description: Get details about the user associated with the supplied
        authorization token.
      operationId: getMe
      parameters: []
      responses:
        "200":
          description: The User Object associated with the authorized token.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/userObject"
              example:
                name: User 1
                email: user-1@lunchmoney.dev
                id: 18328
                account_id: 18221
                budget_name: \U0001F3E0 Family budget
                primary_currency: usd
                api_key_label: Side project dev key
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /summary:
    get:
      tags:
        - summary
      summary: Get summary
      description: Retrieves a summary of the user's budget. Use this endpoint
        to access budget configuration details and performance for a specified
        date range.<p> Use the [/budgets](#tag/budgets) endpoint to manage
        budget objects.
      
      operationId: getBudgetSummary
      parameters:
        - in: query
          name: start_date
          description: Start of date range in ISO 8601 date format (YYYY-MM-DD).
          required: true
          schema:
            type: string
            format: date
          examples:
            "aligned monthly":
              summary: "Start date for monthly budget period"
              description: "First day of month for aligned budget periods"
              value: "2025-07-01"
            "not aligned":
              summary: "Start date for non-aligned period"
              description: "Date that doesn't align with budget periods"
              value: "2025-07-02"
        - in: query
          name: end_date
          description: "End of date range in ISO 8601 date format (YYYY-MM-DD)."
          required: true
          schema:
            type: string
            format: date
          examples:
            "aligned monthly":
              summary: "End date for monthly budget period"
              description: "Last day of month for aligned budget periods"
              value: "2025-08-31"
            "not aligned":
              summary: "End date for non-aligned period"
              description: "Date that doesn't align with budget periods"
              value: "2025-08-27"
        - in: query
          name: include_exclude_from_budgets
          description: Enable to include categories that have the 'Exclude from
            Budgets' flag set in the returned `categories` array.
          required: false
          schema:
            type: boolean
            default: false
        - in: query
          name: include_occurrences
          description: Enable to include an `occurrences` array for each
            category in an aligned response. Each array will include an object
            for each budget period that falls within the specified date range
            which includes details on the activity for the budget period.
          required: false
          schema:
            type: boolean
            default: false
        - in: query
          name: include_past_budget_dates
          description: "Enable to include the three budget occurrences prior to
            the start date in the `occurrences` array for each category in an
            aligned response. This property is ignored if `include_occurrences`
            is not also set to `true`."
          required: false
          schema:
            type: boolean
            default: false
        - in: query
          name: include_totals
          description: "Enable to include a top-level `totals` section that
            summarizes the inflow and outflow across all transactions for the
            specified date range."
          required: false
          schema:
            type: boolean
            default: false
        - in: query
          name: include_rollover_pool
          description: "Enable to include a `rollover_pool` section that
            summarizes the current rollover pool balance and all previous
            adjustments."
          required: false
          schema:
            type: boolean
            default: false
      responses:
        "200":
          description: "Summary of the user's budget for the specified date
            range."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/summaryResponseObject"
              examples:
                "aligned monthly":
                  summary: "Monthly budget summary aligned with budget periods"
                  description: "Example response for a date range that aligns
                    with monthly budget periods (1st to last day of month) with
                    occurrences included"
                  value:
                    aligned: true
                    categories:
                      - category_id: 315177
                        totals:
                          other_activity: 156.64
                          recurring_activity: 0
                          budgeted: 500
                          available: 343.36
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 156.64
                            recurring_activity: 0
                            budgeted: 500
                            budgeted_amount: "500.0000"
                            budgeted_currency: "usd"
                            notes: "Monthly budget allocation"
                          - in_range: true
                            start_date: "2025-08-01"
                            end_date: "2025-08-31"
                            other_activity: 0
                            recurring_activity: 0
                            budgeted: 500
                            budgeted_amount: "500.0000"
                            budgeted_currency: "usd"
                            notes: "Adjusted for seasonal spending"
                      - category_id: 315628
                        totals:
                          other_activity: 424.8
                          recurring_activity: 0
                          budgeted: 200
                          available: -224.8
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 424.8
                            recurring_activity: 0
                            budgeted: 200
                            budgeted_amount: "200.0000"
                            budgeted_currency: "usd"
                            notes: "Based on previous month's activity"
                          - in_range: true
                            start_date: "2025-08-01"
                            end_date: "2025-08-31"
                            other_activity: 0
                            recurring_activity: 0
                            budgeted: 200
                            budgeted_amount: "200.0000"
                            budgeted_currency: "usd"
                            notes: "Emergency fund contribution"
                      - category_id: 86
                        totals:
                          other_activity: 25.69
                          recurring_activity: 0
                          budgeted: 200
                          available: 174.31
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 25.69
                            recurring_activity: 0
                            budgeted: 200
                            budgeted_amount: "200.0000"
                            budgeted_currency: "usd"
                            notes: "Holiday spending budget"
                          - in_range: true
                            start_date: "2025-08-01"
                            end_date: "2025-08-31"
                            other_activity: 0
                            recurring_activity: 0
                            budgeted: 200
                            budgeted_amount: "200.0000"
                            budgeted_currency: "usd"
                            notes: "Summer vacation savings"
                "not aligned":
                  summary: "Budget summary for non-aligned date range"
                  description: "Example response for a date range that does not
                    align with monthly budget periods (July 2 to August 27)"
                  value:
                    aligned: false
                    categories:
                      - category_id: 315177
                        totals:
                          other_activity: 156.64
                          recurring_activity: 0
                          budgeted: 400
                          available: 243.36
                          recurring_remaining: 0
                          recurring_expected: 0
                      - category_id: 315628
                        totals:
                          other_activity: 424.8
                          recurring_activity: 0
                          budgeted: null
                          available: null
                          recurring_remaining: 0
                          recurring_expected: 0
                      - category_id: 78
                        totals:
                          other_activity: 0
                          recurring_activity: 0
                          budgeted: null
                          available: null
                          recurring_remaining: 0
                          recurring_expected: 0
                      - category_id: 83
                        totals:
                          other_activity: 0
                          recurring_activity: 0
                          budgeted: null
                          available: null
                          recurring_remaining: 1700
                          recurring_expected: 1700
                      - category_id: 88
                        totals:
                          other_activity: 0
                          recurring_activity: 2501.68
                          budgeted: null
                          available: null
                          recurring_remaining: 0
                          recurring_expected: 2501.68
                      - category_id: 86
                        totals:
                          other_activity: 25.69
                          recurring_activity: 0
                          budgeted: 200
                          available: 174.31
                          recurring_remaining: 0
                          recurring_expected: 0
                      - category_id: 84
                        totals:
                          other_activity: 401.12
                          recurring_activity: 4.13
                          budgeted: 150
                          available: -255.25
                          recurring_remaining: -4.13
                          recurring_expected: 0
                "summarized totals":
                  summary: "Monthly budget summary with totals included"
                  description: "Example response for aligned monthly budget
                    periods with totals section showing overall inflow and
                    outflow"
                  value:
                    aligned: true
                    categories:
                      - category_id: 315177
                        totals:
                          other_activity: 156.64
                          recurring_activity: 0
                          budgeted: 400
                          available: 243.36
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 156.64
                            recurring_activity: 0
                            budgeted: 400
                            budgeted_amount: "400.0000"
                            budgeted_currency: "usd"
                            notes: "Monthly budget allocation"
                      - category_id: 315628
                        totals:
                          other_activity: 424.8
                          recurring_activity: 0
                          budgeted: 200
                          available: -224.8
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 424.8
                            recurring_activity: 0
                            budgeted: 200
                            budgeted_amount: "200.0000"
                            budgeted_currency: "usd"
                            notes: "Based on previous month's activity"
                      - category_id: 315629
                        totals:
                          other_activity: 0
                          recurring_activity: 0
                          budgeted: 150
                          available: 150
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 0
                            recurring_activity: 0
                            budgeted: 150
                            budgeted_amount: "150.0000"
                            budgeted_currency: "usd"
                            notes: "Emergency fund contribution"
                    totals:
                      inflow:
                        other_activity: -125.50
                        recurring_activity: -89.99
                        uncategorized: 0
                        uncategorized_count: 0
                        uncategorized_recurring: 0
                      outflow:
                        other_activity: 581.44
                        recurring_activity: 0
                        uncategorized: 45.20
                        uncategorized_count: 3
                        uncategorized_recurring: 0
                "with occurrences":
                  summary: "Monthly budget summary with occurrences included"
                  description: "Example response for aligned monthly budget
                    periods with occurrences showing individual budget period
                    details for each category"
                  value:
                    aligned: true
                    categories:
                      - category_id: 315177
                        totals:
                          other_activity: 156.64
                          recurring_activity: 0
                          budgeted: 500
                          available: 343.36
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 156.64
                            recurring_activity: 0
                            budgeted: 500
                            budgeted_amount: "500.0000"
                            budgeted_currency: "usd"
                            notes: "Monthly budget allocation"
                          - in_range: true
                            start_date: "2025-08-01"
                            end_date: "2025-08-31"
                            other_activity: 0
                            recurring_activity: 0
                            budgeted: 500
                            budgeted_amount: "500.0000"
                            budgeted_currency: "usd"
                            notes: "Adjusted for seasonal spending"
                      - category_id: 315628
                        totals:
                          other_activity: 424.8
                          recurring_activity: 0
                          budgeted: 200
                          available: -224.8
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 424.8
                            recurring_activity: 0
                            budgeted: 200
                            budgeted_amount: "200.0000"
                            budgeted_currency: "usd"
                            notes: "Based on previous month's activity"
                          - in_range: true
                            start_date: "2025-08-01"
                            end_date: "2025-08-31"
                            other_activity: 0
                            recurring_activity: 0
                            budgeted: 200
                            budgeted_amount: "200.0000"
                            budgeted_currency: "usd"
                            notes: "Emergency fund contribution"
                      - category_id: 86
                        totals:
                          other_activity: 25.69
                          recurring_activity: 0
                          budgeted: 200
                          available: 174.31
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 25.69
                            recurring_activity: 0
                            budgeted: 200
                            budgeted_amount: "200.0000"
                            budgeted_currency: "usd"
                            notes: "Holiday spending budget"
                          - in_range: true
                            start_date: "2025-08-01"
                            end_date: "2025-08-31"
                            other_activity: 0
                            recurring_activity: 0
                            budgeted: 200
                            budgeted_amount: "200.0000"
                            budgeted_currency: "usd"
                            notes: "Summer vacation savings"
                "with past occurrences":
                  summary: "Monthly budget summary with past occurrences included"
                  description: "Example response for aligned monthly budget
                    periods with include_past_budget_dates=true, showing 3 past
                    occurrences with in_range: false"
                  value:
                    aligned: true
                    categories:
                      - category_id: 315177
                        totals:
                          other_activity: 156.64
                          recurring_activity: 0
                          budgeted: 500
                          available: 343.36
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: false
                            start_date: "2025-04-01"
                            end_date: "2025-04-30"
                            other_activity: 120.50
                            recurring_activity: 0
                            budgeted: 500
                            budgeted_amount: "500.0000"
                            budgeted_currency: "usd"
                            notes: "Monthly budget allocation"
                          - in_range: false
                            start_date: "2025-05-01"
                            end_date: "2025-05-31"
                            other_activity: 180.25
                            recurring_activity: 0
                            budgeted: 500
                            budgeted_amount: "500.0000"
                            budgeted_currency: "usd"
                            notes: null
                          - in_range: false
                            start_date: "2025-06-01"
                            end_date: "2025-06-30"
                            other_activity: 200.00
                            recurring_activity: 0
                            budgeted: 500
                            budgeted_amount: "500.0000"
                            budgeted_currency: "usd"
                            notes: "Adjusted for seasonal spending"
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 156.64
                            recurring_activity: 0
                            budgeted: 500
                            budgeted_amount: "500.0000"
                            budgeted_currency: "usd"
                            notes: "Monthly budget allocation"
                "with rollover pool":
                  summary: "Monthly budget summary with rollover pool included"
                  description: "Example response for aligned monthly budget
                    periods with include_rollover_pool=true, showing rollover
                    pool data for categories with budgets"
                  value:
                    aligned: true
                    rollover_pool:
                      budgeted_to_base: 179.50
                      all_adjustments:
                        - in_range: false
                          date: "2025-06-30"
                          amount: "179.5000"
                          currency: "usd"
                          to_base: 179.50
                        - in_range: false
                          date: "2025-05-31"
                          amount: "120.2500"
                          currency: "usd"
                          to_base: 120.25
                        - in_range: false
                          date: "2025-04-30"
                          amount: "80.0000"
                          currency: "usd"
                          to_base: 80.00                            
                    categories:
                      - category_id: 315177
                        totals:
                          other_activity: 156.64
                          recurring_activity: 0
                          budgeted: 500
                          available: 343.36
                          recurring_remaining: 0
                          recurring_expected: 0
                        occurrences:
                          - in_range: true
                            start_date: "2025-07-01"
                            end_date: "2025-07-31"
                            other_activity: 156.64
                            recurring_activity: 0
                            budgeted: 500
                            budgeted_amount: "500.0000"
                            budgeted_currency: "usd"
                            notes: "Monthly budget allocation"
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /categories:
    get:
      tags:
        - categories
      summary: Get all categories
      description: Retrieve a list of all categories associated with the user's
        account.
      operationId: getAllCategories
      parameters:
        - name: format
          in: query
          description: If `nested`, returns top-level categories (either
            category groups or categories not part of a category group) in
            alphabetical order. Grouped categories are nested within the
            category group under the property `children`. A `flattened`,
            response is similar but it includes grouped categories at the top
            level.<br/><br/> Categories are sorted by their `order`. When
            `order` is null, they are listed in alphabetical order below other
            categories with an `order`.
          required: false
          schema:
            type: string
            default: nested
            enum:
              - nested
              - flattened
        - name: is_group
          in: query
          description: If `false`, only categories not part of a category group
            are returned.<br> If `true`, only category groups are returned.<br>
            When set, the `format` parameter is ignored.
          required: false
          schema:
            type: boolean
      responses:
        "200":
          description: A list of Category Objects
          content:
            application/json:
              schema:
                type: object
                properties:
                  categories:
                    type: array
                    items:
                      $ref: "#/components/schemas/categoryObject"
              examples:
                nested response:
                  value:
                    categories:
                      - id: 86
                        name: Automobile
                        description: Auto related categories
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.238Z"
                        created_at: "2025-01-28T09:49:03.238Z"
                        is_group: true
                        order: 2
                        collapsed: false
                        archived: false
                        group_id: null
                        archived_at: null
                        children:
                          - id: 315174
                            name: Fuel
                            description: Fuel and gas expenses
                            is_income: false
                            exclude_from_budget: false
                            exclude_from_totals: false
                            updated_at: "2025-02-28T09:49:03.238Z"
                            created_at: "2025-01-28T09:49:03.238Z"
                            is_group: false
                            order: 1
                            collapsed: false
                            archived: false
                            group_id: 86
                            archived_at: null
                          - id: 315175
                            name: Maintenance
                            description: Car maintenance and repairs
                            is_income: false
                            exclude_from_budget: false
                            exclude_from_totals: false
                            updated_at: "2025-02-28T09:49:03.238Z"
                            created_at: "2025-01-28T09:49:03.238Z"
                            is_group: false
                            order: 2
                            collapsed: false
                            archived: false
                            group_id: 86
                            archived_at: null
                      - id: 83
                        name: Rent
                        description: Monthly Rent
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.225Z"
                        created_at: "2025-01-28T09:49:03.225Z"
                        is_group: false
                        order: 0
                        collapsed: false
                        archived: false
                        group_id: null
                        archived_at: null
                      - id: 88
                        name: W2 Income
                        description: null
                        is_income: true
                        exclude_from_budget: false
                        exclude_from_totals: true
                        updated_at: "2025-02-28T09:49:03.238Z"
                        created_at: "2025-01-28T09:49:03.238Z"
                        is_group: false
                        order: 3
                        collapsed: false
                        archived: false
                        group_id: null
                        archived_at: null
                flattened response:
                  value:
                    categories:
                      - id: 86
                        name: Automobile
                        description: Auto related categories
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.238Z"
                        created_at: "2025-01-28T09:49:03.238Z"
                        is_group: true
                        order: 1
                        collapsed: false
                        archived: false
                        group_id: null
                        archived_at: null
                        children:
                          - id: 315174
                            name: Fuel
                            description: Fuel and gas expenses
                            is_income: false
                            exclude_from_budget: false
                            exclude_from_totals: false
                            updated_at: "2025-02-28T09:49:03.238Z"
                            created_at: "2025-01-28T09:49:03.238Z"
                            is_group: false
                            order: 1
                            collapsed: false
                            archived: false
                            group_id: 86
                            archived_at: null
                          - id: 315175
                            name: Maintenance
                            description: Car maintenance and repairs
                            is_income: false
                            exclude_from_budget: false
                            exclude_from_totals: false
                            updated_at: "2025-02-28T09:49:03.238Z"
                            created_at: "2025-01-28T09:49:03.238Z"
                            is_group: false
                            order: 2
                            collapsed: false
                            archived: false
                            group_id: 86
                            archived_at: null
                      - id: 315174
                        name: Fuel
                        description: Fuel and gas expenses
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.238Z"
                        created_at: "2025-01-28T09:49:03.238Z"
                        is_group: false
                        order: 1
                        collapsed: false
                        archived: false
                        group_id: 86
                        archived_at: null
                      - id: 315175
                        name: Maintenance
                        description: Car maintenance and repairs
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.238Z"
                        created_at: "2025-01-28T09:49:03.238Z"
                        is_group: false
                        order: 2
                        collapsed: false
                        archived: false
                        group_id: 86
                        archived_at: null
                      - id: 83
                        name: Rent
                        description: Monthly Rent
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.225Z"
                        created_at: "2025-01-28T09:49:03.225Z"
                        is_group: false
                        order: 2
                        collapsed: false
                        archived: false
                        group_id: null
                        archived_at: null
                      - id: 88
                        name: W2 Income
                        description: null
                        is_income: true
                        exclude_from_budget: false
                        exclude_from_totals: true
                        updated_at: "2025-02-28T09:49:03.238Z"
                        created_at: "2025-01-28T09:49:03.238Z"
                        is_group: false
                        order: 3
                        collapsed: false
                        archived: false
                        group_id: null
                        archived_at: null
        "400":
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be equal to one of the allowed values
                    instancePath: /query/format
                    schemaPath: "#/properties/query/properties/format/enum"
                    keyword: enum
                    params:
                      allowedValues:
                        - flattened
                        - nested
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    post:
      tags:
        - categories
      summary: Create a new category or category group
      description: Creates a new category with the given name.<br> If the
        `is_group` attribute is set to true, a category group is created. In
        this case, the `children` attribute may be set to an array of category
        IDs to add to the newly created category group.
      operationId: createCategory
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/createCategoryRequestObject"
            examples:
              category:
                value:
                  name: API Created Category
                  description: Test description of created category
                  is_income: false
                  exclude_from_budget: true
                  exclude_from_totals: false
                  is_group: false
              category group:
                value:
                  name: API Created Category Group
                  description: Test description of Category Group
                  is_income: false
                  exclude_from_budget: false
                  exclude_from_totals: false
                  is_group: true
                  children:
                    - 83
      responses:
        "201":
          description: Category or Category Group Object with the successfully
            created category or category group.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/categoryObject"
              examples:
                category:
                  value:
                    id: 90
                    name: API Created Category
                    description: Test description of created category
                    is_income: false
                    exclude_from_budget: true
                    exclude_from_totals: false
                    updated_at: "2025-05-26T19:56:52.699Z"
                    created_at: "2025-05-26T19:56:52.699Z"
                    is_group: false
                    group_id: null
                    archived: false
                    archived_at: null
                    order: null
                    collapsed: false
                category group:
                  value:
                    id: 91
                    name: API Created Category Group
                    description: Test description of Category Group
                    is_income: false
                    exclude_from_budget: false
                    exclude_from_totals: false
                    updated_at: "2025-05-27T19:59:45.053Z"
                    created_at: "2025-05-27T19:59:45.053Z"
                    is_group: true
                    group_id: null
                    archived: false
                    archived_at: null
                    order: null
                    collapsed: false
                    children:
                      - id: 83
                        name: Rent
                        description: Monthly Rent
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.225Z"
                        created_at: "2025-01-28T09:49:03.225Z"
                        is_group: false
                        order: 1
                        collapsed: false
                        archived: false
                        group_id: null
                        archived_at: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Invalid Request Body
                errors:
                  - errMsg: Cannot specify a 'group_id' in request body if 'is_group' is also true
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /categories/{id}:
    get:
      tags:
        - categories
      summary: Get a single category
      description: Retrieve details of a specific category or category group by
        its ID.
      operationId: getCategoryById
      parameters:
        - name: id
          in: path
          description: ID of the category to retrieve
          required: true
          schema:
            type: integer
            format: int32
          examples:
            category:
              summary: Example of a category's id
              value: 315174
            category group:
              summary: Example of a category group's id
              value: 86
            id not found:
              summary: Example of an id that doesn't exist
              value: 543210
      responses:
        "201":
          description: Category Object with the requested category or category
            group.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/categoryObject"
              examples:
                category:
                  value:
                    id: 315174
                    name: Fuel
                    description: Fuel and gas expenses
                    is_income: false
                    exclude_from_budget: false
                    exclude_from_totals: false
                    updated_at: "2025-02-28T09:49:03.238Z"
                    created_at: "2025-01-28T09:49:03.238Z"
                    group_id: 86
                    is_group: false
                    archived: false
                    archived_at: null
                    order: 1
                    collapsed: false
                category group:
                  value:
                    id: 86
                    name: Automobile
                    description: Auto related categories
                    is_income: false
                    exclude_from_budget: false
                    exclude_from_totals: false
                    updated_at: "2025-02-28T09:49:03.238Z"
                    created_at: "2025-01-28T09:49:03.238Z"
                    is_group: true
                    order: 2
                    collapsed: false
                    archived: false
                    group_id: null
                    archived_at: null
                    children:
                      - id: 315174
                        name: Fuel
                        description: Fuel and gas expenses
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.238Z"
                        created_at: "2025-01-28T09:49:03.238Z"
                        group_id: 86
                        is_group: false
                        archived: false
                        archived_at: null
                        order: 1
                        collapsed: false
                      - id: 315175
                        name: Maintenance
                        description: Car maintenance and repairs
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.238Z"
                        created_at: "2025-01-28T09:49:03.238Z"
                        group_id: 86
                        is_group: false
                        archived: false
                        archived_at: null
                        order: 2
                        collapsed: false
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be a valid integer
                    instancePath: /query/ids/0
                    schemaPath: "#/properties/query/properties/ids/items/type"
                    keyword: type
                    params:
                      type: integer
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no category with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    put:
      tags:
        - categories
      summary: Update an existing category or category group
      description: >-
        Modifies the properties of an existing category or category group.<br><br>
        
        You may submit the response from a `GET /categories/{id}` as the request body; however, only certain
        properties can be updated using this API. The following properties are
        accepted in the request body but their values will be ignored: `id`, `is_group`, `updated_at`, `created_at`, and `order`.<br><br>

        It is also possible to provide only the properties to be updated in the
        request body, as long as the request includes at least one of the
        properties that is not listed above. For example, a request body that contains only a `name` property is valid.<br><br>

        It is not possible to use this API to convert a category to a category group, or vice versa, so while submitting a request body with the `is_group` property is tolerated, it will result in an error response if the value is changed.<br><br>

        It is possible to modify the children of an existing category group with this API by setting the `children` attribute. If this is set, it will replace the existing children with the newly specified children. If the intention is to add or remove a single category, it is more straightforward to update the child category by specifying the new `group_id` attribute. If the goal is to add multiple new children or remove multiple existing children, it is recommended to first call the `GET /categories/{id}` endpoint to get the existing children and then modify the list as desired.<br><br>
      operationId: updateCategory
      parameters:
        - name: id
          in: path
          description: ID of the category to update
          required: true
          schema:
            type: integer
            format: int32
          examples:
            category:
              summary: Example of a category's id
              value: 83
            category group:
              summary: Example of a category group's id
              value: 86
            child category:
              summary: Example of a category belonging to a group
              value: 315164
            not found:
              summary: Example of a category id that does not exist
              value: 543210
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/updateCategoryRequestObject"
            examples:
              Update some category properties:
                value:
                  name: Updated Category Name
                  description: Updated description of the category
              Update same properties with full object:
                value:
                  id: 83
                  name: Updated Category Name
                  description: Updated description of the category
                  is_income: false
                  exclude_from_budget: true
                  exclude_from_totals: false
                  updated_at: "2020-01-28T09:49:03.225Z"
                  created_at: "2020-01-28T09:49:03.225Z"
                  is_group: false
                  group_id: null
                  archived: false
                  archived_at: null
                  order: 0
              Invalid attempt to convert to category group:
                value:
                  id: 83
                  name: Old Category is now a group!
                  is_group: true
              Remove category from a group:
                value:
                  id: 86
                  name: Automobile
                  description: API Removed a sub category
                  children:
                    - 315174
      responses:
        "200":
          description: Category or Category Group updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/categoryObject"
              examples:
                category:
                  value:
                    id: 83
                    name: Updated Category Name
                    description: Updated description of the category
                    is_income: false
                    exclude_from_budget: false
                    exclude_from_totals: true
                    updated_at: "2025-05-26T20:41:18.406Z"
                    created_at: "2025-01-28T09:49:03.225Z"
                    is_group: false
                    order: 0
                    collapsed: false
                    archived: false
                    archived_at: null
                    group_id: null
                category group:
                  value:
                    id: 86
                    name: Automobile
                    description: API Removed a sub category
                    is_income: false
                    exclude_from_budget: false
                    exclude_from_totals: false
                    updated_at: "2025-06-22T19:54:30.921Z"
                    created_at: "2025-01-28T09:49:03.238Z"
                    is_group: true
                    order: 2
                    collapsed: false
                    archived: false
                    group_id: null
                    archived_at: null
                    children:
                      - id: 315174
                        name: Fuel
                        description: Fuel and gas expenses
                        is_income: false
                        exclude_from_budget: false
                        exclude_from_totals: false
                        updated_at: "2025-02-28T09:49:03.238Z"
                        created_at: "2025-01-28T09:49:03.238Z"
                        group_id: 86
                        is_group: false
                        archived: false
                        archived_at: null
                        order: 1
                        collapsed: false
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Invalid Request Body
                errors:
                  - errMsg: Cannot modify the 'group_id' property of an existing category or
                      category group
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no category with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - categories
      summary: Delete a category or category group
      description: Attempts to delete the single category or category group
        specified on the path. By default, this will only work if there are no
        dependencies, such as existing budgets for the category, categorized
        transactions, child categories for a category group, categorized
        recurring items, etc. If there are dependents, this endpoint will return
        an object that describes the number and type of existing dependencies.
      operationId: deleteCategory
      parameters:
        - in: path
          name: id
          description: ID of the category to delete
          required: true
          schema:
            type: integer
            format: int32
          examples:
            delete category:
              summary: Simple category delete
              value: 83
            delete category group:
              summary: Attempt to delete category with dependencies
              value: 84
            id not found:
              summary: Example of an id that doesn't exist
              value: 543210
        - in: query
          name: force
          description: Set to `true` to force deletion even if there are
            dependencies
          required: false
          schema:
            type: boolean
            default: false
      responses:
        "204":
          description: No Content
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no category with the id: 543210."
        "422":
          description: Unprocessable Content
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/deleteCategoryResponseWithDependencies"
              examples:
                delete category with dependencies:
                  summary: Response to an attempt to delete category with dependencies
                  value:
                    category_name: Category to be Deleted
                    dependents:
                      budget: 0
                      category_rules: 1
                      transactions: 10
                      children: 0
                      recurring: 0
                      plaid_cats: 0
                delete category group:
                  summary: Response to attempt to delete a category group with children
                  value:
                    category_name: Category Group to be Deleted
                    dependents:
                      budget: 0
                      category_rules: 0
                      transactions: 0
                      children: 3
                      recurring: 0
                      plaid_cats: 0
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /cryptocurrencies:
    get:
      tags:
        - crypto-manual
      summary: Get all supported cryptocurrencies
      description: >
        Retrieve the list of cryptocurrencies currently supported for manual tracking.<p>

        When creating a new manual crypto balance via `POST /crypto/manual`, the
        `symbol` you specify must match the `symbol` of one of the entries
        returned by this endpoint.
      operationId: getAllCryptocurrencies
      responses:
        "200":
          description: A list of supported cryptocurrencies
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/cryptoCurrencyResponseObject"
              example:
                cryptocurrencies:
                  - id: 1
                    coingecko_id: bitcoin
                    symbol: btc
                    full_name: Bitcoin
                  - id: 2
                    coingecko_id: ethereum
                    symbol: eth
                    full_name: Ethereum
                  - id: 3
                    coingecko_id: solana
                    symbol: sol
                    full_name: Solana
                  - id: 4
                    coingecko_id: ripple
                    symbol: xrp
                    full_name: XRP
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    post:
      tags:
        - crypto-manual
      summary: Add a new supported cryptocurrency
      operationId: createCryptocurrency
      description: >-
        Adds a new cryptocurrency to the supported manual-crypto list.<br><br>

        Lunch Money uses [CoinGecko](https://www.coingecko.com/us/coins/ethereum)
        to convert crypto balances to the user's primary currency. Users add a
        new supported cryptocurrency by submitting a CoinGecko coin-page URL.
        The server validates the URL, extracts the id from `/coins/{id}`,
        checks for an existing supported `coingecko_id`, validates the id
        against CoinGecko, then confirms the resolved symbol is not already
        supported before creating the new entry.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/createCryptocurrencyRequestObject"
            examples:
              by CoinGecko url:
                value:
                  coingecko_url: https://www.coingecko.com/fr/coins/cardano
      responses:
        "201":
          description: Supported cryptocurrency created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/cryptoCurrencyObject"
              example:
                id: 5
                coingecko_id: cardano
                symbol: ada
                full_name: Cardano
        "400":
          description: Invalid request body
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                unexpected property:
                  value:
                    message: Invalid Request Body
                    errors:
                      - errMsg: "Invalid property 'foo' in request body."
        "422":
          description: Request validation failure
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                malformed CoinGecko url:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "Malformed coingecko_url. Expected a URL like 'https://www.coingecko.com/en/coins/ethereum'."
                existing id conflict:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "The coingecko_id 'bitcoin' is already in our supported currency database."
                        existing_coingecko_id: bitcoin
                        existing_symbol: btc
                invalid CoinGecko id:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "Unable to determine cryptocurrency from url"
                        coingecko_url: https://www.coingecko.com/en/coins/xyz
                CoinGecko mapped to existing symbol:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "The coingecko_id 'bitcoin-avalanche-bridged-btc-b' is already in our supported currency database."
                        existing_coingecko_id: bitcoin-avalanche-bridged-btc-b
                        existing_symbol: btc.b
                        coingecko_url: https://www.coingecko.com/en/coins/bitcoin-avalanche-bridged-btc-b
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /crypto/manual:
    get:
      tags:
        - crypto-manual
      summary: Get all manual crypto balances
      description: Retrieve all manually managed crypto balances associated with
        the user's account.
      operationId: getAllCryptoManual
      responses:
        "200":
          description: A list of manual crypto balances
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/cryptoManualListResponseObject"
              example:
                crypto_manual:
                  - id: 22001
                    name: Cold Wallet BTC
                    display_name: Long-term BTC
                    institution_name: Ledger
                    balance: "0.852341920145782301"
                    symbol: btc
                    coingecko_id: bitcoin
                    to_base: 53124.72
                    balance_as_of: "2026-02-25T14:22:10.000Z"
                    exchange_rate_as_of: "2026-02-25T14:10:00.000Z"
                    created_by_name: User 1
                    created_at: "2025-11-12T20:14:32.000Z"
                    updated_at: "2026-02-25T14:22:10.000Z"
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    post:
      tags:
        - crypto-manual
      summary: Create a manual crypto balance
      description: >-
        Create a manually managed crypto asset.<br><br>

        If `display_name` is `null`, clients may derive one from
        `institution_name` + `name`.
      operationId: createCryptoManual
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/createCryptoManualRequestObject"
            examples:
              minimum request body:
                summary: Minimum required fields
                value:
                  name: Cold Wallet BTC
                  balance: "0.852341920145782301"
                  symbol: btc
              full request body:
                summary: Full example with optional display fields
                value:
                  name: Coinbase ETH Holdings
                  display_name: Trading ETH
                  institution_name: Coinbase
                  balance: "12.004500000000000000"
                  symbol: eth
      responses:
        "201":
          description: Manual crypto balance created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/cryptoManualObject"
              example:
                id: 22045
                name: Coinbase ETH Holdings
                display_name: Trading ETH
                institution_name: Coinbase
                balance: "12.004500000000000000"
                symbol: eth
                coingecko_id: ethereum
                to_base: 28998.44
                balance_as_of: "2026-03-01T09:20:41.000Z"
                exchange_rate_as_of: "2026-03-01T09:15:00.000Z"
                created_by_name: User 1
                created_at: "2026-03-01T09:20:41.000Z"
                updated_at: "2026-03-01T09:20:41.000Z"
        "400":
          description: Invalid request body
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing required properties:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "Missing required property 'name' in request body."
                      - errMsg: "Missing required property 'balance' in request body."
                      - errMsg: "Missing required property 'symbol' in request body."
                unsupported symbol:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "Unsupported crypto symbol 'doge'. Use GET /cryptocurrencies to find a supported symbol."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /crypto/manual/{id}:
    get:
      tags:
        - crypto-manual
      summary: Get a single manual crypto balance
      description: Retrieve a single manually managed crypto balance by ID.
      operationId: getCryptoManualById
      parameters:
        - name: id
          in: path
          description: ID of the manual crypto balance to retrieve
          required: true
          schema:
            type: integer
            format: int32
          examples:
            existing manual crypto:
              summary: Existing manual crypto ID
              value: 22001
            id not found:
              summary: Example of an id that doesn't exist
              value: 99999999
      responses:
        "200":
          description: Manual crypto balance object
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/cryptoManualObject"
              example:
                id: 22001
                name: Cold Wallet BTC
                display_name: Long-term BTC
                institution_name: Ledger
                balance: "0.852341920145782301"
                symbol: btc
                coingecko_id: bitcoin
                to_base: 53124.72
                balance_as_of: "2026-02-25T14:22:10.000Z"
                exchange_rate_as_of: "2026-02-25T14:10:00.000Z"
                created_by_name: User 1
                created_at: "2025-11-12T20:14:32.000Z"
                updated_at: "2026-02-25T14:22:10.000Z"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Invalid Path Parameters
                errors:
                  - errMsg: "Invalid value type for path parameter: 'id'. Expected 'number', received 'string'."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no manual crypto account with the id: 99999999."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    put:
      tags:
        - crypto-manual
      summary: Update a manual crypto balance
      description: >-
        Modify a manually managed crypto balance.<br><br>

        You may submit the response from `GET /crypto/manual/{id}` as the request body. System-defined properties
        are accepted according to the `x-updatable` metadata in the update schema.
      operationId: updateCryptoManual
      parameters:
        - name: id
          in: path
          description: ID of the manual crypto balance to update
          required: true
          schema:
            type: integer
            format: int32
          examples:
            existing manual crypto:
              summary: Existing manual crypto ID
              value: 22001
            id not found:
              summary: Example of an id that doesn't exist
              value: 99999999
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/updateCryptoManualRequestObject"
            examples:
              minimum request body:
                summary: Update balance only
                value:
                  balance: "0.900000000000000000"
              full get response body:
                summary: Full object payload with system fields tolerated
                value:
                  id: 22001
                  name: Cold Wallet BTC
                  display_name: Long-term BTC
                  institution_name: Ledger
                  balance: "0.900000000000000000"
                  symbol: btc
                  coingecko_id: bitcoin
                  to_base: 56011.12
                  balance_as_of: "2026-03-01T09:41:18.000Z"
                  exchange_rate_as_of: "2026-03-01T09:35:00.000Z"
                  created_by_name: User 1
                  created_at: "2025-11-12T20:14:32.000Z"
                  updated_at: "2026-02-25T14:22:10.000Z"
      responses:
        "200":
          description: Manual crypto balance updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/cryptoManualObject"
              example:
                id: 22001
                name: Cold Wallet BTC
                display_name: Long-term BTC
                institution_name: Ledger
                balance: "0.900000000000000000"
                symbol: btc
                coingecko_id: bitcoin
                to_base: 56011.12
                balance_as_of: "2026-03-01T09:41:18.000Z"
                exchange_rate_as_of: "2026-03-01T09:35:00.000Z"
                created_by_name: User 1
                created_at: "2025-11-12T20:14:32.000Z"
                updated_at: "2026-03-01T09:41:18.000Z"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing updatable properties:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "A request to update a manual crypto account must include at least one writable property: name, display_name, institution_name, or balance."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no manual crypto account with the id: 99999999."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - crypto-manual
      summary: Delete a manual crypto balance
      description: Delete a single manually managed crypto asset by ID.<p> If
        this crypto asset has a balance history, and you do not explicitly set
        the query parameter`keep_history`, a 422 response will be returned
        requesting you to explicitly set `keep_history` to `true` or `false`.
      operationId: deleteCryptoManual
      parameters:
        - name: id
          in: path
          description: ID of the manual crypto balance to delete
          required: true
          schema:
            type: integer
            format: int32
          examples:
            existing manual crypto:
              summary: Existing manual crypto ID
              value: 22001
            id not found:
              summary: Example of an id that doesn't exist
              value: 99999999
        - name: keep_history
          in: query
          description: Explicitly set to `true` to preserve balance history, or
            `false` to remove associated history during deletion. This must be
            set if the account has a balance history.
          required: false
          schema:
            type: boolean
      responses:
        "204":
          description: No Content. The crypto asset has been deleted.
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no manual crypto balance with the id: 99999999."
        "422":
          description: Unprocessable Content
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Explicit confirmation required
                errors:
                  - errMsg: This crypto manual account has existing balance history. To delete this account, you must explicitly set keep_history to true or false.
                    crypto_manual_id: 22001
                    has_balance_history: true
                    required_parameter: keep_history
                    allowed_values:
                      - true
                      - false
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /crypto/synced:
    get:
      tags:
        - crypto-synced
      summary: Get all synced crypto accounts
      description: Retrieves all synced crypto accounts
        associated with the user's account.
      operationId: getAllCryptoSynced
      responses:
        "200":
          description: A list of synced crypto accounts
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/cryptoSyncedListResponseObject"
              example:
                crypto_synced:
                  - id: 33004
                    provider: coinbase
                    status: active
                    created_by_name: User 1
                    created_at: "2025-10-02T11:02:09.000Z"
                    updated_at: "2026-02-25T14:25:01.000Z"
                    display_name: Coinbase Main
                    balances:
                      - name: ETH
                        balance: "12.004500000000000000"
                        symbol: eth
                        coingecko_id: ethereum
                        to_base: 28998.44
                        balance_as_of: "2026-02-25T14:25:00.000Z"
                        exchange_rate_as_of: "2026-02-25T14:20:00.000Z"
                        updated_at: "2026-02-25T14:25:01.000Z"
                      - name: BTC
                        balance: "0.100020003000400050"
                        symbol: btc
                        coingecko_id: bitcoin
                        to_base: 6231.28
                        balance_as_of: "2026-02-25T14:25:00.000Z"
                        exchange_rate_as_of: "2026-02-25T14:20:00.000Z"
                        updated_at: "2026-02-25T14:25:01.000Z"
                  - id: 33005
                    provider: kraken
                    status: relink
                    created_by_name: User 1
                    created_at: "2025-08-10T10:00:00.000Z"
                    updated_at: "2026-02-26T07:22:30.000Z"
                    display_name: Kraken Wallet
                    balances:
                      - name: XRP
                        balance: "2500.000000000000000000"
                        symbol: xrp
                        coingecko_id: ripple
                        to_base: 1287.50
                        balance_as_of: "2026-02-26T07:22:30.000Z"
                        exchange_rate_as_of: "2026-02-26T07:10:00.000Z"
                        updated_at: "2026-02-26T07:22:30.000Z"
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /crypto/synced/{id}:
    get:
      tags:
        - crypto-synced
      summary: Get a single synced crypto account
      description: Retrieves the synced crypto account and all nested balances
        for the specified synced crypto account ID.
      operationId: getCryptoSyncedById
      parameters:
        - name: id
          in: path
          description: Synced crypto account ID
          required: true
          schema:
            type: integer
            format: int32
          examples:
            existing synced connection:
              summary: Existing synced account ID
              value: 33004
            id not found:
              summary: Example of an id that doesn't exist
              value: 99999999
      responses:
        "200":
          description: Synced crypto account object
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/syncedCryptoAccount"
              example:
                id: 33004
                provider: coinbase
                status: active
                created_by_name: User 1
                created_at: "2025-10-02T11:02:09.000Z"
                updated_at: "2026-02-25T14:25:01.000Z"
                display_name: Coinbase Main
                balances:
                  - name: ETH
                    balance: "12.004500000000000000"
                    symbol: eth
                    coingecko_id: ethereum
                    to_base: 28998.44
                    balance_as_of: "2026-02-25T14:25:00.000Z"
                    exchange_rate_as_of: "2026-02-25T14:20:00.000Z"
                    updated_at: "2026-02-25T14:25:01.000Z"
                  - name: BTC
                    balance: "0.100020003000400050"
                    symbol: btc
                    coingecko_id: bitcoin
                    to_base: 6231.28
                    balance_as_of: "2026-02-25T14:25:00.000Z"
                    exchange_rate_as_of: "2026-02-25T14:20:00.000Z"
                    updated_at: "2026-02-25T14:25:01.000Z"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Invalid Path Parameters
                errors:
                  - errMsg: "Invalid value type for path parameter: 'id'. Expected 'number', received 'string'."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no synced crypto account with the id: 99999999."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /crypto/synced/{id}/{symbol}:
    get:
      tags:
        - crypto-synced
      summary: Get a synced crypto balance by symbol
      description: Retrieves a single balance from the specified synced crypto
        account using the crypto symbol.
      operationId: getCryptoSyncedBalanceBySymbol
      parameters:
        - name: id
          in: path
          description: Synced crypto account ID
          required: true
          schema:
            type: integer
            format: int32
        - name: symbol
          in: path
          description: Crypto symbol within the synced account
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 25
      responses:
        "200":
          description: Synced crypto balance object
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/cryptoSyncedBalance"
              example:
                name: ETH
                balance: "12.004500000000000000"
                symbol: eth
                coingecko_id: ethereum
                to_base: 28998.44
                balance_as_of: "2026-02-25T14:25:00.000Z"
                exchange_rate_as_of: "2026-02-25T14:20:00.000Z"
                updated_at: "2026-02-25T14:25:01.000Z"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                invalid id:
                  value:
                    message: Invalid Path Parameters
                    errors:
                      - errMsg: "Invalid value type for path parameter: 'id'. Expected 'number', received 'string'."
                invalid symbol:
                  value:
                    message: Invalid Path Parameters
                    errors:
                      - errMsg: "Value for path parameter 'symbol' must not be empty."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                account not found:
                  value:
                    message: Not Found
                    errors:
                      - errMsg: "There is no synced crypto account with the id: 99999999."
                symbol not found:
                  value:
                    message: Not Found
                    errors:
                      - errMsg: "There is no synced crypto balance with symbol 'doge' for the crypto account with id: 33004."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /crypto/synced/{id}/refresh:
    post:
      tags:
        - crypto-synced
      summary: Refresh balances for a synced crypto account
      description: Trigger a balance refresh for the specified synced crypto
        account. Returns the refreshed synced crypto account.
      operationId: refreshCryptoSynced
      parameters:
        - name: id
          in: path
          description: Synced crypto account ID
          required: true
          schema:
            type: integer
            format: int32
          examples:
            existing synced connection:
              summary: Existing synced account ID
              value: 33004
            id not found:
              summary: Example of an id that doesn't exist
              value: 99999999
      responses:
        "200":
          description: Refreshed synced crypto account
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/syncedCryptoAccount"
              example:
                id: 33004
                provider: coinbase
                status: active
                created_by_name: User 1
                created_at: "2025-10-02T11:02:09.000Z"
                display_name: Coinbase Main
                balances:
                  - name: ETH
                    balance: "12.004500000000000000"
                    symbol: eth
                    coingecko_id: ethereum
                    to_base: 28998.44
                    balance_as_of: "2026-02-25T14:25:00.000Z"
                    exchange_rate_as_of: "2026-02-25T14:20:00.000Z"
                    updated_at: "2026-02-25T14:25:01.000Z"
                  - name: BTC
                    balance: "0.100020003000400050"
                    symbol: btc
                    coingecko_id: bitcoin
                    to_base: 6231.28
                    balance_as_of: "2026-02-25T14:25:00.000Z"
                    exchange_rate_as_of: "2026-02-25T14:20:00.000Z"
                    updated_at: "2026-02-25T14:25:01.000Z"
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no synced crypto account with the id: 99999999."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /balance_history:
    get:
      tags:
        - balance_history
      summary: Get balance history
      description: >-
        Retrieve historical balance entries.<br><br>

        Balance history is monthly. When `start_date` and `end_date` are both provided,
        they must be first-of-month dates. `start_date` must not be in the future,
        while `end_date` may be in the future. If one of `start_date` or `end_date`
        is provided, the other is required. If neither is provided, all available
        balance history is returned.<br><br>

        The response groups entries by source account. Each item in
        `balance_history` contains a `source` object plus a `balances` array
        containing one balance entry per month in the requested range, or all
        stored entries when no range is provided.<br><br>

        Historical entries for accounts that have been deleted may still
        be returned. These entries use `source.type: deleted` and include
        `deleted_account_id`, archived display fields, and account metadata on the
        `source` object.
      operationId: getBalanceHistory
      parameters:
        - name: start_date
          in: query
          description: Optional start date for the requested history range in YYYY-MM-DD format. If set, `end_date` is also required. This must be the first day of a month and must not be in the future.
          required: false
          schema:
            type: string
            format: date
          examples:
            range start:
              summary: Start date
              value: "2026-01-01"
        - name: end_date
          in: query
          description: Optional end date for the requested history range in YYYY-MM-DD format. If set, `start_date` is also required. This must be the first day of a month. For a single month, set this to the same first-of-month date as `start_date`.
          required: false
          schema:
            type: string
            format: date
          examples:
            range end:
              summary: End date
              value: "2026-03-01"
      responses:
        "200":
          description: Historical balance entries for the requested date range
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/balanceHistoryListResponseObject"
              examples:
                all account types:
                  value:
                    balance_history:
                      - source:
                          type: manual
                          manual_account_id: 119807
                        balances:
                          - id: 101
                            date: "2026-01-01"
                            balance: "41000.0000"
                            currency: usd
                            to_base: 41000
                            crypto_balance: null
                          - id: 102
                            date: "2026-02-01"
                            balance: "41211.8000"
                            currency: usd
                            to_base: 41211.8
                            crypto_balance: null
                      - source:
                          type: plaid
                          plaid_account_id: 119808
                        balances:
                          - id: 103
                            date: "2026-01-01"
                            balance: "5498.2800"
                            currency: usd
                            to_base: 5498.28
                            crypto_balance: null
                      - source:
                          type: crypto_manual
                          crypto_manual_id: 22001
                          symbol: btc
                        balances:
                          - id: 104
                            date: "2026-01-01"
                            balance: "53124.7200"
                            currency: usd
                            to_base: 53124.72
                            crypto_balance: "0.852341920145782301"
                      - source:
                          type: crypto_synced
                          crypto_synced_id: 33004
                          symbol: btc
                        balances:
                          - id: 105
                            date: "2026-01-01"
                            balance: "6231.2800"
                            currency: usd
                            to_base: 6231.28
                            crypto_balance: "0.100020003000400050"
                      - source:
                          type: deleted
                          deleted_account_id: 91
                          name: Savings
                          institution_name: Old Bank
                          display_name: Closed Savings
                          account_type: savings
                          subtype: savings
                          mask: "1234"
                          symbol: null
                        balances:
                          - id: 106
                            date: "2026-01-01"
                            balance: "1250.0000"
                            currency: usd
                            to_base: 1250
                            crypto_balance: null
                manual account history:
                  value:
                    balance_history:
                      - source:
                          type: manual
                          manual_account_id: 119807
                        balances:
                          - id: 201
                            date: "2026-01-01"
                            balance: "41000.0000"
                            currency: usd
                            to_base: 41000
                            crypto_balance: null
                          - id: 202
                            date: "2026-02-01"
                            balance: "41211.8000"
                            currency: usd
                            to_base: 41211.8
                            crypto_balance: null
                plaid account history:
                  value:
                    balance_history:
                      - source:
                          type: plaid
                          plaid_account_id: 119808
                        balances:
                          - id: 301
                            date: "2026-02-01"
                            balance: "5498.2800"
                            currency: usd
                            to_base: 5498.28
                            crypto_balance: null
                synced crypto history:
                  value:
                    balance_history:
                      - source:
                          type: crypto_synced
                          crypto_synced_id: 33004
                          symbol: btc
                        balances:
                          - id: 401
                            date: "2026-02-01"
                            balance: "6231.2800"
                            currency: usd
                            to_base: 6231.28
                            crypto_balance: "0.100020003000400050"
                deleted account history:
                  value:
                    balance_history:
                      - source:
                          type: deleted
                          deleted_account_id: 91
                          name: Savings
                          institution_name: Old Bank
                          display_name: Closed Savings
                          account_type: savings
                          subtype: savings
                          mask: "1234"
                          symbol: null
                        balances:
                          - id: 501
                            date: "2026-01-01"
                            balance: "1250.0000"
                            currency: usd
                            to_base: 1250
                            crypto_balance: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing paired date:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`start_date` and `end_date` must either both be provided or both be omitted."
                invalid range:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`start_date` must be less than or equal to `end_date`."
                not first of month:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`start_date` and `end_date` must both be the first day of a month."
                future start date:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`start_date` must not be in the future."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /balance_history/{account_type}/{account_id}:
    get:
      tags:
        - balance_history
      summary: Get balance history for an account
      description: >-
        Retrieve historical balance entries for one manual, Plaid, manual crypto,
        or deleted account.  Crypto synced accounts require an additional `symbol` path parameter.<br><br>

        The `account_type` path parameter identifies the type of account and the
        `account_id` path parameter identifies the specific id for that account type.<br><br>

        When `start_date` and `end_date` are both provided, they must be first-of-month
        dates. `start_date` must not be in the future, while `end_date` may be in the future.
        If one of `start_date` or `end_date` is provided, the other is required. If neither is
        provided, all available history for the source is returned.
      operationId: getBalanceHistoryForAccount
      parameters:
        - name: account_type
          in: path
          required: true
          description: Source family to retrieve. Use `manual`, `plaid`, `crypto_manual`, or `deleted`.
          schema:
            type: string
            enum: [manual, plaid, crypto_manual, deleted]
        - name: account_id
          in: path
          required: true
          description: Account or deleted-source identifier within the selected `account_type`.
          schema:
            type: integer
            format: int32
        - name: start_date
          in: query
          description: Optional start date for the requested history range in YYYY-MM-DD format. If set, `end_date` is also required. This must be the first day of a month and must not be in the future.
          required: false
          schema:
            type: string
            format: date
        - name: end_date
          in: query
          description: Optional end date for the requested history range in YYYY-MM-DD format. If set, `start_date` is also required. This must be the first day of a month.
          required: false
          schema:
            type: string
            format: date
      responses:
        "200":
          description: Historical balance entries for the requested source
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/balanceHistoryListResponseObject"
              examples:
                manual account history:
                  value:
                    balance_history:
                      - source:
                          type: manual
                          manual_account_id: 119807
                        balances:
                          - id: 201
                            date: "2026-01-01"
                            balance: "41000.0000"
                            currency: usd
                            to_base: 41000
                            crypto_balance: null
                          - id: 202
                            date: "2026-02-01"
                            balance: "41211.8000"
                            currency: usd
                            to_base: 41211.8
                            crypto_balance: null
                deleted account history:
                  value:
                    balance_history:
                      - source:
                          type: deleted
                          deleted_account_id: 91
                          name: Savings
                          institution_name: Old Bank
                          display_name: Closed Savings
                          account_type: savings
                          subtype: savings
                          mask: "1234"
                          symbol: null
                        balances:
                          - id: 501
                            date: "2026-01-01"
                            balance: "1250.0000"
                            currency: usd
                            to_base: 1250
                            crypto_balance: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing paired date:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`start_date` and `end_date` must either both be provided or both be omitted."
                invalid range:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`start_date` must be less than or equal to `end_date`."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                manual not found:
                  value:
                    message: Not Found
                    errors:
                      - errMsg: "There is no manual account with the id: 99999999."
                deleted not found:
                  value:
                    message: Not Found
                    errors:
                      - errMsg: "There is no deleted balance history source with the id: 99999999."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    put:
      tags:
        - balance_history
      summary: Upsert balance history for an account
      description: >-
        Upsert one or more historical balance entries for a single manual, Plaid,
        manual crypto, or deleted acount. Crypto synced accounts require an additional `symbol` path parameter.<br><br>

        The `account_type` path parameter identifies the the type of account and the
        `account_id` path parameter identifies the specific id for that account type.<br><br>

        Submit one or more entries in the `balances` array. Each entry must specify
        a `date` and `balance` value.<br><br>

        Balance history is monthly. Each entry's `date` must be the first day of
        a month and must not be in the future.<br><br>

        `currency` may be provided for any balance entry. If omitted, it defaults
        to the account currency for manual/Plaid accounts, or the user's primary
        currency for crypto/deleted accounts.<br><br>

        `symbol` is optional for `crypto_manual` accounts, tolerated for `deleted`
        accounts, and invalid for `manual` or `plaid` accounts.<br><br>

        `crypto_balance` may be provided for `crypto_manual` and `deleted` accounts,
        and is invalid for `manual` or `plaid` accounts.<br><br>

        Use `PUT /v2/balance_history/deleted/{account_id}/details` to update
        deleted-source metadata.
      operationId: upsertBalanceHistoryForAccount
      parameters:
        - name: account_type
          in: path
          required: true
          description: Source family to update. Use `manual`, `plaid`, `crypto_manual`, or `deleted`.
          schema:
            type: string
            enum: [manual, plaid, crypto_manual, deleted]
        - name: account_id
          in: path
          required: true
          description: Account or deleted-source identifier within the selected `account_type`.
          schema:
            type: integer
            format: int32
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/upsertBalanceHistoryRequestObject"
            examples:
              manual account bulk upsert:
                value:
                  balances:
                    - date: "2026-03-01"
                      balance: "41500.0000"
                    - date: "2026-04-01"
                      balance: "41625.5000"
              crypto manual balance with symbol:
                value:
                  balances:
                    - date: "2026-03-01"
                      balance: "56011.1200"
                      symbol: btc
                      crypto_balance: "0.852341920145782301"
              deleted account bulk upsert:
                value:
                  balances:
                    - date: "2026-03-01"
                      symbol: btc
                      crypto_balance: "0.020000000000000000"
                      currency: usd
                      balance: "1255.0000"
              get-shaped balance entry input:
                value:
                  balances:
                    - id: 601
                      date: "2026-03-01"
                      balance: "41500.0000"
                      currency: usd
                      to_base: 41500
                      crypto_balance: null
      responses:
        "200":
          description: All balance history entries were upserted successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/balanceHistoryAccountObject"
              examples:
                balances updated:
                  value:
                    source:
                      type: manual
                      manual_account_id: 119807
                    balances:
                      - id: 601
                        date: "2026-03-01"
                        balance: "41500.0000"
                        currency: usd
                        to_base: 41500
                        crypto_balance: null
                      - id: 602
                        date: "2026-04-01"
                        balance: "41625.5000"
                        currency: usd
                        to_base: 41625.5
                        crypto_balance: null
        "400":
          description: Bad Request. The entire request is rejected if any row in
            `balances` fails validation; no rows are updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing balances:
                  value:
                    message: Invalid Request Body
                    errors:
                      - errMsg: "Missing required property 'balances' in request body."
                invalid property:
                  value:
                    message: Invalid Request Body
                    errors:
                      - errMsg: "Invalid property 'foo' in request body."
                invalid date:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`date` must be the first day of a month."
                        request_balances_index: 0
                future date:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`date` must not be in the future."
                        request_balances_index: 1
                crypto balance not allowed:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`crypto_balance` may only be set when `account_type` is `crypto_manual` or `deleted`."
                        request_balances_index: 0
                invalid row in bulk request:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`symbol` may not be set when `account_type` is `manual` or `plaid`."
                        request_balances_index: 1
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no manual account with the id: 99999999."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - balance_history
      summary: Delete all balance history for an account
      description: >-
        Delete all historical balance entries for a single manual, Plaid,
        manual crypto, or deleted account. Crypto synced accounts require an additional `symbol` path parameter.
      operationId: deleteBalanceHistoryForAccount
      parameters:
        - name: account_type
          in: path
          required: true
          description: Source family to delete. Use `manual`, `plaid`, `crypto_manual`, or `deleted`.
          schema:
            type: string
            enum: [manual, plaid, crypto_manual, deleted]
        - name: account_id
          in: path
          required: true
          description: Account or deleted-source identifier within the selected `account_type`.
          schema:
            type: integer
            format: int32
      responses:
        "204":
          description: All history for the account/source was deleted
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                source not found:
                  value:
                    message: Not Found
                    errors:
                      - errMsg: "There is no manual account with the id: 99999999."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /balance_history/crypto_synced/{account_id}/{symbol}:
    get:
      tags:
        - balance_history
      summary: Get balance history for a synced crypto symbol
      description: >-
        Retrieve historical balance entries for a single synced crypto symbol stream.<br><br>

        Use the `crypto_synced` account id together with a `symbol` path parameter
        to select one balance stream within that synced crypto account.<br><br>

        When `start_date` and `end_date` are both provided, they must be first-of-month
        dates. `start_date` must not be in the future, while `end_date` may be in the future.
        If one of `start_date` or `end_date` is provided, the other is required. If neither is
        provided, all available history for the symbol stream is returned.
      operationId: getBalanceHistoryForCryptoSynced
      parameters:
        - name: account_id
          in: path
          required: true
          description: Synced crypto account identifier.
          schema:
            type: integer
            format: int32
        - name: symbol
          in: path
          required: true
          description: Crypto symbol identifying one balance stream within the synced crypto account.
          schema:
            type: string
            minLength: 1
            maxLength: 25
        - name: start_date
          in: query
          description: Optional start date for the requested history range in YYYY-MM-DD format. If set, `end_date` is also required. This must be the first day of a month and must not be in the future.
          required: false
          schema:
            type: string
            format: date
        - name: end_date
          in: query
          description: Optional end date for the requested history range in YYYY-MM-DD format. If set, `start_date` is also required. This must be the first day of a month.
          required: false
          schema:
            type: string
            format: date
      responses:
        "200":
          description: Historical balance entries for the synced crypto symbol stream
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/balanceHistoryListResponseObject"
              example:
                balance_history:
                  - source:
                      type: crypto_synced
                      crypto_synced_id: 33004
                      symbol: btc
                    balances:
                      - id: 401
                        date: "2026-02-01"
                        balance: "6231.2800"
                        currency: usd
                        to_base: 6231.28
                        crypto_balance: "0.100020003000400050"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing paired date:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`start_date` and `end_date` must either both be provided or both be omitted."
                invalid range:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`start_date` must be less than or equal to `end_date`."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                source not found:
                  value:
                    message: Not Found
                    errors:
                      - errMsg: "There is no synced crypto account with the id: 99999999."
                symbol not found:
                  value:
                    message: Not Found
                    errors:
                      - errMsg: "There is no synced crypto balance history stream for symbol 'doge' on account id: 33004."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    put:
      tags:
        - balance_history
      summary: Upsert balance history for a synced crypto symbol
      description: >-
        Upsert one or more historical balance entries for a single synced crypto
        symbol stream.<br><br>

        The path identifies both the synced crypto account and the symbol being updated.<br><br>

        Submit one or more entries in the `balances` array. Each entry must specify
        a `date` and `balance` value.<br><br>

        Balance history is monthly. Each entry's `date` must be the first day of
        a month and must not be in the future.<br><br>

        The request body must not include `symbol`; the symbol is supplied by the path.<br><br>

        `currency` may be provided for any balance entry. If omitted, it defaults
        to the user's primary currency for synced crypto balances.<br><br>

        `crypto_balance` may be provided for synced crypto balances.
      operationId: upsertBalanceHistoryForCryptoSynced
      parameters:
        - name: account_id
          in: path
          required: true
          description: Synced crypto account identifier to update.
          schema:
            type: integer
            format: int32
        - name: symbol
          in: path
          required: true
          description: Crypto symbol identifying one balance stream within the synced crypto account.
          schema:
            type: string
            minLength: 1
            maxLength: 25
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/upsertBalanceHistoryRequestObject"
            examples:
              synced crypto bulk upsert:
                value:
                  balances:
                    - date: "2026-03-01"
                      balance: "6400.0000"
                      crypto_balance: "0.100020003000400050"
                    - date: "2026-04-01"
                      balance: "6500.0000"
                      crypto_balance: "0.100020003000400050"
      responses:
        "200":
          description: All balance history entries were upserted successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/balanceHistoryAccountObject"
              examples:
                balances updated:
                  value:
                    source:
                      type: crypto_synced
                      crypto_synced_id: 33004
                      symbol: btc
                    balances:
                      - id: 604
                        date: "2026-03-01"
                        balance: "6400.0000"
                        currency: usd
                        to_base: 6400
                        crypto_balance: "0.100020003000400050"
                      - id: 605
                        date: "2026-04-01"
                        balance: "6500.0000"
                        currency: usd
                        to_base: 6500
                        crypto_balance: "0.100020003000400050"
        "400":
          description: Bad Request. The entire request is rejected if any row in
            `balances` fails validation; no rows are updated.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing balances:
                  value:
                    message: Invalid Request Body
                    errors:
                      - errMsg: "Missing required property 'balances' in request body."
                invalid date:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`date` must be the first day of a month."
                        request_balances_index: 0
                future date:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`date` must not be in the future."
                        request_balances_index: 1
                invalid row in bulk request:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "`balance` must be a valid numeric string or number."
                        request_balances_index: 1
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                source not found:
                  value:
                    message: Not Found
                    errors:
                      - errMsg: "There is no synced crypto account with the id: 99999999."
                symbol not found:
                  value:
                    message: Not Found
                    errors:
                      - errMsg: "There is no synced crypto balance history stream for symbol 'doge' on account id: 33004."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - balance_history
      summary: Delete all balance history for a synced crypto symbol
      description: >-
        Delete all historical balance entries for a single synced crypto symbol stream.<br><br>

        The path identifies both the synced crypto account and the symbol whose
        history should be deleted.
      operationId: deleteBalanceHistoryForCryptoSynced
      parameters:
        - name: account_id
          in: path
          required: true
          description: Synced crypto account identifier.
          schema:
            type: integer
            format: int32
        - name: symbol
          in: path
          required: true
          description: Crypto symbol identifying one balance stream within the synced crypto account.
          schema:
            type: string
            minLength: 1
            maxLength: 25
      responses:
        "204":
          description: All history for the synced crypto symbol stream was deleted
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no synced crypto balance history stream for symbol 'doge' on account id: 33004."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /balance_history/entries/{id}:
    delete:
      tags:
        - balance_history
      summary: Delete a balance history entry
      description: >-
        Delete a single monthly balance history entry by its id.
      operationId: deleteBalanceHistoryEntry
      parameters:
        - name: id
          in: path
          required: true
          description: Balance history row identifier to delete.
          schema:
            type: integer
            format: int32
      responses:
        "204":
          description: The balance history entry was deleted
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no balance history entry with the id: 99999999."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /balance_history/deleted/{account_id}/details:
    put:
      tags:
        - balance_history
      summary: Update details for a deleted account
      description: >-
        Update archived metadata for a deleted balance history source.<br><br>

        Pass the `deleted` source id returned on `source.deleted_account_id`.
        This endpoint updates the stored deleted-source metadata used for all
        historical entries associated with that deleted source.
      operationId: updateBalanceHistoryDetails
      parameters:
        - name: account_id
          in: path
          required: true
          description: Deleted account history source identifier to update.
          schema:
            type: integer
            format: int32
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/updateBalanceHistoryDetailsRequestObject"
            examples:
              update deleted source details:
                value:
                  name: Savings
                  institution_name: Old Bank
                  display_name: Old Savings Account
                  account_type: savings
                  subtype: savings
                  mask: "1234"
      responses:
        "200":
          description: Updated deleted source details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/updateBalanceHistoryDetailsResponseObject"
              example:
                name: Savings
                institution_name: Old Bank
                display_name: Old Savings Account
                account_type: savings
                subtype: savings
                mask: "1234"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Invalid Request Body
                errors:
                  - errMsg: "Request body must include at least one of: name, institution_name, display_name, account_type, subtype, mask."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no deleted balance history source with the id: 99999999."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /manual_accounts:
    get:
      tags:
        - manual_accounts
      summary: Get all manual accounts
      description: Retrieve a list of all manually-managed accounts associated
        with the user's account.
      operationId: getAllManualAccounts
      responses:
        "200":
          description: A list of manual accounts
          content:
            application/json:
              schema:
                type: object
                properties:
                  manual_accounts:
                    type: array
                    items:
                      $ref: "#/components/schemas/manualAccountObject"
              example:
                manual_accounts:
                  - id: 119807
                    name: Individual Brokerage
                    institution_name: Fidelity
                    display_name: null
                    type: investment
                    subtype: brokerage
                    balance: "41211.8000"
                    currency: usd
                    to_base: 41211.8
                    balance_as_of: "2025-06-25T17:00:04.000Z"
                    status: active
                    closed_on: null
                    external_id: null
                    exclude_from_transactions: false
                    created_by_name: User 1
                    created_at: "2025-06-25T17:00:04.414Z"
                    updated_at: "2025-06-26T19:03:38.312Z"
                  - id: 119909
                    name: Euro Travel Card
                    institution_name: WeBank
                    display_name: null
                    type: credit
                    subtype: credit card
                    balance: "1004.8000"
                    currency: usd
                    to_base: 1004.8
                    balance_as_of: "2023-06-25T17:00:04.000Z"
                    status: active
                    closed_on: null
                    external_id: null
                    exclude_from_transactions: false
                    created_by_name: User 1
                    created_at: "2025-06-25T17:00:04.414Z"
                    updated_at: "2025-06-26T19:03:38.312Z"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must NOT have additional properties
                    instancePath: /query
                    schemaPath: "#/properties/query/additionalProperties"
                    keyword: additionalProperties
                    params:
                      additionalProperty: foo
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    post:
      tags:
        - manual_accounts
      summary: Create a manual account
      description: Create a new manually-managed account.
      operationId: createManualAccount
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/createManualAccountRequestObject"
            examples:
              minimum request body:
                summary: Minimum required fields for creating a manual account
                value:
                  name: API created Account
                  type: cash
                  balance: "100"
              full example:
                summary: Full example with all fields
                value:
                  name: API created loan
                  type: vehicle
                  subtype: loan
                  display_name: Car loan
                  balance: "9999.99"
                  balance_as_of: "2024-10-12"
                  closed_on: null
                  currency: usd
                  institution_name: Bank of America
                  exclude_from_transactions: false
              display_name not unique:
                summary: Explicit display_name not unique
                value:
                    name: API created card
                    type: credit
                    display_name: WeBank Euro Travel Card
                    balance: "1004.8000"
              implicit display_name not unique:
                summary: Derived display_name not unique
                value:
                  name: Individual Brokerage
                  type: investment
                  institution_name: Fidelity
                  balance: "41211.8000"
      responses:
        "201":
          description: Successfully created manual account
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/manualAccountObject"
              examples:
                minimum request response:
                  value:
                    id: 119999
                    name: API created Account
                    institution_name: null
                    display_name: null
                    type: cash
                    subtype: null
                    balance: "100"
                    currency: usd
                    to_base: 100
                    balance_as_of: "2024-10-06T18:55:08.599Z"
                    status: active
                    closed_on: null
                    external_id: null
                    exclude_from_transactions: false
                    created_by_name: User 1
                    created_at: "2024-10-06T18:55:08.599Z"
                    updated_at: "2024-10-06T18:55:08.599Z"
                complete request response:
                  value:
                    id: 119999
                    name: API created loan
                    institution_name: Bank of America
                    display_name: Car loan
                    type: vehicle
                    subtype: loan
                    balance: "9999.99"
                    currency: usd
                    to_base: 9999.99
                    balance_as_of: "2024-10-06T18:55:08.599Z"
                    status: active
                    closed_on: null
                    external_id: null
                    exclude_from_transactions: false
                    created_by_name: User 1
                    created_at: "2024-10-06T18:57:12.029Z"
                    updated_at: "2024-10-06T18:57:12.029Z"
        "400":
          description: Invalid request body
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing required properties:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "Missing required property 'name' in request body."
                      - errMsg: "Missing required property 'type' in request body."
                      - errMsg: "Missing required property 'balance' in request body."
                explicit display_name not unique:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "A manual account with the same display_name: 'WeBank Travel Card' already exists."
                        existing_manual_account_id: 219909
                        requested_display_name: "WeBank Travel Card"
                        existing_display_name: "WeBank Travel Card"
                        existing_name: "Euro Travel Card"
                        requested_name: "API created card"
                implicit display_name not unique:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "A manual account with the same implicit display_name derived from name: 'Individual Brokerage' and institution_name: 'Fidelity' already exists."
                        existing_manual_account_id: 219807
                        requested_name: Individual Brokerage
                        existing_name: Individual Brokerage
                        requested_institution_name: Fidelity
                        existing_institution_name: Fidelity
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /manual_accounts/{id}:
    get:
      tags:
        - manual_accounts
      summary: Get a single manual account
      description: Retrieve the details of the manual account with the specified
        ID.
      operationId: getManualAccountById
      parameters:
        - name: id
          in: path
          description: ID of the manual account to retrieve
          required: true
          schema:
            type: integer
            format: int32
          examples:
            basic manual account:
              summary: Basic manual account by id request
              value: 119807
            id not found:
              summary: Example of an id that doesn't exist
              value: 9999999999999
      responses:
        "200":
          description: Manual Account Object with the requested account
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/manualAccountObject"
              example:
                id: 119807
                name: Individual Brokerage
                institution_name: Fidelity
                display_name: null
                type: investment
                subtype: brokerage
                balance: "41211.8000"
                currency: usd
                to_base: 41211.8
                balance_as_of: "2025-06-25T17:00:04.000Z"
                status: active
                closed_on: null
                external_id: null
                exclude_from_transactions: false
                created_by_name: User 1
                created_at: "2025-06-25T17:00:04.414Z"
                updated_at: "2025-06-26T19:03:38.312Z"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                invalid account id type:
                  value:
                    message: Invalid Path Parameters
                    errors:
                      - errMsg: "Invalid value type for path parameter: 'id'. Expected 'number', received 'string'."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: There is no manual account with the id:'9999999999999'`
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    put:
      tags:
        - manual_accounts
      summary: Update an existing manual account
      description: >-
        Modifies the properties of an existing manual account.<br><br>
        
        You may submit the response from a `GET /manual_accounts/{id}` as the request body, however only certain
        properties can be updated using this API. The following system set properties are
        accepted in the request body but their values will be ignored: `id`, `to_base`, `created_at`, and `updated_at`.<br><br>

        It is also possible to provide only the properties to be updated in the
        request body, as long as the request includes at least one of the
        properties that is not listed above. For example a request body that contains only a `name` property is valid.<br><br>

      operationId: updateManualAccount
      parameters:
        - name: id
          in: path
          description: ID of the manual account to update
          required: true
          schema:
            type: integer
            format: int32
          examples:
            category:
              summary: Example of a manual account's id
              value: 119807
            not found:
              summary: Example of a manual account ID that does not exist
              value: 999999999
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/updateManualAccountRequestObject"
            examples:
              minimum request body:
                summary: type change
                value:
                  type: credit
              close account:
                summary: close and exclude
                value:
                  closed_on: "2024-10-15"
                  exclude_from_transactions: true
              use get request:
                summary: Only display name has changed
                value:
                  id: 119909
                  name: Euro Travel Card
                  type: credit
                  subtype: credit card
                  display_name: New Display Name
                  balance: "1004.8000"
                  balance_as_of: "2023-06-25T17:00:04.000Z"
                  closed_on: null
                  currency: usd
                  institution_name: WeBank
                  exclude_from_transactions: false
                  created_at: "2025-06-25T17:00:04.414Z"
                  updated_at: "2025-06-26T19:03:38.312Z"
      responses:
        "200":
          description: Manual Account updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/manualAccountObject"
              examples:
                type changed to credit:
                  value:
                    id: 119807
                    name: Individual Brokerage
                    institution_name: Fidelity
                    display_name: null
                    type: investment
                    subtype: brokerage
                    balance: "41211.8000"
                    currency: usd
                    to_base: 41211.8
                    balance_as_of: "2025-06-25T17:00:04.000Z"
                    status: active
                    closed_on: null
                    external_id: null
                    exclude_from_transactions: false
                    created_by_name: User 1
                    created_at: "2025-06-25T17:00:04.414Z"
                    updated_at: "2025-06-26T19:03:38.312Z"
                closed account:
                  value:
                    id: 119807
                    name: Individual Brokerage
                    institution_name: Fidelity
                    display_name: null
                    type: investment
                    subtype: brokerage
                    balance: "41211.8000"
                    currency: usd
                    to_base: 41211.8
                    balance_as_of: "2025-06-25T17:00:04.000Z"
                    status: closed
                    closed_on: "2024-10-06"
                    external_id: null
                    exclude_from_transactions: true
                    created_by_name: User 1
                    created_at: "2025-06-25T17:00:04.414Z"
                    updated_at: "2024-10-06T19:03:09.506Z"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing required properties:
                  value:
                    message: Invalid Request Body
                    errors:
                      - errMsg: "A request to update a manual account must include at least one of the
                          following properties: name, type, subtype, display_name,
                          balance, balance_as_of, closed_on, currency,
                          institution_name, exclude_from_transactions"
                duplicate display_name: 
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "A manual account with the same display_name: 'WeBank Travel Card' already exists."
                        existing_manual_account_id: 219909
                        requested_display_name: "WeBank Travel Card"
                        existing_display_name: "WeBank Travel Card"
                        existing_name: "Euro Travel Card"
                        requested_name: "API created card"
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no manual account with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - manual_accounts
      summary: Delete a manual account
      description: Deletes the single manual account with the ID specified on
        the path. If any transactions exist with the `manual_account_id`
        property set to this account's ID they will appear with a warning when
        displayed in the web view.
      operationId: deleteManualAccount
      parameters:
        - in: path
          name: id
          description: ID of the manual account to delete
          required: true
          schema:
            type: integer
            format: int32
          examples:
            delete manual account:
              summary: Account ID to delete
              value: 119807
            id not found:
              summary: Example of an id that doesn't exist
              value: 543210
        - in: query
          name: delete_items
          description: When set to true will also delete any transactions,
            rules, and recurring items associated with this account. Use this
            option with caution, it is irreversible!
          required: false
          schema:
            type: boolean
            default: false
        - in: query
          name: delete_balance_history
          description: When set to true will delete any balance history
            associated with this account.
          required: false
          schema:
            type: boolean
            default: false
      responses:
        "204":
          description: No Content
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no manual account with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /plaid_accounts:
    get:
      tags:
        - plaid_accounts
      summary: Get all accounts synced via Plaid
      description: Retrieve a list of all synced accounts associated with the
        user's account.
      operationId: getAllPlaidAccounts
      responses:
        "200":
          description: A list of accounts synced via Plaid
          content:
            application/json:
              schema:
                type: object
                properties:
                  plaid_accounts:
                    type: array
                    items:
                      $ref: "#/components/schemas/plaidAccountObject"
              example:
                plaid_accounts:
                  - id: 119804
                    plaid_item_id: "aB2cD3eF4gH5iJ6kL7mN8oP9qR0sT1uV2wX3yZ4"
                    date_linked: "2020-01-28"
                    linked_by_name: User 1
                    name: 401k
                    display_name: ""
                    type: brokerage
                    subtype: 401k
                    mask: "7468"
                    institution_name: Vanguard
                    status: inactive
                    allow_transaction_modifications: false
                    limit: null
                    balance: "12345.6700"
                    currency: usd
                    to_base: 12345.67
                    balance_last_update: "2025-01-27T01:38:11.862Z"
                    import_start_date: "2023-01-01"
                    last_import: "2025-01-24T12:57:09.190Z"
                    last_fetch: "2025-01-28T01:38:11.862Z"
                    plaid_last_successful_update: "2025-01-27T01:38:11.862Z"
                  - id: 119805
                    plaid_item_id: "xY9zW8vU7tS6rQ5pO4nM3lK2jI1hG0fE9dC8bA7"
                    date_linked: "2020-01-28"
                    linked_by_name: User 1
                    name: Freedom
                    display_name: Penny's Visa
                    type: credit
                    subtype: credit card
                    mask: "1973"
                    institution_name: Chase
                    status: active
                    allow_transaction_modifications: true
                    limit: 15000
                    balance: "0.0000"
                    currency: usd
                    to_base: 0
                    balance_last_update: "2025-01-27T01:38:07.460Z"
                    import_start_date: "2023-01-01"
                    last_import: "2025-01-24T12:57:03.250Z"
                    last_fetch: "2025-01-28T01:38:11.862Z"
                    plaid_last_successful_update: "2025-01-27T01:38:11.862Z"
                  - id: 119807
                    plaid_item_id: "mK8nL9oP0qR1sT2uV3wX4yZ5aB6cD7eF8gH9iJ0"
                    date_linked: "2020-01-28"
                    linked_by_name: User 1
                    name: Checking
                    display_name: Penny's Checking
                    type: cash
                    subtype: checking
                    mask: "2046"
                    institution_name: Western Bank
                    status: active
                    allow_transaction_modifications: true
                    limit: null
                    balance: "5498.2800"
                    currency: usd
                    to_base: 5498.28
                    balance_last_update: "2025-01-27T01:38:07.460Z"
                    import_start_date: "2023-01-01"
                    last_import: "2025-01-24T12:57:03.250Z"
                    last_fetch: "2025-01-28T01:38:11.862Z"
                    plaid_last_successful_update: "2025-01-27T01:38:11.862Z"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must NOT have additional properties
                    instancePath: /query
                    schemaPath: "#/properties/query/additionalProperties"
                    keyword: additionalProperties
                    params:
                      additionalProperty: foo
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /plaid_accounts/{id}:
    get:
      tags:
        - plaid_accounts
      summary: Get a single account that is synced via Plaid
      description: Retrieve the details of the plaid account with the specified
        ID.
      operationId: getPlaidAccountById
      parameters:
        - name: id
          in: path
          description: ID of the plaid account to retrieve
          required: true
          schema:
            type: integer
            format: int32
          examples:
            basic manual account:
              summary: Basic plaid account by id request
              value: 119805
            id not found:
              summary: Example of an id that doesn't exist
              value: 9999999999999
      responses:
        "200":
          description: Plaid Account Object with the requested account.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/plaidAccountObject"
              example:
                id: 119805
                plaid_item_id: "xY9zW8vU7tS6rQ5pO4nM3lK2jI1hG0fE9dC8bA7"
                date_linked: "2020-01-28"
                linked_by_name: User 1
                name: Freedom
                display_name: Penny's Visa
                type: credit
                subtype: credit card
                mask: "1973"
                institution_name: Chase
                status: active
                allow_transaction_modifications: true
                limit: 15000
                balance: "0.0000"
                currency: usd
                to_base: 0
                balance_last_update: "2025-01-27T01:38:07.460Z"
                import_start_date: "2023-01-01"
                last_import: "2025-01-24T12:57:03.250Z"
                last_fetch: "2025-01-28T01:38:11.862Z"
                plaid_last_successful_update: "2025-01-27T01:38:11.862Z"
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be integer
                    instancePath: /path/id
                    schemaPath: "#/properties/path/properties/ids/items/type"
                    keyword: type
                    params:
                      type: integer
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no plaid account with the id: 9999999999999"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /plaid_accounts/fetch:
    post:
      tags:
        - plaid_accounts
      summary: Trigger Fetch from Plaid
      description: >-
        Use this endpoint to trigger a fetch for latest data from Plaid.<br><br>

        Eligible accounts are those who last_fetch value is over 1 minute ago.
        (Although the limit is every minute, please use this endpoint
        sparingly!) Successive calls to this endpoint under a minute after the
        first will return a 425 TOO EARLY response.<br><br>

        Successful calls will return a 202 ACCEPTED response. Note that fetching
        from Plaid is a background job. This endpoint simply queues up the job.
        You may track the `plaid_last_successful_update`, `last_fetch` and
        `last_import` properties to verify the results of the fetch. The `last
        fetch` property is updated when Plaid accepts a request to fetch data.
        The `plaid_last_successful_update`is updated when it successfully
        contacts the associated financial institution. The `last_import` field
        is updated only when new transactions have been imported.
      operationId: triggerPlaidAccountFetch
      parameters:
        - name: start_date
          in: query
          schema:
            type: string
            format: date
          description: Indicates the beginning of the time period to fetch
            transactions for. If omitted, the most recent transactions will be
            returned. <br> Required if end_date exists. <br>
        - name: end_date
          in: query
          schema:
            type: string
            format: date
          description: "Indicates the end of the time period to fetch
            transactions for. Required if start_date exists. "
        - name: id
          in: query
          description: Specific ID of a plaid account to fetch. If not set the
            endpoint will trigger a fetch for all eligible accounts.
          schema:
            type: integer
            format: int32
          examples:
            basic manual account:
              summary: Basic manual account by id request
              value: 119807
            id not found:
              summary: Example of an id that doesn't exist
              value: 9999999999999
      responses:
        "202":
          description: A 202 ACCEPTED status is returned if Plaid acknowledged
            the fetch request. This indicates that it is possible to
            subsequently query the `GET /plaid_accounts` endpoint to determine
            if the request was successful (`plaid_last_successful_update` is
            more recent than `last_fetch`), or if new transactions were synced
            (`last_import` is more recent than `last_fetch`).<br>
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing end_date:
                  value:
                    message: Invalid Request Parameters
                    errors:
                      - errMsg: "Both 'start_date' and 'end_date' must be specified."
                invalid id type:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: must be integer
                        instancePath: /path/id
                        schemaPath: "#/properties/path/properties/ids/items/type"
                        keyword: type
                        params:
                          type: integer
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "425":
          description: Too Early
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Too Early
                errors:
                  - errMsg: "Please wait at least 60 seconds between fetch requests."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /transactions:
    get:
      tags:
        - transactions (bulk)
      summary: Get all transactions
      description: Retrieve a list of all transactions associated with a user's
        account. <br>If called with no parameters, this endpoint will return the
        most recent transactions, up to the specified `limit`.
      operationId: getAllTransactions
      parameters:
        - name: start_date
          in: query
          schema:
            type: string
            format: date
          description: Indicates the beginning of the time period to fetch
            transactions for. If omitted, the most recent transactions will be
            returned. See `limit`. Required if end_date exists. <br>
        - name: end_date
          in: query
          schema:
            type: string
            format: date
          description: "Indicates the end of the time period to fetch
            transactions for. Required if start_date exists. "
        - name: created_since
          in: query
          schema:
            oneOf:
              - type: string
                format: date
              - type: string
                format: date-time
          description: Filter transactions to those created after the specified
            timestamp. Accepts either a date (YYYY-MM-DD) or ISO 8601 datetime
            string. Date-only values are interpreted as midnight UTC
            (00:00:00Z).
        - name: updated_since
          in: query
          schema:
            oneOf:
              - type: string
                format: date
              - type: string
                format: date-time
          description: Filter transactions to those updated after the specified
            timestamp. Accepts either a date (YYYY-MM-DD) or ISO 8601 datetime
            string. Date-only values are interpreted as midnight UTC
            (00:00:00Z).
        - name: manual_account_id
          in: query
          schema:
            type: integer
            format: int32
          description: Filter transactions to those associated with specified
            manual account ID or set this to 0 to omit any transactions from
            manual accounts. Setting both this and `plaid_account_id` to 0 will
            return transactions with no account. These are listed as "Cash
            Transactions" in the Lunch Money app.<br> Note that transaction
            groups are not associated with any account. If you want the response
            to include transactions from transaction groups, set the
            `include_group_children` query parameter to `true` when filtering by
            manual accounts.
          examples:
            euro travel card:
              value: 219909
            no manual accounts:
              value: 0
        - name: plaid_account_id
          in: query
          schema:
            type: integer
            format: int32
          description: Filter transactions to those associated with specified
            plaid account ID or set this to 0 to omit any transactions from
            plaid accounts. Setting both this and `manual_account_id` to 0 will
            return transactions with no account. These are listed as "Cash
            Transactions" in the Lunch Money app.<br> Note that transaction
            groups are not associated with any account. If you want the response
            to include transactions from transaction groups, set the
            `include_group_children` query parameter to `true` when filtering by
            plaid accounts.
          examples:
            brokerage account:
              value: 119807
            no plaid accounts:
              value: 0
        - name: recurring_id
          in: query
          schema:
            type: integer
            format: int32
          description: >
            Filter transactions to those associated with the specified recurring
            item ID.
          examples:
            paychecks:
              value: 994069
            rent:
              value: 994079
        - name: category_id
          in: query
          schema:
            type: integer
            format: int32
          description: Filter transactions to those associated with the
            specified category ID. Will also match category groups. Set this to
            0 to return only uncategorized transactions.
          examples:
            rent:
              value: 83
            food category group:
              value: 84
        - name: tag_id
          in: query
          schema:
            type: integer
            format: int32
          description: Filter transactions to those that have the specified tag
            ID
        - name: is_group_parent
          in: query
          schema:
            type: boolean
          description: Filter by group (returns only transaction groups if
            `true`)
        - name: status
          in: query
          schema:
            type: string
            enum:
              - reviewed
              - unreviewed
              - delete_pending
          description: "Filter transactions to those with the specified
            status:<br> -
            `reviewed`: Only user reviewed transactions or those that were
            automatically marked as reviewed due to reviewed recurring_item
            logic<br> - `unreviewed`: Only transactions that need to be
            reviewed<br> - `delete_pending`: Only transactions that require
            manual intervention because the plaid account deleted this
            transaction after it was updated by the user."
          examples:
            needs review:
              value: unreviewed
            needs deletion:
              value: delete_pending
        - name: is_pending
          in: query
          schema:
            type: boolean
          description: >
            Filter transactions by pending status. Set to `true` to return only pending transactions,
            or `false` to return only non-pending transactions. When this parameter is set, it takes
            precedence over `include_pending`. Note: Pending transactions always have a status of
            `unreviewed`, so when setting this parameter to `true`, either omit the `status` parameter
            or set it to `unreviewed`.
          examples:
            only pending:
              value: true
            exclude pending:
              value: false
        - name: include_pending
          in: query
          schema:
            type: boolean
            default: false
          description: >
            By default, pending transactions are excluded from results. Set to `true` to include
            imported transactions with a pending status in the results. This query param is ignored
            if the `is_pending` query param is also set.
        - name: include_metadata
          in: query
          schema:
            type: boolean
            default: false
          description: By default, custom and plaid metadata are not included in
            the response. Set to true if you'd like the returned transaction
            objects to include any metadata associated with the transactions.
        - name: include_split_parents
          in: query
          schema:
            type: boolean
            default: false
          description: By default, transactions that were split into multiple
            transactions are not included in the response. Set to true if you'd
            like the returned transaction objects to include transactions that
            were split into multiple transactions. Use with caution, as this
            data is normally not exposed after the split transactions are
            created.
        - name: include_group_children
          in: query
          schema:
            type: boolean
            default: false
          description: By default, individual transactions that joined into a
            transaction group are not included in the response. Set to true if
            you'd like the returned transactions objects to include any
            transactions that joined into a transaction group.
        - name: include_children
          in: query
          schema:
            type: boolean
            default: false
          description: By default, the `children` property is not included in
            the response. Set to true if you'd like the children property to be
            populated with the transactions that make up a transaction group,
            or, if the `include_split_parents` query param is also set, the
            transactions that were split from a parent transaction.
        - name: include_files
          in: query
          schema:
            type: boolean
            default: false
          description: By default, the `files` property is not included in the
            response. Set to true if you'd like the responses to include a list
            of objects that describe any files attached to the transactions.
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 2000
            default: 1000
          description: Sets the maximum number of transactions to return. If
            more match the filter criteria, the response will include a
            `has_more` attribute set to `true`. See
            [Pagination](https://lm-v2-api-next-a7fabcab8e9a.herokuapp.com/v2/pagination)
        - name: offset
          in: query
          schema:
            type: integer
          description: Sets the offset for the records returned. This is
            typically set automatically in the header. See
            [Pagination](https://lm-v2-api-next-a7fabcab8e9a.herokuapp.com/v2/pagination)
      responses:
        "200":
          description: Returns an array of transactions. <br><br>The `has_more`
            property is set to `true` if more transactions are available. See
            [Pagination](https://lm-v2-api-next-a7fabcab8e9a.herokuapp.com/v2/pagination)
          content:
            application/json:
              schema:
                properties:
                  transactions:
                    items:
                      $ref: "#/components/schemas/transactionObject"
                    type: array
                  has_more:
                    type: boolean
                    description: Set to true if more transactions are available
                  error:
                    type: string
                required:
                  - transactions
                  - has_more
              examples:
                default response:
                  summary: Default response
                  value:
                    transactions:
                      - id: 2112150655
                        date: "2024-07-28"
                        amount: "1250.8400"
                        currency: usd
                        to_base: 1250.84
                        recurring_id: 994069
                        payee: Paycheck
                        original_name: DIRECT DEPOSIT PAYROLL
                        category_id: 88
                        notes: null
                        status: reviewed
                        is_pending: false
                        created_at: "2024-07-28T17:00:06.192Z"
                        updated_at: "2024-07-28T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119806
                        tag_ids:
                          - 94317
                        source: plaid
                        external_id: null
                      - id: 2112150655
                        date: "2024-07-24"
                        amount: "21.9800"
                        currency: usd
                        to_base: 21.98
                        recurring_id: null
                        payee: Noodle House
                        original_name: NOODLE HOUSE RESTAURANT #5678
                        category_id: null
                        notes: null
                        status: unreviewed
                        is_pending: false
                        created_at: "2024-07-24T17:00:06.192Z"
                        updated_at: "2024-07-24T17:00:06.192Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119805
                        tag_ids:
                          - 94317
                        source: plaid
                        external_id: null
                      - id: 2112150653
                        date: "2024-07-22"
                        amount: "-847.2200"
                        currency: usd
                        to_base: -847.22
                        recurring_id: null
                        payee: Credit Card Payment
                        original_name: CHASE CREDIT CARD PAYMENT
                        category_id: 82
                        is_pending: false
                        status: reviewed
                        notes: null
                        created_at: "2024-07-22T17:00:06.192Z"
                        updated_at: "2024-07-22T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119804
                        tag_ids: []
                        source: plaid
                        external_id: null
                      - id: 2112150651
                        date: "2024-07-22"
                        amount: "250.0000"
                        currency: usd
                        to_base: 250
                        recurring_id: null
                        payee: Fidelity
                        original_name: Fidelity
                        category_id: 82
                        notes: Transfer from Checking to Fidelity
                        status: reviewed
                        is_pending: false
                        created_at: "2024-07-22T17:00:06.192Z"
                        updated_at: "2024-07-22T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: 119807
                        plaid_account_id: null
                        tag_ids: []
                        source: csv
                        external_id: null
                    has_more: false
                recurring paychecks:
                  summary: recurring paychecks
                  value:
                    transactions:
                      - id: 2112150655
                        date: "2024-07-28"
                        amount: "1250.8400"
                        currency: usd
                        to_base: 1250.84
                        recurring_id: 994069
                        payee: Paycheck
                        original_name: DIRECT DEPOSIT PAYROLL
                        category_id: 88
                        notes: null
                        status: reviewed
                        is_pending: false
                        created_at: "2024-07-28T17:00:06.192Z"
                        updated_at: "2024-07-28T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119806
                        tag_ids:
                          - 94317
                        source: plaid
                        external_id: null
                      - id: 2112150653
                        date: "2024-07-14"
                        amount: "1250.8400"
                        currency: usd
                        to_base: 1250.84
                        recurring_id: 994069
                        payee: Paycheck
                        original_name: DIRECT DEPOSIT PAYROLL
                        category_id: 88
                        notes: null
                        status: reviewed
                        is_pending: false
                        created_at: "2024-07-14T17:00:06.192Z"
                        updated_at: "2024-07-14T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: true
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119806
                        tag_ids:
                          - 94317
                        source: plaid
                        external_id: null
                    has_more: false
                limit 2 - paginated response:
                  summary: Limit 2 paginated response
                  value:
                    transactions:
                      - id: 2112150655
                        date: "2024-07-28"
                        amount: "1250.8400"
                        currency: usd
                        to_base: 1250.84
                        recurring_id: 994069
                        payee: Paycheck
                        original_name: DIRECT DEPOSIT PAYROLL
                        category_id: 88
                        notes: null
                        status: reviewed
                        is_pending: false
                        created_at: "2024-07-28T17:00:06.192Z"
                        updated_at: "2024-07-28T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119806
                        tag_ids:
                          - 94317
                        source: plaid
                        external_id: null
                      - id: 2112150654
                        date: "2024-07-24"
                        amount: "21.9800"
                        currency: usd
                        to_base: 21.98
                        recurring_id: null
                        payee: Noodle House
                        original_name: NOODLE HOUSE RESTAURANT #5678
                        category_id: null
                        notes: null
                        status: unreviewed
                        is_pending: false
                        created_at: "2024-07-24T17:00:06.192Z"
                        updated_at: "2024-07-24T17:00:06.192Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119805
                        tag_ids:
                          - 94317
                        source: plaid
                        external_id: null
                    has_more: true
        "400":
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be integer
                    instancePath: /query/category_id
                    schemaPath: "#/properties/query/properties/category_id/type"
                    keyword: type
                    params:
                      type: integer
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    post:
      tags:
        - transactions (bulk)
      summary: Insert one or more transactions.
      description: >-
        Use this endpoint to add transactions to a budget.<p>

        The request body for this endpoint must include a list of transactions
        with at least one transaction and not more than 500 transactions to
        insert.<p>

        The successful request to this endpoint will return a response
        body which will include two arrays:<br> 
        - `transactions`: A list of transactions that were
        successfully inserted.<br>
        - `skipped_duplicates`: A list of
        transactions that were duplicates of existing transactions and were not
        inserted.
      operationId: createNewTransactions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                transactions:
                  type: array
                  minItems: 1
                  maxItems: 500
                  description: List of transactions to insert.
                  items:
                    $ref: "#/components/schemas/insertTransactionObject"
                apply_rules:
                  type: boolean
                  default: false
                  description: If explicitly set to `true`, any rules associated
                    with the account specified by the `manual_account_id`
                    property for each transaction will be applied.
                skip_duplicates:
                  type: boolean
                  default: false
                  description: If `true`, the system will flag new transactions
                    that have the same `date`, `payee`, `amount`, and account_id
                    (plaid or manual), as an existing transaction, as a
                    duplicate. <br><br> Note that deduplication based on
                    `external_id` will always occur regardless of how this
                    property is set.
                skip_balance_update:
                  type: boolean
                  default: false
                  description: If `true`, and new transactions include a
                    `manual_account_id`, the balances of these accounts will not
                    be updated, when the transactions are inserted.
              required:
                - transactions
            examples:
              categorized cash transaction:
                value:
                  transactions:
                    - date: "2024-12-01"
                      amount: 42.89
                      payee: Food Town
                      category_id: 315163
                      status: reviewed
              bare minimum new transaction:
                value:
                  transactions:
                    - date: "2024-11-01"
                      amount: 99.99
              two new cash transactions:
                value:
                  transactions:
                    - date: "2024-11-01"
                      amount: 15.00
                      payee: Lunch with James
                      notes: Cash Transaction
                      category_id: 315163
                    - date: "2024-11-01"
                      amount: "-9.99"
                      payee: me
                      notes: Interest from Investment Account Cash
                      status: unreviewed
              with external_id and custom_metadata:
                value:
                  transactions:
                    - date: "2024-12-01"
                      amount: "19.99"
                      payee: Test Payee 3
                      manual_account_id: 219807
                      external_id: A658214
                      notes: API Test created Transaction
                      custom_metadata:
                        note: API Test Added Custom MetaData
                        testNumber: 42
                        testBool: false
                        testArray:
                          - 1
                          - foo
                          - false
                          - 42.42
                        testObject:
                          foo: bar
              duplicate external_id:
                value:
                  transactions:
                    - date: "2024-12-01"
                      amount: "19.99"
                      payee: Test Payee 3
                      manual_account_id: 219807
                      external_id: A658214
                      notes: API Test created Transaction with new external_id
                      custom_metadata:
                        note: API Test Added Custom MetaData
                        testNumber: 42
                        testBool: false
                        testArray:
                          - 1
                          - foo
                          - false
                          - 42.42
                        testObject:
                          foo: bar
                    - date: "2025-06-20"
                      amount: "250.0000"
                      payee: Fidelity
                      manual_account_id: 219807
                      external_id: "12345"
                      notes: API Test created Transaction with duplicate external_id
              multiple duplicates:
                value:
                  skip_duplicates: true
                  transactions:
                    - date: "2025-06-24"
                      amount: "21.9800"
                      payee: "Noodle House"
                      notes: "Duplicate date, payee and amount. Note date may need to be changed in \"Try It\" mode."
                      plaid_account_id: 119805
                    - date: "2025-04-20"
                      amount: "250.0000"
                      payee: "Fidelity"
                      category_id: 82
                      notes: "Duplicate external ID"
                      external_id: "12345"
                      manual_account_id: 219807
                    - date: "2024-12-01"
                      amount: "19.99"
                      payee: "Test Payee 3"
                      notes: "API Test created Transaction"
                      manual_account_id: 219807
                      external_id: "A658214"
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/insertTransactionsResponseObject"
              examples:
                categorized cash transaction:
                  value:
                    transactions:
                      - id: 123456789
                        date: "2024-12-01"
                        amount: "42.89"
                        currency: usd
                        to_base: 42.89
                        recurring_id: null
                        payee: Food Town
                        category_id: 315163
                        notes: null
                        status: reviewed
                        is_pending: false
                        created_at: "2024-12-18T04:05:58.072Z"
                        updated_at: "2024-12-18T04:05:58.072Z"
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: null
                        tag_ids: []
                        source: api
                        external_id: null
                        custom_metadata: null
                        plaid_metadata: null
                    skipped_duplicates: []
                bare minimum request:
                  value:
                    transactions:
                      - id: 123456789
                        date: "2024-11-01"
                        amount: "99.99"
                        currency: usd
                        to_base: 99.99
                        recurring_id: null
                        payee: '[No Payee]'
                        category_id: null
                        notes: null
                        status: unreviewed
                        is_pending: false
                        created_at: "2024-11-20T16:09:11.544Z"
                        updated_at: "2024-11-20T16:09:11.544Z"
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: null
                        tag_ids: []
                        source: api
                        external_id: null
                        custom_metadata: null
                        plaid_metadata: null
                    skipped_duplicates: []
                two new cash transactions:
                  value:
                    transactions:
                      - id: 123456789
                        date: "2024-11-01"
                        amount: "15.00"
                        currency: usd
                        to_base: 15
                        recurring_id: null
                        payee: Lunch with James
                        category_id: null
                        notes: Cash Transaction
                        status: unreviewed
                        is_pending: false
                        created_at: "2024-11-20T16:10:23.395Z"
                        updated_at: "2024-11-20T16:10:23.395Z"
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: null
                        tag_ids: []
                        source: api
                        external_id: null
                        custom_metadata: null
                        plaid_metadata: null
                      - id: 123456790
                        date: "2024-11-01"
                        amount: "-9.99"
                        currency: usd
                        to_base: -9.99
                        recurring_id: null
                        payee: me
                        category_id: null
                        notes: Interest from Investment Account Cash
                        status: unreviewed
                        is_pending: false
                        created_at: "2024-11-20T16:10:23.395Z"
                        updated_at: "2024-11-20T16:10:23.395Z"
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: null
                        tag_ids: []
                        source: api
                        external_id: null
                        custom_metadata: null
                        plaid_metadata: null
                    skipped_duplicates: []
                with external_id and custom_metadata:
                  value:
                    transactions:
                      - id: 123456789
                        date: "2024-12-01"
                        amount: "19.99"
                        currency: usd
                        to_base: 19.99
                        recurring_id: null
                        payee: Test Payee 3
                        category_id: null
                        notes: API Test created Transaction
                        status: unreviewed
                        is_pending: false
                        created_at: "2024-11-20T16:15:19.475Z"
                        updated_at: "2024-11-20T16:15:19.475Z"
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: 219807
                        plaid_account_id: null
                        tag_ids: []
                        source: api
                        external_id: A658214
                        custom_metadata:
                          note: API Test Added Custom MetaData
                          testNumber: 42
                          testBool: false
                          testArray:
                            - 1
                            - foo
                            - false
                            - 42.42
                          testObject:
                            foo: bar
                    skipped_duplicates: []
                duplicate external id skipped:
                  value:
                    transactions:
                      - id: 123456789
                        date: "2024-12-01"
                        amount: "19.99"
                        currency: usd
                        to_base: 19.99
                        recurring_id: null
                        payee: Test Payee 3
                        category_id: null
                        notes: API Test created Transaction with new external_id
                        status: unreviewed
                        is_pending: false
                        created_at: "2025-07-18T14:15:23.159Z"
                        updated_at: "2025-07-18T14:15:23.159Z"
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: 219807
                        plaid_account_id: null
                        tag_ids: []
                        source: api
                        external_id: A658214
                        custom_metadata:
                          note: API Test Added Custom MetaData
                          testNumber: 42
                          testBool: false
                          testArray:
                            - 1
                            - foo
                            - false
                            - 42.42
                          testObject:
                            foo: bar
                    skipped_duplicates:
                      - reason: duplicate_external_id
                        request_transactions_index: 1
                        existing_transaction_id: 2112150651
                        request_transaction:
                          date: "2025-06-20"
                          amount: "250.0000"
                          payee: Fidelity
                          manual_account_id: 219807
                          external_id: "12345"
                          notes: API Test created Transaction with duplicate external_id
                multiple skipped duplicates:
                  value:
                    transactions:
                      - id: 123456789
                        date: "2024-12-01"
                        amount: "19.99"
                        currency: usd
                        to_base: 19.99
                        recurring_id: null
                        payee: Test Payee 3
                        category_id: null
                        notes: API Test created Transaction
                        status: unreviewed
                        is_pending: false
                        created_at: "2025-07-18T14:05:29.253Z"
                        updated_at: "2025-07-18T14:05:29.253Z"
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: 219807
                        plaid_account_id: null
                        tag_ids: []
                        source: api
                        external_id: A658214
                    skipped_duplicates:
                      - reason: duplicate_payee_amount_date
                        request_transactions_index: 0
                        existing_transaction_id: 2112150654
                        request_transaction:
                          date: "2025-06-24"
                          amount: "21.9800"
                          payee: Noodle House
                          notes: Duplicate date, payee and amount. Note date may need to be changed in "Try It" mode.
                          plaid_account_id: 119805
                      - reason: duplicate_external_id
                        request_transactions_index: 1
                        existing_transaction_id: 2112150651
                        request_transaction:
                          date: "2025-04-20"
                          amount: "250.0000"
                          payee: Fidelity
                          category_id: 82
                          notes: Duplicate external ID
                          external_id: "12345"
                          manual_account_id: 219807
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                invalid ids in new transactions:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "transactions[0] manual account ID does not exist: 9999999"
                        transaction_index: 0
                        error: Invalid Manual Account ID
                        invalid_property: manual_account_id
                        manual_account_id: 9999999
                      - errMsg: "transactions[1] manual account ID does not exist: 9999999"
                        transaction_index: 1
                        error: Invalid Manual Account ID
                        invalid_property: manual_account_id
                        manual_account_id: 9999999
                      - errMsg: "transactions[2] recurring ID does not exist: 88888888"
                        transaction_index: 2
                        error: Invalid Recurring ID
                        invalid_property: recurring_id
                        recurring_id: 88888888
                duplicate external_ids within request:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: Duplicate External IDs found in the request body
                        error: Duplicate External ID
                        transaction_property: external_id
                        external_id: "12345"
                        transactions_indices:
                          - 0
                          - 1
                      - errMsg: Duplicate External IDs found in the request body
                        error: Duplicate External ID
                        transaction_property: external_id
                        external_id: "54321"
                        transactions_indices:
                          - 2
                          - 3
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    put:
      tags:
        - transactions (bulk)
      summary: Update multiple transactions
      description: >-
        Modifies the properties of multiple existing transactions in a single request.<br><br>
        
        You may submit complete transaction objects from the response returned by a `GET /transactions` in the request body for each transaction, however only certain
        properties can be updated using this API. The following system set properties are
        accepted in the request body, but their values will be ignored: `id`, `to_base`, `is_pending`, `created_at`, `updated_at`, `source`, and `plaid_metadata`.<br><br>
        
        Transactions that have been previously split or grouped may not be
        modified by this endpoint. Therefore the `is_split_parent`, `split_parent_id`, `is_group_parent`, `group_parent_id`, and `children` properties are also ignored when provided in the request body.<br><br>

        Each transaction in the array **must** include an `id` property to identify which transaction to update, along with at least one other property to be updated. For example, a transaction object that contains only an `id` and `category_id` property is valid.<br><br>
        
        The request can include between 1 and 500 transactions to update in a single call.
      operationId: updateTransactions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                transactions:
                  type: array
                  minItems: 1
                  maxItems: 500
                  description: List of transactions to update. Each transaction
                    must have an `id` property and at least one other property
                    to update.
                  items:
                    allOf:
                      - type: object
                        required: [id]
                        properties:
                          id:
                            type: integer
                            format: int64
                            description: The ID of the transaction to update
                      - $ref: "#/components/schemas/updateTransactionObject"
              required:
                - transactions
            examples:
              categorize multiple transactions:
                value:
                  transactions:
                    - id: 2112150654
                      category_id: 315162
                      notes: "Treat restaurants the same as groceries"
                    - id: 2112150649
                      category_id: 315162
                      notes: "Treat restaurants the same as groceries"
                    - id: 2112140372
                      category_id: 315162
                      notes: "Treat restaurants the same as groceries"
              update with full objects:
                value:
                  transactions:
                    - id: 2112150688
                      date: "2025-07-17"
                      amount: "4.1300"
                      currency: "usd"
                      to_base: 4.13
                      recurring_id: 994081
                      payee: "Holey Donuts"
                      category_id: 315164
                      notes: "Coffee - cash"
                      status: "reviewed"
                      is_pending: false
                      created_at: "2025-07-17T17:00:06.192Z"
                      updated_at: "2025-07-17T17:00:06.192Z"
                      is_split_parent: false
                      split_parent_id: null
                      is_group_parent: false
                      group_parent_id: null
                      manual_account_id: null
                      plaid_account_id: null
                      tag_ids:
                        - 94317
                      source: "csv"
                      external_id: null
                    - id: 2112150649
                      category_id: 315162
                      notes: "Treat restaurants the same as groceries"
              update with errors:
                value:
                  transactions:
                    - id: 9999999
                      notes: "Invalid transaction ID"
                    - id: 2112150688
                      category_id: 999999999
                      manual_account_id: 999999999
                      notes: "Invalid category and manual account IDs"
                    - id: 2112150649
                      plaid_account_id: 999999999
                      tag_ids: [888888888, 999999999]
                      notes: "Invalid tag and plaid account IDs"
                    - id: 2112150649
                      additional_tag_ids: [888888888, 999999999]
                      notes: "Invalid additional_tag_ids"
                    - id: 2212150657
                      notes: "Transaction belongs to locked plaid account"
                      payee: "New Payee"
                      amount: "100.0000"
                      currency: "jpy"
      responses:
        "200":
          description: Transactions successfully updated
          content:
            application/json:
              schema:
                properties:
                  transactions:
                    items:
                      $ref: "#/components/schemas/transactionObject"
                    type: array
                required:
                  - transactions
              examples:
                bulk update transactions:
                  value:
                    transactions:
                      - id: 2112150654
                        date: "2025-06-24"
                        amount: "21.9800"
                        currency: "usd"
                        to_base: 21.98
                        recurring_id: null
                        payee: "Noodle House"
                        category_id: 315162
                        notes: "Treat restaurants the same as groceries"
                        status: "reviewed"
                        is_pending: false
                        created_at: "2025-06-24T17:00:06.192Z"
                        updated_at: "2025-06-24T17:00:06.192Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119805
                        tag_ids:
                          - 94317
                        source: "plaid"
                        external_id: null
                        custom_metadata: null
                      - id: 2112150649
                        date: "2025-06-18"
                        amount: "4.1300"
                        currency: "usd"
                        to_base: 4.13
                        recurring_id: 994081
                        payee: "Holey Donuts"
                        category_id: 315162
                        notes: "Treat restaurants the same as groceries"
                        status: "reviewed"
                        is_pending: false
                        created_at: "2025-06-18T17:00:06.192Z"
                        updated_at: "2025-06-18T17:00:06.192Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: null
                        tag_ids:
                          - 94317
                        source: "csv"
                        external_id: null
                        custom_metadata: null
                      - id: 2112140372
                        date: "2025-06-12"
                        amount: "50.00"
                        currency: "usd"
                        to_base: 50
                        recurring_id: null
                        payee: "Starbucks"
                        category_id: 315162
                        notes: "Treat restaurants the same as groceries"
                        status: "reviewed"
                        is_pending: false
                        created_at: "2025-06-12T17:00:06.192Z"
                        updated_at: "2025-06-12T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119807
                        tag_ids: []
                        source: "plaid"
                        external_id: null
                        custom_metadata: null
                update with full objects:
                  value:
                    transactions:
                      - id: 2112150688
                        date: "2025-07-17"
                        amount: "4.1300"
                        currency: "usd"
                        to_base: 4.13
                        recurring_id: 994081
                        payee: "Holey Donuts"
                        category_id: 315164
                        notes: "Coffee - cash"
                        status: "reviewed"
                        is_pending: false
                        created_at: "2025-07-17T17:00:06.192Z"
                        updated_at: "2025-07-17T17:00:06.192Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: null
                        tag_ids:
                          - 94317
                        source: "csv"
                        external_id: null
                        custom_metadata: null
                      - id: 2112150649
                        date: "2025-06-18"
                        amount: "4.1300"
                        currency: "usd"
                        to_base: 4.13
                        recurring_id: 994081
                        payee: "Holey Donuts"
                        category_id: 315162
                        notes: "Treat restaurants the same as groceries"
                        status: "reviewed"
                        is_pending: false
                        created_at: "2025-06-18T17:00:06.192Z"
                        updated_at: "2025-06-18T17:00:06.192Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: null
                        tag_ids:
                          - 94317
                        source: "csv"
                        external_id: null
                        custom_metadata: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                invalid ids in id list:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "transactions[0] manual account ID does not exist: 999999999"
                        transaction_index: 0
                        error: Invalid Manual Account ID
                        invalid_property: manual_account_id
                        manual_account_id: 999999999
                      - errMsg: "transactions[1] manual account ID does not exist: 999999999"
                        transaction_index: 1
                        error: Invalid Manual Account ID
                        invalid_property: manual_account_id
                        manual_account_id: 999999999
                      - errMsg: "transactions[2] recurring ID does not exist: 888888888"
                        transaction_index: 2
                        error: Invalid Recurring ID
                        invalid_property: recurring_id
                        recurring_id: 888888888
                update with errors:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "There is no transaction with the id: 9999999"
                        error: Invalid Transaction ID
                        invalid_property: id
                        transaction_id: 9999999
                        transaction_index: 0
                      - errMsg: "transactions[1] category ID does not exist: 999999999"
                        transaction_index: 1
                        error: Invalid Category ID
                        invalid_property: category_id
                        category_id: 999999999
                      - errMsg: "transactions[1] manual account ID does not exist: 999999999"
                        transaction_index: 1
                        error: Invalid Manual Account ID
                        invalid_property: manual_account_id
                        manual_account_id: 999999999
                      - errMsg: "transactions[2] plaid account ID does not exist: 999999999"
                        transaction_index: 2
                        error: Invalid Plaid Account ID
                        invalid_property: plaid_account_id
                        plaid_account_id: 999999999
                      - errMsg: "transactions[2] tag_ids[0] ID does not exist: 888888888"
                        transaction_index: 2
                        error: Invalid Tag ID
                        invalid_property: tag_ids
                        tag_id: 888888888
                        tag_ids_index: 0
                      - errMsg: "transactions[2] tag_ids[1] ID does not exist: 999999999"
                        transaction_index: 2
                        error: Invalid Tag ID
                        invalid_property: tag_ids
                        tag_id: 999999999
                        tag_ids_index: 1
                      - errMsg: "transactions[3] additional_tag_ids[0] ID does not exist: 888888888"
                        transaction_index: 3
                        error: Invalid Tag ID
                        invalid_property: additional_tag_ids
                        tag_id: 888888888
                        additional_tag_ids_index: 0
                      - errMsg: "transactions[3] additional_tag_ids[1] ID does not exist: 999999999"
                        transaction_index: 3
                        error: Invalid Tag ID
                        invalid_property: additional_tag_ids
                        tag_id: 999999999
                        additional_tag_ids_index: 1
                      - errMsg: "Cannot change the currency for a transaction that belongs to a Plaid Account which is not configured to allow modifications to transactions. Plaid Account ID: 119804"
                        error: Transaction belongs to a locked Plaid account
                        id: 2212150657
                        transaction_index: 4
                        locked_property: currency
                      - errMsg: "Cannot change the amount for a transaction that belongs to a Plaid Account which is not configured to allow modifications to transactions. Plaid Account ID: 119804"
                        error: Transaction belongs to a locked Plaid account
                        id: 2212150657
                        transaction_index: 4
                        locked_property: amount
                duplicate external_ids within request:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: Duplicate External IDs found in the request body
                        error: Duplicate External ID
                        transaction_property: external_id
                        external_id: "12345"
                        transactions_indices:
                          - 0
                          - 1
                      - errMsg: Duplicate External IDs found in the request body
                        error: Duplicate External ID
                        transaction_property: external_id
                        external_id: "54321"
                        transactions_indices:
                          - 2
                          - 3
                invalid ids:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "There is no transaction with the id: 1"
                        error: Invalid Transaction ID
                        invalid_property: id
                        transaction_id: 1
                        transaction_index: 0
                      - errMsg: "There is no transaction with the id: 2"
                        error: Invalid Transaction ID
                        invalid_property: id
                        transaction_id: 2
                        transaction_index: 1
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - transactions (bulk)
      summary: Bulk delete existing transactions
      description: >-
        Deletes the transaction with the IDs specified in the request body.<p>

        If any of the specified transactions are a split transaction or a split
        parent, or if any are a grouped transactions or part of a transaction
        group, the request will fail with a suggestion on how to unsplit or
        ungroup the transaction(s) prior to deletion. This will also fail if any
        of the specified transaction IDs do not exist.<p>

        Otherwise, the specified transactions are deleted.<p>
        
        <span class="red-text"><strong>Use with caution. This action is not reversible!</strong></span>
      operationId: deleteTransactions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                ids:
                  type: array
                  description: Array of existing Transaction IDs to delete
                  minItems: 1
                  maxItems: 500
                  items:
                    type: integer
                    format: int64
              required:
                - ids
            examples:
              delete three transactions:
                value:
                  ids:
                    - 2112150653
                    - 2112150654
                    - 2112150655
              duplicate ids:
                value:
                  ids:
                    - 2112150653
                    - 2112150653
                    - 2112150654
                    - 2112150654
              invalid ids:
                value:
                  ids:
                    - 2112150653
                    - 9999999999
                    - 2112150654
      responses:
        "204":
          description: No Content
        "400":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Invalid Request Body
                errors:
                  - errMsg: "Duplicate transaction ID found: 2112150653"
                    transaction_id: 2112150653
                    ids_index: 0
                    invalid_property: ids
                  - errMsg: "Duplicate transaction ID found: 2112150653"
                    transaction_id: 2112150653
                    ids_index: 1
                    invalid_property: ids
                  - errMsg: "Duplicate transaction ID found: 2112150654"
                    transaction_id: 2112150654
                    ids_index: 2
                    invalid_property: ids
                  - errMsg: "Duplicate transaction ID found: 2112150654"
                    transaction_id: 2112150654
                    ids_index: 3
                    invalid_property: ids
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: "There is no transaction with the id: 8888888888"
                    ids_index: 0
                    id: 8888888888
                  - errMsg: "There is no transaction with the id: 9999999999"
                    ids_index: 1
                    id: 9999999999
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /transactions/{id}:
    get:
      tags:
        - transactions
      summary: Get a single transaction
      description: >
        Retrieves the details of a specific transaction by its ID, including the
        following properties which are not returned by default in the response
        to a `GET /transactions` request:<br>


        - `plaid_metadata` will either be `null` or contain the metadata for
        transactions associated with an account that is synced via plaid. 

        - `custom_metadata` will either be `null` or contain any custom_metadata
        added to transactions that were inserted or updated via the API.

        - `files` will be a list of objects that describe any attachments to the
        transaction.


        If `is_group_parent` is true in the returned transaction, the object will also
        include the `children` property which will contain a list of the 
        original transactions that make up the transaction group.<br>

        If `is_split_parent` is true in the returned transaction, the object will also
        include the `children` property which will contain a list
        of the split transactions.
      operationId: getTransactionById
      parameters:
        - name: id
          in: path
          description: ID of the transaction to retrieve
          required: true
          schema:
            type: integer
            format: int64
          examples:
            basic transaction:
              summary: Basic transaction by id request
              value: 2112150654
            transaction with plaid metadata:
              summary: Transaction with plaid metadata
              value: 2112150655
            transaction group:
              summary: Transaction group
              value: 2112140959
            id not found:
              summary: Example of an id that doesn't exist
              value: 9999999999999
      responses:
        "200":
          description: Transaction Object with the requested transaction.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/transactionObject"
              examples:
                basic transaction:
                  value:
                    id: 2112150654
                    date: "2024-07-24"
                    amount: "21.9800"
                    currency: usd
                    to_base: 21.98
                    recurring_id: null
                    payee: Noodle House
                    original_name: NOODLE HOUSE RESTAURANT #5678
                    category_id: null
                    notes: null
                    status: unreviewed
                    is_pending: false
                    created_at: "2024-07-24T17:00:06.192Z"
                    updated_at: "2024-07-24T17:00:06.192Z"
                    split_parent_id: null
                    children: []
                    is_group_parent: false
                    group_parent_id: null
                    manual_account_id: null
                    plaid_account_id: 119805
                    tag_ids: []
                    source: csv
                    external_id: null
                transaction with plaid metadata:
                  value:
                    id: 2112150655
                    date: "2025-05-28"
                    amount: "1250.8400"
                    currency: usd
                    to_base: 1250.84
                    recurring_id: 994069
                    payee: Paycheck
                    original_name: DIRECT DEPOSIT PAYROLL
                    category_id: null
                    notes: null
                    status: pending
                    is_pending: true
                    created_at: "2025-05-28T17:00:06.192Z"
                    updated_at: "2025-05-28T17:00:06.733Z"
                    is_split_parent: false
                    split_parent_id: null
                    is_group_parent: false
                    group_parent_id: null
                    manual_account_id: null
                    plaid_account_id: 119806
                    tag_ids:
                      - 94317
                    source: plaid
                    external_id: null
                    custom_metadata: null
                    plaid_metadata:
                      note: This is an artificially constructed example of metadata
                      account_id: 9DYYMLBoaxIqRkAOKaVDuaPZrmE5qJhVxyZyv
                      account_owner: null
                      amount: "1250.8400"
                      authorized_datetime: "2025-05-28T17:00:06.192Z"
                      counterparties:
                        - confidence_level: LOW
                          entity_id: null
                          logo_url: null
                          name: Employers Inc.
                transaction group:
                  value:
                    id: 2112140959
                    date: "2025-05-17"
                    amount: "25.6900"
                    currency: usd
                    to_base: 25.69
                    recurring_id: null
                    payee: Valero
                    original_name: Valero
                    category_id: 315174
                    notes: Net Gas for roadtrip
                    status: reviewed
                    is_pending: false
                    created_at: "2025-05-17T17:00:06.192Z"
                    updated_at: "2025-05-17T17:00:06.733Z"
                    split_parent_id: null
                    is_group_parent: true
                    group_parent_id: null
                    manual_account_id: null
                    plaid_account_id: null
                    tag_ids:
                      - 94318
                      - 94317
                    source: csv
                    external_id: null
                    children:
                      - id: 2112150647
                        date: "2025-05-17"
                        amount: "25.000"
                        currency: usd
                        to_base: 25
                        recurring_id: null
                        payee: Me
                        original_name: Me
                        category_id: 315174
                        notes: Gas repay from Tim for roadtrip
                        status: reviewed
                        is_pending: false
                        created_at: "2025-05-17T17:00:06.192Z"
                        updated_at: "2025-05-17T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: 2112140959
                        manual_account_id: null
                        plaid_account_id: null
                        tag_ids:
                          - 94318
                          - 94317
                        source: csv
                        external_id: null
                      - id: 2112150859
                        date: "2025-05-16"
                        amount: "25.000"
                        currency: usd
                        to_base: 25
                        recurring_id: null
                        payee: Me
                        category_id: 315174
                        notes: Gas repay from Liz for roadtrip
                        status: reviewed
                        is_pending: false
                        created_at: "2025-05-16T17:00:06.192Z"
                        updated_at: "2025-05-16T17:00:06.192Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: 2112140959
                        manual_account_id: null
                        plaid_account_id: null
                        tag_ids:
                          - 94318
                          - 94317
                        source: csv
                        external_id: null
                      - id: 2112150659
                        date: "2025-05-15"
                        amount: "75.6900"
                        currency: usd
                        to_base: 75.69
                        recurring_id: null
                        payee: Valero
                        category_id: 315174
                        notes: Gas on roadtrip with Tim and Liz
                        status: reviewed
                        is_pending: false
                        created_at: "2025-05-15T17:00:06.192Z"
                        updated_at: "2025-05-15T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: 2112140959
                        manual_account_id: null
                        plaid_account_id: 119805
                        tag_ids:
                          - 94318
                          - 94317
                        source: plaid
                        external_id: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be integer
                    instancePath: /path/id
                    schemaPath: "#/properties/path/properties/id/type"
                    keyword: type
                    params:
                      type: integer
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no transaction with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    put:
      tags:
        - transactions
      summary: Update an existing transaction
      description: >-
        Modifies the properties of an existing transaction.<br><br>
        
        You may submit the response from a `GET /transactions/{id}` as the request body, however only certain
        properties can be updated using this API. The following system set properties are
        accepted in the request body but their values will be ignored: `id`, `to_base`, `is_pending`, `created_at`, `updated_at`, `source`, and `plaid_metadata`.<br><br>
        
        Transactions that have been previously split or grouped may not be
        modified by this endpoint. Therefore the `is_split_parent`, `split_parent_id`, `is_group_parent`, `group_parent_id`, and `children` properties are also ignored when provided in the request body.<br><br>

        It is also possible to provide only the properties to be updated in the
        request body, as long as the request includes at least one of the
        properties that is not listed above. For example a request body that contains only
        an `category_id` attribute is valid.
        
      operationId: updateTransaction
      parameters:
        - name: id
          in: path
          description: ID of the transaction to update
          required: true
          schema:
            type: integer
            format: int64
          examples:
            basic transaction:
              summary: Basic transaction by id request
              value: 2112140361
            id not found:
              summary: Example of an id that doesn't exist
              value: 9999999999999
        - name: update_balance
          in: query
          description: Set this to `false` to skip updating the transaction's
            associated account balance. Default behavior is to update balances.
          required: false
          schema:
            type: boolean
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/updateTransactionObject"
            examples:
              update categories simple:
                value:
                  category_id: 315162
              update transaction category with previous get response:
                value:
                  id: 2112140361
                  date: "2024-12-09"
                  amount: "300.00"
                  currency: usd
                  to_base: 300
                  recurring_id: null
                  payee: Best Buy
                  category_id: 315162
                  notes: Electronics
                  status: reviewed
                  is_pending: false
                  created_at: "2024-12-09T17:00:06.192Z"
                  updated_at: "2024-12-09T17:00:06.733Z"
                  is_split_parent: false
                  split_parent_id: null
                  is_group_parent: false
                  group_parent_id: null
                  manual_account_id: null
                  plaid_account_id: 119810
                  tag_ids: []
                  source: plaid
                  external_id: null
      responses:
        "201":
          description: Transaction successfully updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/transactionObject"
              examples:
                transaction with updated category:
                  value:
                    id: 2112140361
                    date: "2024-12-09"
                    amount: "300.00"
                    currency: usd
                    to_base: 300
                    recurring_id: null
                    payee: Best Buy
                    category_id: 315162
                    notes: Electronics
                    status: reviewed
                    is_pending: false
                    created_at: "2024-12-09T17:00:06.192Z"
                    updated_at: "2024-12-09T17:00:06.733Z"
                    is_split_parent: false
                    split_parent_id: null
                    is_group_parent: false
                    group_parent_id: null
                    manual_account_id: null
                    plaid_account_id: 119810
                    tag_ids: []
                    source: plaid
                    external_id: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be integer
                    instancePath: /path/id
                    schemaPath: "#/properties/path/properties/id/type"
                    keyword: type
                    params:
                      type: integer
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no transaction with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - transactions
      summary: Delete a transaction
      description: >-
        Deletes the transaction with the ID specified on the path.<p>

        If the specified transaction is a split transaction or a split parent,
        or if it is a grouped transactions or part of a transaction group, the
        request will fail with a suggestion on how to unsplit or ungroup the
        transaction(s) prior to deletion. Otherwise, the specified transaction
        is deleted. <p>

        <span class="red-text"><strong>Use with caution. This action is not reversible!</strong></span>
      operationId: deleteTransactionById
      parameters:
        - in: path
          name: id
          description: ID of the transaction to delete
          required: true
          schema:
            type: integer
            format: int64
          examples:
            delete transaction:
              summary: Simple transaction delete
              value: 2112140361
            delete split transaction:
              value: 2112140459
            delete transaction group:
              value: 2112140959
            id not found:
              summary: Example of an id that doesn't exist
              value: 543210
      responses:
        "204":
          description: No Content
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no transaction with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /transactions/group:
    post:
      tags:
        - transactions (group)
      summary: Create a transaction group
      description: >
        Specify a set of existing transaction IDs to group together as a single
        grouped transaction. 

        The new transaction will have an amount equal to the sum of the grouped
        transaction amounts. If the 

        grouped transactions have different currencies, the new group
        transaction will be set in the user's

        default currency.<br><br> 

        After a transaction has been grouped, the original transactions are no
        longer shown on the 

        transactions page or returned by a `GET /transactions` request. The
        newly created grouped 

        transaction is returned instead.


        To see the details of the original transactions that were used to create
        a transaction group, use the

        `GET /transactions/{id}` endpoint and pass the ID of the grouped
        transaction. The grouped transactions will

        be included in the `children` property of the transaction returned in
        the response
      operationId: groupTransactions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                ids:
                  type: array
                  minItems: 2
                  maxItems: 500
                  description: List of existing transaction IDs to group. Split
                    and recurring transactions may not be grouped. Transactions
                    that are already grouped must be ungrouped before being
                    regrouped.
                  items:
                    type: integer
                    format: int64
                date:
                  type: string
                  format: date
                  description: Date for the new grouped transaction in ISO 8601
                    format.
                payee:
                  type: string
                  description: |
                    The payee for the new grouped transaction.
                  minLength: 0

                category_id:
                  type: integer
                  format: int64
                  nullable: true
                  description: The ID of an existing category to assign to the
                    grouped transaction. If not set and all the grouped
                    transactions have the same category, the grouped transaction
                    will inherit the category, otherwise the new transaction
                    will have no category.
                notes:
                  type: string
                  nullable: true
                  description: |
                    Notes for the grouped transaction.
                status:
                  type: string
                  description: If set, must be either `reviewed` or
                    `unreviewed`. If not set, defaults to `reviewed`.
                  enum:
                    - reviewed
                    - unreviewed
                tag_ids:
                  type: array
                  description: A list of IDs for the tags associated with the
                    grouped transaction. Each ID must match an existing tag
                    associated with the user's account. If not set, no tags will
                    be associated with the created transaction.
                  items:
                    type: integer
                    format: int64
              required:
                - ids
                - date
                - payee
            examples:
              group inherits category:
                value:
                  ids:
                    - 2112140365
                    - 2112140361
                  payee: Home Entertainment Transactions
                  date: "2024-12-10"
      responses:
        "201":
          description: The new grouped parent transaction with populated
            children attribute
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/transactionObject"
              examples:
                group inherits category:
                  value:
                    id: 123456789
                    date: "2024-12-10"
                    amount: "375.0000"
                    currency: usd
                    to_base: 375
                    recurring_id: null
                    payee: Home Entertainment Transactions
                    category_id: 315628
                    notes: null
                    status: reviewed
                    is_pending: false
                    created_at: "2024-12-18T14:45:03.366Z"
                    updated_at: "2024-12-18T14:45:03.366Z"
                    split_parent_id: null
                    is_group_parent: true
                    group_parent_id: null
                    manual_account_id: null
                    plaid_account_id: null
                    tag_ids: []
                    source: api
                    external_id: null
                    custom_metadata: null
                    children:
                      - id: 2112140365
                        date: "2024-11-10"
                        amount: "75.00"
                        currency: usd
                        to_base: 75
                        recurring_id: null
                        payee: Target
                        category_id: 315628
                        notes: Household items
                        status: reviewed
                        is_pending: false
                        created_at: "2024-11-10T17:00:06.192Z"
                        updated_at: "2024-11-10T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: 123456789
                        manual_account_id: null
                        plaid_account_id: 119809
                        tag_ids: []
                        source: plaid
                        external_id: null
                      - id: 2112140361
                        date: "2024-11-09"
                        amount: "300.00"
                        currency: usd
                        to_base: 300
                        recurring_id: null
                        payee: Best Buy
                        category_id: 315628
                        notes: Electronics
                        status: reviewed
                        is_pending: false
                        created_at: "2024-11-09T17:00:06.192Z"
                        updated_at: "2024-11-09T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: 123456789
                        manual_account_id: null
                        plaid_account_id: 119810
                        tag_ids: []
                        source: plaid
                        external_id: null
                group with all reviewed children:
                  summary: When all children have status 'reviewed', the grouped transaction also has status 'reviewed'
                  value:
                    id: 123456789
                    date: "2024-12-25"
                    amount: "0.0000"
                    currency: usd
                    to_base: 0
                    recurring_id: null
                    payee: Grouped Transaction Payee
                    category_id: 82
                    notes: API Created Test Transaction Group
                    status: reviewed
                    is_pending: false
                    created_at: "2025-11-13T21:39:27.609Z"
                    updated_at: "2025-11-13T21:39:27.609Z"
                    split_parent_id: null
                    is_group_parent: true
                    group_parent_id: null
                    manual_account_id: null
                    plaid_account_id: null
                    tag_ids: [94318]
                    source: api
                    external_id: null
                    custom_metadata: null
                    children:
                      - id: 2112150653
                        date: "2025-10-22"
                        amount: "-847.2200"
                        currency: usd
                        to_base: -847.22
                        recurring_id: null
                        payee: Credit Card Payment
                        category_id: 82
                        notes: null
                        status: reviewed
                        is_pending: false
                        created_at: "2025-10-22T17:00:06.192Z"
                        updated_at: "2025-10-22T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: 123456789
                        manual_account_id: null
                        plaid_account_id: 119804
                        tag_ids: []
                        source: plaid
                        external_id: null
                        custom_metadata: null
                      - id: 2112150652
                        date: "2025-10-21"
                        amount: "847.2200"
                        currency: usd
                        to_base: 847.22
                        recurring_id: null
                        payee: Transfer to Credit Card
                        category_id: 82
                        notes: "Lenny's Amex Bill"
                        status: reviewed
                        is_pending: false
                        created_at: "2025-10-21T17:00:06.192Z"
                        updated_at: "2025-10-21T17:00:06.733Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: 123456789
                        manual_account_id: null
                        plaid_account_id: 119806
                        tag_ids: []
                        source: plaid
                        external_id: null
                        custom_metadata: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                missing ids:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "There is no transaction with the id: 89999999"
                        ids_index: 0
                        id: 89999999
                      - errMsg: "There is no transaction with the id: 99999999"
                        ids_index: 1
                        id: 99999999
                duplicate ids:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "Duplicate transaction ID found: 2112150653"
                        ids_index: 1
                        transaction_id: 2112150653
                        invalid_property: ids
                split transactions:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "Transaction with id 2112150653 is a split transaction and cannot be added to a transaction group."
                        ids_index: 0
                        id: 2112150653
                      - errMsg: "Transaction with id 2112150654 is a split transaction and cannot be added to a transaction group."
                        ids_index: 1
                        id: 2112150654
                grouped transactions:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "Transaction with id 2112140959 is a transaction group and cannot be added to another transaction group."
                        ids_index: 0
                        id: 2112140959
                      - errMsg: "Transaction with id 2112150647 is in a transaction group already and cannot be added to another transaction group."
                        ids_index: 1
                        id: 2112150647
                        group_parent_id: 2112140959
                recurring transactions:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "Transaction 2112150655 is a recurring transaction and cannot be added to a transaction group."
                        ids_index: 0
                        id: 2112150655
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /transactions/group/{id}:
    delete:
      tags:
        - transactions (group)
      summary: Delete a transaction group
      description: >-
        Deletes the transaction group with the ID specified on the path.<br>

        The transactions within the group are not removed and will subsequently
        be treated as "normal" ungrouped transactions.
      operationId: ungroupTransactions
      parameters:
        - in: path
          name: id
          description: ID of the transaction group to delete
          required: true
          schema:
            type: integer
            format: int64
          examples:
            delete transaction group:
              summary: Simple transaction group delete
              value: 2112140959
            delete non group transaction:
              summary: ID is not a transaction group
              value: 2112150649
            id not found:
              summary: Example of an id that doesn't exist
              value: 543210
      responses:
        "204":
          description: No Content
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no transaction with the id: 543210"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /transactions/split/{id}:
    post:
      tags:
        - transactions (split)
      summary: Split a transaction
      description: >-
        Splits an existing transaction into a set of smaller child
        transactions.<br><br> After a transaction has been split, the original
        transaction is no longer shown on the transactions page or returned by a
        `GET /transactions` request. The newly created child transactions are
        returned instead.

        To see the details of the original parent transaction after it has been
        split, use the `GET /transactions/{id}` endpoint and pass the value of
        the `split_parent_id` of one of the children.
      operationId: splitTransaction
      parameters:
        - name: id
          in: path
          description: ID of the transaction to spit
          required: true
          schema:
            type: integer
            format: int64
          examples:
            spit transaction:
              summary: Basic transaction by id request
              value: 2112150650
            already split transaction:
              summary: Attempt to split a transaction that has already been split
              value: 2112140459
            id not found:
              summary: Example of an id that doesn't exist
              value: 9999999999999
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                child_transactions:
                  type: array
                  minItems: 2
                  maxItems: 500
                  description: List of child transactions to create. The sum of
                    the `amounts` must match the split transaction amount.
                  items:
                    $ref: "#/components/schemas/splitTransactionObject"
              required:
                - child_transactions
            examples:
              split 88.45 Transaction:
                value:
                  child_transactions:
                    - amount: 44.23
                      payee: Food Town - Lenny
                    - amount: 44.22
                      payee: Food Town - Penny
              invalid math on 88.45 Transaction:
                value:
                  child_transactions:
                    - amount: 1.5
                      payee: Food Town - Lenny
                    - amount: 1.5
                      payee: Food Town - Penny
      responses:
        "201":
          description: The new split parent transaction with populated children
            attribute
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/transactionObject"
              examples:
                split 88.45 Transaction:
                  value:
                    id: 2112150650
                    date: "2024-10-19"
                    amount: "88.4500"
                    currency: usd
                    to_base: 88.45
                    recurring_id: null
                    payee: Food Town
                    category_id: 315162
                    notes: null
                    status: reviewed
                    is_pending: false
                    created_at: "2024-10-19T17:00:06.192Z"
                    updated_at: "2024-11-30T22:25:53.232Z"
                    split_parent_id: null
                    is_split_parent: true
                    is_group_parent: false
                    group_parent_id: null
                    manual_account_id: null
                    plaid_account_id: 119805
                    tag_ids: []
                    source: plaid
                    external_id: null
                    children:
                      - id: 2112150750
                        date: "2024-10-19"
                        amount: "44.2300"
                        currency: usd
                        to_base: 44.23
                        recurring_id: null
                        payee: Food Town - Lenny
                        category_id: 315162
                        notes: null
                        status: reviewed
                        is_pending: false
                        created_at: "2024-11-30T22:25:53.232Z"
                        updated_at: "2024-11-30T22:25:53.232Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119805
                        tag_ids: []
                        source: plaid
                        external_id: null
                      - id: 2112150751
                        date: "2024-10-19"
                        amount: "44.2200"
                        currency: usd
                        to_base: 44.22
                        recurring_id: null
                        payee: Food Town - Penny
                        category_id: 315162
                        notes: null
                        status: reviewed
                        is_pending: false
                        created_at: "2024-11-30T22:25:53.232Z"
                        updated_at: "2024-11-30T22:25:53.232Z"
                        is_split_parent: false
                        split_parent_id: null
                        is_group_parent: false
                        group_parent_id: null
                        manual_account_id: null
                        plaid_account_id: 119805
                        tag_ids: []
                        source: plaid
                        external_id: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                bad math:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: Sum of split transactions do not add up to the original transaction amount.
                split recurring:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: You cannot split a recurring transaction.
                        id: 2112150655
                split group:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: You cannot split a group transaction. Ungroup it before splitting.
                split split:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: You cannot split an already split transaction. Unsplit it before splitting again.
                missing amount in child transaction:
                  value:
                    message: Invalid Request Body
                    errors:
                      - errMsg: "child_transactions[0] is missing required property 'amount' in request body."
                        child_transactions_index: 0
                        error: Missing required property
                        invalid_property: amount
                invalid category in child transaction:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "child_transactions[0] category ID does not exist: 899999999"
                        child_transactions_index: 0
                        error: Invalid category ID
                        invalid_property: category_id
                        category_id: 899999999
                category group in child transaction:
                  value:
                    message: Request Validation Failure
                    errors:
                      - errMsg: "child_transactions[0] category ID is a category group and cannot be assigned to a transaction: 86"
                        child_transactions_index: 0
                        error: Invalid category ID
                        invalid_property: category_id
                        category_id: 86
                        category_group_name: Food
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - transactions (split)
      summary: Unsplit a previously split transactions
      description: >-
        Deletes the split children of a previously split transactions and
        restores the parent transactions to the normal unsplit state.<br><br>

        Use the value of the `split_parent_id`property of a split transaction to
        specify the parent ID.
      operationId: unsplitTransaction
      parameters:
        - in: path
          name: id
          description: ID of the previously split transaction to delete.
          required: true
          schema:
            type: integer
            format: int64
          examples:
            unsplit a transaction:
              value: 2112140459
            invalid parent id:
              value: 2112140361
            id not found:
              value: 543210
      responses:
        "204":
          description: No Content
        "400":
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no transaction with the id: 2112140458"
                    id: 2112140458
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /transactions/{transaction_id}/attachments:
    post:
      tags:
        - transactions (files)
      summary: Attach a file to a transaction
      operationId: attachFileToTransaction
      description: >-
        Attaches a file to a transaction. The file must be less than 10MB in size.<br><br>
        The file will be attached to the transaction and can be downloaded from the link returned by a `GET /transactions/attachments/{file_id}` request.
      parameters:
        - name: transaction_id
          in: path
          required: true
          schema:
            type: integer
            format: int64
            description: The ID of the transaction to attach the file to
          examples:
            attach file to transaction:
              summary: Basic transaction by id request
              value: 2112150655
            id not found:
              summary: Example of an id that doesn't exist
              value: 9999999999999
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
              properties:
                file:
                  type: string
                  format: binary
                  description: |
                    The file to attach via multipart form encoding.  File size may not exceed 10MB.
                notes:
                  type: string
                  description: Optional notes about the file
            example:
              file: ./test-attachment.png
              notes: "Test file attachment"
      responses:
        "201":
          description: File attached successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/transactionAttachmentObject"
              example:
                id: 1234567890
                uploaded_by: 1
                name: "receipt.png"
                type: "image/png"
                size: 4330
                notes: null
                source: "api"
                created_at: "2025-06-11T22:33:20.294Z"
        "400":
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              examples:
                invalidFileType:
                  value:
                    message: "Invalid Request Body"
                    errors:
                      - errMsg: "File type application/zip not allowed. Allowed types are: image/jpeg, image/png, application/pdf, image/heic, image/heif"
                fileTooLarge:
                  value:
                    message: "Invalid Request Body"
                    errors:
                      - errMsg: "File size exceeds maximum allowed size of 10MB"
                invalidFileTypeString:
                  value:
                    message: "Invalid Request Body"
                    errors:
                      - errMsg: "Invalid value for property 'file'. Expected 'object', received 'string'"
                        error: Invalid type
                        invalid_property: file
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Transaction not found
  /transactions/attachments/{file_id}:
    get:
      summary: Get a url to download a file attachment
      description: Returns a signed url that can be used to download the file
        attachment.
      operationId: getTransactionAttachmentUrl
      tags:
        - transactions (files)
      parameters:
        - name: file_id
          in: path
          required: true
          schema:
            type: integer
            format: int32
            description: The ID of the file attachment to download
          examples:
            existing file attachment id:
              summary: Basic file attachment by id request
              value: 1234567890
            id not found:
              summary: Example of an id that doesn't exist
              value: 9999999999999
      responses:
        "200":
          description: Successfully retrieved the file attachment
          content:
            application/json:
              schema:
                properties:
                  url:
                    type: string
                    description: The signed url to download the file attachment
                  expires_at:
                    type: string
                    format: date-time
                    description: The date and time the signed url will expire
                required:
                  - url
                  - expires_at
              example:
                url: "https://files.lunchmoney.app/66938-41ebb56a066bf09898de.png?X-Header1=X-Value1&X-Header2=Test-Do-Not-Use"
                expires_at: "2025-07-14T12:00:00Z"
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: File attachment not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: File attachment 1234567890 not found
  
    delete:
      summary: Delete a file attachment
      operationId: deleteTransactionAttachment
      description: >-
        Deletes a file attachment from a transaction.
      tags:
        - transactions (files)
      parameters:
        - name: file_id
          in: path
          required: true
          schema:
            type: integer
            format: int32
            description: The ID of the file attachment to delete
          examples:
            existing file attachment id:
              summary: Basic file attachment by id request
              value: 1234567890
            id not found:
              summary: Example of an id that doesn't exist
              value: 9999999999999
      responses:
        "204":
          description: File attachment successfully deleted
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: File attachment not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: File attachment 1234567890 not found



  /tags:
    get:
      tags:
        - tags
      summary: Get All Tags
      description: Retrieve a list of all tags associated with the user's
        account.
      operationId: getAllTags
      responses:
        "200":
          description: A list of tags
          content:
            application/json:
              schema:
                type: object
                properties:
                  tags:
                    type: array
                    items:
                      $ref: "#/components/schemas/tagObject"
              example:
                tags:
                  - id: 94317
                    name: Penny's
                    description: For transactions not related to Lenny
                    updated_at: "2025-02-28T09:49:03.238Z"
                    created_at: "2025-01-28T09:49:03.238Z"
                    text_color: "333"
                    background_color: "FFE7D4"
                    archived: false
                    archived_at: null
                  - id: 94318
                    name: Road Trip
                    description: ""
                    updated_at: "2025-02-28T09:50:03.238Z"
                    created_at: "2025-01-28T09:50:03.238Z"
                    text_color: "333"
                    background_color: "CFF4F3"
                    archived: false
                    archived_at: null
                  - id: 94319
                    name: Date Night
                    description: ""
                    updated_at: "2025-02-28T09:59:03.238Z"
                    created_at: "2025-01-28T10:02:03.238Z"
                    text_color: "333"
                    background_color: "D7F5CC"
                    archived: false
                    archived_at: null
        "400":
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be equal to one of the allowed values
                    instancePath: /query/format
                    schemaPath: "#/properties/query/properties/format/enum"
                    keyword: enum
                    params:
                      allowedValues:
                        - flattened
                        - nested
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    post:
      tags:
        - tags
      summary: Create a new tag
      description: Creates a new tag with the given name
      operationId: createTag
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/createTagRequestObject"
            examples:
              name only:
                value:
                  name: API Created Tag with no description
              with description:
                value:
                  name: API Created Tag
                  description: Description of tag created via API
      responses:
        "201":
          description: Tag Object with the successfully created tag
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/tagObject"
              examples:
                name only:
                  value:
                    id: 94350
                    name: API Created Tag with no description
                    description: null
                    created_at: "2024-07-28T01:01:38.716Z"
                    updated_at: "2024-07-28T01:01:38.716Z"
                    text_color: null
                    background_color: null
                    archived: false
                    archived_at: null
                with description:
                  value:
                    id: 94351
                    name: API Created Tag
                    description: Description of tag created via API
                    text_color: null
                    background_color: null
                    created_at: "2024-07-28T01:01:38.716Z"
                    updated_at: "2024-07-28T01:01:38.716Z"
                    archived: false
                    archived_at: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Invalid Request Body
                errors:
                  - errMsg: Tag with name 'New Tag' already exists
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /tags/{id}:
    get:
      tags:
        - tags
      summary: Get a single tag
      description: Retrieve the details of a specific tag with the specified ID.
      operationId: getTagById
      parameters:
        - name: id
          in: path
          description: ID of the tag to retrieve
          required: true
          schema:
            type: integer
            format: int32
          examples:
            tag:
              summary: Example of a tags's id
              value: 94319
            not found:
              summary: Example of a tag id that does not exist
              value: 543210
      responses:
        "200":
          description: Tag Object with the requested Tag ID
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/tagObject"
              example:
                id: 94319
                name: Date Night
                description: ""
                updated_at: "2025-02-28T09:59:03.238Z"
                created_at: "2025-01-28T10:02:03.238Z"
                text_color: null
                background_color: null
                archived: false
                archived_at: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be a valid integer
                    instancePath: /query/ids/0
                    schemaPath: "#/properties/query/properties/ids/items/type"
                    keyword: type
                    params:
                      type: integer
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: There is no tag with the id:'543210'
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    put:
      tags:
        - tags
      summary: Update an existing tag
      description: >-
        Updates an existing tag.<br><br>
        
        You may submit the response from a `GET /tags/{id}` as the request body; however, only certain
        properties can be updated using this API. The following system set properties are
        accepted in the request body but their values will be ignored: `id`, `updated_at`, and `created_at`.<br><br>

        It is also possible to provide only the properties to be updated in the
        request body, as long as the request includes at least one of the
        properties that is not listed above. For example, a request body that contains only a
        `name` attribute is valid.
      operationId: updateTag
      parameters:
        - name: id
          in: path
          description: ID of the tag to update
          required: true
          schema:
            type: integer
            format: int32
          examples:
            tag:
              summary: Example of a tags's id
              value: 94319
            not found:
              summary: Example of a tag id that does not exist
              value: 543210
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/updateTagRequestObject"
            examples:
              Update tag name:
                value:
                  name: Updated Tag Name
              Update with full object:
                value:
                  id: 94319
                  name: Updated Tag Name
                  description: API Updated Description
                  text_color: "333"
                  background_color: "FFE7D4"
                  updated_at: "2025-02-28T09:59:03.238Z"
                  created_at: "2025-01-28T10:02:03.238Z"
                  archived: false
                  archived_at: null
      responses:
        "200":
          description: Tag updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/tagObject"
              examples:
                new name:
                  value:
                    id: 94319
                    name: Updated Tag Name
                    description: null
                    text_color: null
                    background_color: null
                    updated_at: "2025-02-28T09:59:03.238Z"
                    created_at: "2025-01-28T10:02:03.238Z"
                    archived: false
                    archived_at: null
                new name and description:
                  value:
                    id: 94319
                    name: Updated Tag Name
                    description: API Updated Description
                    text_color: "333"
                    background_color: "FFE7D4"
                    updated_at: "2025-02-28T09:59:03.238Z"
                    created_at: "2025-01-28T10:02:03.238Z"
                    archived: false
                    archived_at: null
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: "A request to update a tag must include at least one of the following properties: name, description, archived."
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no tag with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - tags
      summary: Delete a tag
      description: >-
        Deletes the tag with the ID specified on the path.<br>

        If transactions or rules exist with the tag, a dependents object is
        returned and the tag is not deleted. This behavior can be overridden by
        setting the `force` parameter to `true`.
      operationId: deleteTag
      parameters:
        - in: path
          name: id
          description: ID of the tag to delete
          required: true
          schema:
            type: integer
            format: int32
          examples:
            delete tag:
              summary: Simple tag delete
              value: 94319
            delete tag with dependents:
              summary: Tag request with dependents
              value: 94317
            id not found:
              summary: Example of an id that doesn't exist
              value: 543210
        - in: query
          name: force
          description: Set to true to force deletion even if there are
            dependencies
          required: false
          schema:
            type: boolean
            default: false
      responses:
        "204":
          description: No Content
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no tag with the id: 543210."
        "422":
          description: Unprocessable Content
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/deleteTagResponseWithDependencies"
              example:
                tag_name: Tag to be Deleted
                dependents:
                  rules: 1
                  transactions: 10
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /recurring_items:
    get:
      tags:
        - recurring_items
      summary: Get all recurring items
      description: Retrieve recurring items for a specified time frame.
      operationId: getAllRecurring
      parameters:
        - name: start_date
          in: query
          schema:
            type: string
            format: date
          description: Indicates the beginning of the range used to populate the
            `matching` object in the recurring items. If omitted, the current
            month will be used as the range.<br> Required if end_date exists.
        - name: end_date
          in: query
          schema:
            type: string
            format: date
          description: "Indicates the end of the range used to populate the
            `matching` object in the recurring items. Required if start_date
            exists. "
        - name: include_suggested
          in: query
          schema:
            type: boolean
            description: When set to true will include recurring items that have
              been suggested by the system, but have not been reviewed and are
              not actively updating transactions.
      responses:
        "200":
          description: A list of recurring items
          content:
            application/json:
              schema:
                type: object
                properties:
                  recurring_items:
                    type: array
                    items:
                      $ref: "#/components/schemas/recurringObject"
              example:
                recurring_items:
                  recurring_items:
                    - id: 994069
                      description: Income
                      status: reviewed
                      transaction_criteria:
                        start_date: "2024-09-01"
                        end_date: "2024-10-31"
                        anchor_date: "2024-09-14"
                        granularity: month
                        quantity: 1
                        payee: Penny Lane
                        amount: "1250.8400"
                        to_base: 1250.84
                        currency: usd
                        plaid_account_id: 119806
                        manual_account_id: null
                      overrides:
                        payee: Paycheck
                        category_id: 88
                      matches:
                        request_start_date: "2024-10-01"
                        request_end_date: "2024-10-31"
                        expected_occurrence_dates:
                          - "2024-10-14"
                          - "2024-10-28"
                        found_transactions:
                          - date: "2024-10-14"
                            transaction_id: 2212150658
                        missing_transaction_dates:
                          - "2024-10-28"
                      created_by: 18328
                      created_at: "2024-07-28T01:01:38.716Z"
                      updated_at: "2024-07-28T01:01:38.716Z"
                      source: manual
                    - id: 994079
                      description: Monthly rent payable to Mrs Smith
                      status: reviewed
                      transaction_criteria:
                        start_date: "2024-09-01"
                        end_date: "2024-10-31"
                        anchor_date: "2024-09-01"
                        granularity: month
                        quantity: 1
                        payee: '[No Payee]'
                        amount: "850.0000"
                        to_base: 850
                        currency: usd
                        plaid_account_id: 119806
                        manual_account_id: null
                      overrides:
                        payee: Rent
                        notes: Monthly rent payable to Mrs Smith
                        category_id: 83
                      matches:
                        request_start_date: "2024-10-01"
                        request_end_date: "2024-10-31"
                        expected_occurrence_dates:
                          - "2024-10-01"
                        found_transactions:
                          - date: "2024-10-01"
                            transaction_id: 2212150656
                        missing_transaction_dates: []
                      created_by: 18328
                      created_at: "2025-06-28T01:01:38.195Z"
                      updated_at: "2025-06-28T01:01:38.195Z"
                      source: manual
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be a valid integer
                    instancePath: /query/ids/0
                    schemaPath: "#/properties/query/properties/ids/items/type"
                    keyword: type
                    params:
                      type: integer
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no recurring item with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /recurring_items/{id}:
    get:
      tags:
        - recurring_items
      summary: Get a single recurring item
      description: Retrieve the details of a specific recurring item with the
        specified ID.
      operationId: getRecurringById
      parameters:
        - name: id
          in: path
          description: ID of the recurring item to retrieve
          required: true
          schema:
            type: integer
            format: int32
          examples:
            tag:
              summary: Example of a recurring ID
              value: 994069
            not found:
              summary: Example of a recurring ID that does not exist
              value: 543210
        - name: start_date
          in: query
          schema:
            type: string
            format: date
          description: Indicates the beginning of the range used to populate the
            `matching` object in the recurring items. If omitted, the current
            month will be used as the range.<br> Required if end_date exists.
        - name: end_date
          in: query
          schema:
            type: string
            format: date
          description: "Indicates the end of the range used to populate the
            `matching` object in the recurring items. Required if start_date
            exists. "
      responses:
        "200":
          description: Recurring item object with the requested recurring item
            ID
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/recurringObject"
              example:
                id: 994069
                description: Income
                status: reviewed
                transaction_criteria:
                  start_date: "2024-09-01"
                  end_date: "2024-10-31"
                  anchor_date: "2024-09-14"
                  granularity: month
                  quantity: 1
                  payee: Penny Lane
                  amount: "1250.8400"
                  to_base: 1250.84
                  currency: usd
                  plaid_account_id: 119806
                  manual_account_id: null
                overrides:
                  payee: Paycheck
                  category_id: 88
                matches:
                  request_start_date: "2024-10-01"
                  request_end_date: "2024-10-31"
                  expected_occurrence_dates:
                    - "2024-10-14"
                    - "2024-10-28"
                  found_transactions:
                    - date: "2024-10-14"
                      transaction_id: 2212150658
                  missing_transaction_dates:
                    - "2024-10-28"
                created_by: 18328
                created_at: "2024-07-28T01:01:38.716Z"
                updated_at: "2024-07-28T01:01:38.716Z"
                source: manual
        "400":
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Request Validation Failure
                errors:
                  - errMsg: must be a valid integer
                    instancePath: /query/ids/0
                    schemaPath: "#/properties/query/properties/ids/items/type"
                    keyword: type
                    params:
                      type: integer
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "404":
          description: Not Found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/errorResponseObject"
              example:
                message: Not Found
                errors:
                  - errMsg: "There is no recurring item with the id: 543210."
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /budgets/settings:
    get:
      tags:
        - budgets
      summary: Get budget settings
      description: Returns the budget-related settings for the user's account.
      operationId: getBudgetSettings
      responses:
        "200":
          description: Budget settings for the account
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/budgetSettingsResponseObject"
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
  /budgets:
    put:
      tags:
        - budgets
      summary: Upsert budget
      description: |-
        Create or update a budget for a category and period.<p>
        If a budget already exists for the specified `start_date` and `category_id`, the `amount` (and optional `currency` and `notes`) are updated; otherwise a new budget entry is created.<p>

        Note that `start_date` **must** be a valid budget period start for the account (based on the account's
        budget period settings). If an invalid `start_date` is provided, the request will fail with an error that indicates what the previous and next valid start dates are.<p>

        Use the [budgets/settings](#tag/budgets/GET/budgets/settings) endpoint to view the account's budget settings.<br>
        To view details for existing budgets, use the [summary](#tag/summary) endpoint.
      operationId: upsertBudget
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/upsertBudgetRequestObject"
            example:
              start_date: "2025-01-01"
              category_id: 315177
              amount: 500
              currency: "usd"
              notes: "Monthly groceries"
      responses:
        "200":
          description: Budget upserted successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/budgetUpsertResponseObject"
              example:
                category_id: 315177
                start_date: "2025-01-01"
                amount: 500
                currency: "usd"
                to_base: 500.0
                notes: "Monthly groceries"
        "400":
          description: Bad Request (invalid period start, invalid category, or
            validation failure)
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/budgetInvalidPeriodErrorObject"
                  - $ref: "#/components/schemas/errorResponseObject"
              examples:
                invalid period:
                  summary: Start date not a valid budget period start
                  value:
                    message: Invalid Request
                    errors:
                      - errMsg: "The requested start date is not a valid budget period start for this account."
                        requested_start_date: "2025-01-15"
                        previous_valid_start_date: "2025-01-01"
                        next_valid_start_date: "2025-02-01"
                validation error:
                  summary: Bad Category ID
                  value:
                    message: Invalid Request Body
                    errors:
                      - errMsg: "Category ID does not exist"
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"
    delete:
      tags:
        - budgets
      summary: Delete budget
      description: Removes the budget for the given category and period. If
        there already is no budget set for that period, the request still
        succeeds (idempotent).<p> Note that `start_date` **must** be a valid
        budget period start for the account (based on the account's budget
        period settings). If an invalid `start_date` is provided, the request
        will fail with an error that indicates what the previous and next valid
        start dates are.<p> Use the
        [budgets/settings](#tag/budgets/GET/budgets/settings) endpoint to view
        the account's budget settings.<br> To view details for existing budgets,
        use the [summary](#tag/summary) endpoint.
      operationId: deleteBudget
      parameters:
        - in: query
          name: category_id
          required: true
          description: Category ID of the budget to delete
          schema:
            type: integer
            format: int32
        - in: query
          name: start_date
          required: true
          description: Start date of the budget period in ISO 8601 date format
            (YYYY-MM-DD)
          schema:
            type: string
            format: date
      responses:
        "204":
          description: Budget deleted (or no budget existed for the given
            category and period)
        "400":
          description: Bad Request (invalid period start, invalid category, or
            validation failure)
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/budgetInvalidPeriodErrorObject"
                  - $ref: "#/components/schemas/errorResponseObject"
              examples:
                invalid period:
                  summary: Bad Category ID
                  value:
                    message: Invalid Request
                    errors:
                      - errMsg: "The requested start date is not a valid budget period start for this account."
                        requested_start_date: "2025-01-15"
                        previous_valid_start_date: "2025-01-01"
                        next_valid_start_date: "2025-02-01"
                validation error:
                  summary: Invalid request body
                  value:
                    message: Invalid Request Body
                    errors:
                      - errMsg: "Category ID does not exist"
        "401":
          $ref: "#/components/responses/unauthorizedToken"
        "429":
          $ref: "#/components/responses/rateLimited"
        "500":
          $ref: "#/components/responses/serverError"

security:
  - bearerSecurity: []
  - cookieAuth: []
