Skip to content

Apps Script Development

Use the bkper-gs library to build Bkper automations that run inside Google's serverless Apps Script platform — scheduled jobs, spreadsheet triggers, custom add-ons, and workflows that combine Bkper with Sheets, Drive, and Gmail.

Google Apps Script is Google’s serverless platform for extending Google Workspace. With the bkper-gs library, you can build Bkper automations that run inside Google’s infrastructure — no servers, no deployment pipeline, and native access to Sheets, Drive, Calendar, and Gmail.

When to use Apps Script

Use Apps Script when your automation lives in the Google Workspace ecosystem:

  • Scheduled jobs that read from or write to Google Sheets
  • Spreadsheet triggers (on-edit, on-form-submit) that record transactions
  • Custom add-ons distributed to a team or domain
  • Workflows that combine Bkper with other Google services (Drive, Calendar, Gmail)

If you need real-time event handling, a web UI, or automation that runs outside Google Workspace, use Node.js scripts or a platform app instead.

Setup

Add the library

bkper-gs is published as an Apps Script library. To add it to your script:

  1. Open your script in the Apps Script editor
  2. Click + next to Libraries in the left-side panel
  3. In the “Script ID” field, enter:
    1hMJszJGSUVZDB3vmsWrUZfRhY1UWbhS0SQ6Lzl06gm1zhBF3ioTM7mpJ
  4. Click Look up, choose the latest version, and click Add

The BkperApp global is now available in your script.

TypeScript definitions

For TypeScript development with autocomplete, install the type definitions:

Terminal window
npm i -S @bkper/bkper-gs-types

Configure tsconfig.json:

{
"compilerOptions": {
"typeRoots": ["node_modules/@bkper", "node_modules/@types"]
}
}

See Develop Apps Script using TypeScript and use clasp to push TypeScript projects to Apps Script.

The BkperApp entry point

BkperApp works the same way as CalendarApp, DocumentApp, and SpreadsheetApp — it’s a global entry point that follows familiar Apps Script conventions.

The book ID comes from the URL when you open a book at bkper.com:

// Get a book by its ID (from the URL)
const book = BkperApp.getBook('agtzfmJrcGVyLWhyZHIOCxIGTGVkZ2VyGNKJAgw');

Common patterns

Get a book

function getBookName() {
const book = BkperApp.getBook('agtzfmJrcGVyLWhyZHIOCxIGTGVkZ2VyGNKJAgw');
Logger.log(book.getName());
}

Record a transaction

function recordTransaction() {
const book = BkperApp.getBook('agtzfmJrcGVyLWhyZHIOCxIGTGVkZ2VyGNKJAgw');
book.record('#gas 63.23');
}

Transactions use the same shorthand syntax you’d use in the Bkper UI.

Batch record transactions

For bulk operations, pass an array. The library sends all records in a single API call — important for avoiding Apps Script execution time limits:

function importExpenses() {
const book = BkperApp.getBook('agtzfmJrcGVyLWhyZHIOCxIGTGVkZ2VyGNKJAgw');
const transactions = [
'#breakfast 15.40',
'#lunch 27.45',
'#dinner 35.86',
];
book.record(transactions);
}

Query transactions

The getTransactions() method returns a TransactionIterator for handling large datasets without loading everything into memory:

function listTransactions() {
const book = BkperApp.getBook('agtzfmJrcGVyLWhyZHIOCxIGTGVkZ2VyGNKJAgw');
const iterator = book.getTransactions("account:'Bank' after:01/01/2024");
while (iterator.hasNext()) {
const transaction = iterator.next();
Logger.log(transaction.getDescription());
}
}

See Querying Transactions for the full query syntax.

List accounts with balances

function listAccountBalances() {
const book = BkperApp.getBook('agtzfmJrcGVyLWhyZHIOCxIGTGVkZ2VyGNKJAgw');
const accounts = book.getAccounts();
for (const account of accounts) {
if (account.isPermanent() && account.isActive()) {
Logger.log(`${account.getName()}: ${account.getBalance()}`);
}
}
}

Building triggers

Apps Script triggers let your automation run on a schedule or respond to spreadsheet events — without any always-on infrastructure.

Time-based (scheduled)

function setupDailySync() {
ScriptApp.newTrigger('syncTransactions')
.timeBased()
.everyDays(1)
.atHour(6)
.create();
}
function syncTransactions() {
const book = BkperApp.getBook('YOUR_BOOK_ID');
const sheet = SpreadsheetApp.openById('YOUR_SHEET_ID').getActiveSheet();
// Read rows from Sheets, record to Bkper
const rows = sheet.getDataRange().getValues();
const transactions = rows.slice(1).map(row => `${row[0]} ${row[1]} ${row[2]}`);
book.record(transactions);
}

Spreadsheet edit trigger

function onEdit(e) {
const sheet = e.source.getActiveSheet();
if (sheet.getName() !== 'Expenses') return;
const row = e.range.getRow();
const amount = sheet.getRange(row, 3).getValue();
const description = sheet.getRange(row, 2).getValue();
if (amount && description) {
const book = BkperApp.getBook('YOUR_BOOK_ID');
book.record(`${description} ${amount}`);
}
}

TypeScript development workflow

For non-trivial scripts, use clasp for local development with TypeScript:

Terminal window
# Install clasp
npm install -g @google/clasp
# Log in
clasp login
# Clone an existing script
clasp clone <scriptId>
# Push changes
clasp push
# Watch for changes
clasp push --watch

With @bkper/bkper-gs-types configured, your editor provides full autocomplete for BkperApp, Book, Transaction, Account, and all other bkper-gs types.

API reference

The complete bkper-gs reference is at bkper.com/docs/bkper-gs.