
# Use the library

The npm package that installs the CLI is also a Node.js library. The CLI calls the same functions, so anything a command can do, your code can do.

```bash
npm install @finopsbricks/fob-actual
```

It's an ES module and needs Node.js 22 or later.

## A client per budget

```js
import { fobActual } from '@finopsbricks/fob-actual';

const actual = fobActual({
  server_url: 'https://budget.example.com',
  session_token: process.env.ACTUAL_TOKEN,
  sync_id: '1b4e28ba-2fa1-41d2-883f-0016d3cca427',
  data_dir: '/var/cache/fob-actual/household',
  // encryption_password: '…',   // for an end-to-end encrypted budget
});

const accounts = await actual.accounts.list();
const balance = await actual.accounts.balance(accounts[0].id);
```

- The library takes credentials **only as arguments**. It never reads environment variables or the CLI's config file.
- `data_dir` is where the engine keeps its local copy of the budget. Use one folder per budget, and keep it private: it's a full copy, decrypted if the budget is encrypted.
- `sync_id` is needed for everything except `budgets.list()`.

## Sessions and hold()

Each call opens the budget (fetching the latest changes), does its work, syncs any writes, and closes. That's simple but repeats the open for every call. To make several calls share one open session, wrap them in `hold()`:

```js
const report = await actual.hold(async () => {
  const out = {};
  for (const a of await actual.accounts.list()) out[a.name] = await actual.accounts.balance(a.id);
  return out;
});
```

Writes inside `hold()` sync once, when it finishes.

The Actual engine allows **one budget session per process**. Don't run calls on two clients at the same time; for several budgets, use them one after another.

## What's on the client

| Namespace | Covers |
| --- | --- |
| `budgets` | List budget files, months, a month's budget, set amounts, carryover, hold |
| `accounts` | List, get, balance, create, update, close, reopen, delete |
| `transactions` | List by account and dates, add, import (duplicate detection and rules), update, delete |
| `categories`, `categoryGroups`, `payees`, `tags` | List, get, create, update, delete; merge payees |
| `rules`, `schedules` | List, get, create, update, delete |
| `query` | Run an ActualQL query |

Plus `serverVersion()` and `hold(fn)`. Amounts are Actual's integer minor units throughout.

## Errors

Failures throw `ActualError` (exported) with a `code` you can branch on, such as `token-expired`, `network-failure`, `file-not-found` or `needs-key`. The messages match the CLI's; see [Troubleshooting](/docs/actual/troubleshooting).
