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