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.

Open the app

read-only PSD2 · EU data · AI inference in the EU · export everything, always

The Spendprism ledger — categorized transactions with tags and inline currency conversions, 124 results across PLN, EUR and USD
your agent · gmail + spendprism over MCP

~ % 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.

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.

A live AI category suggestion on a EUR transfer — proposed category, plain-language rationale, and an Apply button the human must press

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 code
claude mcp add spendprism \
  --transport http \
  --client-id spendprism-mcp \
  https://spendprism.com/mcp
.mcp.json — any MCP client
{
  "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.

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.

Accounts across PLN, EUR and USD consolidated into one base-currency total at NBP daily rates

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.

a saved analysis — copy it, send 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()
Pivot analytics — income vs expenses per month with a category-by-month breakdown table over the demo ledger

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.

A real Biedronka receipt OCR'd into line items with an AI-drafted category breakdown awaiting confirmation

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
Start free

Sync

20 zł / month

  • Everything in Ledger
  • PSD2 bank sync — transactions arrive on their own
  • AI categorization & receipt OCR, monthly cap
Get started

Unlimited

35 zł / month

  • Everything in Sync
  • Unmetered AI categorization & receipt OCR
Get started

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.