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 Resources → Libraries
  3. In the “Add a Library” field, enter the Script ID:
    1hMJszJGSUVZDB3vmsWrUZfRhY1UWbhS0SQ6Lzl06gm1zhBF3ioTM7mpJ
  4. Choose the latest version and click Save

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.