openapi: 3.0.2 info: title: Lunch Money API - v2 description: |- Welcome to the Lunch Money v2 API. 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). ### Introduction 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. **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://lunchmoney.dev/v2/introduction) - [Getting Started Guide](https://lunchmoney.dev/v2/getting-started) - [v2 API Overview](https://lunchmoney.dev/v2/overview) - [v2 API Changelog](https://lunchmoney.dev/v2/changelog) - [Migration Guide](https://lunchmoney.dev/v2/migration-guide) - [Rate Limits](https://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.9.4 servers: - url: https://api.lunchmoney.dev/v2 description: v2 Lunch Money API Server - changes will affect real data! - url: https://mock.lunchmoney.dev/v2 description: Static mock version of the v2 Lunch Money API Server tags: - name: me description: View details and settings for the current user and account - name: categories description: Work with categories externalDocs: description: Learn more about categories url: https://support.lunchmoney.app/setup/categories - name: manual_accounts description: Work with manually managed accounts (formerly called assets) externalDocs: description: Learn more about manual accounts url: https://support.lunchmoney.app/setup/linked-accounts#how-are-manually-managed-account-balances-updated - name: plaid_accounts description: Work with accounts synced through Plaid externalDocs: description: Learn more about synced accounts url: https://support.lunchmoney.app/setup/linked-accounts#how-often-should-i-expect-new-transactions-to-get-imported - name: 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 the [/summary](#tag/summary) endpoint to view the budget details performance.
externalDocs:
description: Learn more about budgets
url: https://support.lunchmoney.app/finances/budgets
- name: summary
description: View a summary of the user's budget
components:
schemas:
userObject:
type: object
title: user object (returned by /me)
additionalProperties: false
properties:
name:
type: string
description: The user's name
email:
type: string
description: The user's email
id:
type: integer
format: int32
description: Unique ID for the user
account_id:
type: integer
format: int64
description: Unique ID for the linked budgeting account
budget_name:
type: string
description: Name of the linked budgeting account
primary_currency:
description: Primary currency set in the user's settings
allOf:
- $ref: "#/components/schemas/currencyEnum"
api_key_label:
type: string
nullable: true
description: Label assigned by the user to the API key being used. Returns null if no label
is set
required:
- name
- email
- id
- account_id
- budget_name
- primary_currency
- api_key_label
categoryObject:
type: object
title: category object
additionalProperties: false
properties:
id:
type: integer
format: int32
nullable: false
description: System defined unique ID for the category
name:
type: string
nullable: false
description: The name of the category.
minLength: 1
maxLength: 100
description:
type: string
nullable: true
description: The description of the category or `null` if not set.
maxLength: 200
is_income:
type: boolean
nullable: false
description: 'If `true`, the transactions in this category will be treated as income. (See Category Properties for more details)'
exclude_from_budget:
type: boolean
nullable: false
description: 'If `true`, the transactions in this category will be excluded from
the budget. (See Category Properties for more details)'
exclude_from_totals:
type: boolean
nullable: false
description: 'If `true`, the transactions in this category will be excluded from
totals. (See Category Properties for more details)'
updated_at:
type: string
format: date-time
nullable: false
description: The date and time of when the category 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 category was created (in the ISO 8601
extended format).
group_id:
type: integer
format: int64
nullable: true
description: The ID of the category group this category belongs to or `null` if
the category doesn't belong to a group, or is itself a category
group.
is_group:
type: boolean
description: If `true`, the category is created as a category group.
children:
type: array
items:
$ref: "#/components/schemas/childCategoryObject"
description: For category groups, this will populate with details about the
categories that belong to this group. The objects in this array are
similar to Category Objects but do not include the `is_income`,
`exclude_from_budget`, and `exclude_from_totals` properties as these
are inherited from the category group. In addition, 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 not displayed in relevant
areas of the Lunch Money app.
archived_at:
type: string
format: date-time
nullable: true
description: The date and time of when the category was last archived (in the
ISO 8601 extended format).
order:
type: integer
nullable: true
default: null
description: "An integer specifying the position in which the category is displayed
on the categories page in the Lunch Money GUI. For categories within
a category group the order is relative to the other categories
within the group.
Categories with `order: null` will be displayed in
alphabetical order by name, prior to any categories with an order"
collapsed:
type: boolean
nullable: false
default: false
description: If `true`, the category is collapsed in the Lunch Money GUI.
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 basically a categoryObject that has no
# `children` attribute. We create this to ensure that no categories
# are added to a category group if they have children and are a 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: A system defined unique identifier for the category.
name:
type: string
nullable: false
description: The name of the category.
minLength: 1
maxLength: 100
description:
type: string
nullable: true
description: The description of the category or `null` if not set.
maxLength: 200
is_income:
type: boolean
nullable: false
description: If true, the transactions in this category will be treated as
income. Inherited from Category Group.
exclude_from_budget:
type: boolean
nullable: false
description: If true, the transactions in this category will be excluded from
the budget. Inherited from Category Group.
exclude_from_totals:
type: boolean
nullable: false
description: If true, the transactions in this category will be excluded from
totals. Inherited from Category Group.
updated_at:
type: string
format: date-time
nullable: false
description: The date and time of when the category 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 category was created (in the ISO 8601
extended format).
group_id:
type: integer
format: int64
nullable: true
description: The ID of the category group this category belongs to or `null` if
the category doesn't belong to a group, or is itself a category
group.
is_group:
type: boolean
enum:
- false
description: Will always be false for a category that is part of category group.
archived:
type: boolean
description: If true, the category is archived and not displayed in relevant
areas of the Lunch Money app.
archived_at:
type: string
format: date-time
nullable: true
description: The date and time of when the category was last archived (in the
ISO 8601 extended format).
order:
type: integer
nullable: true
description: An index specifying the position in which the category is displayed
on the categories page in the Lunch Money GUI. For categories within
a category group the order is relative to the other categories
within the group.
API.
collapsed:
type: boolean
nullable: true
description: If `true`, the category is collapsed in the Lunch Money GUI.
required:
- id
- name
- description
- is_income
- exclude_from_budget
- exclude_from_totals
- updated_at
- created_at
- group_id
- is_group
- archived
- archived_at
- order
# 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: >-
The name of the new category. Must be between 1 and 100 characters.
Must not match the name of any existing categories or category
groups.
minLength: 1
maxLength: 100
description:
type: string
nullable: true
default: null
description: The description of the category. Must not exceed 200 characters.
minLength: 0 # Allow empty strings
maxLength: 200
is_income:
type: boolean
nullable: false
default: false
description: If `true`, the transactions in this category will be treated as
income. (See Category Properties for more details)
exclude_from_budget:
type: boolean
nullable: false
default: false
description: If `true`, the transactions in this category will be excluded from
the budget. (See Category Properties for more details)
exclude_from_totals:
type: boolean
nullable: false
default: false
description: If `true`, the transactions in this category will be excluded from
totals. (See Category Properties for more details)
is_group:
type: boolean
nullable: false
default: false
description: If `true`, the category is 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, this new category
will be assigned to that group. Cannot be set if `is_group` is true.
archived:
type: boolean
default: false
description: If `true`, the category is archived and not displayed in relevant
areas of the Lunch Money app.
children:
type: array
nullable: false
description: The list of existing category objects, or existing category IDs or
names of new categories to add to the new category group. This
attribute should only be set if `is_group` is also set to true.
The categories or IDs specified must already exist and may not be category groups themselves.
Categories that already belong to
another category group will be moved. If strings are specified, they
will be used as the names of new categories that will be added to
the new category group. The request will fail if any names are the
same as the name of an existing category.
It is permissible to
provide both full category objects and IDs as well as strings for
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: An index specifying the position in which the category is displayed
on the categories page in the Lunch Money GUI. For categories within
a category group the order is relative to the other categories
within the group.
While this property can be set via the API it is generally set by the user in the Lunch Money GUI.
API.
collapsed:
type: boolean
nullable: true
description: If `true`, the category is collapsed in the Lunch Money GUI.
While this property can be set via the API it is generally set by the user in the Lunch Money GUI.
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, the new name of the category. 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 category. Must not exceed 200
characters.
minLength: 0 # Allow empty strings
maxLength: 200
x-updatable: true
is_income:
type: boolean
nullable: false
description: If set, will indicate if this category will be treated as income. (See Category Properties for more details)
x-updatable: true
exclude_from_budget:
type: boolean
nullable: false
description: If set, will indicate if this category will be excluded from budgets. (See Category Properties for more details)
x-updatable: true
exclude_from_totals:
type: boolean
nullable: false
description: If set, will indicate if this category will be excluded from totals. (See Category Properties for more details)
x-updatable: true
archived:
type: boolean
description: If set, will indicate if 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 a child of the
specified group.
x-updatable: true
is_group:
type: boolean
nullable: true
default: false
description: This attribute may not be set to a value that is different
than the current status of the category or category group. In other
words, this API may not be used to convert a category to a category
group or vice versa.
children:
type: array
nullable: false
description: The list of existing category objects, or existing category IDs or
names of new categories to add to the new category group. This
attribute should only be set if modifying an existing category
group.
The categories or IDs specified must already exist and
not belong to an existing category group. Categories that already
belong to another category group will be moved. If strings are
specified, they will be used as the names of new categories that
will be added to the new category group. The request will fail if
any names are the same as the name of an existing category.
It
is permissible to provide both full category objects and IDs as well
as strings for 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: An index specifying the position in which the category is displayed
on the categories page in the Lunch Money GUI. For categories within
a category group the order is relative to the other categories
within the group.
While this property can be set via the API it is generally set by the user in the Lunch Money GUI.
API.
x-updatable: true
collapsed:
type: boolean
nullable: true
description: If `true`, the category is collapsed in the Lunch Money GUI.
While this property can be set via the API it is generally set by the user in the Lunch Money GUI.
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: If set, updates the archived timestamp for the category.
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. (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
# 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 created 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 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
description: If set, an optional account subtype. Examples include
-
retirement - checking - savings - prepaid credit card
minLength: 1
maxLength: 100
x-updatable: true
balance:
oneOf:
- type: number
format: double
- type: string
pattern: ^-?\d+(\.\d{1,4})?$
example: "195.50"
description: Numeric value of the current balance, up to four decimal places, of
the manual account as a number or string. Do not include any special
characters aside from a decimal point.
x-updatable: true
currency:
description: If set, the new three-letter lowercase currency code of the manual account
balance.
x-updatable: true
allOf:
- $ref: "#/components/schemas/currencyEnum"
balance_as_of:
type: string
oneOf:
- format: date-time
- format: date
description: "A new date for the `updated_at` property.
May be set as a date, ie: YYYY-MM-DD, or date-time string in ISO 8601 extended format.
This property is ignored if `balance` is not 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, the status of the manual account. If set to `closed`, the `closed_on_date` date 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 created 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 web 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
# 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, represents 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. **Can it be assigned via the
API**
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 category. 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 category. 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, will indicate if this category is archived.
x-updatable: true
id:
type: integer
format: int32
description: System-defined unique identifier for the category. 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 transaction
date:
type: string
format: date
description: Date of transaction 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 GUI.
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 GUI.
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 GUI.
external_id:
type: string
nullable: true
description: A user-defined external ID for any transaction that was added via
csv import, `POST /transactions` API call, or manually added via the
Lunch Money GUI. No external ID exists for transactions associated
with synced accounts, and they cannot be added. For transactions
associated with manual accounts, the external ID must be unique as
attempts to add a subsequent transaction with the same external_id
and manual_account_id will be flagged as duplicates and fail.
minLength: 0
maxLength: 75
tag_ids:
type: array
nullable: false
description: A list of tag_ids for the tags associated with this transaction. If
the transaction has no tags this will be an empty list.
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 GUI.
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: Is set if this transaction is part of a group. Denotes the ID of
the grouped transaction this is now 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 Transactions.
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 transaction
date:
type: string
format: date
description: Date of transaction 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 GUI.
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 GUI.
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: Is set if this transaction is part of a group. Denotes the ID of
the grouped transaction this is now 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 GUI.
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 GUI.
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 for any transaction that was added via
csv import, `POST /transactions` API call, or manually added via the
Lunch Money GUI. No external ID exists for transactions associated
with synced accounts, and they cannot be added. For transactions
associated with manual accounts, the external ID must be unique as
attempts to add a subsequent transaction with the same external_id
and manual_account_id will be flagged as duplicates and fail.
minLength: 0
maxLength: 75
plaid_metadata:
type: object
nullable: true
description: If requested, the transaction's plaid_metadata that came when this
transaction was obtained. This will be a json object, but the schema
is variable. This will only be present for transactions associated
with a plaid account.
custom_metadata:
type: object
nullable: true
description: If requested, the transaction's custom_metadata that was included
when the transaction was inserted via the API. This will be a json
object, but the schema is variable.
files:
type: array
nullable: false
description: A list of objects that describe any attachments to the transaction
items:
$ref: "#/components/schemas/transactionAttachmentObject"
required:
- id
- date
- amount
- currency
- to_base
- recurring_id
- payee
- category_id
- notes
- status
- is_pending
- created_at
- updated_at
- split_parent_id
- is_group_parent
- group_parent_id
- manual_account_id
- plaid_account_id
- tag_ids
- source
- external_id
# The request object for a POST /transactions request
# It contains only user settable properties.
insertTransactionObject:
type: object
x-internal: true
additionalProperties: false
properties:
date:
type: string
format: date
description: Date of transaction in ISO 8601 format
amount:
oneOf:
- type: number
format: double
- type: string
pattern: ^-?\d+(\.\d{1,4})?$
description: Numeric value of amount without currency symbol. i.e. $4.25 should be denoted 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://alpha.lunchmoney.dev/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 transactions. 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 GUI.
manual_account_id:
type: integer
format: int32
nullable: true
description: The Unique identifier for the associated manually managed 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 GUI. It is an
error if this, and `plaid_account_id` is also set on the same
transaction.
plaid_account_id:
type: integer
format: int32
nullable: true
description: The Unique identifier for the associated plaid synced 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 GUI. It is an
error if this, and `manual_account_id` is also 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: Date of transaction in ISO 8601 format
x-updatable: true
amount:
oneOf:
- type: number
format: double
- type: string
pattern: ^-?\d+(\.\d{1,4})?$
description: Numeric value of amount without currency symbol. i.e. $4.25 should be denoted 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.
x-updatable: true
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 to another account
will not work if the transaction belongs to a synced account who's
"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 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 that exists when a transaction has
been split or if the transaction is a group. Split
x-updatable: false
and Grouped transactions may not be modified using this API. Ignored if set.
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
maxLength: 140
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 of the transaction in the request body's transactions
array that was skipped.
existing_transaction_id:
type: integer
format: int64
description: The id of the existing transactions that the requested transaction
duplicates.
request_transaction:
type: object
description: The requested transaction that was skipped.
allOf:
- $ref: "#/components/schemas/insertTransactionObject"
# The object returned from a successful POST /transactions request
insertTransactionsResponseObject:
type: object
x-internal: true
additionalProperties: false
description: The object returned from a successful POST /transactions request
properties:
transactions:
description: An array of the inserted transactions.
items:
$ref: "#/components/schemas/transactionObject"
type: array
skipped_duplicates:
description: An array of the requested transactions that were duplicates of
existing transactions and were not inserted.
items:
$ref: "#/components/schemas/skippedExistingExternalIdObject"
type: array
required:
- transactions
- skipped_duplicates
# The object containing information about a file attached to a transaction
transactionAttachmentObject:
type: object
title: transaction attachment object
additionalProperties: false
# description: An object containing information about a file attached to a transaction
properties:
id:
type: integer
format: int32
description: The unique identifier of the attachment
uploaded_by:
type: integer
format: int64
description: The id of the user who uploaded the attachment
name:
type: string
description: The name of the file
type:
type: string
description: The MIME type of the file
size:
type: integer
description: The size of the file in kilobytes
notes:
type: string
nullable: true
description: Optional notes about the attachment
created_at:
type: string
format: date-time
description: The date and time when the attachment was created in ISO 8601 format
# Object that describes a budget's amount, category and start_date
budgetObject:
type: object
title: budget object
additionalProperties: false
description: "A budget object represents a budgeted amount for a specific category and budget period. Each budget entry is tied to a specific time period defined by its `start_date`. The budget object includes information about the budget amount, currency, period settings, and how future periods will be automatically calculated."
properties:
id:
type: integer
format: int64
description: System created unique identifier for the budget entry.
category_id:
type: integer
format: int32
description: The ID of the category this budget applies to.
amount:
type: number
format: double
description: The budgeted amount for this period.
currency:
allOf:
- $ref: "#/components/schemas/currencyEnum"
description: The currency of the budgeted amount in ISO 4217 format.
start_date:
type: string
format: date
description: The start date of the budget period in ISO 8601 format (YYYY-MM-DD). This represents the beginning of the period for which this budget applies.
next_start_date:
type: string
format: date
readOnly: true
description: The calculated start date of the next budget period based on the category's period settings (granularity, quantity, and anchor_date). This is useful for determining when the next budget period begins.
notes:
type: string
nullable: true
description: Optional notes associated with this budget period.
auto_budget_type:
type: string
readOnly: true
enum:
- nothing
- fixed
- spend
- budget
description: "The budget preset type that determines how future periods will be automatically calculated. `nothing` means no automatic calculation (budgets must be set manually for each period). `fixed` uses a fixed amount for all future periods. `spend` uses the previous period's spending amount. `budget` uses the previous period's budgeted amount."
auto_budget_amount:
type: number
format: double
nullable: true
readOnly: true
description: "If `auto_budget_type` is `fixed`, this is the fixed amount that will be used for future periods."
auto_budget_currency:
allOf:
- $ref: "#/components/schemas/currencyEnum"
nullable: true
readOnly: true
description: "If `auto_budget_type` is `fixed`, this is the currency of the fixed amount."
rollover_option:
type: string
nullable: true
readOnly: true
enum:
- same category
- available funds
description: "The rollover setting for this category. `same category` means unspent funds roll over to the next period for this category. `available funds` means unspent funds are added to the available funds pool. `null` means rollover is disabled."
granularity:
type: string
readOnly: true
enum:
- month
- week
- twice a month
description: "The granularity of the budget period (e.g., monthly, weekly, twice a month). This is determined by the category's custom budget settings or the account's default budget period settings."
quantity:
type: integer
format: int32
readOnly: true
description: "The quantity of granularity units that make up each budget period. For example, if granularity is `week` and quantity is `2`, each budget period is 2 weeks."
is_group:
type: boolean
readOnly: true
description: "Whether the category is a category group. Category groups can have their own budgets that apply to all subcategories, or subcategories can have individual budgets."
group_id:
type: integer
format: int32
nullable: true
readOnly: true
description: "If this budget is for a subcategory, this is the ID of the parent category group. `null` if this is not a subcategory."
created_at:
type: string
format: date-time
description: The date and time when this budget entry was created (in ISO 8601 extended format).
updated_at:
type: string
format: date-time
description: The date and time when this budget entry was last updated (in ISO 8601 extended format).
required:
- id
- category_id
- amount
- currency
- start_date
- next_start_date
- auto_budget_type
- granularity
- quantity
- is_group
- created_at
- updated_at
# Request body for PUT /budgets (upsert)
upsertBudgetRequestObject:
x-internal: true
type: object
additionalProperties: false
properties:
start_date:
type: string
format: date
description: Start date of the budget period in ISO 8601 date format (YYYY-MM-DD). Must be a valid budget period start for the account.
category_id:
type: integer
format: int32
description: Category ID for the budget
amount:
oneOf:
- type: number
format: double
- type: string
pattern: ^-?\d+(\.\d{1,4})?$
description: Budget amount. May be a string or a number in double format.
currency:
allOf:
- $ref: "#/components/schemas/currencyEnum"
description: Three-letter currency code. If omitted, the primary currency for the user's account is used.
notes:
type: string
nullable: true
description: Optional notes for the budget period
minLength: 0
maxLength: 350
required:
- start_date
- category_id
- amount
# Response body for PUT /budgets (200)
budgetUpsertResponseObject:
x-internal: true
type: object
properties:
category_id:
type: integer
format: int32
description: Category ID
start_date:
type: string
format: date
description: Start date of the budget period
amount:
type: string
description: Budget amount in the stored currency (string for consistency with other amount fields in the API)
currency:
type: string
description: Currency code for the budget
to_base:
type: number
format: float
description: Amount converted to the user's primary currency
notes:
type: string
nullable: true
description: Notes for the budget period
# Response body for GET /budgets/settings (200)
budgetSettingsResponseObject:
x-internal: true
type: object
additionalProperties: false
description: Budget period and display settings
properties:
budget_period_granularity:
type: string
enum:
- day
- week
- month
- year
- twice a month
description: Budget period granularity
budget_period_quantity:
type: number
format: double
description: The number of `granularity` units that make up a single budgeting period.
budget_period_anchor_date:
type: string
format: date
description: The date from which the budgeting period is calculated.
All future (and past) periods are derived by applying `quantity` × `granularity` forward and backward from this date.
budget_hide_no_activity:
type: boolean
default: false
description: The 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: The display preference for using the last day of the month as the period end for monthly periods
budget_income_option:
type: string
enum:
- max
- budgeted
- activity
description: Determines which income value is used as the base when calculating available funds for a budgeting period
budget_rollover_left_to_budget:
type: boolean
default: false
description: Determines whether the remaining unallocated funds (“Left to Budget”) at the end of a budgeting period are carried forward to the next period
required:
- budget_hide_no_activity
- budget_period_quantity
- budget_period_granularity
- budget_period_anchor_date
- budget_use_last_day_of_month
- budget_income_option
- budget_rollover_left_to_budget
# Summary endpoint response schemas
summaryResponseObject:
type: object
title: summary object
additionalProperties: false
description: Budget summary for the requested range
properties:
aligned:
type: boolean
description: "`true` if start_date and end_date are aligned with the user's budget period setting; `false` otherwise.
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 un-categorized transactions type: number uncategorized_count: description: Number of un-categorized transactions for the given date range type: integer uncategorized_recurring: description: "Total amount, in the user's default currency, of recurring activity coming from un-categorized 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"
rollover_pool:
$ref: "#/components/schemas/summaryRolloverPoolObject"
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 budgets 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 which is aligned with 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. I don't think we will expose this in the summary since it's gettable by querying the recurring_id"
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 will 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: An 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.
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
# - `xau`: Gold
# - `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. operationId: getMe parameters: [] responses: "200": description: The User Object associated with the authorized token. content: application/json: schema: $ref: "#/components/schemas/userObject" example: name: User 1 email: user-1@lunchmoney.dev id: 18328 account_id: 18221 budget_name: \U0001F3E0 Family budget primary_currency: usd api_key_label: Side project dev key "401": $ref: "#/components/responses/unauthorizedToken" "429": $ref: "#/components/responses/rateLimited" "500": $ref: "#/components/responses/serverError" /summary: get: tags: - summary summary: Get summary description: Retrieves a summary of the user's budget. Use this endpoint to access budget configuration details and performance for a specified date range.
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
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"
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
"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 existing 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 a 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,
children categories for a category group, categorized recurring items,
etc. If there are dependents, this endpoint will return an object that
describes the amount 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 Entity
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"
/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: Denotes 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: "Denotes the end of the time period you'd like to get 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 `limit` number of transactions.
operationId: getAllTransactions
parameters:
- name: start_date
in: query
schema:
type: string
format: date
description: Denotes 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: "Denotes the end of the time period you'd like to get 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 GUI.
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 GUI.
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 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
un-categorized 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 a tag with 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 transactions
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 transactions objects to include any 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
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://alpha.lunchmoney.dev/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://alpha.lunchmoney.dev/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://alpha.lunchmoney.dev/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 `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
maxLength: 140
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: Category or Category Group 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 transaction 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` param 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 Entity
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: Get info about the recurring items for a specified time frame
operationId: getAllRecurring
parameters:
- name: start_date
in: query
schema:
type: string
format: date
description: Denotes 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: "Denotes 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 tag 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: Denotes 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: "Denotes the end of the range used to populate the `matching`
object in the recurring items. Required if start_date exists. "
responses:
"200":
description: Tag Object with the requested Tag 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 tag with the id:'543210'
"429":
$ref: "#/components/responses/rateLimited"
"500":
$ref: "#/components/responses/serverError"
/budgets/settings:
get:
tags:
- budgets
summary: Get budget settings
description: Returns the budget-related settings for the user's account.
operationId: getBudgetSettings
responses:
"200":
description: Budget settings for the account
content:
application/json:
schema:
$ref: "#/components/schemas/budgetSettingsResponseObject"
"401":
$ref: "#/components/responses/unauthorizedToken"
"429":
$ref: "#/components/responses/rateLimited"
"500":
$ref: "#/components/responses/serverError"
/budgets:
put:
tags:
- budgets
summary: Upsert budget
description: |-
Create or update a budget for a category and period.
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 account's budget settings.
To view existing budgets details 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 existing budgets details 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: []