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.
npm install @finopsbricks/fob-actual
It's an ES module and needs Node.js 22 or later.
A client per budget#
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_diris 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_idis needed for everything exceptbudgets.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():
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.