Habeas

Bank connections for your app, without an aggregator

If you build a personal-finance app, you already know the wall: reading your users' bank transactions programmatically means paying an aggregator, and the entry price is out of reach for a small team. Habeas is another way in. It is free, open source, and any app can use it.

The short version. Habeas is a browser extension your user installs. It reads their own data from their own authenticated session, on their machine, and delivers it to an endpoint on your domain. No server-side scraping, no stored credentials, no third party accumulating anyone's financial history.

How it works

  1. Your user installs Habeas and enables the sources they care about (their bank, their broker).
  2. Your app asks for a connection. Habeas opens its own consent screen. Nothing runs until the user approves it there.
  3. Data arrives at your endpoint, already normalized, as new items appear. You acknowledge what you actually stored; the rest is retried.

Two ways to integrate

Pull — you fetch

You propose a specific source, and once the user approves it you can trigger collection whenever you want (a "Sync" button in your UI).

await habeas('propose-workflow', {
  source: 'ing-es',
  sink: {
    type: 'http',
    url: 'https://your-app.com/ingest',
    headers: { 'x-pair-token': '…' },
  },
});
// then, later:
await habeas('collect', { grantId });

Push — they send

You register only as a destination, with no source and no permission to fetch anything. The user routes whichever sources they want to you, from Habeas.

await habeas('register-sink', {
  sink: {
    type: 'http',
    url: 'https://your-app.com/ingest',
    headers: { 'x-pair-token': '…' },
  },
});

Both are documented in external-hooks.md. Most apps start with pull and add push later.

What you receive

The rules that make this safe

These are enforced in code, not promised in a contract:

The bank your users need: they can add it themselves

The obvious objection to any catalog is "my users' bank isn't in it". Here's the part that matters: nobody has to wait for us to add it.

Reading happens inside the account holder's own session, which means the person who can teach Habeas a new bank is whoever already banks there — not us. So the extension ships a recorder for exactly that, in Settings → Record & contribute:

  1. The user browses their bank as they normally would, signed in, while it records.
  2. Habeas drafts the source automatically from what it saw — endpoints, paging, fields — and the user maps anything left over in a visual editor, with a Test button that runs against their live session so they see real rows before sharing anything.
  3. What reaches us is redacted: every value is replaced by a type placeholder and only the structure survives. We author and verify the source without ever seeing their data.
  4. Once published, that source works for everyone — your users and ours.

No code is written by anyone, and a source is a definition file rather than a program, which is why this can be a commons at all. If you'd rather write one by hand, that path is open too: AUTHORING-SOURCES.md and ASSISTED-AUTHORING.md.

This is where collaborating actually pays off. Adapters are shared plumbing; the product you build on top is where you compete.

What this is not

So you can decide with the real trade-offs on the table:

Start here

Integration guide API reference Source (AGPL-3.0)

Habeas is licensed under AGPL-3.0: if you improve it, the improvements come back to the commons. Cuéntamo was the first app to integrate it, and it is not meant to be the last.

Building something and hit the same wall? Open an issue on GitHub, or write to hola@habeas.dev.