Skip to content

Event Handlers

Write code that reacts to book events — checked transactions, new accounts, comments — to automate calculations, sync data between books, and call external services. Covers response format, loop prevention, and replay.

Event handlers are the code that reacts to events in your Bkper Books. When a transaction is checked, an account is created, or any other event occurs, your handler receives it and can take action — calculate taxes, sync data between books, post to external services, and more.

Bkper Event Handler

How it works

  1. You declare which events your app handles in bkper.yaml
  2. Bkper sends an HTTP POST to your webhook URL when those events fire
  3. Your handler processes the event and returns a response

On the Bkper Platform, events are routed to your events package automatically — including local development via tunnels. For self-hosted setups, you configure the webhook URL directly.

Agent identity

Event handlers run on behalf of the user who installed the app. Their transactions and activities are identified in the UI by the app’s logo and name:

Event handler agents identified in the activity stream

Responses

Handler responses are recorded in the activity that triggered the event. You can view and replay them by clicking the response at the bottom of the activity:

Event handler responses in the activity stream

Response format

Your handler must return a response in this format:

{ result?: string | string[] | boolean; error?: string; warning?: string }
  • The result is recorded as the handler response in the book activity
  • If you return { result: false }, the response is suppressed and not recorded
  • Errors like { error: "This is an error" } show up as error responses

To show the full error stack trace for debugging:

try {
// handler logic
} catch (err) {
return { error: err instanceof Error ? err.message : String(err) }
}

HTML in responses

If you return an HTML snippet (e.g., a link) in the result, it will be rendered in the response popup.

Development mode

Event handlers run in Development Mode when executed by the developer or owner of the App.

In development mode, both successful results and errors are shown as responses:

Event handler error in development mode

You can click a response to replay failed executions — useful for debugging without recreating the triggering event.

Preventing loops

When your event handler creates or modifies transactions, those changes fire new events. To prevent infinite loops, check the event.agent.id field:

function handleEvent(event: bkper.Event) {
// Skip events triggered by this app
if (event.agent?.id === 'your-app-id') {
return { result: false }
}
// Process the event
// ...
}

This pattern is essential for any handler that writes back to the same book.

Event routing pattern

On the Bkper Platform, the events package uses Hono to receive webhook calls. A typical pattern routes events by type:

app.post('/', async (c) => {
const event: bkper.Event = await c.req.json()
switch (event.type) {
case 'TRANSACTION_CHECKED':
return c.json(await handleTransactionChecked(book, event))
case 'ACCOUNT_CREATED':
return c.json(await handleAccountCreated(book, event))
default:
return c.json({ result: false })
}
})

For the full event type reference, see Events.