Ledger · CLI · MCP · API
Your household's money.
Root access.
Know where the household's money actually goes — one shared ledger for every account, currency, and receipt. A deterministic pipeline does the categorizing, an LLM handles the leftovers, and the whole thing is open to your own agents over MCP.
read-only PSD2 · EU data · AI inference in the EU · export everything, always
~ % claude "three transfers from last week are uncategorized — figure them out from my email"
⏺ spendprism · listTransactions(status=uncategorized, days=7) → 3 rows
⏺ gmail · search("Allegro OR InPost OR zamówienie after:2026/06/25") → 5 threads
⏺ spendprism · getTransaction(tx_9f2c) → PRZELEW · −184,99 zł · 2026-06-27
matched → Allegro order #4821-33 „lampka nocna, kabel USB-C”
⏺ spendprism · suggestCategory(tx_9f2c → Dom i ogród) [+2 more]
✓ 3 suggestions staged. Nothing lands in the ledger until you approve.
- MT940 + CSV import
- PLN / EUR / USD, one ledger
- NBP daily rates
- dedup: app-level + DB-level
- 18 MCP tools
- read-only PSD2
How it's built
Deterministic first. The model last. You commit.
Every transaction walks the same gauntlet. Most never reach the model.
transactions in
├─ merchant catalog → resolved · 0 tokens spent
├─ your rules → resolved · 0 tokens spent
├─ LLM batch → suggested · grouped by merchant, with rationale
└─ you → the only writer
AI suggests. Only you commit. Nothing lands in the ledger until a human says so — it's a review workflow, not an autopilot.
-
Deterministic first, AI second
A merchant catalog and your rules clear the obvious for free. The model only ever sees the remainder.
-
Grouped by merchant, with reasoning
Suggestions arrive bundled per merchant with a confidence level and a short rationale. Accept a group at once, or refine.
-
Similarity-guarded propagation
Approve one merchant and it propagates to matching transactions — guarded by similarity, never blindly.
Open surface
The same API the app runs on. Yours.
Spendprism doesn't just use AI — it's built to be used by yours. MCP server and CLI are first-party, speak the same permission-checked API as the app, and ship in the free tier.
claude mcp add spendprism \ --transport http \ --client-id spendprism-mcp \ https://spendprism.com/mcp
{
"mcpServers": {
"spendprism": {
"type": "http",
"url": "https://spendprism.com/mcp",
"oauth": { "clientId": "spendprism-mcp" }
}
}
} | read | listTenants · listAccounts · listTransactions · getTransaction · listCategories · listTags |
|---|---|
| write | categorizeTransaction · suggestCategory · bulkAnnotate · updateTransactionNote · createCategory · updateCategory · createTag |
| import | importTransactions · getImportStatus · listImportErrorRows · listImportSkippedRows |
| analytics | pivot |
OAuth against your account (PKCE, no client secret), scoped to your household. Your agent can never see another tenant — the same authorization aspect that guards the app guards it.
spendprism transactions list --counterparty biedronka spendprism pivot --rows CATEGORY_ID --columns MONTH --from 2026-01 --to 2026-06 --json spendprism imports start-mt940 --file wyciag_czerwiec.sta
data → stdout · messages → stderr · --json everywhere · pipes cleanly into jq
curl -H "Authorization: Bearer $TOKEN" \ https://spendprism.com/api/tenants/$TENANT/accounts
the exact endpoints the webapp calls — nothing privileged, nothing hidden
FX & edge cases
The ugly rows are the product.
Real bank data is messy: three currencies, duplicate card authorizations, statement files that reuse bank references. The ledger stays correct anyway — that's the job.
- ✓ original currency preserved on every row
- ✓ consolidated totals at daily NBP rates
- ✓ base currency is the owner's choice
- ✓ ING card-authorization rows deduped against posted transactions
- ✓ MT940 shared-bank-reference collisions handled
- ✓ import dedup at app level and DB level
In the shot: 2450,00 EUR ≈ 10 499,97 PLN — the conversion the app itself rendered, at the day's NBP rate, rolling into one base-currency total.
Analytics
Analysis state is a URL.
The pivot — category × month, quarter, account, tag, counterparty — lives entirely in the query string. Bookmark a view, send it to your partner, or have your agent open it with the filters already set. Drill into any cell to the exact transactions behind it.
https://spendprism.com/analytics?granularity=QUARTER&dateMode=TRAILING_4Q&from=2025-10-01&to=2026-09-30&tagId=2672df31
- Slice by category, account, tag, period, counterparty
- Drill down from any cell to the raw rows
-
The same pivot is one MCP call:
pivot()
Built for two (or more)
The other user of your system.
You run the stack; your household just uses a friendly app. You read it in English, she reads it in Polish — language is per user, not per household. Same ledger, same live picture, and nobody ever needs to see a terminal.
Invite by email
Send one link. They accept, and the household appears in their dashboard — no setup on their side.
Roles that fit
Owners manage members and settings; everyone else keeps the books up to date.
Every edit attributed
Each change carries the member who made it. No more “did you log that?”
Also in the box
The rest, in one line each.
Receipt OCR, line by line
Snap a paper receipt in the mobile app — every item read, bound to the matching bank transaction, category split drafted for your one-tap confirm.
Rules engine with preview
Counterparty is “Netflix” → Subskrypcje. See what a rule would hit before it runs.
Splits & tags
One card payment, three categories. Tag groups for cross-cutting views.
Hierarchical categories
13 curated parents with income/expense/transfer types — extend them with your own.
Saved views
The monthly reviews you actually reopen — one click away.
Cash wallets
The rest of life, on the same ledger as the banks.
Pricing
The open surface is free.
You can run the whole system by hand at 0 zł — importing files, categorizing, pivoting, scripting it over MCP. You pay for the two things that cost us money: bank connections and model inference. early-access pricing
Ledger
0 zł forever
- Full ledger — splits, tags, categories
- File imports: CSV + MT940
- Pivot analytics + saved views
- CLI + MCP + REST API
- Invite your household
Sync
20 zł / month
- Everything in Ledger
- PSD2 bank sync — transactions arrive on their own
- AI categorization & receipt OCR, monthly cap
FAQ
The questions you should be asking.
Where does the AI run?
Inference runs in the EU. Only transaction descriptions and amounts go to the model — never account numbers, balances, or credentials. Deterministic matching resolves most transactions before any model is involved.
What happens if you shut down?
You export everything — transactions, splits, categories, receipts — as plain JSON through the same API the app uses, via CLI or MCP, any time. Export is a standing capability, not a hostage negotiation.
Is my data used to train models?
No.
Which banks and formats?
PSD2 sync for EU banks. File import for PKO BP, ING, mBank and Revolut CSV, and any MT940 statement. Manual cash wallets for the rest of life.
Is this a budgeting app?
No — it's a ledger. A rear-view mirror done right, on purpose. If you need envelopes and goals today, YNAB is better at that. If you need to know where money actually went — across banks, currencies, and two people — that's us.
Can I self-host?
Not today. But the open API surface means you're never locked in on intelligence or analysis, and export is always one command away.
Who builds this?
Spendprism is built in Poland and runs EU-first. Say hello — the reply comes from a person.