# Truenote: the whole site
> Your finances, readable by any AI.
---
# Truenote
> Your finances, readable by any AI. Your accounts and the context behind them, in one place you own, for whatever AI you bring. Read-only to your banks.
Canonical: https://usetruenote.com/
Truenote gathers your bank, card, loan and brokerage accounts (through Plaid, read-only) and keeps them next to the things an account can't say: a spending plan, savings buckets, goals, each income source and what to set aside for taxes, which business a charge belongs to, notes and plans. Claude, ChatGPT, Claude Code or your own scripts read it over MCP and a REST API, each with a grant you can see, narrow and revoke, and every call leaves a receipt you can read.
It never moves money. Agents can only read what you allow and write Truenote's own records.
## What Truenote holds
- **Your accounts.** Bank, card, loan and brokerage accounts through Plaid. Balances every day, transactions as they post, holdings, and what you owe.
- **What an account can't tell.** A spending plan. Savings buckets on one account. Goals. Each income source and what to set aside for taxes. Which business a charge belongs to. Notes and plans.
- **Whatever AI you bring.** Claude, ChatGPT, Claude Code or a script of your own, over MCP (`https://app.usetruenote.com/mcp`) and a REST API (`https://app.usetruenote.com/v1`). Each gets a grant you set: what it may see, which accounts stay hidden, whether it may write.
## How it works
1. **Connect your accounts.** Sign in at your bank inside Plaid Link. Truenote gets read access and nothing else.
2. **Add the context.** Your plan, buckets, goals and income, typed in or written by your agent as you talk. Upload a paystub and the tax figures come from it.
3. **Connect an agent.** Paste one URL into Claude or ChatGPT, or run one command for Claude Code. Approve what it may see on a consent screen. New connections start read-only.
4. **Read the receipts.** Every call lands in your Activity log: which agent, what it asked, how many rows. Narrow or revoke any agent in one click.
## Things to ask
- "How much should I set aside for my January 15 estimated payment?"
- "Which bills hit in the next two weeks? Anything we pay for and don't use?"
- "Are we on track for six months of runway before the baby comes in March?"
- "How much is in the vacation bucket, and are we on pace for $8,000 by June?"
- "Will we get money back or owe this year? How much more should come out of each paycheck?"
- "From now on, put every Lowe's charge under Flamingo Pros."
## Truenote never moves money
- **Read-only, forever.** No endpoint that moves money exists in the code. Agents write only Truenote's own records.
- **Sealed tokens.** Plaid access tokens and your documents are sealed with AES-256-GCM, keys kept outside the database.
- **Grants you can see.** Each agent's scopes and hidden accounts are on one page. Revoking applies to its very next call.
- **Yours to take out.** Export everything as JSON or CSV. Delete the account and every bank is removed at Plaid too.
See [Security](/security.md).
## Price
One plan, everything included: $12 a month or $100 a year, with a 14-day free trial (card up front; it converts unless cancelled). See [Pricing](/pricing.md). Sign up at https://app.usetruenote.com/sign-in.
---
# Connect Claude to your bank accounts with Truenote
> Add Truenote as a custom connector in claude.ai, approve what Claude may see, and ask about your money in the Claude apps.
Canonical: https://usetruenote.com/connect/claude
## What Claude gets
Claude calls Truenote's tools: the overview, the spending plan and how the month compares, buckets, goals, recurring bills, holdings and what's owed, the yearly tax projection, and transactions filtered any way it likes. Answers are compact and pre-added, so Claude doesn't spend its context on raw rows unless it asks for them.
## When Claude wants to write
The first time Claude tries to save something (a plan line, a note, a rule, a bucket move), Truenote asks you to allow writing for that connection. Writes only touch Truenote's own records: nothing moves at your bank. Rows an agent wrote say so.
## Where the receipts are
Every call Claude makes is in Connected agents → Activity in Truenote: the tool, a summary of the arguments, the row count. Revoke there cuts the connector off on its next call.
## Things to ask
- "Which bills hit before next payday, and what's left after them?"
- "How much is in the vacation bucket, and are we on pace for June?"
- "Will we owe for the year? How much more should come out of each paycheck?"
- "Remember that we want to refinance below 5%, tagged mortgage." (asks to write)
---
# Getting started
> From sign-up to an agent reading your money: connect accounts, add context, connect Claude or ChatGPT, read the receipts.
Canonical: https://usetruenote.com/docs/getting-started
## 1. Make an account
Go to [app.usetruenote.com](https://app.usetruenote.com/sign-in) and type your email. A six-digit code signs you in and makes the account; the first 14 days are free. Save a passkey in Settings afterwards and you won't need codes again.
## 2. Connect your accounts
Accounts → **Connect an account** opens Plaid Link. Sign in at your bank there (Truenote never sees the login). Accounts appear within seconds; history imports over the next minute or so (Plaid sends about 30 days first, then the rest). A house, a car or anything Plaid can't reach goes in as a manual account with dated balances.
Accounts you never use are hidden after a sync so they stay out of totals; Settings → Hidden accounts shows them again.
## 3. Add the context
The welcome steps ask for the basics: who's in the household, each income source, one goal. Then:
- **Plan**: regular take-home and how it's split into groups and lines.
- **Buckets**: a virtual split of a savings account, each with a ledger and an optional target. Deposits are split by what each bucket is due; spending is charged by rules you approve in **Review**.
- **Context**: businesses (so their money is reported apart), categories and rules, notes, plans.
- **Taxes**: both W-2s, self-employed income, bonuses and estimated payments → the year's projection. Upload a paystub under **Documents** and its figures are offered as the inputs.
All of it can be written by an agent instead, once one is connected.
## 4. Connect an agent
Connected agents shows the MCP URL and the steps for each client:
- [Claude](/connect/claude): Settings → Connectors → Add custom connector.
- [ChatGPT](/connect/chatgpt): Settings → Apps → developer mode → Create app.
- [Claude Code](/connect/claude-code): `claude mcp add --transport http truenote https://app.usetruenote.com/mcp`.
- [Scripts](/connect/api): a personal access token and `/v1`.
A consent screen shows what the agent may see; you can hide accounts or a business from it. New connections start read-only. The first time an agent wants to write, it asks and you approve again.
## 5. Read the receipts
Connected agents → **Activity** lists every call: the agent, the tool, a summary of the arguments, the row count, refusals. **Revoke** cuts an agent off on its next call.
## Things to ask
See [Prompts that work well](/docs/prompts).
---
# Can I connect my bank accounts to ChatGPT?
> Yes, two ways: ChatGPT's own bank connection, which keeps what it learns inside ChatGPT, or a connector like Truenote that holds your accounts and context in one place any AI can read.
Canonical: https://usetruenote.com/guides/connect-bank-accounts-to-chatgpt
Yes. Since 2026 ChatGPT can read bank accounts through Plaid on its own, and it can also use apps you add, which is how Truenote connects. The difference is where your money's story lives afterwards.
## ChatGPT's own connection
Settings → Personal finance (names move around) walks you through Plaid Link. ChatGPT then sees balances and transactions and can answer "what did I spend on restaurants last month". What it learns stays in ChatGPT's memory, which means the next assistant you try starts from zero, and the context you explained in chat ("that deposit is 1099 income, set aside 30%") lives in a conversation, not in a record you can check.
## Through Truenote
Truenote holds the same accounts (through Plaid, read-only) next to the context an account can't tell: the spending plan, savings buckets on one account, goals, each income source and its tax set-aside, which business a charge belongs to, notes, plans and uploaded paystubs. ChatGPT connects to it as an app over MCP:
1. Settings → Apps → Advanced settings → developer mode.
2. Create app → name it Truenote → paste `https://app.usetruenote.com/mcp` → OAuth.
3. Truenote's consent screen: choose what ChatGPT may see (you can hide an account or a business), allow.
Then ask: "How is this month going against the plan?" or "What's left in the vacation bucket?" The full steps are at [Connect ChatGPT](/connect/chatgpt).
The same data is there for Claude, Claude Code and your own scripts, so switching assistants, or using two, doesn't mean starting over. Every call lands in an audit log you can read, and revoking an app takes one click.
## Is it safe?
The short version: your bank login never reaches ChatGPT or Truenote (you type it inside Plaid Link); Truenote seals the Plaid token before storing it; nothing can move money; and the agent sees only what its grant allows. The longer version is [Is it safe to connect your finances to an AI?](/guides/is-it-safe-to-connect-finances-to-ai) and the [security page](/security).
---
# How it works
> Connect your accounts through Plaid, add the context an account can't tell, connect Claude, ChatGPT, Claude Code or a script over MCP and an API, and read every call's receipt.
Canonical: https://usetruenote.com/how-it-works
Four steps, about ten minutes. Then any agent you bring knows your money the way you do.
## 1. Connect your accounts
Truenote reads banks through Plaid: checking, savings, credit cards, loans, mortgages and brokerage accounts, from most US institutions. You sign in at your bank inside Plaid Link; Truenote receives a read-only access token and seals it with AES-256-GCM before storing it. It asks Plaid only for balances, transactions, investments, liabilities and recurring payments. There is no transfer, payment or "auth" product in the integration, so nothing can move money.
Balances are snapshotted daily (net worth history comes from that). New transactions arrive by webhook within minutes of posting. Accounts you never use are hidden automatically after a sync; anything Plaid can't reach (a house, a car) goes in as a manual account with dated balances.
## 2. Add the context
An account can't tell an AI that a deposit is 1099 income with 30% to set aside, that a Lowe's charge was for a business, or that a baby is due in March. Truenote keeps that as structured rows:
- **The spending plan:** regular take-home split into groups (Expenses, Wants, Save and invest) with a share each, and lines with an amount and cadence.
- **Buckets:** a virtual split of one savings account (Emergencies, Vacations, the car), each with its own ledger and an optional target. Deposits are split by what each bucket is due; spending is charged to a bucket by rules you approved.
- **Goals, income sources, entities:** what you're saving for; each W-2 and 1099 source with its figures; the businesses whose money is reported apart from the household's.
- **Taxes:** a yearly federal projection from both W-2s, self-employed income, bonuses and estimated payments, with the extra withholding per paycheck that breaks even. Upload a paystub and the figures come from it.
- **Notes and plans:** dated facts and decisions, and scenarios an agent writes for you to review.
Every one of these has an agent tool too, so context can be added by talking.
## 3. Connect an agent
Truenote is an MCP server at `https://app.usetruenote.com/mcp` and a REST API under `https://app.usetruenote.com/v1`. Agents connect with OAuth 2.1 (discovered from the URL) or a personal access token.
- [Claude](/connect/claude.md): Settings → Connectors → Add custom connector, paste the URL.
- [ChatGPT](/connect/chatgpt.md): Settings → Apps → developer mode → Create app, paste the URL.
- [Claude Code](/connect/claude-code.md): `claude mcp add --transport http truenote https://app.usetruenote.com/mcp`.
- [Scripts and the API](/connect/api.md): a bearer token and an OpenAPI spec.
Each connection is a grant: which kinds of data it may read (accounts, transactions, investments, liabilities, context, documents), which accounts or businesses it must never see, and whether it may write. New connections start read-only; a write asks again.
## 4. Read the receipts
Every call is written to an append-only audit log before the agent gets its answer: the agent, the tool or route, a summary of what it asked, how many rows came back, and whether it was refused. Revoke cuts an agent off on its next call.
## What Truenote is not
- Not a chat app: no built-in AI; bring the one you already pay for.
- Not a way to move money: it can't pay, transfer or trade.
- Not advice: it reports and projects. See [Not advice](/legal/not-advice.md).
---
# Terms of service
> The agreement between you and Zachery Gentry LLC for using Truenote.
Canonical: https://usetruenote.com/legal/terms
These terms are between you and Zachery Gentry LLC ("Truenote", "we"), Austin, Texas. By making an account you agree to them.
## The service
Truenote gathers your financial accounts (through Plaid, read-only) and the context you add, and makes them available to the AI agents and scripts you authorize over MCP and an API. It never moves money, and it can't. It reports and projects; it does not give tax, legal, investment or financial advice ([Not advice](/legal/not-advice)).
## Your account
You must be 18 or older and give a real email address. Keep your passkeys and tokens to yourself; what happens under your account is yours. One person per account. Tell us at once if you think it's been compromised.
## What you may not do
Use Truenote for anything illegal; try to reach data that isn't yours; probe, overload or reverse-engineer the service beyond what the API allows; resell access; or connect accounts you aren't entitled to.
## Billing
The plan is $12 a month or $100 a year, in US dollars, through Stripe. The first 14 days are free; you enter a card up front and it is charged when the trial ends unless you cancel before then. We email a reminder three days before. Cancel any time in Settings → Billing; you keep access until the end of the period you paid for. Prices can change with 30 days' notice by email; a change never applies to a period you've already paid. Refunds for a period already started are at our discretion, except where the law requires them.
If a payment fails, we'll retry and tell you. After a grace period syncing stops, your banks are removed at Plaid, and your data is kept 30 days (export still works) and then deleted.
## Your data
It's yours. We hold it to run the service, as the [privacy policy](/legal/privacy) describes. You can export or delete it at any time. Agents you connect act under grants you approve; you're responsible for what you let them do, and we show you every call they make.
## Third parties
Bank connections depend on Plaid and on your institutions, which can fail, change or refuse at any time. Agents are provided by their makers under their own terms. We're not responsible for either.
## Availability and changes
We aim to keep Truenote up but don't promise it, and we can change or retire features. We'll announce API changes in the changelog; `/v1` changes are additive, with deprecations announced in advance.
## Termination
You can delete your account any time. We can suspend or close an account that breaks these terms, with notice where we can give it, and you'll be able to export your data first unless the law prevents it.
## Disclaimers and liability
Truenote is provided as is. We don't warrant that it's error-free or that any figure, projection or categorization is correct; check anything that matters before acting on it. To the extent the law allows, our total liability to you is what you paid us in the twelve months before the claim, and we aren't liable for indirect or consequential losses.
## Law
Texas law applies; disputes go to the state or federal courts in Travis County, Texas.
## Contact
hello@usetruenote.com
---
# Connect ChatGPT to your bank accounts with Truenote
> Add Truenote as an app in ChatGPT's developer mode, approve what it may see, and ask about your money with your own context behind it.
Canonical: https://usetruenote.com/connect/chatgpt
## Why not ChatGPT's own bank connection?
ChatGPT can read Plaid accounts on its own, but what it learns stays inside its chat. Truenote keeps the accounts *and* the context (the plan, buckets, income sources, which business a charge belongs to) in one place you own, so ChatGPT, Claude and a script all see the same picture, and you can switch assistants without starting over.
## When ChatGPT wants to write
The first time it tries to save something, Truenote asks you to allow writing for that connection. Writes only touch Truenote's own records; nothing moves at your bank.
## Where the receipts are
Connected agents → Activity in Truenote lists every call ChatGPT made. Revoke cuts it off on its next call.
---
# Is it safe to connect your finances to an AI?
> What actually happens to your bank login, your transactions and your context when you connect Claude or ChatGPT, what can go wrong, and what a careful setup looks like.
Canonical: https://usetruenote.com/guides/is-it-safe-to-connect-finances-to-ai
The honest answer is "it depends on what's between the AI and the bank". Three questions decide it.
## 1. Where does my bank login go?
With Plaid (what ChatGPT, Truenote and most finance apps use), you type your bank login into Plaid's own window. The app never sees it. The app receives an *access token* that can only read. Truenote seals that token with AES-256-GCM before it touches the database, keeps the keys outside the database, opens it only in memory right before a Plaid call, and never returns it through any endpoint, tool, export or log.
## 2. Can anything move money?
Ask the app directly, because it's a code question, not a policy one. Truenote's integration uses only Plaid's read products: transactions, balances, investments, liabilities, recurring. There is no transfer, payment or "auth for payments" endpoint anywhere in it, so an AI couldn't move money even if asked to.
What an AI *can* write in Truenote: the spending plan, buckets (a ledger inside Truenote; nothing moves at your bank), rules, goals, notes, plans, categories. Rows it writes say which agent wrote them.
## 3. What does the AI actually see, and can I prove it?
Here's where connections differ most. In Truenote each agent gets a *grant*: which kinds of data it may read (accounts, transactions, investments, liabilities, context, documents), which accounts or businesses it must never see, and whether it may write. Exclusions are applied inside the database query, totals included, so an agent hidden from the brokerage can't infer it from net worth. New connections start read-only.
And every call, allowed or refused, lands in an append-only audit log: the agent, the tool, a summary of what it asked, how many rows came back. If you ever wonder what Claude looked at, the answer is on one page. Revoke applies to the agent's very next call.
## What can still go wrong
- **Prompt injection.** A transaction description could carry instructions ("ignore previous instructions and…"). The agent might follow them, but it can only read what it's allowed and write Truenote's own records; you'd see the calls in the log and could undo the rows.
- **Leaky text.** A visible transaction can name a hidden account in its description ("TRANSFER TO SAV ...7730"). Truenote says so on the consent screen.
- **The AI provider's side.** Whatever an agent reads, it reads into its own context under its provider's terms. Truenote never sends data to a provider; the agent fetches it.
- **Your own device.** A stolen signed-in laptop is a stolen session. Passkeys and 14-day sessions help; so does signing out.
## A careful setup
1. Connect accounts read-only through Plaid. Hide the ones the AI has no business seeing.
2. Give each agent its own connection with only the scopes it needs. Keep writing off until you want it.
3. Read the Activity log the first week. It's quick, and it's how you learn what the assistant actually does with a question.
4. Revoke anything you stop using.
More detail: [Security](/security).
---
# Privacy policy
> What Truenote collects, why, who else touches it, how long it's kept, and how to take it out.
Canonical: https://usetruenote.com/legal/privacy
Truenote is made by Zachery Gentry LLC ("we"), Austin, Texas. This policy covers the app at app.usetruenote.com and this site. Plain words, because you should be able to read it.
## What we collect
- **Your account:** email address, a name if you give one, passkeys (public keys only), sessions.
- **Bank data, through Plaid:** accounts, balances, transactions, holdings, liabilities and recurring payments from the institutions you connect. We never see your bank login; you enter it inside Plaid Link. We receive a read-only access token, which we seal with AES-256-GCM before storing. We never store card numbers.
- **What you add:** your household profile, businesses, income sources, the spending plan, buckets, goals, notes, plans, rules, and documents you upload (paystubs, tax forms, statements), sealed the same way as tokens.
- **What your agents do:** an audit log of every tool call and API request made with a grant you issued (which agent, what it asked, how many rows, when), and the agents' names and metadata.
- **Technical data:** request logs (method, path, status, a request id), IP addresses for rate limits and the audit log, error reports (Sentry) scrubbed of tokens, bodies, cookies and bank text. On this site, cookie-free analytics (Cloudflare Web Analytics): pages and countries, no identifiers.
- **Billing:** handled by Stripe. We store your Stripe customer id and subscription state, never your card.
## Why
To run the service you asked for: sync your accounts, keep your context, answer your agents within the grants you set, bill you, sign you in, keep the service secure, and fix what breaks. We don't profile you, sell data, or use your data to train anything.
## AI providers
Truenote does not send your data to any AI provider. When you connect Claude, ChatGPT or another agent, *that agent* reads from Truenote with a grant you approved, under the provider's own terms. You can see every call it made and revoke it at any time.
## Who else touches it
- **Plaid** (bank connections): [plaid.com/legal](https://plaid.com/legal/).
- **Railway** (hosting and the database, encrypted at rest).
- **Resend** (sign-in emails).
- **Stripe** (billing).
- **Sentry** (error reports, scrubbed).
- **Cloudflare** (this site, DNS, analytics).
Each is a processor acting on our instructions. We don't share data with anyone else, except as required by law, and we would tell you if we could.
## How long
For as long as your account is open. Delete the account (Settings → Delete account) and every bank is removed at Plaid, every agent's access is revoked, and everything you own is deleted, sessions and passkeys included. A lapsed subscription keeps your data 30 days (export still works), then deletes it. Database backups keep their copies for 6 to 89 days after a deletion, then age out. Rate-limit counters live a day.
## Your rights
Export everything any time (Settings → Your data, as JSON or CSV). Correct anything by editing it. Delete everything yourself. Ask us anything at hello@usetruenote.com; we answer within a few days. California and other residents with statutory rights can exercise them the same way.
## Cookies
The app sets one session cookie (httpOnly, SameSite, Secure) so you stay signed in, and remembers your theme on your device. This site sets no cookies.
## Children
Truenote is for adults (18 and over).
## Changes
We'll post changes here with the date above, and email you about anything material.
---
# Pricing
> One plan with everything in it: $12 a month or $100 a year, 14 days free. Bank connections, the spending plan, buckets, taxes, MCP and the API included.
Canonical: https://usetruenote.com/pricing
**$12 a month or $100 a year.** 14 days free with a card up front; it converts unless you cancel, which takes one click. No tiers, no add-ons, no per-agent fees. Sign up: https://app.usetruenote.com/sign-in
## Included
- Bank, card, loan and brokerage accounts through Plaid
- The spending plan, savings buckets and the Review queue
- Goals, income sources, businesses, notes and plans
- The yearly federal tax projection, with paystub and tax-form uploads
- Claude, ChatGPT and Claude Code over MCP
- The REST API and personal access tokens, with the same limits as the app
- Every agent's grant, scopes, hidden accounts and the Activity log
- Full export (JSON and CSV) any time
## Questions
**What happens after the 14 days?** The card is charged the plan you picked unless you cancelled. A reminder goes out three days before.
**How do I cancel?** One click in Settings → Billing. Cancelling stops the next charge; access lasts until the paid period ends.
**What happens to my data if I stop paying?** Syncing stops. After a grace period your banks are removed at Plaid, your data is kept for 30 days (export still works), then deleted.
**Is there a cheaper plan without the self-employed features?** No. One plan; a household with two W-2s simply doesn't fill those parts in.
**Does the API cost extra?** No. Building on your own data is included, never a higher tier.
**Which AI do I need?** Any you already use. Truenote has no built-in AI and no AI charges.
---
# Connect Claude Code to Truenote
> One command adds Truenote as an MCP server in Claude Code, so it can read your finances from the terminal.
Canonical: https://usetruenote.com/connect/claude-code
```sh
claude mcp add --transport http truenote https://app.usetruenote.com/mcp
```
Then `/mcp` → **truenote** → **Authenticate**.
## Scripts next to it
For a script rather than a chat, make a personal access token in Truenote (Connected agents → New access token) and send it as a bearer token to `/mcp` or to the REST API under `/v1`. See [Scripts and the API](/connect/api).
## Uploading a document from the terminal
Give the connection `documents:write` and ask Claude Code to file a paystub: it calls `prepare_upload`, gets a one-time link, and sends the file itself with `curl`. The file never passes through the model.
---
# Claude vs ChatGPT for personal finance
> Where each is strong, what they can and can't see of your money, and why the better answer may be giving both the same data.
Canonical: https://usetruenote.com/guides/claude-vs-chatgpt-for-personal-finance
Both can read a bank account now. Both can reason about a budget, explain a tax rule, and draft a plan. The differences that matter in practice are smaller than the difference between an assistant that knows your context and one that doesn't.
## Where they differ
- **Memory.** ChatGPT's own bank connection stores what it learns in ChatGPT. Claude's custom connectors (and ChatGPT's apps) read from a server you choose, so the context can live outside the assistant.
- **Tools.** Both speak MCP, so both can call Truenote's tools: the overview, the plan, buckets, the tax projection, filtered transactions. Claude Code adds a terminal, which is handy for scripts and for filing documents without pasting them into a chat.
- **Long documents.** Claude tends to handle a year of statements or a tax return in one go more gracefully; ChatGPT tends to be quicker at short back-and-forth. Models change; test the one you have.
- **Price and plan.** Truenote charges nothing per assistant and has no built-in AI, so you use whichever you already pay for, and switch when the better one changes.
## What makes either one good
An assistant answering "can we afford this?" needs: current balances; what's committed before the next payday; the plan's shares; what's set aside in buckets; which money is the business's; what's owed for taxes. None of that is in a transaction list. Truenote keeps it as structured rows with agent-shaped tools (`get_overview`, `get_plan`, `plan_vs_actual`, `list_buckets`, `get_tax_projection`), so the assistant spends its context on reasoning rather than on five thousand rows.
## Use both
Connect Claude and ChatGPT to the same Truenote, each with its own grant. Ask one the question you asked the other. You'll find out which you prefer for which kind of question, and nothing you set up is lost when you decide. Steps: [Claude](/connect/claude), [ChatGPT](/connect/chatgpt).
---
# Not advice
> Truenote reports and projects. It is not tax, legal, investment or financial advice.
Canonical: https://usetruenote.com/legal/not-advice
Truenote shows you your own figures and works out things from them: how the month compares with your plan, what a bucket is due, a projection of the year's federal tax from the figures you and your paystubs gave it. Those are calculations, not advice.
- The tax projection covers federal income tax for a simplified household (W-2 wages, self-employed income, common deductions and credits). It leaves out state income tax, the alternative minimum tax and much else, and it's only as good as the figures entered. Your return is yours and your preparer's.
- Nothing here is a recommendation to buy, sell or hold anything, to pay or not pay a debt, or to change your withholding. If Truenote says a certain extra withholding would break even, that's arithmetic on your inputs, not a filing instruction.
- The AI agents you connect form their own answers from what Truenote gives them. They can be wrong, and they are not us.
Check anything that matters with a professional who knows your situation. Truenote is a tool for thinking about your money, not a substitute for judgment.
---
# Security
> What Truenote keeps, how it's protected, and what agents can do: read-only to banks, sealed Plaid tokens, per-agent grants, an append-only audit log, row-level security, and an honest list of known gaps.
Canonical: https://usetruenote.com/security
Boring on purpose: few secrets, each one sealed or hashed, every access scoped and logged, and nothing that can move money.
## The short version
- **Truenote can't move money.** It uses only Plaid's read products (transactions, balances, investments, liabilities, recurring). No transfer, payment or "auth for payments" endpoint exists in the code, and no agent tool writes to a bank.
- **Your bank logins never reach Truenote.** You sign in to your bank inside Plaid Link; Truenote gets a Plaid access token for reading, sealed with AES-256-GCM before it touches the database.
- **Agents get only what you allow,** per connection: which kinds of data (scopes), and which accounts, businesses or manual assets they must never see. Change or revoke that in one click; it applies to the agent's very next call.
- **Every agent call leaves a receipt** in your Activity log: which agent, what it asked, how many rows, whether it was refused.
- **You can take everything out** (Settings → Your data) **or delete everything** (Settings → Delete account), which also tells Plaid to forget every bank.
## What's stored
| Data | Protection |
|---|---|
| Email, name, sessions, passkeys | Signed cookies (httpOnly, SameSite, Secure). Passkeys are public keys; the private key never leaves your device. |
| Sign-in codes | Six digits, 10 minutes, 3 tries, stored hashed. |
| Plaid access tokens | AES-256-GCM, random IV, the row's identity bound in. Keys in the server's environment, never the database. Opened only in memory before a Plaid call. Never returned by any endpoint, tool, export or log. |
| Documents | Sealed like Plaid tokens. Agents need a documents scope; the text they get has Social Security and long account numbers masked to the last four. |
| Bank data and your context | Rows in Postgres, scoped to you by the API and by row-level security. Rows an agent wrote say which agent. |
| Agent access | Every bearer secret is a random 256-bit string stored only as its SHA-256 hash. Shown once. |
| The audit log | Append-only: the database refuses updates and deletes. Arguments summarized, never secrets. |
Not stored: bank passwords, card numbers, any token in the clear.
## Who can reach it
**You:** an emailed code or a passkey, no passwords; rate-limited. A session lasts 14 days from last use. Managing agents, exports and deleting the account need your browser session; an agent's token can never do them.
**Agents:** OAuth 2.1 (PKCE, exact redirect URIs, tokens bound to the endpoint) or a personal access token. One grant per connection with scopes (accounts, transactions, investments, liabilities, context read/write, documents read/write) and exclusions (accounts, businesses, manual accounts) filtered in SQL in every read, totals included, and checked on every write. New connections start read-only. Agents can write the spending plan, buckets (Truenote's ledger only), rules and Review decisions, profile, entities, goals, income sources, notes, plans, categories; never a bank, money, your sign-in, other agents' access, the audit log, exports or your account. 240 calls a minute per grant.
| Token | Lifetime |
|---|---|
| OAuth authorization code | 5 minutes, once |
| OAuth access token | 1 hour |
| OAuth refresh token | 30 days, rotated on every use |
| Personal access token | 7, 30, 90 or 365 days; revocable |
| Web session | 14 days from last use |
## Defense in depth
1. The API is the only door; the web app never touches the database or Plaid.
2. Every query is scoped in code to the signed-in user; someone else's id is a 404.
3. Row-level security in Postgres: a query that forgot its filter still gets only your rows.
4. Same-user foreign keys.
5. A strict Content Security Policy, no framing, HSTS; agent endpoints ignore cookies and refuse unknown browser origins.
6. Logs and error reports never carry secrets or bank text.
## Known gaps
- Bank text isn't filtered by exclusions (a visible transaction may name a hidden account). Free text you write isn't filtered either.
- Background jobs run outside row-level security.
- Backups keep deleted data until they age out (6 to 89 days).
- One person per account; household sharing with separate grants is planned.
- No independent security review yet; one is planned.
## Deleting your account
Every bank is removed at Plaid, every agent's access revoked, the audit log purged, everything deleted. Backups keep their copies until they expire.
Report an issue: security@usetruenote.com
---
# About
> Truenote was built by Zachery Gentry in Texas for one household first, his own. Why it exists, what it believes, and who's behind it.
Canonical: https://usetruenote.com/about
Truenote started as the spreadsheet its maker kept trying to explain to an AI.
Zachery Gentry runs a small software company in Texas. The household has two W-2 jobs with their own 401(k)s, 1099 work through an LLC, a mortgage, a car loan and a baby on the way. Every finance app wanted to be the place to think about money, and every AI knew nothing about any of it. So he built one place that holds the accounts *and* the context, owned by the household, that any AI can read with permission. Not another assistant: the data and the memory, with the agent interchangeable.
## What it believes
- **Your data, your agents.** Every connection is an explicit grant you can see, narrow and revoke.
- **Every access leaves a receipt.**
- **Context is data.** Goals, the plan, income and notes are structured rows, not free text in a chat.
- **Read-only to banks, forever.** Truenote never moves money.
- **Boring security.** Sealed tokens, least privilege, short-lived credentials.
## Who it's for
Any household that's into its finances and already talks to an AI. The self-employed features are there because the maker needs them, not because they define the audience.
## The company
Truenote is made by Zachery Gentry LLC, Austin, Texas. Bank connections through Plaid; the app runs on Railway; the site on Cloudflare. No investors; your data is never sold. Contact: hello@usetruenote.com
---
# Build on your own data with the Truenote API
> A personal access token and an OpenAPI spec. Read your accounts, transactions, the plan, buckets and the tax projection from any script, with the same scopes and receipts as an agent.
Canonical: https://usetruenote.com/connect/api
```sh
curl https://app.usetruenote.com/v1/overview \
-H "Authorization: Bearer tn_pat_…"
```
## What's there
`/v1/overview`, `/v1/accounts`, `/v1/transactions` (filters and keyset paging), `/v1/spending`, `/v1/recurring`, `/v1/net-worth-history`, `/v1/holdings`, `/v1/investment-transactions`, `/v1/liabilities`, `/v1/context`, `/v1/plan`, `/v1/plan/actuals`, `/v1/taxes/projection`, `/v1/tasks`, `/v1/buckets`, `/v1/review-items`, `/v1/bucket-rules`, `/v1/documents` (list, read, upload a file) and `/v1/export` (everything, JSON or a zip of CSVs). The same scopes and exclusions as MCP apply, in SQL, totals included.
The same token also works against the MCP endpoint, for a client that speaks MCP but not OAuth.
## Limits and promises
240 requests a minute per token. `/v1` changes are additive; deprecations are announced in the [changelog](/changelog). Money is integer cents; days are `YYYY-MM-DD`; transaction amounts keep Plaid's sign (positive is money out).
Full reference: [API reference](/docs/api).
---
# Budgeting with buckets instead of categories
> Why fitting every transaction into a category budget rarely sticks, and how savings buckets on one account, with a plan for regular take-home, do the same job with less friction.
Canonical: https://usetruenote.com/guides/buckets-instead-of-budgets
Most budgets fail the same way. You make twenty category lines, the first month a tire blows out, and the tire goes nowhere. By the third month the budget is a document you avoid.
## The shape that sticks
Two parts:
1. **A plan for regular take-home.** Each paycheck is split into groups with a share: Expenses (bills, groceries, the mortgage), Wants, and Save and invest. Lines inside the groups are the things with a fixed amount and cadence. Everyday spending is checked against the group's share, not line by line.
2. **Buckets on one savings account.** Emergencies, Vacations, Christmas, Pets, the next car. Each has its own ledger and, if you like, a target and a date. One transfer every payday carries the sum of what each bucket is due. When the tire blows, it comes out of the Car bucket; the plan is untouched.
The bank sees one savings balance. The buckets are a ledger you (or your agent) keep.
## How Truenote runs it
- The plan's lines that "fill a bucket" set what each bucket is due. A deposit to the savings account is split by what's due, the extra to an overflow bucket (Emergencies, say). Nothing to type.
- Spending charged to a bucket by a rule you approved (the vet → Pets) is recorded automatically. Anything less certain waits in a **Review** queue with a proposal; you approve, change or dismiss in one tap.
- A charge on another account that a bucket paid for is "owed from savings" until a transfer out settles it. Settle once a month, in one batch.
- A bucket at its target gets a stamp.
Agents see and write all of it: `list_buckets`, `move_between_buckets`, `record_bucket_entry`, `list_review_items`, `resolve_review_item`. "Move $500 from Emergencies to Vacations" is one sentence and one receipt.
## What goals are for, then
Goals are for the broad things funded by whole accounts (a down payment in a brokerage account, a cabin in twelve years). A bucket can carry its own target for the smaller, dated ones. Both show on the overview.
---
# How much to set aside for taxes when you're self-employed
> A rule of thumb (25 to 35 percent of 1099 income), why it's rough, and how a yearly projection from your real figures replaces it, including the trick of raising W-2 withholding instead of paying quarterlies.
Canonical: https://usetruenote.com/guides/self-employed-tax-set-aside
## The rule of thumb
Set aside 25 to 35 percent of what a 1099 client pays you. Self-employment tax runs about 15.3 percent of net profit (you deduct half of it), and federal income tax lands on top at your marginal rate. If you also have a W-2 job, that job's wages already fill the lower brackets, so the 1099 money is taxed at the top of your pile: a household with a six-figure W-2 and a side consulting gig often ends up near 30 percent, higher if the consulting is large.
Rough, because the rule ignores the QBI deduction, your actual bracket, how much your W-2 withholding already covers, retirement contributions, and whether you itemize.
## The better way: project the year
Truenote's tax projection takes what it can see and what you tell it:
- each W-2's year-to-date gross, 401(k), and federal withholding (typed in, or read from a paystub you upload);
- each 1099 or business source: money received (from the connected accounts), still expected, expenses;
- bonuses, estimated payments already made, last year's tax (for the safe harbor), investment income.
It returns the statement line by line (wages, self-employment tax, the deduction for half of it, QBI, the standard or itemized deduction, credits, tax), whether you'll get money back or owe, and the extra withholding per paycheck that breaks even. Texas has no state income tax; elsewhere the projection says it's federal only.
Ask your agent: "Will we owe for the year? How much more should come out of each paycheck?" It calls `get_tax_projection` and answers with the figures and the assumptions.
## Withholding instead of quarterlies
If you have a W-2 job, raising its withholding (a new W-4 with extra per paycheck) does the job of quarterly estimates with no deadlines: withholding counts as paid evenly across the year, even if you raise it in October. The projection's "extra per paycheck" is exactly that number. Where there's no W-2, quarterlies it is: the projection shows the quarterly set-aside and the next due date on the overview.
## Where the money sits
A bucket called Taxes on the savings account, filled by a plan line or by a share of each 1099 deposit, keeps the set-aside visible and out of the way. Truenote's buckets do that without a second bank account; see [Buckets instead of budgets](/guides/buckets-instead-of-budgets).
This isn't tax advice: it's arithmetic on your inputs. [Not advice](/legal/not-advice).
---
# An AI budgeting app that isn't a chatbot
> What to look for in an AI budgeting app in 2026: who holds the data, whether the AI is swappable, what it can write, and whether you can see what it did.
Canonical: https://usetruenote.com/guides/ai-budgeting-app
Every budgeting app grew an assistant in 2025. Most of them are a chat box bolted onto the app's own data, running one vendor's model, with no way to see what the assistant looked at or to take the context with you.
Four questions sort them out.
## 1. Who holds the data?
If the budget, the goals and the notes live inside the assistant's memory, you're renting your own context. Truenote keeps them as structured rows in an account you own, exportable as JSON or CSV any time, and deletable in one step.
## 2. Is the AI swappable?
Models leapfrog each other every quarter. An app with a built-in model is as good as that model this month. Truenote has no built-in AI; Claude, ChatGPT, Claude Code and your own scripts connect over MCP and a REST API, each with its own grant, and you can run two at once on the same data.
## 3. What can the AI write?
A good assistant should be able to *do* things: add a plan line, charge a vet bill to the Pets bucket, make a rule, save a scenario. It should never be able to move money. Truenote's write tools cover its own records and nothing at the bank; the integration has no payment code at all.
## 4. Can you see what it did?
Every call an agent makes to Truenote is in an append-only Activity log: which agent, which tool, what it asked, how many rows. Rows an agent wrote say which agent. Revoke takes one click.
## The budget itself
Truenote budgets the way people who keep budgets actually do: a plan for regular take-home (Expenses, Wants, Save and invest with a share each) and savings buckets on one account for the lumpy things, instead of twenty category lines that break the first time a tire blows. Details in [Buckets instead of budgets](/guides/buckets-instead-of-budgets).
[How it works](/how-it-works) · [Pricing](/pricing): one plan, $12 a month or $100 a year, 14 days free.
---
# A personal finance API for your own scripts
> Read your accounts, transactions, the plan, buckets and the tax projection from a script with a bearer token and an OpenAPI spec, with the same scopes and receipts as an AI agent.
Canonical: https://usetruenote.com/guides/personal-finance-api
Spreadsheet people, home-lab people, people who want a Sunday script that posts "here's where we stand" to a family chat: Truenote's API is for you, and it's the same door the AI agents use.
## One token
Connected agents → **New access token**. Pick the scopes (accounts, transactions, investments, liabilities, context, documents), a lifetime from 7 to 365 days, and which accounts or businesses the token must never see. It's shown once.
```sh
curl https://app.usetruenote.com/v1/overview \
-H "Authorization: Bearer tn_pat_…"
```
## What you can read
- `/v1/overview`: net worth, cash, this month, the plan at a glance, bills due, goals, the next estimated payment.
- `/v1/accounts`, `/v1/transactions` (filters and keyset paging), `/v1/spending` (by category, merchant, entity or month), `/v1/recurring`, `/v1/net-worth-history`.
- `/v1/holdings`, `/v1/investment-transactions`, `/v1/liabilities`.
- `/v1/context` (profile, entities, income sources, goals, notes), `/v1/plan`, `/v1/plan/actuals`, `/v1/buckets`, `/v1/review-items`, `/v1/tasks`.
- `/v1/taxes/projection`.
- `/v1/documents` (and `POST` to upload a paystub), `/v1/export` (everything).
The spec is at `https://app.usetruenote.com/v1/openapi.json`; the [API reference](/docs/api) is drawn from it. Money is integer cents, days are `YYYY-MM-DD`, transaction amounts keep Plaid's sign (positive is money out). 240 requests a minute per token. Changes are additive, deprecations announced in the [changelog](/changelog).
## Receipts
Every request a token makes is in the Activity log next to the agents' calls. Revoke the token there.
## Example: a weekly note
```sh
#!/bin/sh
# Where we stand, every Monday.
TOKEN="tn_pat_…"
curl -s https://app.usetruenote.com/v1/overview \
-H "Authorization: Bearer $TOKEN" \
| jq -r '"Net worth \(.netWorth.totalCents/100 | floor), cash \(.cash.totalCents/100 | floor), left of take-home this month \(.plan.leftCents/100 | floor)"'
```
(Field names as in the spec; check the reference for the exact shapes.)
Planned next, in the [changelog](/changelog) when they land: a changes feed (`updatedSince`) so a script keeps a sheet in step without re-reading everything, REST writes for everything MCP can write, and signed webhooks.
---
# Mint, YNAB, Monarch and Copilot: where Truenote fits
> An honest comparison for people choosing after Mint: what each app does well, what Truenote does differently (buckets, context, bring-your-own AI, an API), and who should pick which.
Canonical: https://usetruenote.com/guides/mint-ynab-monarch-copilot-alternative
Mint is gone and its users scattered. Here's what the usual candidates do well, and where Truenote is different. No stars, no scores.
## Monarch
The most complete Mint successor: every account, budgets by category, goals, net worth, a partner's login, a polished app. Its AI assistant is built in and reads Monarch's data. Pick it if you want the broadest app and don't care which model answers.
## Copilot
The nicest-looking one, iOS and Mac first, with careful categorization and an assistant that's part of the app. Pick it if you live on Apple devices and want the prettiest daily check-in.
## YNAB
A method as much as an app: give every dollar a job, zero-based, every month. It changes behavior if you keep it up, and it's work. Pick it if you want the discipline and the community.
## Truenote
Different in four ways:
1. **Buckets, not category budgets.** A plan for regular take-home (Expenses, Wants, Save and invest) and savings buckets on one account for the lumpy things. Less typing, and it survives the month a tire blows out.
2. **Context as data.** Which business a charge belongs to, each income source and its tax set-aside, the yearly federal tax projection, notes, plans, uploaded paystubs. Monarch and Copilot don't try to know that your Lowe's charge was for the LLC.
3. **Bring your own AI.** No built-in assistant. Claude, ChatGPT, Claude Code and scripts connect over MCP and an API, each with a grant you can see and revoke, and an audit log of every call.
4. **An API, included.** Your data for your own scripts, never a higher tier.
Pick it if you already talk to an AI about money and want it to actually know your situation, if you're self-employed or have a side business, or if you want the data to be yours and portable.
What Truenote doesn't have yet: a native app (the web app works well on a phone), household sharing with a partner's own login, state income tax in the projection, a free tier. Everything else is $12 a month or $100 a year, 14 days free.
[How it works](/how-it-works) · [Pricing](/pricing)
---
# What MCP means for your money
> The Model Context Protocol in plain words, how Claude and ChatGPT use it to reach your data, and what a good financial MCP server should and shouldn't let an agent do.
Canonical: https://usetruenote.com/guides/what-is-mcp-for-your-money
MCP, the Model Context Protocol, is how AI assistants reach outside their chat: a server offers *tools* (named functions with typed arguments), and the assistant calls them when a question needs them. Claude's connectors and ChatGPT's apps are MCP clients. Truenote is an MCP server.
## What that looks like
You ask Claude "how is this month going against the plan?" Claude sees it has a tool called `plan_vs_actual` on a server called Truenote, calls it, gets a compact answer (bills paid, set aside, everyday spending by category against the trailing average, what's left of take-home), and writes you a reply. If you then say "charge the vet visit to Pets and make it a rule", it calls `resolve_review_item` and `create_bucket_rule`, which need write access, so Truenote asks you to allow that first.
## What a financial MCP server should do
- **Authenticate properly.** OAuth 2.1 with PKCE and a consent screen that shows what the client will see. Truenote's discovers everything from the URL; no keys to paste.
- **Scope narrowly.** Separate scopes for accounts, transactions, investments, liabilities, context and documents, plus the ability to hide specific accounts or a business from one agent. Read-only by default.
- **Give agent-shaped answers.** Summaries first (the overview, the plan, the tax projection), raw rows on request, so the assistant doesn't spend its context on five thousand transactions.
- **Never move money.** The server should have no way to, not merely a policy against it.
- **Leave receipts.** Every call in a log the person can read, with revoke one click away.
## What it shouldn't
Hold a bank login (Plaid Link exists so it doesn't have to), hand out long-lived tokens, let an agent change its own permissions, or hide what it did.
## Try it
Truenote's server is `https://app.usetruenote.com/mcp`. [Connect Claude](/connect/claude), [ChatGPT](/connect/chatgpt) or [Claude Code](/connect/claude-code); the [tool reference](/docs/mcp-tools) lists every tool with its scopes and arguments.
---
# Auth, scopes and exclusions
> How an agent or script authenticates (OAuth 2.1 or a personal access token), what each scope allows, and how exclusions hide accounts and businesses in every query.
Canonical: https://usetruenote.com/docs/auth-and-scopes
## Two ways in
**OAuth 2.1** for MCP clients. The client discovers everything from the server URL: `/.well-known/oauth-protected-resource/mcp` → the authorization server metadata → dynamic client registration (or a client metadata document) → PKCE (S256 only) → Truenote's consent screen. Tokens are bound to the resource they were issued for (`/mcp` or `/v1`). Access tokens last an hour; refresh tokens 30 days, rotated on every use (a used one coming back revokes the whole family).
**Personal access tokens** for scripts and clients that don't do OAuth. Connected agents → New access token: choose the scopes, the lifetime (7, 30, 90 or 365 days) and what it must never see. It's shown once. Send it as `Authorization: Bearer tn_pat_…` to `/v1` or `/mcp`.
Either way the connection is one *grant*, read fresh on every call.
## Scopes
| Scope | Allows |
|---|---|
| `accounts:read` | Accounts, balances, net worth history, buckets (with `context:read`) |
| `transactions:read` | Transactions, spending summaries, recurring streams, plan vs actual (with `context:read`) |
| `investments:read` | Holdings and investment transactions |
| `liabilities:read` | Loans and cards: APR, minimum payment, due date |
| `context:read` | Profile, entities, income sources, goals, notes, plans, the spending plan, tasks |
| `context:write` | Write all of the above plus categories, rules, buckets' ledger, Review decisions, transaction categories and entities, manual accounts; refresh or disconnect a bank. Implies `context:read`. |
| `documents:read` | List and read uploaded documents (text masked: Social Security and long account numbers to the last four) |
| `documents:write` | Upload a document (`prepare_upload`, `POST /v1/documents`) and edit what one is; delete one. Implies `documents:read`. |
`get_overview` needs no scope: it answers with the sections the grant allows and lists the rest as `notIncluded`.
New OAuth connections start read-only. A write tool called without `context:write` returns an error naming the scope; the client asks the person to allow more and you approve again on the consent screen.
## Exclusions
A grant can exclude specific accounts, businesses (entities) or manual accounts. Exclusions are applied in SQL on every read, totals included (net worth, spending, the plan, goals, the tax set-aside), and checked on every write: an agent can't categorize a transaction it can't see, create a rule that would reach one, or delete a record that would change what it's hidden from. Accounts you've hidden (or Truenote hid as unused) are excluded the same way unless the grant was given "Let it see them".
Bank text isn't filtered: a transaction on a visible account may name a hidden one in its description. The consent screen says so.
## Limits
240 calls a minute per grant. Every call, allowed or refused, is written to the audit log with a summary of its arguments (ids and filters, never secrets).
---
# Prompts that work well
> Questions the tools answer well, from the overview to the tax projection, and the ones that write.
Canonical: https://usetruenote.com/docs/prompts
Truenote hands agents compact, pre-added answers (the overview, the spending plan, plan vs actual, the tax projection, buckets) as well as raw transactions, so questions like these work well:
## Reading
- "How much should I set aside for my January 15 estimated payment?"
- "How much is left in our Wants share this month, and what changes when the car is paid off?"
- "Which bills and subscriptions hit in the next two weeks? Anything we're paying for and not using?"
- "Are we on track for six months of runway before the baby comes in March? What would close the gap?"
- "Will we get money back or owe for the year? How much more should come out of each paycheck to break even?"
- "How much has the consulting client paid this year, and how lumpy is it month to month?"
- "Compare the business's money in and out this season with last year."
- "What's waiting in my Review queue?"
## Writing (asks for `context:write`)
- "Move $500 from Emergencies to Vacations." (Truenote's ledger only; nothing moves at the bank)
- "Charge the vet visit to Pets and make it a rule."
- "From now on, put every Lowe's charge under the business."
- "Add a plan line: $180 a month for the gym, until next June."
- "Remember that we want to refinance if rates drop below 5%; tag it mortgage."
- "Draft a plan for 12 weeks of unpaid leave starting in March and save it."
- "Here's my latest paystub; update my income source from it." (with `documents:write`, the agent files the paystub too)
## How agents should start
`get_overview` first, then `get_context` before advising or writing anything: it explains the household and gives the ids the write tools need. Prefer the summaries (`spending_summary`, `get_plan`, `plan_vs_actual`, `get_recurring`) to paging through transactions. "Household" means the personal entities; each business's money is reported on its own.
---
# Uploading documents
> How a paystub, W-2 or statement gets into Truenote from an agent or a script without the file passing through the model.
Canonical: https://usetruenote.com/docs/uploads
Documents (paystubs, W-2s, 1098s, last year's return, statements) are kept sealed at rest, their text extracted for agents with sensitive numbers masked, and tied to what they're about: a tax year, an income source, an account.
## From an agent
With `documents:write`, an agent calls `prepare_upload` with what the document is (name, kind, tax year, the income source or account it belongs to). Truenote answers with a one-time link, good for 15 minutes and one file. The agent either sends the file itself (`curl -F file=@paystub.pdf `) or hands the link to the person, who drops the file on its page. The model never carries the bytes.
## From a script
```sh
curl https://app.usetruenote.com/v1/documents \
-H "Authorization: Bearer tn_pat_…" \
-F file=@paystub.pdf \
-F 'metadata={"name":"Paystub Oct 16","kind":"paystub","taxYear":2026}'
```
PDF, PNG, JPEG and WebP, up to 10 MB. The real type is read from the bytes.
## What agents read back
`list_documents` (search by text, kind, year) and `read_document`: a PDF's text, masked, or an image as itself, with a hint about what it's good for. A paystub's year-to-date gross, 401(k) and federal withholding are offered as the tax inputs (`upsert_income_source`) after asking. `get_tax_projection` names the paystubs and forms behind its figures and warns when a newer paystub exists.
---
# MCP tools
> Every tool Truenote's MCP server offers, with its scopes and arguments, from the server's own definitions.
Canonical: https://usetruenote.com/docs/mcp-tools
Truenote's MCP server is `https://app.usetruenote.com/mcp` (Streamable HTTP; OAuth 2.1 discovered from the URL, or a personal access token as a bearer). Every tool is checked against the connection's scopes and exclusions and written to the audit log. Amounts arrive formatted ("$1,234.56"); write tools take plain dollars.
## Read tools
### `get_overview`: Financial overview
Where the household stands right now, in one call: net worth (cash, investments, debts), this month's spending and income (household and each business separately), the spending plan at a glance, bills due in the next two weeks, goals, the next quarterly estimated tax payment, bank connections that need attention, the checklist's next tasks, what they own and owe by kind (property, retirement, investments, cash; mortgage, loans, cards) with home equity, how much of the last twelve months' income was kept (saving), the emergency fund in months of the plan's spending, and the spotlight (the dated event the person's home page counts down to). Start here for any general question about the person's finances. Sections the connection isn't allowed to see are listed in notIncluded. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: none (any connection).
### `list_accounts`: List accounts
Every connected account (checking, savings, cards, loans, brokerage) with its institution, latest balance, the entity it belongs to (household or a business), and for debts the rate, minimum payment and due date; plus manual accounts (a house, a car) and net worth totals. Balances are what the account is worth to the person: debts are negative. Use the ids with query_transactions or get_holdings. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `accounts:read`.
Arguments:
- `type`: Only this account type
- `includeHidden`: Also closed accounts and archived manual ones, and accounts the person hid from totals if this connection is allowed to see hidden accounts
### `query_transactions`: Search transactions
Transactions newest first, filtered by date range, account, category, entity, merchant, amount, direction or text, 50 per page (pass nextCursor to continue). Each row has its id (for categorize_transactions), resolved category and entity, and flow: spending, income, transfer (between the person's own accounts) or excluded; ownerContribution marks a business's spending paid from a personal account (the owner put that money into the business). totals covers every match, not just the page: prefer spending_summary for "how much on X" questions. Without from/to it searches all history (about a year). Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `transactions:read`.
Arguments:
- `from`: First day, inclusive (YYYY-MM-DD)
- `to`: Last day, inclusive
- `accountId`:
- `categoryId`: A category id from get_context (subcategories included), or none for uncategorized
- `entityId`: An entity id from get_context
- `merchant`: Merchant or description contains
- `text`: Description, merchant or note contains
- `minAmount`: At least this many dollars, either direction
- `maxAmount`: At most this many dollars
- `direction`: Money in or money out
- `pending`:
- `ownerContribution`: true: only owner contributions, a business's spending paid from a personal account (with entityId, totals is what the owner put into that business)
- `limit`: Rows per page (default 50)
- `cursor`: nextCursor from the previous page
### `spending_summary`: Spending summary
Spending (net of refunds) over a date range grouped by category, merchant, entity or month, biggest first, with each group's share. By default it's the household's spending only (the personal entities, the same number get_overview's month reports); pass entityId for one business, or scope=all for the household and every business together. The result says which scope it used. Transfers between the person's own accounts, card payments and transactions they left out don't count; income isn't spending. Default range: this month so far. Use groupBy=month for trends. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `transactions:read`.
Arguments:
- `from`: Default: the first of this month
- `to`: Default: today
- `groupBy`:
- `scope`: household (default): personal spending only; all: household and businesses
- `entityId`: Only this entity (e.g. one business); overrides scope
- `categoryId`: Only this category and its subcategories
- `limit`: Groups to list (default 25)
### `get_recurring`: Recurring bills and income
Subscriptions, bills and paychecks the bank detected as recurring, with frequency, last and average amount (positive), last and next date, and flow: spending, income, or transfer (card payments and moves between the person's own accounts, like savings or a brokerage). monthlyOutflow and monthlyInflow count spending and income streams only (card payments would double-count the card's own subscriptions); monthlyTransfers is the rest. Covers the household and businesses alike. Use for "what are my subscriptions", "what's due" or "what do we spend every month". Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `transactions:read`.
Arguments:
- `direction`: inflow: income; outflow: bills
- `includeInactive`: Also streams that stopped
### `get_net_worth_history`: Net worth history
Net worth over time from daily balance snapshots: assets, liabilities and a breakdown by account type (cash, investments, credit, loans, other, manual assets). Interval month (default; last day of each month) or week over up to three years, or day over up to 93 days. Default range: the last year. heldBack means an account joined later and is held at its first value before that. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `accounts:read`.
Arguments:
- `from`:
- `to`:
- `interval`:
### `get_holdings`: Investment holdings
Positions in each investment account: symbol, quantity, price, value, cost basis and gain, with account and overall totals; optionally the 25 latest investment transactions (buys, sells, dividends; positive amounts are cash out of the account): for a date range, a kind or a symbol, query_investment_transactions. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `investments:read`.
Arguments:
- `accountId`:
- `includeTransactions`:
### `query_investment_transactions`: Search investment transactions
Buys, sells, dividends, interest, deposits and fees in the investment accounts (about two years), newest first, filtered by date range, account, type (buy, sell, cash, fee, transfer, cancel), subtype (dividend, interest, deposit, sell…), symbol or text, 50 per page (pass nextCursor to continue). Money into the account is +$ (a sell's proceeds, a dividend), out is -$ (a buy). totals covers every match, not just the page: count, and the amount by type and subtype (this year's dividends: from Jan 1, subtype dividend). A sell carries its proceeds, not the gain: the bank doesn't send the cost of the shares sold (the year's 1099-B has it); get_holdings has the cost basis of what's still held. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `investments:read`.
Arguments:
- `from`: First day, inclusive (YYYY-MM-DD)
- `to`: Last day, inclusive
- `accountId`: An investment account's id from list_accounts
- `type`:
- `subtype`: dividend, interest, deposit, sell…
- `symbol`: Ticker, like VTI or BTC
- `text`: Description contains
- `limit`: Rows per page (default 50)
- `cursor`: nextCursor from the previous page
### `get_liabilities`: Debts
Credit cards, student loans, the mortgage and other loans: amount owed, APR, minimum payment, next due date, last payment and statement, original principal and maturity. Use for payoff or interest questions. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `liabilities:read`.
### `get_context`: The household's context
What accounts can't say, in one call: the profile (household members, a baby's due date, state, filing status, risk tolerance, "about us"), entities (household and businesses), income sources with tax set-aside rates, goals, categories and rules (with ids for the write tools), pinned and recent notes, plans, and the open checklist (tasks with due dates). Read this before giving advice or writing anything. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `context:read`.
### `get_plan`: Spending plan
The household's spending plan: regular monthly take-home (salaries, counting two paychecks a month for every-two-weeks pay; 1099 work after its tax set-aside; bonuses and the third paychecks two months a year bring are windfalls and don't count: extraYearly), split into groups with a target share (e.g. Expenses 45%, Wants 25%, Save & invest 30%). Each group has its lines (an amount per payment, how often, the monthly figure, the every-two-weeks transfer, an end date), what's planned, the target, and what's left over. Also: what's unplanned overall, the transfers to set up every two weeks, and what frees up when lines end. This is where the money is meant to go, not a budget of transactions; use it for "can we afford X", "how much is left for Y" or "what changes when the car is paid off". Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `context:read`.
### `plan_vs_actual`: Plan vs actual
A month of the household's money against the spending plan (get_plan), the way the person runs it: bills get paid, money gets set aside, the rest is everyday spending. bills: lines with match text (each line's kind is in get_plan), paid when a household payment out contains the text (lines sharing text each take the payment nearest their amount; status paid, due while the month is going, unpaid once it's over, not_this_month for a quarterly or yearly bill not paid this month); expected is what this month's bills ask. setAside: lines filling a bucket (its contributions), or naming an account (transfers in; for an investment account its own deposits and withdrawals; or payments out containing their match text); lines sharing a bucket or account split what arrived in plan order; via null means nothing to follow; status met, in_progress (this month) or short (a month that's over). everyday: every other spending line together (planned), against all other household spending whatever its category (actual), less bucket charges (chargedToBuckets: they count against the bucket, list_buckets) and tax payments (taxPayments: get_tax_projection); status over, ahead_of_pace (past the share of the month gone, monthGonePct, by more than a tenth) or on_track; categories breaks it down biggest first, a category a line names collecting its children, with each one's planned, trailing 3 full months' average (averageOf) and transaction count: the place to see what the plan is missing or which estimate is off (to change one, upsert_plan_line, after asking). left: the plan's monthly take-home (plannedIncome) less bills (paid, or still due), set-asides (made, or still to make this month), everyday spending and taxes: what the month leaves for goals and plans. income is what actually came in (bonuses too). Business spending is never included. month defaults to this one; use a past month for "how did September go". Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `context:read`, `transactions:read`.
Arguments:
- `month`: A month like 2026-10 (default: this month; never one that hasn't started)
### `get_tax_projection`: Yearly tax projection
The household's federal income tax for a year, projected from today, and whether they'll get money back or owe at filing time. Federal only: stateNote says whether the household's state has an income tax this leaves out (tell the person when it does). outcome says refund, owe or even and how much. statement is the math line by line, top to bottom: each W-2's wages (pay + bonus − 401(k) and other pre-tax), each business's profit (deposits found by payerMatch + money received elsewhere + what's still expected − expenses), total income, half of self-employment tax, AGI, the standard (or itemized) deduction, the qualified business income deduction, taxable income, income tax by bracket, the child tax credit, self-employment tax, the additional Medicare tax, then withholding (to date from a paystub + the paychecks after it × per paycheck + a bonus still to come), estimated payments found in the accounts (estimatedPayments lists each with its date and quarter; one paid in February to April may be last year's balance due rather than this year's estimate: ask, and record it with update_tax_settings priorYearPayments) and made elsewhere, and the result. breakEven gives, for each W-2 job with paychecks left after today, how much more (positive) to withhold per paycheck at that job alone to owe nothing (the person raises W-2 withholding instead of paying quarterly estimates; negative means that much could come off). Each breakEven entry closes the whole gap by itself: they are alternatives (this job OR that one), never to be added together or done at both; to share it across jobs, split the total owed yourself. safeHarbor and safeHarborSummary say whether an underpayment penalty is likely (90% of this year's tax, or 100%/110% of last year's, quarter by quarter; withholding counts as paid evenly through the year, estimated payments from their date). jobs and businesses are the inputs per source (ids for upsert_income_source); settings are the year's household figures (update_tax_settings). Read warnings (inputs that are missing: fix them with the person), assumptions and ignores (what this estimate leaves out) before relying on the number, and say it's an estimate. year defaults to this one. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `context:read`, `transactions:read`.
Arguments:
- `year`: Tax year (default: this one)
### `list_buckets`: Savings buckets
Buckets: the person's own virtual split of a savings (or checking) account (automation reads deposits and transfers out only on savings), like Ally's savings buckets but kept by Truenote for any bank, since banks only report the account's total. For each account split into buckets: its balance, each bucket's balance (from Truenote's ledger), its optional target and date with progress and the monthly amount needed to make it, what the spending plan puts in a month (fundedBy: the plan lines), and the latest ledger entries. unassigned is the account's balance less what the buckets hold (where interest lands, like Ally's "Core Savings"); negative means the buckets claim more than the account holds, which the person should fix with a correction or a move. A bucket below zero had more taken out than it held: it holds nothing, the extra came out of unassigned, and shortfall is what such buckets are short together. owed is what buckets were charged for spending paid from another account (a vet bill on the card) that hasn't been moved back out of this account yet: until it is, unassigned is that much higher. Entries marked auto were made by bucket automation (a bucket rule, or a deposit split by what each bucket is due: its plan lines a month, caught up from its start, else its target's monthly amount by its date, never past its target; what's left goes to the overflow bucket, else stays unassigned). Buckets are for lumpy, irregular spending (a vet bill, a vacation, car repairs, Christmas) rather than a monthly budget line. Use for "how much is in the vacation bucket", "can we cover this from savings" or "what's not assigned". Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `accounts:read`, `context:read`.
Arguments:
- `accountId`: Only this account's buckets
- `includeArchived`:
- `recentEntries`: Latest ledger entries per bucket (default 3)
### `list_review_items`: Review queue
What bucket automation wasn't sure enough to do on its own, waiting for the person (or you, on their behalf) to decide. kind: deposit (money came into a bucketed savings account from outside the person's accounts, more than its buckets are due: the proposal fills what each is due and puts the rest in the overflow bucket), charge (spending that looks like a bucket's, e.g. a vet visit → Pets: the proposal charges it, and rule is the bucket rule approving can save so the next one is automatic), withdrawal (money moved out of a bucketed savings account that doesn't exactly pay back what buckets are owed: paysBack lists the charges it would settle, owedCharges every unpaid charge it could settle instead; the rest comes out of Unassigned unless allocations name buckets; waiting true means it matches spending still in the queue, so decide that spending first and leave this one). Each item says why (reason). Certain things never show up here: money moved in from the person's own accounts is split by what each bucket is due automatically, bucket rules charge their matches, an exact pay-back settles itself, and interest stays in Unassigned. Ask the person before deciding anything you're unsure of. status resolved lists the latest decisions instead. Amounts are formatted strings in the account's currency; for transactions, money in is +$ and money out is -$.
Scopes: `accounts:read`, `transactions:read`, `context:read`.
Arguments:
- `status`: open (default) or resolved
### `list_bucket_rules`: Bucket rules
The person's bucket rules, in the order they apply (the first match wins): spending whose merchant or description contains the text (optionally on one account, in one category, within an amount range) is charged to the bucket automatically, back to the bucket's start and on every sync. chargedCount is how many entries each has made. Use before create_bucket_rule to avoid a duplicate.
Scopes: `accounts:read`, `context:read`.
### `list_tasks`: The checklist
The person's checklist: dated to-dos from planning ("Mail the 83(b) by Dec 5", "Backdoor Roths by Apr 15"), each with its kind (task, or event: a dated thing that happens, done once its day has passed), its state against today (overdue, due_soon within two weeks, upcoming, someday without a date, done), its sum (what it costs or brings), the goal or bucket it serves, and spotlight (the one the Overview counts down to). status: open (default), done or all. Open tasks come by due date; done ones newest first. get_context already lists the open ones.
Scopes: `context:read`.
Arguments:
- `status`:
### `list_documents`: List documents
Documents the person uploaded: paystubs, W-2s, 1099s, 1098s, tax returns, benefits and plan papers (a bonus withholding policy), statements, receipts. Each has its kind, tax year, the date on it, whose it is (entity), the income source a paystub is for, the account (or manual account, like the mortgage) a statement is of, and readable: text (read_document returns its text), image (read_document returns the picture), scan or unreadable (nothing to read; ask the person). q finds documents by words in their name, notes or text ("bonus withholding", "escrow"), each with the line it matched. Filter by kind or taxYear. Newest first by the date on it. get_context lists the latest few; get_tax_projection and list_accounts point at the ones behind their figures.
Scopes: `documents:read`.
Arguments:
- `q`: Words to find
- `kind`:
- `taxYear`:
### `read_document`: Read a document
One document's contents (an id from list_documents): a PDF's text page by page ("[Page 1]" …; Social Security and account numbers masked), up to 20,000 characters a call (pass nextOffset as offset for more), or an image document as the image itself. guidance says what the document is good for: a paystub's year-to-date figures can become its income source's tax inputs (upsert_income_source), but only after showing the person the numbers and hearing yes. Never repeat a full Social Security or account number.
Scopes: `documents:read`.
Arguments:
- `id` (required):
- `offset`: Where to continue (nextOffset)
## Write tools
### `update_tax_settings`: Set the tax year's household figures
Change the household's figures for a tax year that the projection (get_tax_projection) can't find in the accounts: priorYearTax (last year's total tax, Form 1040 line 24) and priorYearAgi (for the 100%/110% safe harbor), otherPayments (estimated payments made from accounts Truenote can't see, this year's), priorYearPayments (of the IRS payments get_tax_projection found this year, the dollars that paid last year's return, a balance due or an extension payment, so they don't count toward this year), otherIncome (this year's interest, ordinary dividends, short-term gains and other ordinary income; negative for a net capital loss, up to 3000), capitalGains (this year's long-term capital gains and qualified dividends, taxed at 0/15/20%; both count toward the 3.8% net investment income tax), itemizedDeductions (used only when larger than the standard deduction), qualifyingChildren (children under 17 at year end; null: counted from the profile's household, a baby due by December 31 included) and notes. Only the fields you pass change; null clears. Per-job and per-business figures belong on the income source (upsert_income_source). Changes the person's data: say what you set.
Scopes: `context:write`.
Arguments:
- `year`: Default: this one
- `priorYearTax`:
- `priorYearAgi`:
- `otherPayments`:
- `priorYearPayments`:
- `otherIncome`:
- `capitalGains`:
- `itemizedDeductions`:
- `qualifyingChildren`:
- `notes`:
### `upsert_goal`: Set a goal
Create or change a savings or payoff goal: by id, else by name (case-insensitive), else new (then kind and targetAmount are required). links are what counts toward it, each with the percent of it that counts: an account (accountId from list_accounts), a manual account (manualAccountId from list_accounts' manualAccounts: the house, an HSA) or a bucket (bucket: a name or id from list_buckets, for money kept in a savings bucket like an emergency fund); exactly one per link; giving links replaces them. Changes the person's data: say what you set.
Scopes: `context:write`.
Arguments:
- `id`:
- `name` (required):
- `kind`:
- `targetAmount`: Dollars
- `targetDate`:
- `priority`: 1 is the most important
- `notes`:
- `archived`:
- `links`:
### `upsert_manual_account`: Add or update a manual account
Something no bank connection reports, kept by hand: the house (asset, type real_estate) and its mortgage (liability, type loan), a car loan, an HSA, IRA or pension held elsewhere (type retirement), private company stock or a startup stake (type equity), cash. By id, else by name (any case), else new: a new one needs kind and balance. balance is dollars, positive: what it's worth, or what's owed on a liability; it's recorded on balanceOn (default today, never a day still to come) and replaces that day's entry, so call it again with a new balance to update the value. These count in net worth and appear in list_accounts' manualAccounts; a goal can link them (upsert_goal links with manualAccountId). archived: true hides one that's gone (a sold car). What you leave out stays. Truenote's records only. Tell the person what you set.
Scopes: `context:write`.
Arguments:
- `id`:
- `name` (required):
- `kind`:
- `type`: real_estate, vehicle, loan, retirement, equity, cash, crypto, other
- `entityId`: Household (null) or a business
- `notes`:
- `archived`:
- `balance`:
- `balanceOn`: The day the balance is for (default today)
### `upsert_income_source`: Set an income source
Create or change an income source (a W-2 job, a 1099 client, a business, a bonus): by id, else by name, else new (then type and cadence are required). expectedAmount is take-home per payment (a paycheck's net pay). regular sources (salaries; the default for w2) are the spending plan's income; anything else (a bonus, 1099 work) is a windfall allocated when it lands. earner is who in the household earns it. taxSetAsidePct is the share of each payment to set aside for taxes (30 for 30%); payerMatch is text its deposits carry ("GUIDEIT") so Truenote can find them. For the yearly tax projection (get_tax_projection), a W-2 job takes grossPay (this year's salary before deductions, bonus apart), retirement (401(k)/403(b) for the year), otherPretax (health, HSA, FSA through payroll for the year), withheldYtd with withheldAsOf (federal income tax withheld so far and the date of the paystub it's from, both or neither), withholdingPerPaycheck (federal tax withheld from each regular paycheck), bonus, bonusOn (paid or expected) and bonusWithholdingPct (default 22); a 1099 client or business takes receivedElsewhere (paid this year into accounts Truenote can't see), expectedRestOfYear (still expected this year; null: from expectedAmount) and expensesEstimate (deductible expenses for the year; null: its entity's spending). Fields you leave out keep their value; null clears. Changes the person's data: say what you set.
Scopes: `context:write`.
Arguments:
- `id`:
- `name` (required):
- `type`:
- `cadence`:
- `expectedAmount`: Dollars per payment
- `taxSetAsidePct`:
- `payerMatch`:
- `entityId`:
- `earner`: A household member's name
- `regular`: Counts toward the spending plan's income (default: true for w2)
- `active`:
- `notes`:
- `grossPay`: W-2: this year's salary, bonus apart
- `retirement`: W-2: 401(k)/403(b) deferrals for the year
- `otherPretax`: W-2: health, HSA, FSA through payroll, per year
- `withheldYtd`: W-2: federal income tax withheld so far this year (from a paystub)
- `withheldAsOf`: The paystub's date (with withheldYtd)
- `withholdingPerPaycheck`: W-2: federal income tax withheld per regular paycheck
- `bonus`: W-2: this year's bonus
- `bonusOn`: When the bonus was or will be paid
- `bonusWithholdingPct`: Default 22
- `receivedElsewhere`: 1099/business: paid this year into accounts Truenote can't see
- `expectedRestOfYear`: 1099/business: still expected this year (null: from expectedAmount)
- `expensesEstimate`: 1099/business: deductible expenses for the year (null: the entity's spending)
### `update_profile`: Update the household profile
Change the profile every agent reads first: the person's name, household members (each with a relationship, and a birthDate or, for a baby on the way, a dueDate), state (postal code like TX), filing status, risk tolerance, the free-form "about us" and time zone. Only the fields you pass change. householdMembers replaces the whole list: read get_context first and send everyone, including the person themself (relationship self). Changes the person's data: say what you set.
Scopes: `context:write`.
Arguments:
- `name`: What to call the person
- `householdMembers`:
- `state`:
- `filingStatus`:
- `riskTolerance`:
- `about`:
- `timeZone`: IANA zone, e.g. America/Chicago
### `upsert_entity`: Set an entity
Add or rename an entity money can belong to: the household (personal) or a business (an LLC, a side business). By id, else by name (case-insensitive), else new (then kind is required). Assign accounts and transactions to it with create_rule or categorize_transactions; each business's money is then reported on its own. Changes the person's data: say what you set.
Scopes: `context:write`.
Arguments:
- `id`: An existing entity to rename
- `name` (required):
- `kind`: personal or business
### `upsert_plan_line`: Set a spending plan line
Add or change a line of the spending plan (read get_plan first): by id, else by name (case-insensitive), else new (then group and amount are required). group is a group's name or id; amount is dollars per payment, cadence how often (default monthly; a $139 yearly Amazon Prime is amount 139, cadence annually). endsOn is the last day it's paid (a car loan's final month); startsOn delays a line that hasn't begun (daycare from April). match is text its payment's bank description or merchant contains ("Valon" for the mortgage, "CoServ" for electricity): a line with match and no destination is a bill, paid when a payment out contains it (find the text with query_transactions or get_recurring). accountId (from list_accounts) is where saved money goes (a brokerage: its own deposits count); bucketId (from list_buckets) is the bucket it fills ("Vacation / Travel" → the Vacations bucket), which also sets the account. categoryId (from get_context) only breaks everyday spending down (Groceries, Dining). Anything you leave out stays as it is. To cancel something, delete_record with kind plan_line. Changes the person's data: say what you set.
Scopes: `context:write`.
Arguments:
- `id`:
- `name` (required):
- `group`: A group's name or id
- `amount`: Dollars per payment
- `cadence`:
- `startsOn`:
- `endsOn`: The last day it's paid
- `categoryId`:
- `accountId`:
- `bucketId`: A bucket it fills (from list_buckets); the line then goes to its account
- `match`: Text its payment's bank description or merchant contains; null clears it
- `notes`:
### `upsert_plan_group`: Set a spending plan group
Add, rename or retarget a group of the spending plan: by id, else by name (case-insensitive), else new (then kind is required: spending for expenses and wants, saving for savings and investing). targetPct is the share of take-home it should hold (45 for 45%); the groups' targets usually add up to 100. Changes the person's data: say what you set.
Scopes: `context:write`.
Arguments:
- `id`:
- `name` (required):
- `kind`:
- `targetPct`:
- `position`: Order, 0 first
### `upsert_bucket`: Set a bucket
Create or change a bucket (a virtual part of a savings or checking account, see list_buckets): by id, else by name (case-insensitive; pass accountId when two accounts have a bucket with that name), else new (then accountId is required: a checking or savings account from list_accounts). target is the bucket's own goal in dollars and targetDate when it should be reached (both optional; null clears). startingBalance (new buckets only) is what it holds today; to correct an existing bucket's balance use record_bucket_entry with kind set_balance. overflow makes it the account's overflow bucket: what a deposit has left after filling what each bucket is due goes there (one per account; setting it moves it from another). archived hides a bucket once it's empty. This changes only Truenote's records, never the bank: no money moves. Say what you set.
Scopes: `context:write`, `accounts:read`.
Arguments:
- `id`:
- `name` (required):
- `accountId`: The account it splits (required for a new bucket)
- `target`: Dollars
- `targetDate`:
- `notes`:
- `overflow`: Extra from deposits goes here
- `archived`:
- `startingBalance`: Dollars it holds today (new buckets only)
### `move_between_buckets`: Move money between buckets
Move an amount from one bucket to another bucket of the same account (by name or id from list_buckets), e.g. $500 from Emergencies to Vacations. Both buckets change in one step; the account's total and Unassigned stay the same (unless it takes the from bucket below zero: what it's short comes out of Unassigned). This is Truenote's bookkeeping only: no money moves at the bank. date defaults to today (it can't be in the future). Say what you moved.
Scopes: `context:write`, `accounts:read`.
Arguments:
- `from` (required): A bucket's name or id
- `to` (required): A bucket's name or id, in the same account
- `amount` (required): Dollars
- `date`:
- `memo`:
### `record_bucket_entry`: Record a bucket entry
Record money going into or out of a bucket (by name or id from list_buckets) in Truenote's ledger. kind: contribution (money put into the account for this bucket, e.g. a transfer to savings), withdrawal (money taken out of the account from this bucket), charge (spending paid from another account, like a vet bill on checking, that this bucket covers: it needs the transactionId, and the bucket drops now while the account's total drops when the money is moved back), or set_balance (a correction: the bucket holds exactly amount as of date). transactionId (from query_transactions) ties the entry to the bank transaction it accounts for. date defaults to today. This never moves money at the bank. When unsure which bucket something belongs to, ask the person rather than guess. Say what you recorded.
Scopes: `context:write`, `accounts:read`.
Arguments:
- `bucket` (required): A bucket's name or id
- `accountId`: When two accounts have a bucket with that name
- `kind` (required):
- `amount` (required): Dollars (for set_balance: the balance it holds)
- `date`:
- `memo`:
- `transactionId`: The transaction it accounts for (needed for charge)
### `resolve_review_item`: Decide a review item
Decide an item from list_review_items for the person: decision approve does what its proposal says (or, with allocations, puts other amounts in other buckets: bucket names or ids, dollars; for a withdrawal, paysBack lists the charge entry ids it pays back instead of the proposal's), and createRule (a charge only, to one bucket) also saves the proposed bucket rule so the next match is automatic; decision dismiss leaves the transaction out of buckets for good (a deposit stays in Unassigned). Together the amounts can't be more than the transaction. Only decide what the person asked you to, or what's plainly right; otherwise ask. This is Truenote's bookkeeping: no money moves at the bank. Say what you decided.
Scopes: `context:write`, `accounts:read`, `transactions:read`.
Arguments:
- `id` (required): The item's id from list_review_items
- `decision` (required):
- `allocations`: Instead of the proposal's buckets and amounts
- `paysBack`: A withdrawal: the charge entry ids it pays back, instead of the proposal's
- `createRule`: A charge: also save the proposed bucket rule
### `create_bucket_rule`: Create a bucket rule
A rule that charges matching spending to a bucket automatically ("Banfield" → Pets), for everything since the bucket's start and every sync after: textContains is matched against the merchant and the bank's description (any case); accountId (from list_accounts), categoryId (from get_context) and minAmount/maxAmount (dollars) narrow it. Money out only. The first matching rule wins; a transaction the person already decided (charged by hand, an entry deleted, a review item answered) is left alone, and nothing is ever charged twice. Returns how many it charged right away. Prefer a specific text (a merchant's name) over a broad one: a wrong automatic charge is worse than a review item. Truenote's bookkeeping only: no money moves.
Scopes: `context:write`, `accounts:read`.
Arguments:
- `bucket` (required): A bucket's name or id from list_buckets
- `bucketAccountId`: When two accounts have a bucket with that name
- `textContains` (required):
- `accountId`: Only spending on this account
- `categoryId`: Only spending in this category
- `minAmount`:
- `maxAmount`:
### `add_note`: Remember a fact
Save a dated fact or decision for every agent to know later ("Baby due 2027-03-14", "Decided to pay the Visa in full monthly"). Short tags (lowercase words) help find it. Use for durable context, not for chat history.
Scopes: `context:write`.
Arguments:
- `body` (required):
- `occurredOn`: The day it's about, if any
- `tags`:
- `pinned`: Always shown first in get_context
### `update_note`: Change a note
Change a note (an id from get_context): fix or rewrite its body when a fact or decision changes, re-date it, retag it, or pin or unpin it (pinned notes always come first in get_context). What you leave out stays. Prefer this over adding a second note that contradicts the first. Changes the person's data: say what you changed.
Scopes: `context:write`.
Arguments:
- `id` (required):
- `body`:
- `occurredOn`: The day it's about; null: none
- `tags`: Replaces the note's tags
- `pinned`:
### `upsert_task`: Add or change a checklist task
Add a to-do to the person's checklist, or change one: by id, else by title (any case), else new. Use it for the dated actions a plan leaves behind ("Exercise options before the 409A", due 2026-11-06), one task per action, with a due date when there's a deadline. kind event is a dated thing that happens rather than something to do ("Brooke's due date", "JJ back to work", "Closing on the house"): it needs dueOn and has no checkbox. amount (dollars) is what it costs or brings when it's about money (the $15,000 a payment needs; it reads back as sum). done: true ticks it off, false opens it again. goalId (from get_context) or bucket (a name or id from list_buckets) say what it serves; null unlinks. spotlight: true makes it the Overview's countdown, at the top of the person's home page; there is only one, so this replaces the current one (list_tasks shows which). Spotlight the one dated event that matters most to the household's money in the coming months (a birth, a move, a wedding, a job change, a big payment being saved for), not routine to-dos; the person can change it. What you leave out stays. Truenote's records only: it never acts on the task. Tell the person what you added or changed.
Scopes: `context:write`.
Arguments:
- `id`:
- `kind`: task (default) or event
- `title` (required):
- `dueOn`: The day it's due (an event's day); null: no date
- `notes`:
- `done`:
- `amount`: Dollars; null clears it
- `spotlight`: The Overview's countdown; replaces the current one
- `goalId`:
- `bucket`: A bucket's name or id
- `bucketAccountId`: When two accounts have a bucket with that name
### `save_plan`: Save a plan
Save a named scenario for the person to review: a markdown body and structured assumptions (numbers, dates, lists) such as a parental-leave budget or a tax plan. By id, else by name, else new (status draft). Saving again with the same name updates it.
Scopes: `context:write`.
Arguments:
- `id`:
- `name` (required):
- `summary`:
- `body`: Markdown
- `assumptions`:
- `status`:
### `categorize_transactions`: Recategorize transactions
Set the category, entity (household or a business) or excluded flag of up to 200 transactions at once (ids from query_transactions, category and entity ids from get_context), and/or a note. A category, entity or exclusion set here wins over rules for those transactions. All of them change or none do. To fix a whole merchant going forward, use create_rule instead.
Scopes: `context:write`, `transactions:read`.
Arguments:
- `transactionIds` (required):
- `categoryId`: null: back to the automatic category
- `entityId`:
- `excluded`: true: leave out of spending and income
- `note`:
### `create_rule`: Create a categorization rule
A rule that sets the category, entity or excluded flag of every matching transaction, past and future (except ones edited by hand), and/or a business share: businessShare splits each match, percent of it going to a business entity as a part of its own (the rest stays the household's), for a bill partly used for business (internet 60% to the LLC). Conditions all must hold: merchant or description contains text, an account, an amount range in dollars (by size), a direction (outflow is money out). Returns how many transactions it now decides. Prefer this over categorize_transactions or split_transaction for anything recurring.
Scopes: `context:write`, `transactions:read`.
Arguments:
- `name` (required):
- `conditions` (required):
- `setCategoryId`:
- `setEntityId`:
- `setExcluded`:
- `businessShare`:
- `priority`: Lower runs first
### `split_transaction`: Split a transaction
Split one transaction (an id from query_transactions; a part's id means its whole) into parts that add up to it exactly, each with its own category, entity and note: the business part of a mixed purchase, a bill shared with the LLC. amount is each part's size in dollars (the whole's direction is kept). The parts count in place of the whole everywhere (spending, the plan, each business's taxes), and query_transactions lists them instead (with splitOf). Replaces any split it had; rules leave it alone afterwards. unsplit: true puts it back together. For a recurring share, use create_rule's businessShare instead. Changes the person's records only: say what you split.
Scopes: `context:write`, `transactions:read`.
Arguments:
- `transactionId` (required):
- `parts`:
- `unsplit`:
### `prepare_upload`: Prepare a document upload
Get a one-time link to keep one file (a paystub, W-2, 1099, 1098, tax return, statement, receipt; PDF or image, 10 MB at most) in the person's documents. Returns curl, a command that sends a local file straight to Truenote (replace FILE with the path; the file never passes through you), and uploadUrl, a page where the person drops the file themselves (for when you can't reach their files). Say what it is: kind, taxYear, documentOn, and the incomeSourceId a paystub is for (from get_context); name, kind and taxYear left out are guessed from the file's name. One call per file; the link lasts 15 minutes. Then read_document can read it.
Scopes: `documents:write`.
Arguments:
- `name`: Default: the file's name
- `kind`:
- `taxYear`:
- `documentOn`: The date on the document (a paystub's pay date)
- `entityId`: Whose it is (default: the household)
- `incomeSourceId`: The income source a paystub or W-2 is for
- `accountId`: The connected account a statement is of
- `manualAccountId`: The manual account (list_accounts) it's about: the mortgage, the HSA
- `notes`:
### `update_document`: Edit a document
Change what a kept document is and whose (an id from list_documents): name, kind, taxYear, documentOn (the date on it, e.g. a statement's date), entityId, incomeSourceId (the job a paystub or W-2 is for), accountId (a connected account a statement is of), manualAccountId (a manual account it's about, like the mortgage), notes. Fields you leave out keep their value; null clears. The file itself never changes, and documents can't be deleted here. Changes the person's records: say what you changed.
Scopes: `documents:write`.
Arguments:
- `id` (required):
- `name`:
- `kind`:
- `taxYear`:
- `documentOn`:
- `entityId`:
- `incomeSourceId`:
- `accountId`:
- `manualAccountId`:
- `notes`:
### `delete_record`: Delete a record
Delete one of the person's records by kind and id: goal, income_source, entity (its accounts and transactions go back to the household; rules that set it go too), category (transactions in it fall back to Plaid's mapping; rules that set it go too), rule (what it decided goes back to the other rules), manual_account (with its balance history), plan, plan_group (only once it has no lines), plan_line (something canceled or entered by mistake; for one that ends later, set its endsOn with upsert_plan_line so the plan shows what frees up), task (to finish one, upsert_task with done: true instead), note (when a decision changes, add the new note, then delete the old one so agents don't read both), bucket (its money goes back to Unassigned; no money moves), bucket_rule, bucket_entry (undoes one ledger entry: a move's both sides; an automatic one isn't redone; an archived bucket's entries stay; needs accounts:read). Ids come from get_context, get_plan, list_tasks, list_accounts, list_buckets and list_bucket_rules. Documents use delete_document. It can't be undone: confirm with the person first (a note or entry you made in this conversation excepted), then say what you deleted.
Scopes: `context:write`.
Arguments:
- `kind` (required):
- `id` (required):
### `delete_document`: Delete a document
Permanently delete an uploaded document (an id from list_documents): the file and its text. Use when the person asks, or for a duplicate or wrong upload. It can't be undone: confirm with the person first.
Scopes: `documents:write`.
Arguments:
- `id` (required):
### `upsert_category`: Add or change a category
Add a spending category, or rename one, change its kind (expense, income, transfer: transfers don't count as spending) or nest it under a parent (parentId, null: top level): by id, else by name (any case), else new (then kind is required). Which of the bank's categories land in it stays the person's to set in Truenote. Then categorize_transactions or create_rule to fill it. Say what you changed.
Scopes: `context:write`.
Arguments:
- `id`:
- `name` (required):
- `kind`:
- `parentId`:
### `update_rule`: Change a categorization rule
Change a rule (an id from get_context): its name, conditions (given conditions replace them all; amounts in dollars by size), what it sets (category, entity, excluded; null clears), its businessShare (null removes it), priority (lower runs first) or active (false pauses it). What you leave out stays. Saving re-decides every transaction nobody edited by hand. To remove a rule, delete_record with kind rule.
Scopes: `context:write`, `transactions:read`.
Arguments:
- `id` (required):
- `name`:
- `conditions`:
- `setCategoryId`:
- `setEntityId`:
- `setExcluded`:
- `businessShare`:
- `priority`:
- `active`:
### `update_account`: Change a bank account's settings
Change how Truenote treats a connected account (an id from list_accounts): nickname (null: the bank's name again), hidden (true drops it out of totals, net worth and this connection; only the person can show it again unless this connection sees hidden accounts) or entityId (the business it belongs to; null: the household). Never touches the bank. Say what you changed.
Scopes: `context:write`, `accounts:read`.
Arguments:
- `accountId` (required):
- `nickname`:
- `hidden`:
- `entityId`:
### `reset_transactions`: Undo transaction edits
Undo hand edits on transactions (ids from query_transactions): their category, entity, exclusion and any hand split go back to what the rules decide. Notes stay. Use when an earlier categorize_transactions or split_transaction was wrong.
Scopes: `context:write`, `transactions:read`.
Arguments:
- `transactionIds` (required):
### `refresh_bank`: Refresh a bank connection
Ask the bank for what's new on the connection holding an account (an id from list_accounts): balances and transactions, in the background (a minute or two). Use when the person says something posted that Truenote doesn't show yet. A connection that needs the person to sign in again can't be refreshed: tell them to reconnect it in Truenote.
Scopes: `context:write`, `accounts:read`.
Arguments:
- `accountId` (required):
### `disconnect_bank`: Disconnect a bank
Remove the bank connection holding an account (an id from list_accounts): Truenote stops syncing it, and every account on that connection and its history are deleted from Truenote. Truenote is read-only to banks: nothing changes at the bank itself. Connecting it again means the person signs in to the bank in Truenote. It can't be undone: confirm with the person first, naming every account it removes.
Scopes: `context:write`, `accounts:read`.
Arguments:
- `accountId` (required):
---
# API reference
> Every /v1 route, from the OpenAPI spec the server generates.
Canonical: https://usetruenote.com/docs/api
Base URL `https://app.usetruenote.com/v1`. Send `Authorization: Bearer ` (a personal access token from Connected agents, or an OAuth access token). The spec: https://app.usetruenote.com/v1/openapi.json. Money is integer cents; days are YYYY-MM-DD; transaction amounts keep Plaid's sign (positive is money out). Errors are JSON with a `code` and a message; 403 names the scope that's missing.
### GET /v1/overview
Net worth, this month, the plan, bills, goals and the next estimated tax in one call
Needs any read scope. Accounts and entities the token excludes are invisible here, totals included.
### GET /v1/accounts
Accounts with latest balances (debts negative), manual accounts and net worth totals
Needs accounts:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `type` (query, depository | credit | loan | investment | other): Only accounts of this type
- `includeHidden` (query, string): Include closed accounts, and accounts the person hid if this token may see hidden accounts
### GET /v1/transactions
Transactions newest first, filtered, keyset-paged (money in positive)
Needs transactions:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `from` (query, string): First day (inclusive); default: all history
- `to` (query, string): Last day (inclusive)
- `accountId` (query, uuid):
- `categoryId` (query): A category id (its subcategories included), or `none` for uncategorized
- `entityId` (query, uuid):
- `merchant` (query, string): Merchant or description contains this (any case)
- `q` (query, string): Description, merchant or note contains this
- `minAmountCents` (query, integer,null): Size at least this, in cents (either direction)
- `maxAmountCents` (query, integer,null):
- `direction` (query, in | out): Money in or money out
- `pending` (query, string):
- `ownerContribution` (query, string): true: only a business's spending paid from a personal account
- `limit` (query, integer): Rows per page (default 50, max 200)
- `cursor` (query, string): `nextCursor` of the last page
### GET /v1/spending
Spending grouped by category, merchant, entity or month: the household's by default (scope=all adds the businesses; entityId picks one)
Needs transactions:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `from` (query, string): Default: the first of this month
- `to` (query, string): Default: today
- `groupBy` (query, category | merchant | entity | month):
- `scope` (query, household | all): household (default): the personal entities, as the overview's month counts them; all: the household and every business together. Ignored with entityId
- `entityId` (query, uuid): Only this entity's spending (one business)
- `categoryId` (query, uuid): Only this category (and its subcategories)
- `limit` (query, integer): Groups to list (default 25); the rest are summed
### GET /v1/recurring
Recurring bills, subscriptions and income with next dates and monthly totals
Needs transactions:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `direction` (query, inflow | outflow):
- `includeInactive` (query, string):
### GET /v1/net-worth-history
Net worth over time by account type (day, week or month points)
Needs accounts:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `from` (query, string): Default: a year ago
- `to` (query, string): Default: today
- `interval` (query, day | week | month):
### GET /v1/holdings
Investment positions by account, optionally the latest investment transactions
Needs investments:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `accountId` (query, uuid):
- `includeTransactions` (query, string): Also the latest investment transactions (buys, sells, dividends)
### GET /v1/investment-transactions
Investment transactions newest first, filtered by date, account, type, subtype or symbol, keyset-paged, with totals by kind (cash in positive)
Needs investments:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `from` (query, string): First day (inclusive); default: all history
- `to` (query, string): Last day (inclusive)
- `accountId` (query, uuid):
- `type` (query, buy | sell | cash | fee | transfer | cancel):
- `subtype` (query, string): Plaid's subtype, any case: dividend, interest, buy, sell, deposit…
- `symbol` (query, string): Ticker, any case
- `q` (query, string): Description contains this
- `limit` (query, integer): Rows per page (default 50, max 200)
- `cursor` (query, string): `nextCursor` of the last page
### GET /v1/liabilities
Cards and loans: owed, APR, minimums, due dates
Needs liabilities:read. Accounts and entities the token excludes are invisible here, totals included.
### GET /v1/context
Profile, entities, income sources, goals, categories, rules, notes, plans
Needs context:read. Accounts and entities the token excludes are invisible here, totals included.
### GET /v1/plan
The spending plan: regular take-home split into groups and lines
Needs context:read. Accounts and entities the token excludes are invisible here, totals included.
### GET /v1/plan/actuals
Plan vs actual for a month: household spending per plan group and category line against the plan, the trailing 3 months' average, and spending no line names
Needs context:read, transactions:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `month` (query, string): A month like 2026-10; default this month
### GET /v1/taxes/projection
The year's federal tax projected from today: the statement line by line, the refund or amount owed, the extra withholding per paycheck that breaks even, the safe harbor
Needs context:read, transactions:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `year` (query, integer):
### GET /v1/tasks
The checklist: open tasks by due date (status=done|all for the rest)
Needs context:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `status` (query, open | done | all):
### GET /v1/buckets
Buckets: each account's virtual split, balances from Truenote's ledger, targets and what's Unassigned
Needs accounts:read, context:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `accountId` (query, uuid): Only this account's buckets
- `includeArchived` (query, string): Also archived buckets
- `recentEntries` (query, integer,null): Latest ledger entries per bucket (default 3)
### GET /v1/review-items
The Review queue: deposits to split, spending that looks like a bucket's, money taken out of a bucketed account, each with a proposal
Needs accounts:read, transactions:read, context:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `status` (query, open | resolved): open (default): waiting for a decision; resolved: the latest decided
### GET /v1/bucket-rules
Bucket rules: spending they charge to a bucket automatically, first match wins
Needs accounts:read, context:read. Accounts and entities the token excludes are invisible here, totals included.
### GET /v1/documents
Documents the person uploaded (paystubs, tax forms, statements), newest first
Needs documents:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `q` (query, string): Words in the name, notes or text (Social Security and account numbers masked)
- `kind` (query, paystub | w2 | form_1099 | form_1098 | tax_return | benefits | statement | receipt | other):
- `taxYear` (query, integer):
### POST /v1/documents
Keep a document for the person (multipart: file + metadata, a SaveDocument as JSON)
Needs documents:write. A PDF, PNG, JPEG or WebP image, at most 10 MB; the same file twice is a 409. Its entity, income source and account must be ones this token can see. Example: curl -H 'Authorization: Bearer tn_pat_…' -F file=@paystub.pdf -F 'metadata={"name":"Paystub Oct 16","kind":"paystub","taxYear":2026}' /v1/documents
### GET /v1/documents/{id}
One document's text (masked, paged by offset); an image's bytes are at /file
Needs documents:read. Accounts and entities the token excludes are invisible here, totals included.
Parameters:
- `id` (path, required, uuid): Id
- `offset` (query, integer,null): Where to continue a long text (the last call's nextOffset)
### GET /v1/documents/{id}/file
A document's file as uploaded (unmasked)
Needs documents:read.
Parameters:
- `id` (path, required, uuid): Id
### GET /v1/export
Everything this token can see, every table, as JSON (truenote-export/1)
Needs accounts:read, transactions:read, investments:read, liabilities:read, context:read. Accounts and entities the token excludes are invisible here, totals included.
### GET /v1/export.zip
The same export as a zip of CSV files, one per table
Needs accounts:read, transactions:read, investments:read, liabilities:read, context:read.
---
# Data conventions
> Money, dates, signs, ids, paging and errors, the same everywhere in the API and the tools.
Canonical: https://usetruenote.com/docs/conventions
- **Money.** The API uses integer cents in fields ending `Cents`; never floats. MCP tools format amounts as strings (`"$1,234.56"`) and write tools take plain dollars (`650` for $650.00). Rates are in basis points where they appear (`3000` = 30%).
- **Days** are `YYYY-MM-DD` strings. Instants are ISO 8601 with a zone.
- **Signs.** Transactions keep Plaid's convention in the API: positive is money out. Tools present them readably: money in `+$`, money out `-$`. A card's or loan's balance is what's owed, positive.
- **Household vs business.** Every account and transaction belongs to an entity. The household is the personal entities; each business is reported on its own. A business purchase on a personal card is flagged as an owner contribution.
- **Ids** are UUIDs. Someone else's id is a 404, the same as a missing one.
- **Paging** is keyset: pass back the `cursor` an answer gives you; `limit` caps a page.
- **Errors** are JSON `{ code, message, field? }`. 400 names the field; 403 names the scope that's missing; 429 means the per-grant limit (240 a minute).
- **Writes say who.** Rows an agent wrote carry the grant, and the audit log carries the call.
- **Hidden accounts** are out of lists, totals and pickers unless the grant was given them.
---
# Export and deletion
> Take everything out as JSON or CSV at any time, and what deleting the account does.
Canonical: https://usetruenote.com/docs/export
## Export
Settings → Your data exports everything you own: accounts, transactions, holdings, liabilities, the plan, buckets and their ledgers, goals, income sources, entities, categories, rules, notes, plans, tasks, documents' metadata, and the audit log. As one JSON document, or a zip of CSVs. Over the API: `GET /v1/export` and `GET /v1/export.zip` with any token that has the matching read scopes (the export holds only what the token may see).
## Deleting the account
Settings → Delete account (type your email to confirm). Every bank is removed at Plaid, so Plaid stops sharing; every agent's access is revoked; the audit log is purged; everything you own is deleted, sessions and passkeys included. If Plaid refuses one removal, the banks already removed stay removed, nothing else changes, and you can try again. Backups keep their copies until they age out (6 to 89 days).
## A lapsed subscription
Syncing stops. After a grace period your banks are removed at Plaid; your data is kept for 30 days (export still works), then deleted.