openapi: 3.0.2 info: title: Lunch Money API - v2 description: |- Welcome to the Lunch Money v2 API reference. This is the **v2.11.1** spec. It includes previews of the proposed `/crypto` and `/balance_history` endpoints. Only the mock service works with these endpoints.

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). The v2 API is in open alpha and is still subject to change. Use the mock server or a test budget when getting started. **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.1 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.

Use [/me/account/settings](#tag/me/GET/me/account/settings) and [/me/user/settings](#tag/me/GET/me/user/settings) for account- and user-level preferences. - 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.

Use [/budgets/settings](#tag/budgets/GET/budgets/settings) to view budget period settings.

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 current budgeting account budget_name: type: string description: Name of the current budgeting account.

Also available as `display_name` on [/me/account/settings](#tag/me/GET/me/account/settings), which is the preferred endpoint for reading and updating account settings. primary_currency: description: Primary currency for the current budgeting account.

Also available on [/me/account/settings](#tag/me/GET/me/account/settings), which is the preferred endpoint for reading and updating account 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.
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.
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.
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.
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.
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.
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.
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.
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.
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 asset name for this balance, typically the uppercased currency symbol (e.g. ETH). display_name: type: string nullable: true description: Optional display name for the synced crypto asset as set by the user. If `null`, clients may derive a display name from syncedCryptoAccount's `provider` + `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: 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 - display_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
- 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.
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
- 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.
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 nullable: true description: If set, an optional account subtype. Set to `null` to clear it. Examples include
- retirement - checking - savings - prepaid credit card minLength: 1 maxLength: 100 example: prepaid credit card 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
- active: Account is actively syncing transactions and/or balance
- inactive: Account marked inactive from user. Transaction imports and balance updates will not occur for this account.
- closed: Account is marked as closed
- 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.'
- not found: Account was once linked but can no longer be found with Plaid.
- not supported: Account is not supported by Plaid.
- relink: Account (and others with the same connection) need to be relinked with Plaid.
- syncing: Account is awaiting the first import of transactions.
- revoked: Account connection has been revoked by Plaid and syncing is no longer possible. A new connection needs to be set up again.
- error: Account (and others with the same connection) is in error with Plaid and requires intervention to re-activate it.
" 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: > Monthly balance history entries for the source account. On GET responses, this includes all entries in the requested range. On PUT upsert responses, this includes only the entries modified by that request. 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, as a numeric string with up to four decimal places. Trailing zeros and decimal places are not guaranteed in responses. 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 be in a past month. 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.
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 associated with the transaction. For transactions belonging to manual accounts, the external ID must be unique for each transaction associated with the account. 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.
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`.
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.
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.
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 associated with the transaction. For transactions belonging to manual accounts, the external ID must be unique for each transaction associated with the account. 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.
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.
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: type: object title: budget settings object additionalProperties: false description: Budget period and display settings for the current budgeting account. properties: budget_period_granularity: type: string enum: - day - week - month - year - twice a month description: Budget period granularity budget_period_quantity: type: integer format: int32 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 weekStartsOnEnum: type: string title: week starts on enum enum: - sunday - monday description: The day on which a calendar week begins. monthYearFormatEnum: type: string title: month and year format enum description: Format string for displaying month and year values in the Lunch Money app. enum: - "MMMM YYYY" - "MMM YYYY" - "YYYY MMM" - "MM YYYY" - "MM-YYYY" - "MM.YYYY" - "MM/YYYY" - "M YYYY" - "M-YYYY" - "M.YYYY" - "M/YYYY" - "YYYY M" - "YYYY-M" - "YYYY.M" - "YYYY/M" - "YYYY MM" - "YYYY-MM" - "YYYY.MM" - "YYYY/MM" monthDayYearFormatEnum: type: string title: month, day and year format enum description: Format string for displaying full dates in the Lunch Money app. enum: - "MMM D, YYYY" - "D MMM YYYY" - "YYYY MM DD" - "YYYY-MM-DD" - "YYYY.MM.DD" - "YYYY/MM/DD" - "YYYY M DD" - "YYYY-M-DD" - "YYYY.M.DD" - "YYYY/M/DD" - "YYYY MM D" - "YYYY-MM-D" - "YYYY.MM.D" - "YYYY/MM/D" - "YYYY M D" - "YYYY-M-D" - "YYYY.M.D" - "YYYY/M/D" - "DD MM YYYY" - "DD-MM-YYYY" - "DD.MM.YYYY" - "DD/MM/YYYY" - "DD M YYYY" - "DD-M-YYYY" - "DD.M.YYYY" - "DD/M/YYYY" - "D MM YYYY" - "D-MM-YYYY" - "D.MM.YYYY" - "D/MM/YYYY" - "D M YYYY" - "D-M-YYYY" - "D.M.YYYY" - "D/M/YYYY" - "M D YYYY" - "M-D-YYYY" - "M.D.YYYY" - "M/D/YYYY" - "MM D YYYY" - "MM-D-YYYY" - "MM.D.YYYY" - "MM/D/YYYY" - "MM DD YYYY" - "MM-DD-YYYY" - "MM.DD.YYYY" - "MM/DD/YYYY" - "M DD YYYY" - "M-DD-YYYY" - "M.DD.YYYY" - "M/DD/YYYY" monthDayFormatEnum: type: string title: month and day format enum description: Format string for displaying month and day values without a year. enum: - "MMM D" - "MMM DD" - "D MMM" - "DD MMM" - "MM D" - "MM-D" - "MM.D" - "MM/D" - "MM DD" - "MM-DD" - "MM.DD" - "MM/DD" - "M D" - "M-D" - "M.D" - "M/D" - "M DD" - "M-DD" - "M.DD" - "M/DD" - "D MM" - "D-MM" - "D.MM" - "D/MM" - "DD MM" - "DD-MM" - "DD.MM" - "DD/MM" - "D M" - "D-M" - "D.M" - "D/M" - "DD M" - "DD-M" - "DD.M" - "DD/M" accountSettingsObject: type: object title: account settings object additionalProperties: false description: Account-level settings for the budgeting account associated with the authorized API token. properties: primary_currency: description: Primary currency for the account. allOf: - $ref: "#/components/schemas/currencyEnum" supported_currencies: type: array items: $ref: "#/components/schemas/currencyEnum" description: Currencies available when creating or editing transactions, balances, and other amounts in the Lunch Money app. display_name: type: string nullable: true description: Display name of the budgeting account in the Lunch Money app. locale: type: string description: Locale used for formatting dates and numbers in the Lunch Money app (for example, `en-US`). When no locale is explicitly stored for the account, the effective locale is derived from the `default_locale` associated with `primary_currency` in the currencies table (for example, `usd` → `en-US`, `cad` → `en-CA`, `gbp` → `en-GB`). auto_create_category_rules: type: boolean default: true description: If `true`, category rules are created automatically when categorizing transactions. auto_create_suggested_transaction_rules: type: boolean default: true description: If `true`, suggested transaction rules are created automatically. auto_review_transaction_on_update: type: boolean default: true description: If `true`, transactions are marked as reviewed when updated. auto_review_transaction_on_creation: type: boolean default: true description: If `true`, transactions are marked as reviewed when created. required: - primary_currency - supported_currencies - display_name - locale - auto_create_category_rules - auto_create_suggested_transaction_rules - auto_review_transaction_on_update - auto_review_transaction_on_creation updateAccountSettingsRequestObject: x-internal: true type: object additionalProperties: false description: Request body for updating account settings. Include at least one property to update. properties: primary_currency: allOf: - $ref: "#/components/schemas/currencyEnum" description: If set, updates the account's primary currency. x-updatable: true supported_currencies: type: array items: $ref: "#/components/schemas/currencyEnum" description: If set, replaces the list of supported currencies for the account. x-updatable: true display_name: type: string nullable: true description: If set, updates the display name of the budgeting account. x-updatable: true locale: type: string description: If set, updates the locale used for formatting dates and numbers in the Lunch Money app. x-updatable: true auto_create_category_rules: type: boolean description: If set, updates whether category rules are created automatically. x-updatable: true auto_create_suggested_transaction_rules: type: boolean description: If set, updates whether suggested transaction rules are created automatically. x-updatable: true auto_review_transaction_on_update: type: boolean description: If set, updates whether transactions are marked as reviewed when updated. x-updatable: true auto_review_transaction_on_creation: type: boolean description: If set, updates whether transactions are marked as reviewed when created. x-updatable: true userSettingsObject: type: object title: user settings object additionalProperties: false description: User-level display and formatting preferences for the user associated with the authorized API token. properties: show_debits_as_negative: type: boolean default: true description: Display preference for how amounts are shown in the Lunch Money app. When `true`, debits are shown as negative values and credits as positive values.

This setting does **not** change amount sign conventions in API responses. Amount fields such as `amount` and `to_base` on transaction objects always use positive values for debits and negative values for credits. auto_suggest_payee: type: boolean default: true description: If `true`, payee suggestions are shown when entering transactions in the Lunch Money app. month_year_format: allOf: - $ref: "#/components/schemas/monthYearFormatEnum" default: "MMM YYYY" description: Format string used when displaying month and year values. month_day_year_format: allOf: - $ref: "#/components/schemas/monthDayYearFormatEnum" default: "MMM D, YYYY" description: Format string used when displaying full dates (month, day, and year). month_day_format: allOf: - $ref: "#/components/schemas/monthDayFormatEnum" default: "MMM D" description: Format string used when displaying month and day values without a year. show_am_pm: type: boolean default: true description: If `true`, times are displayed using a 12-hour clock with AM/PM. If `false`, times are displayed using a 24-hour clock. week_starts_on: allOf: - $ref: "#/components/schemas/weekStartsOnEnum" default: sunday description: The day on which a calendar week begins. always_display_year: type: boolean default: false description: If `true`, dates always include the year and `month_day_format` is not used. always_display_weekday: type: boolean default: true description: If `true`, weekday names are included when displaying dates. required: - show_debits_as_negative - auto_suggest_payee - month_year_format - month_day_year_format - month_day_format - show_am_pm - week_starts_on - always_display_year - always_display_weekday updateUserSettingsRequestObject: x-internal: true type: object additionalProperties: false description: Request body for updating user settings. Include at least one property to update. properties: show_debits_as_negative: type: boolean description: If set, updates the display preference for amount signs in the Lunch Money app. Does not affect amount sign conventions in API responses. x-updatable: true auto_suggest_payee: type: boolean description: If set, updates whether payee suggestions are shown. x-updatable: true month_year_format: allOf: - $ref: "#/components/schemas/monthYearFormatEnum" description: If set, updates the month and year display format. x-updatable: true month_day_year_format: allOf: - $ref: "#/components/schemas/monthDayYearFormatEnum" description: If set, updates the full date display format. x-updatable: true month_day_format: allOf: - $ref: "#/components/schemas/monthDayFormatEnum" description: If set, updates the month and day display format. x-updatable: true show_am_pm: type: boolean description: If set, updates whether times use a 12-hour (AM/PM) or 24-hour clock. x-updatable: true week_starts_on: allOf: - $ref: "#/components/schemas/weekStartsOnEnum" description: If set, updates the day on which a calendar week begins. x-updatable: true always_display_year: type: boolean description: If set, updates whether dates always include the year. x-updatable: true always_display_weekday: type: boolean description: If set, updates whether weekday names are shown when displaying dates. x-updatable: true # 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.

When the response is not aligned, category `totals` will not include values for the `budgeted` and `available` properties, so aligned responses are usually preferred.

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.

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.

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.
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.
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.
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.
If multiple errors were encountered, the list will contain multiple objects.
Each `error` object is guaranteed to have an `errMsg`, but it may also contain other error-specific properties such as `code` (for example `VALIDATION_ERROR`), or other properties that are useful to map the error to the relevant part of the request. 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).

To # interact with the Static Mock Server simply enter an API key of 11 # characters or more.

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.

For account- and user-level preferences, prefer [/me/account/settings](#tag/me/GET/me/account/settings) and [/me/user/settings](#tag/me/GET/me/user/settings). Properties such as `primary_currency` and `budget_name` remain on this response for backwards compatibility. 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" /me/account/settings: get: tags: - me summary: Get account settings description: Returns account-level settings for the budgeting account associated with the authorized API token. operationId: getAccountSettings responses: "200": description: Account settings for the current budgeting account content: application/json: schema: $ref: "#/components/schemas/accountSettingsObject" example: primary_currency: usd supported_currencies: - usd - cad - jpy display_name: "\U0001F3E0 Family budget" locale: en-US auto_create_category_rules: true auto_create_suggested_transaction_rules: true auto_review_transaction_on_update: true auto_review_transaction_on_creation: true "401": $ref: "#/components/responses/unauthorizedToken" "429": $ref: "#/components/responses/rateLimited" "500": $ref: "#/components/responses/serverError" put: tags: - me summary: Update account settings description: |- Updates account-level settings for the budgeting account associated with the authorized API token.

You may submit the response from a `GET /me/account/settings` as the request body; however, only certain properties can be updated.

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 updatable property. operationId: updateAccountSettings requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/updateAccountSettingsRequestObject" examples: Update display name: value: display_name: "Travel budget" Update automation preferences: value: auto_create_category_rules: false auto_review_transaction_on_creation: false responses: "200": description: Account settings updated successfully content: application/json: schema: $ref: "#/components/schemas/accountSettingsObject" "400": description: Invalid request body content: application/json: schema: $ref: "#/components/schemas/errorResponseObject" "401": $ref: "#/components/responses/unauthorizedToken" "429": $ref: "#/components/responses/rateLimited" "500": $ref: "#/components/responses/serverError" /me/user/settings: get: tags: - me summary: Get user settings description: Returns user-level display and formatting preferences for the user associated with the authorized API token. operationId: getUserSettings responses: "200": description: User settings for the authorized user content: application/json: schema: $ref: "#/components/schemas/userSettingsObject" example: show_debits_as_negative: true auto_suggest_payee: true month_year_format: "MMM YYYY" month_day_year_format: "MMM D, YYYY" month_day_format: "MMM D" show_am_pm: true week_starts_on: sunday always_display_year: false always_display_weekday: true "401": $ref: "#/components/responses/unauthorizedToken" "429": $ref: "#/components/responses/rateLimited" "500": $ref: "#/components/responses/serverError" put: tags: - me summary: Update user settings description: |- Updates user-level display and formatting preferences for the user associated with the authorized API token.

You may submit the response from a `GET /me/user/settings` as the request body; however, only certain properties can be updated.

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 updatable property.

Updating `show_debits_as_negative` affects display in the Lunch Money app only. Amount fields in API responses always use positive values for debits and negative values for credits. operationId: updateUserSettings requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/updateUserSettingsRequestObject" examples: Update date formats: value: month_year_format: "YYYY-MM" month_day_year_format: "YYYY-MM-DD" month_day_format: "MM-DD" Use 24-hour time and Monday week start: value: show_am_pm: false week_starts_on: monday responses: "200": description: User settings updated successfully content: application/json: schema: $ref: "#/components/schemas/userSettingsObject" "400": description: Invalid request body content: application/json: schema: $ref: "#/components/schemas/errorResponseObject" "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.

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.

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.
If `true`, only category groups are returned.
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.
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.

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`.

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.

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.

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.

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.

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.

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.

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: Invalid Request Body 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." invalid balance: value: message: Invalid Request Body errors: - errMsg: "Invalid value for property 'balance'. 'abc' cannot be converted to a number" - errMsg: "Invalid value for property 'balance'. Invalid input" invalid property: value: message: Invalid Request Body errors: - errMsg: "Invalid property 'coingecko_id' 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.

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.

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.

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.

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.

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 before 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.

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

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 before 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: "Deleted balance history source 99999999 was not found." "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 account. Crypto synced accounts require an additional `symbol` path parameter.

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

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

Balance history is monthly. Each entry's `date` must be the first day of a month and must be in a past month.

`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.

`symbol` may only be set when `account_type` is `crypto_manual` or `crypto_synced`. It is optional for `crypto_manual` accounts and tolerated for `deleted` accounts.

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

The response contains only the balance entries that were submitted in this request. 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" 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: Returns the modified balance entries only. Other historical entries for the account are omitted from `balances`. content: application/json: schema: $ref: "#/components/schemas/balanceHistoryAccountObject" examples: manual account bulk upsert: summary: Two upserted rows returned (not full account history) 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 crypto manual balance with symbol: summary: Single upserted row returned value: source: type: crypto_manual crypto_manual_id: 22001 symbol: btc balances: - id: 603 date: "2026-03-01" balance: "56011.1200" currency: usd to_base: 56011.12 crypto_balance: "0.852341920145782301" deleted account bulk upsert: summary: Single upserted row returned value: 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: btc balances: - id: 504 date: "2026-03-01" balance: "1255" currency: usd to_base: 1255 crypto_balance: "0.020000000000000000" "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." empty balances array: value: message: Invalid Request Body errors: - errMsg: "Invalid value for property 'balances'. Array must contain at least 1 element(s)" 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 code: VALIDATION_ERROR future date: value: message: Request Validation Failure errors: - errMsg: "`date` must be in a past month." 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`, `crypto_synced`, or `deleted`." request_balances_index: 0 invalid row in bulk request: value: message: Request Validation Failure errors: - errMsg: "`symbol` may only be set when `account_type` is `crypto_manual` or `crypto_synced`." 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.

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

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 before 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 balance history for symbol 'doge' on this account." "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.

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

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

Balance history is monthly. Each entry's `date` must be the first day of a month and must be in a past month.

The request body may include an optional `symbol` on each balance entry. If provided, it must match the `symbol` path parameter. Omit `symbol` to use the path value.

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

`crypto_balance` may be provided for synced crypto balances.

The response contains only the balance entries that were submitted in this request. 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: Returns the modified balance entries only. Other historical entries for the symbol stream are omitted from `balances`. content: application/json: schema: $ref: "#/components/schemas/balanceHistoryAccountObject" examples: synced crypto bulk upsert: summary: Two upserted rows returned (not full symbol history) 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." empty balances array: value: message: Invalid Request Body errors: - errMsg: "Invalid value for property 'balances'. Array must contain at least 1 element(s)" 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 be in a past month." request_balances_index: 1 symbol mismatch: value: message: Request Validation Failure errors: - errMsg: "`symbol` in request body (doge) does not match the path symbol (eth)." request_balances_index: 0 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 balance history for symbol 'doge' on this account." "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.

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 balance history for symbol 'doge' on this account." "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 "400": description: Bad Request content: application/json: schema: $ref: "#/components/schemas/errorResponseObject" example: message: Request Validation Failure 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 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.

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: "At least one property must be provided: 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: "Deleted balance history source 99999999 was not found." "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.

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`.

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.

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.

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.

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.
Required if end_date exists.
- 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`).
"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.
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.
- 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.
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.
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:
- `reviewed`: Only user reviewed transactions or those that were automatically marked as reviewed due to reviewed recurring_item logic
- `unreviewed`: Only transactions that need to be reviewed
- `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.

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.

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.

The successful request to this endpoint will return a response body which will include two arrays:
- `transactions`: A list of transactions that were successfully inserted.
- `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.

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.

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`.

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.

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.

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.

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.

Otherwise, the specified transactions are deleted.

Use with caution. This action is not reversible! 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:
- `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.
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.

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`.

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.

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.

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.

Use with caution. This action is not reversible! 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.

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.
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.

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.

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.

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.

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`.

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.
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.
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.
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 period settings description: |- Returns budget period and display settings for the budget associated with this API token.

These control how budget **periods** are calculated (granularity, anchor date, rollover, and related options). For general budget preferences such as currency and locale, see [/me/account/settings](#tag/me/GET/me/account/settings). operationId: getBudgetSettings responses: "200": description: Budget period settings for the current budget 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.

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.

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.

Use the [/budgets/settings](#tag/budgets/GET/budgets/settings) endpoint to view the budget period settings for the account.
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).

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.

Use the [/budgets/settings](#tag/budgets/GET/budgets/settings) endpoint to view the account's budget settings.
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: []