Node.js Scripts
Write standalone Node.js scripts with bkper-js for complex logic, bulk data operations, scheduled jobs, and integrations that go beyond what the CLI alone can do.
For tasks that go beyond CLI piping — complex logic, external API integration, scheduled jobs — write a Node.js script with bkper-js.
Setup
# Create a script projectmkdir my-bkper-script && cd my-bkper-scriptnpm init -ynpm install bkper-js bkperAuthenticate once via the CLI:
bkper auth loginThe pattern
Every script follows the same structure: authenticate, get a book, do work.
import { Bkper } from 'bkper-js';import { getOAuthToken } from 'bkper';
Bkper.setConfig({ oauthTokenProvider: async () => getOAuthToken(),});
const bkper = new Bkper();const book = await bkper.getBook('your-book-id');
// Your logic hereExamples
Export balances to JSON
import { Bkper } from 'bkper-js';import { getOAuthToken } from 'bkper';import { writeFileSync } from 'fs';
Bkper.setConfig({ oauthTokenProvider: async () => getOAuthToken(),});
const bkper = new Bkper();const book = await bkper.getBook('your-book-id');
const report = await book.getBalancesReport('on:2025-12-31');const rows = report.getBalancesContainers().map(container => ({ name: container.getName(), balance: container.getCumulativeBalance().toString(),}));
writeFileSync('balances.json', JSON.stringify(rows, null, 2));console.log(`Exported ${rows.length} balances`);Bulk-create accounts from a JSON export
import { Account, Bkper } from 'bkper-js';import { getOAuthToken } from 'bkper';import { readFileSync } from 'fs';
type AccountInput = { name: string; type: 'ASSET' | 'LIABILITY' | 'INCOMING' | 'OUTGOING'; groups?: Array<{ id?: string; name?: string }>;};
Bkper.setConfig({ oauthTokenProvider: async () => getOAuthToken(),});
const bkper = new Bkper();const book = await bkper.getBook('your-book-id');
const data: AccountInput[] = JSON.parse(readFileSync('accounts.json', 'utf-8'));
const accounts = data.map(acc => { const account = new Account(book).setName(acc.name).setType(acc.type); if (acc.groups?.length) { account.setGroups(acc.groups); } return account;});
const created = await book.batchCreateAccounts(accounts);console.log(`Created ${created.length} accounts`);Query transactions and generate a report
import { Amount, Bkper } from 'bkper-js';import { getOAuthToken } from 'bkper';
Bkper.setConfig({ oauthTokenProvider: async () => getOAuthToken(),});
const bkper = new Bkper();const book = await bkper.getBook('your-book-id');
const result = await book.listTransactions('account:Expenses after:2025-01-01');
let total = new Amount(0);for (const tx of result.getItems()) { const amount = tx.getAmount(); if (!amount) continue;
total = total.plus(amount); console.log(`${tx.getDate()} | ${tx.getDescription()} | ${amount.toString()}`);}console.log(`\nTotal: ${total.toString()}`);Scheduled jobs
With cron
# Run daily at 8am0 8 * * * cd /path/to/script && node export.mjsIn CI environments
The CLI helper getOAuthToken() is designed for local developer machines, where the CLI can store and refresh credentials. In GitHub Actions or other unattended environments, provide your own token source:
import { Bkper } from 'bkper-js';
const bkper = new Bkper({ oauthTokenProvider: async () => { const token = process.env.BKPER_OAUTH_TOKEN; if (!token) { throw new Error('BKPER_OAUTH_TOKEN is not set'); } return token; },});Use this pattern only when another system is already issuing and rotating the token for the job. For unattended long-running automation, implement your own OAuth flow instead of relying on the CLI’s locally stored credentials.
Error handling
Wrap API calls with proper error handling:
import { BkperError } from 'bkper-js';
try { const book = await bkper.getBook('your-book-id'); // ...} catch (error) { if (error instanceof BkperError && error.code === 404) { console.error('Book not found'); } else if (error instanceof BkperError && error.code === 403) { console.error('No access to this book'); } else if (error instanceof Error) { console.error('API error:', error.message); } else { console.error('Unknown error:', String(error)); } process.exit(1);}When to use scripts vs apps
| Scenario | Use |
|---|---|
| One-off data migration | Script |
| Scheduled export/report | Script |
| Reacting to book events in real time | Platform app |
| Custom UI for users | Platform app |
| Complex multi-step workflow with external APIs | Script or app, depending on trigger |
Next steps
- bkper-js API Reference — Full SDK documentation
- CLI Scripting & Piping — For simpler tasks, the CLI may be enough
- Direct API Usage — Use the REST API from any language