The Lunch Money API spec uses a modified version of SEMVER for its versioning methodology as follows.
The major version is the API version. This will always be 2 for the v2 version of the API.
The minor version represents the number of main endpoints the current version of the spec supports. For example, a version of the API that supports the /me, /categories, and /transactions endpoints would have a minor version of 3.
The revision number represents the number of updates since the last endpoint was added. For example, each time changes are made to one of the existing three APIs as described above, the revision number will be bumped.
v2.11.0 - TBD
Add GET /balance_history
Add GET /balance_history/{account_type}/{account_id}
Add GET /balance_history/crypto_synced/{account_id}/{symbol}
Add PUT /balance_history/{account_type}/{account_id}
Add PUT /balance_history/crypto_synced/{account_id}/{symbol}
Add PUT /balance_history/deleted/{account_id}/details
Remove rollover_pool from the category object returned in the summary response. It is in the main summary response.
v2.10.0 - TBD
Add v2 crypto endpoints which support:
Discovering the currently supported currencies for manually managed crypto assets
Managing the complete lifecycle of manually managed crypto assets (create, read, update, delete)
Viewing the balances for currencies associated with both manually managed crypto assets and those that are synced via a synced crypto account (ie: coinbase, kraken, ethereum wallet)
Refreshing synced crypto account balances
v2.9.3 - Apr 27, 2026
Add xag and xau to the supported currency codes.
v2.9.2 - Apr 22, 2026
Increase allowable length for a transaction payee
v2.9.1 - Apr 22, 2026
You may now set archived_at when modifying a category or tag via the PUT /categories or PUT /tags endpoints.
v2.9.0 - Feb 26, 2026
Add initial /budgets endpoint support:
GET /budgets/settings for account budget settings
PUT /budgets to create or update budget amounts
DELETE /budgets to remove budget amounts
Updates the GET /summary endpoint to return an occurrences array for both aligned and non-aligned summary responses when include_occurrences=true.
It can be useful to inspect the start_date and end_date of occurrences in a non-aligned response for use in subsequent requests to get an aligned response, which will include complete budget information.
Add support for setting tag_ids on child transactions in POST /transactions/split/{id}.
v2.8.5 - Feb 2, 2026
Add plaid_item_id and linked_by_name properties to the Plaid Account Object
Expand Plaid Account Object status enum to include closed, revoked, and deactivated
Restore the v1 original_name property to the v2 Transaction Object
The collapsed property on the childCategoryObject is no longer nullable and is always set to false.
Add status and created_by_name properties to the Manual Account Object
BREAKING CHANGE
It was possible to 'close' a manual account simply by setting the closed_on property in a PUT or POST request. Now status must also be set to closed.
v2.8.4 - Jan 16, 2026
Add new created_since and updated_since query parameters to the GET /transactions endpoint.
Add a new include_group_children query parameter to the GET /transactions endpoint.
Add new include_rollover_pool and include_past_budget_dates query params to the GET /summary endpoint.
Add to_base to the allowed properties in the updateManualAccountObject. This is tolerated but ignored (matches behavior in updateTransactionObject)
New x-updatable attributes have been added to the properties of the update objects to more clearly describe which system defined properties are tolerated but ignored.
BREAKING CHANGES
Renamed several properties in the transaction object:
is_parent -> is_split_parent
parent_id -> split_parent_id
is_group -> is_group_parent
group_id -> group_parent_id
Renamed a query parameter on the GET /transactions endpoint
is_group -> is_group_parent
Renamed a property in the occurrences object returned by the GET /summary endpoint
current -> in_range
v2.8.3 - Dec 23, 2025
The default for the GET /transactions query parameter limit has been changed from 100 to 1000. The max for this parameter is now 2000.
Added new guides covering pagination and supported currencies.
v2.8.2 - Nov 26, 2025
The category object now includes both an order and collapsed property. These properties are used by GUIs that display a list of categories.
The DELETE /manual_accounts endpoint now supports two optional query parameters:
delete_items (boolean, default: false): When set to true, also deletes transactions, rules, and recurring items associated with the account
delete_balance_history (boolean, default: false): When set to true, deletes balance history associated with the account
v2.8.1 - Nov 14, 2025
Removed debits_as_negative from the userObject
For api users, positive values always indicate a debit transaction, and negative values indicate a credit transaction.
Added background_color and text_color to the tagObject
Added to_base to the recurring_item.transaction_criteria object
POST /transactions/{transaction_id}/attachments now returns 201 Created instead of 200 OK
Updated example responses to align with the current implementation
Error response formats, metadata field names, and error messages have been standardized across all endpoints
v2.8.0
A new v2/summary endpoint has been added. This replaces the v1/budgets endpoint, which no longer works with the new budgeting feature.
The 'pending' value for status in the transactions object has been deprecated. This was redundant with the is_pending boolean property.
A new is_pending query parameter has been added to the GET /transactions endpoint.
POST /transactions/split/{id} and POST /transactions/group now return a single transaction with children and not an array of transactions.
A custom_metadata property has been added to the Manual Account object.
The maximum length of the Manual Account's subtype property has increased from 75 to 100 characters.
An empty description string may now be passed in the request body for the POST and PUT /categories endpoint
v2.7.11
Added new endpoints for managing transaction file attachments:
POST /transactions/{transaction_id}/attachments - Upload a file to be attached to a transaction
GET /transactions/attachments/{file_id} - Get a signed URL to download the file attachment
DELETE /transactions/attachments/{file_id} - Remove a file attachment from a transaction
Added support for file attachments in transaction objects:
The files property is now included in transaction objects when include_files is set to true
The files property contains an array of transactionAttachmentObject objects
File metadata (type and name) is properly returned when downloading files
The v2 /recurring endpoint has been renamed back to /recurring_items.
The overrides property has been removed from the transaction object. This ws meant to provide the original info that was overridden by a recurring rule, but turned out to be un-implementable.
The bulk PUT /transactions API has been completely redesigned. It now is similar to the POST /transactions API, taking an array of transactions which must include an id along with any other properties to do be updated.
The payee/date/amount transaction duplication logic that is triggered by the skip_duplicates request body property on a POST /transactions request will now be applied to plaid accounts as well as manual accounts.
Improved readability of Request validation errors. The example responses in the spec and those returned by the mock server have been updated to match those that will be returned by the actual implementation of the v2 API.
The v2 proxy using v1 service has been removed from the spec.
v2.7.10
Add a transactionAttachments type that captures details about files attached to a transaction.
Modified the behavior of the GET /transactions endpoint:
For performance reasons, transactions returned by this endpoint will, by default, not include plaid_metadata, custom_metadata, children, or files properties. These properties ARE provided by default in the GET /transactions/:id endpoint.
A new include_children query parameter has been added. If set to true, transaction groups will include a children property with an array of transactions that make up the group.
A new include_metadata query parameter has been added. If set to true, transactions returned will include the properties plaid_metadata and custom_metadata, which will be null when metadata is not associated with the transaction.
An include_files query parameter is added. When set to true, a files property is returned with an array of objects that describe any attachments to the transaction.
For completeness, an include_split_parents query parameter is added. Will override default behavior and return transactions that were split when set. The split transactions are also returned. When used in conjunction with the include_children parameter, split parents will have a children property that also includes the split transactions.
Documented that include_pending query param is ignored if status query param is also set.
Modified the behavior of the GET /transactions/:id endpoint:
A successful response will always include all available transaction details, including plaid_metadata, custom_metadata, and files properties.
When is_group or is_parent is true in the response, it will also include a children property.
Modified the response body returned from a successful POST /transactions request:
A skipped_duplicates array property will always be returned along with the transactions array.
This will include details on any requested transactions that were not inserted due to duplicate detection.
Duplicates will always be flagged if the manual_account_id and external_id of a requested transaction match existing transactions.
Duplicates may also be flagged if the skip_duplicates request body property was set to true, and the requested transaction has the same manual_account_id, payee, date, and amount of an existing transaction.
The insertTransactionResponseObject is now included in the models section of the documentation.
Updated the examples for the PUT /transactions (bulk) endpoint
Increased the max length of the subtype string that can be set on a manual account object to 75 characters
v2.7.9
Updated several type definitions in the spec to use the type integer instead of number for properties such as ids, orders, and indexes which are always an integer. Amounts, balances and limits still use type number.
v2.7.8
The request body for a PUT /tags request will now accept, and ignore, system set tag object properties such as id and created_at.
Response codes for the POST /plaid_accounts/fetch endpoint have changed:
A successful fetch request will return a 202 ACCEPTED status with no response body.
A fetch request made within one minute of a previous fetch request will return a 425 TOO EARLY response.
Setting the query param category_id to 0 on a GET /transactions request will now return un-categorized transactions.
The to_base property of the transaction_criteria object in the recurringObject returned by the GET /recurring API has been removed. This property as this is not used to match transactions to a recurring item.
v2.7.7
The ability to set the order property of a category via the API has been removed.
Setting order in the body of a POST /categories request will result in a validation error.
The value of order in the body of PUT /categories request is treated as a "system defined" property and is ignored.
This release makes some non-functional changes to the spec to make it behave better with programmatic consumers (ie: type and sdk generators).
The transactionObject's children array now has a defined items type.
There is no default value for the children property in the request body schema for a POST or PUT /categories request. If this property is not explicitly set it is treated as if it does not exist.
The GET /categories optional is_group query parameter is now defined a boolean instead of an enum of true and false
The Models section of the documentation has been slightly changed as follows
We are now consistently showing only the primary Object for each endpoint. Schemas for request bodies are not shown in this section but remain in the individual endpoint's documentation.
Renamed the AccountTypeEnum to accountTypeEnum to maintain consistency in schema naming style
v2.7.6
This release adds the to_base property to the Manual and Plaid Account objects to align with a recent change in the v1 API.
v2.7.5
This release adds the following new transactions endpoints:
PUT /transactions/:id
This works similarly to the same endpoint in v1.
PUT /transactions
This new endpoint enables updating multiple existing transactions with a common update object.
This release modifies the following endpoint behavior
POST/PUT /categories
It is now permissible to specify the ids of categories that belong to another category group in the children property of a request. The categories will be moved to the group being created or updated without error.
It is also now permissible to include strings in the children property. These will be used as the names of new child categories that will be created.
This release also updates the following schemas:
Correctly specifies that all properties of the manualAccountObject are required
Updates the updateManualAccountObject and updatePlaidManualAccountObject to allow the balance property to be either a string or a number.
Updates the userObject to include the debits_as_negative property. The documentation for Transaction Objects returned by GET requests have been updated to reflect how/if this setting affects the amount property of the transaction.
Updates the childCategoryObject to restore the exclude_from_budget, exclude_from_totals and is_income properties. These properties are inherited from the Category Group and not settable but are provided for convenience.
v2.7.4
This release adds the following new transactions endpoints:
POST /transactions/group/
This works similarly to the same endpoint in v1. Use this endpoint to group a set of transactions into a single transaction.
DELETE /transactions/group/{id}
This endpoint replaces the v1 /transactions/ungroup endpoint.
Use this endpoint to delete a transaction group and restore, the grouped transactions to their "normal" transaction state.
DELETE /transactions/split
This endpoint replaces the v1 /transactions/unsplit endpoint and the v2 version that was introduced in the previous release.
Use this endpoint to delete the split transaction and restore the parent transaction to the "normal" transaction state.
The documentation for the various /transactions endpoints has been reorganized:
The transactions section covers endpoints that impact a single transaction.
The transactions (bulk) section covers endpoints that impact multiple transactions.
The transactions (group) section covers endpoints related to grouping and ungrouping transactions.
The transactions (split) section covers endpoints related to splitting and unsplitting transactions.
v2.7.3
This release adds the following new transactions endpoints:
POST /transactions/split/{id}
This is a new endpoint in v2. Use this endpoint to a split a transaction into multiple child transactions. The POST /transactions endpoint will no longer support splits
POST /transactions/unsplit
This has only minor changes from the existing v1 version of this API
DELETE /transactions/{id}
This new endpoint will delete a single transaction by ID
DELETE /transactions
This new endpoint will bulk delete all the transactions who's IDs were submitted in the ids property in the request body.
Both DELETE endpoints will generate errors if the IDs submitted belong to group or split transactions or do not exist.
Changes to existing endpoints:
It is now permissible to set a plaid_account_id on a transaction passed in to POST /transactions.
The following objects have been modified:
The Plaid Account Object
A new boolean allow_transaction_modifications property has been added. This represents the state of the "Allow Modifications To Transactions" toggle which is enabled by default. When this property is false, attempts to add transactions to this account will fail.
v2.7.2
The following objects have been modified:
The Transactions Object
An optional custom_metadata object has been added. This can be set or modified via the API.
This release adds the following to the /transactions endpoint
POST /transactions
Properties in the transaction object passed in the request have been updated to new v2 naming standards
A new custom_metadata may be included as a property on the new transaction objects. This can be any valid JSON object.
The debit_as_negative property on the request body is no longer supported
Requests that contain transactions with external_ids behave differently
Duplicate external_ids within the request body are treated as an error
Requested transactions with an external_id that already exists in the database are now skipped. Any remaining transactions in the request are inserted.
The following endpoints have been modified:
GET /transactions/{id}
The include_plaid_metadata parameter name has changed back to include_metadata and will now return both plaid and custom metadata.
Tests
Tests now require Portman version 1.30.7 or later.
A new script check-for-duplicates.sh was added to the tests/scripts directory. When the newman output is redirected to a file, this script can identify tests that were skipped.
v2.7.1
This release updates the sample responses for the /recurring endpoints
v2.7.0
This release adds the initial version of the /plaid_accounts endpoint
Updated changelog to mention the renamed /manual_accounts endpoints
Minor update to the Manual Account Object Schema
A new external_id property was added which can be set via the POST and PUT /manual_transactions endpoints
Minor update to the GET /categories endpoint
A new query optional parameter is_group can be set to false in order to get the API to return only a set of assignable categories.
v2.6.0
This release adds the initial version of the /manual_accounts endpoint
v2.5.0
This release adds the initial version of the /recurring endpoint
A minor update was made to the response body of a DELETE /categories requests
The category_name property has been removed from the dependents object and is now returned as a top-level property in the response body.
Made the static mock server the default server
v1 proxy is still available in the servers drop down.
The links in the changelogs work with Stoplight but not Scalar, so having this as the default makes it more likely that users will be able to navigate the changelogs.
v2.4.1
This release makes minor changes to the existing categories and tags endpoints
Tags Object
The properties created_at, updated_at, and archived_at have been added
DELETE /tags endpoint
Will now return a 422 with a dependents object if the tag is used in rules or transactions
Will now support a force query param
v2.4.0
This release adds the initial version of the /tags endpoint
v2.3.7
This release makes minor changes to the existing categories and transactions endpoints
Categories Object
The group_name property has been removed
Transactions Object
Restores the property name plaid_metadata. This anticipates a new user_metatdata property in a future release.
GET /categories endpoint
The is_group query parameter has been removed
GET /transactions/{id} endpoint
Renamed include_metadata to include_plaid_metadata
Added split as a new value for the source enum. It's set for split transactions.
It also corrects typos in the names of the servers listed in the spec
The tests in this release require a version of Portman at or above 1.30.2
v2.3.6
This release restores the hydration of children for category and transaction objects
Categories Object
The child_ids property of the category object is renamed children and is populated by fully hydrated category objects
The children property will always be present for a category group.
If the group has no child categories, children will be an empty list.
Objects in the children list property are Child Category Objects that are similar to Category Objects, but with some differences:
is_income, exclude_from_budget, and exclude_from_totals are not included since these are inherited from the category group and are no longer properties of the child categories.
group_id is never null, group_name is always present, and children will never be present.
GET /categories endpoint
When format is set to flattened all categories and category groups are returned in the top level list
Category groups will still have their children property
This is done to conform to a policy that objects should have the same properties consistently across requests
Since categories that belong to category groups are represented in the children property of their category group and also in the top level these categories can be found twice in the flattened response.
Top-level categories that happen to belong to a category group are still full Category Objects and not Child Category Objects.
This means they will have the is_income, exclude_from_budget and exclude_from_totals, properties.
The format query param now has a default value of nested, which means that a nested list of category objects is returned by default.
This approach is preferred since the flattened list has redundant info with each grouped category represented once in the children attribute of its category croup and then once in its own spot in the top-level list
An is_group query parameter has been added to the GET /categories method.
This can be set to false to return a list of assignable categories. No Category Groups are returned.
Setting it to true will return a list of Category Groups, with fully hydrated children objects. No ungrouped categories are returned.
When this query param is set, the value of the format query param is ignored if also set.
POST and PUT /categories endpoints
The request body for the POST and PUT /categories may now include a children property.
This property is a list which may contain category objects, child category objects, or simply ids.
Mixing the types of allowed elements in the children property of the request body is permitted.
A successful response body will always include the fully hydrated Child Category Objects in the children property.
v2.3.5
This branch adds a second demonstration server to the spec. The first server is a traditional "mock data" server that uses static canned data. The new server implements the V2 API on top of the V1 API and can be used to manipulate actual data in Lunch Money. This initial version supports only the /categories endpoint. Requests to other endpoints continue to use canned data
Spec Updates
The spec now includes two servers in the servers section
The synced_metadata property of the transaction object was renamed metadata in anticipation of metadata availability in imported transactions associated with manual accounts.
Test Updates
A large number of new tests were added in the tests/configs/variations/category-variations.yaml. With a real backend, we can do more testing of the POST, PUT, and DELETE endpoints. Many of these tests are skipped if the postman variable isMockServer is set to true. (See Test README)
Tests work with Portman version 1.30.0. This release addresses reported bugs and supports tests that set form encoded query params like the ids param on the GET /categories endpoint.
Commit Hook Updates
The commit hook that toggles URLs in index.html and the spec between the local and deploy URLs was updated to support two separate URLs
v2.3.4
This branch removes hydration options from the /categories and /transaction endpoints and objects.
Renamed the children property of the category object to children to match the new agreed upon standard for naming types and id lists.
Eliminated the two types of category objects, opting instead for a simpler single category object. This eliminates some of the automatic request body validation that we had but I think simplifies the docs. Additional tests were added to ensure that
Category Groups have a child_id and no group_name property and group_id is null
Categories that are part of a group have no child_id property, have a non null group_id property and have a group_name property.
Ungrouped categories have a group_id with a value of null and do no have a children or group_name property
Renamed transaction status values "cleared" and "uncleared" to "reviewed" and "unreviewed"
Created a visual representation of the changes to the objects in changelog-visual.html
Continued iteration on the recurring_items object.
This version include an updated schema for the recurringItems object
It also proposes an alternateRecurringItems object
v2.3.3
This branch introduces the GET /transactions/{id} endpoint. As of this release this is the only endpoint that supports hydration of the category, account, recurring items and tags. Hydration is enabled via query parameter. There is also a query parameter to request synced (plaid) metadata for the transaction.
The branch also introduces changes to the transaction object:
A new overrides object property is added to the transaction object. This object is populated when a recurring rule has overridden one or more properties of the transaction as displayed in the transactions page on the GUI.
The payee, category_id, and notes properties will now have values that match the transactions page in the GUI. The display_* properties of the transaction object have been removed. The original values can now be found in the new overrides object.
The order of the properties in the transaction object schema is changed to introduce the new overrides property before any properties that may have been overridden. The ordering should now more closely match the transaction page on the GUI.
The children property that exists in a transaction that has been split has been renamed children
The transaction object now supports the optional properties: synced_metadata, hydrated_recurring, hydrated_category, hydrated_account, and hydrated_tags
A set of required properties has been added to the transaction object's schema definition
Schema definitions have been added for the manualAccountObject, syncedAccountObject and recurringItemObject in order to support hydration
Tests were added
Filter transactions by category group
GET /transactions/{id} tests
Updates to /categories tests
Tests work with Portman version 1.28.0. A known bug with this version of portman requires that one of the /me variation tests is commented out
v2.3.2
This branch updates the tests to take advantage of bug fixes and features added to Portman 1.28.0
Projects that implement the Lunch Money API server should update to this version of Portman
The portman config now sets a global directive variableCasing to snakeCase. Use of this directive in prior versions caused some tests to fail
The tests now have a global dynamic pre-request script that is run prior to any requests that take an ID as a path parameter. This script will "reset" the variable that the ID is set to when PORTMAN_IS_MOCK_SERVICE=true is set in the .env-portman file. Implementers of a Mock API server should see further details on how to define the "canned" IDs to use in the ./tests/README.md
Tests added as part of this release
/me
Validate proper error response when no Authorization header is sent
/transactions
validate setting manual_account_ids to zero will filter out all manual account transactions
validate setting plaid_account_ids to zero will filter out all synced account transactions
validate setting both to zero will return on "cash transactions"
v2.3.1
This is the initial branch using the versioning described above
It is the v2 version of the API - hence the major version 2.
The API Spec currently supports 3 endpoints /me, /categories, and /transactions. hence the minor version 3.
This version of the spec contains minor modifications to the previously published spec and therefore has a revision number 1