# Bkper REST API

> Full OpenAPI reference for the Bkper REST API — endpoints, parameters, and response schemas.

RESTful API for managing financial books, accounts, transactions, and balances in [Bkper](https://bkper.com).

## Base URL

```
https://api.bkper.app
```

All endpoints are under `/v5/`. For example:
- `GET https://api.bkper.app/v5/user` — Get the authenticated user
- `GET https://api.bkper.app/v5/books` — List books
- `GET https://api.bkper.app/v5/books/{bookId}` — Get a specific book

## Authentication

All requests require a [Google OAuth2](https://developers.google.com/identity/protocols/oauth2) access token with the `email` scope, sent as a Bearer token:

```
Authorization: Bearer <access_token>
```

### Getting a token

The easiest way to authenticate is through the [Bkper CLI](https://www.npmjs.com/package/bkper), which manages the OAuth flow for you:

```bash
npm i -g bkper
bkper auth login  # Opens browser for Google sign-in
bkper book list   # You're connected
```

For programmatic access, use a client library that handles token management:

- **Node.js** — [bkper-js](https://www.npmjs.com/package/bkper-js) with the CLI's `getOAuthToken()` for local scripts, or with [@bkper/web-auth](https://www.npmjs.com/package/@bkper/web-auth) for browser apps
- **Google Apps Script** — [bkper-gs](https://www.npmjs.com/package/@bkper/bkper-gs) library, which uses Apps Script's built-in OAuth

You can also set up your own [OAuth2 client credentials](https://developers.google.com/identity/protocols/oauth2) in a Google Cloud project if you need full control over the authentication flow.

## API Key (optional)

For dedicated quota and project-level usage tracking, you can pass an API key via the `key` query parameter. API keys are for quota management only — they do not replace OAuth2 authentication.

## OpenAPI Specification

The machine-readable spec is available at [`https://bkper.com/docs/api/rest/openapi.json`](https://bkper.com/docs/api/rest/openapi.json). Use it with Swagger UI, Postman, or any OpenAPI-compatible tool.

Content-Type: `application/json`

## Endpoints

All `/v5/books/{bookId}/...` endpoints require `bookId` (path, string, required) — the book's unique identifier.

### Apps

#### `GET /v5/apps` — listApps

**Response 200:** AppList

**Response default:** ApiError

#### `POST /v5/apps` — createApp

**Request body:** App

**Response 200:** App

**Response default:** ApiError

#### `PUT /v5/apps` — updateApp

**Request body:** App

**Response 200:** App

**Response default:** ApiError

#### `GET /v5/apps/{agentId}` — getApp

**Parameters:**

- `agentId` (path, string, required)

**Response 200:** App

**Response default:** ApiError

### Books

#### `GET /v5/books` — listBooks

**Parameters:**

- `query` (query, string) — Optional search term to filter books

**Response 200:** BookList

**Response default:** ApiError

#### `POST /v5/books` — createNewBook

**Parameters:**

- `name` (query, string)

**Request body:** Book

**Response 200:** Book

**Response default:** ApiError

#### `PUT /v5/books` — updateBook

**Request body:** Book

**Response 200:** Book

**Response default:** ApiError

#### `GET /v5/books/{bookId}` — getBook

Load a book

**Parameters:**

- `loadAccounts` (query, boolean) — Optionally load accounts and groups
- `loadGroups` (query, boolean) — Optionally load groups

**Response 200:** Book

**Response default:** ApiError

#### `PUT /v5/books/{bookId}` *(deprecated)* — updateBookDeprecated

**Request body:** Book

**Response 200:** Book

**Response default:** ApiError

#### `DELETE /v5/books/{bookId}` — deleteBook

**Response 200:** Book

**Response default:** ApiError

#### `GET /v5/books/{bookId}/apps` — listBookApps

**Response 200:** AppList

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/audit` — auditBook

Audit a book async

**Response 204:** Successful response with no content.

**Response default:** ApiError

#### `POST /v5/books/{bookId}/copy` — copyBook

Copy a book with optional transaction copying

**Parameters:**

- `name` (query, string) — Name for the copied book
- `copyTransactions` (query, boolean) — Whether to copy transactions
- `fromDate` (query, integer (int32)) — Start date for copying transactions (YYYYMMDD format)

**Response 200:** Book

**Response default:** ApiError

### Accounts

#### `GET /v5/books/{bookId}/accounts` — listAccounts

**Response 200:** AccountList

**Response default:** ApiError

#### `POST /v5/books/{bookId}/accounts` — createAccount

**Request body:** Account

**Response 200:** Account

**Response default:** ApiError

#### `PUT /v5/books/{bookId}/accounts` — updateAccount

**Request body:** Account

**Response 200:** Account

**Response default:** ApiError

#### `POST /v5/books/{bookId}/accounts/batch` — createAccountsBatch

Batch create accounts

**Request body:** AccountList

**Response 200:** AccountList

**Response default:** ApiError

#### `PUT /v5/books/{bookId}/accounts/batch` — updateAccountsBatch

Batch update accounts

**Request body:** AccountList

**Response 200:** AccountList

**Response default:** ApiError

#### `POST /v5/books/{bookId}/accounts/delete/batch` — deleteAccountsBatch

Batch delete accounts

**Request body:** AccountList

**Response 200:** AccountList

**Response default:** ApiError

#### `GET /v5/books/{bookId}/accounts/{id}` — getAccount

**Parameters:**

- `id` (path, string, required) — The account id or name

**Response 200:** Account

**Response default:** ApiError

#### `DELETE /v5/books/{bookId}/accounts/{id}` — deleteAccount

**Parameters:**

- `id` (path, integer (int64), required) — The account id

**Response 200:** Account

**Response default:** ApiError

#### `GET /v5/books/{bookId}/accounts/{id}/groups` — listAccountGroups

List the groups of an account

**Parameters:**

- `id` (path, string, required) — The account id or name

**Response 200:** GroupList

**Response default:** ApiError

### Balances

#### `GET /v5/books/{bookId}/balances` — getBalances

**Parameters:**

- `query` (query, string, required) — The query to filter balances

**Response 200:** Balances

**Response default:** ApiError

### Collaborators

#### `GET /v5/books/{bookId}/collaborators` — listCollaborators

List collaborators of the book

**Response 200:** CollaboratorPayloadCollection

**Response default:** ApiError

#### `POST /v5/books/{bookId}/collaborators` — addCollaborator

Add or update a collaborator to the book

**Parameters:**

- `message` (query, string) — Optional message to send with the invitation email

**Request body:** Collaborator

**Response 200:** Collaborator

**Response default:** ApiError

#### `POST /v5/books/{bookId}/collaborators/request` — requestBookAccess

Request access to a Book

**Parameters:**

- `permission` (query, string — `OWNER` | `EDITOR` | `POSTER` | `RECORDER` | `VIEWER` | `NONE`, required) — The permission requested in the Book
- `message` (query, string) — An optional message to the Book owner

**Response 204:** Successful response with no content.

**Response default:** ApiError

#### `GET /v5/books/{bookId}/collaborators/request/{id}` — getBookAccessRequest

Resolve a Book access request

**Parameters:**

- `id` (path, string, required) — The Book access request id

**Response 200:** Collaborator

**Response default:** ApiError

#### `DELETE /v5/books/{bookId}/collaborators/{id}` — removeCollaborator

Remove a collaborator from the book

**Parameters:**

- `id` (path, string, required) — The collaborator id or email

**Response 200:** Collaborator

**Response default:** ApiError

### Collections

#### `GET /v5/collections` — listCollections

**Response 200:** CollectionList

**Response default:** ApiError

#### `POST /v5/collections` — createCollection

**Request body:** Collection

**Response 200:** Collection

**Response default:** ApiError

#### `PUT /v5/collections` — updateCollection

**Request body:** Collection

**Response 200:** Collection

**Response default:** ApiError

#### `DELETE /v5/collections/{id}` — deleteCollection

**Parameters:**

- `id` (path, string, required)

**Response 200:** BookList

**Response default:** ApiError

#### `PATCH /v5/collections/{id}/books/add` — addBooksToCollection

**Parameters:**

- `id` (path, string, required)

**Request body:** BookList

**Response 200:** BookList

**Response default:** ApiError

#### `PATCH /v5/collections/{id}/books/remove` — removeBooksFromCollection

**Parameters:**

- `id` (path, string, required)

**Request body:** BookList

**Response 200:** BookList

**Response default:** ApiError

### Events

#### `GET /v5/books/{bookId}/events` — listEvents

**Parameters:**

- `after` (query, string (date-time)) — After date and time, on RFC3339 format
- `before` (query, string (date-time)) — Before date and time, on RFC3339 format
- `error` (query, boolean) — Filter by error
- `resoureId` (query, string) — The resourceId associated
- `type` (query, string — `FILE_CREATED` | `FILE_UPDATED` | `FILE_DELETED` | `TRANSACTION_CREATED` | `TRANSACTION_UPDATED` | `TRANSACTION_DELETED` | `TRANSACTION_POSTED` | `TRANSACTION_CHECKED` | `TRANSACTION_UNCHECKED` | `TRANSACTION_RESTORED` | `ACCOUNT_CREATED` | `ACCOUNT_UPDATED` | `ACCOUNT_DELETED` | `QUERY_CREATED` | `QUERY_UPDATED` | `QUERY_DELETED` | `GROUP_CREATED` | `GROUP_UPDATED` | `GROUP_DELETED` | `COMMENT_CREATED` | `COMMENT_DELETED` | `COLLABORATOR_ADDED` | `COLLABORATOR_UPDATED` | `COLLABORATOR_REMOVED` | `INTEGRATION_CREATED` | `INTEGRATION_UPDATED` | `INTEGRATION_DELETED` | `BOOK_CREATED` | `BOOK_AUDITED` | `BOOK_UPDATED` | `BOOK_DELETED`) — Filter by event type
- `limit` (query, integer (int32)) — The dataset limit. Useful for pagination

**Response 200:** EventList

**Response default:** ApiError

#### `GET /v5/books/{bookId}/events/backlog` — getBookEventsBacklog

Get book events backlog

**Response 200:** Backlog

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/events/replay/batch` — replayEvents

Batch replay events responses

**Parameters:**

- `errorsOnly` (query, boolean) — Replay errors only

**Request body:** EventList

**Response 204:** Successful response with no content.

**Response default:** ApiError

#### `PUT /v5/books/{bookId}/events/{id}/responses/{agentId}` — replayEventResponse

Replay an event response

**Parameters:**

- `id` (path, string, required) — The event id
- `agentId` (path, string, required) — The agent id

**Response 200:** Event

**Response default:** ApiError

#### `DELETE /v5/books/{bookId}/events/{id}/responses/{agentId}` — deleteEventResponse

Delete an event response

**Parameters:**

- `id` (path, string, required) — The event id
- `agentId` (path, string, required) — The agent id

**Response 200:** Event

**Response default:** ApiError

### Files

#### `GET /v5/books/{bookId}/files` — listFiles

**Parameters:**

- `limit` (query, integer (int32)) — The dataset limit. Useful for pagination

**Response 200:** FileList

**Response default:** ApiError

#### `POST /v5/books/{bookId}/files` — createFile

**Request body:** File

**Response 200:** File

**Response default:** ApiError

#### `PUT /v5/books/{bookId}/files` — updateFile

**Request body:** File

**Response 200:** File

**Response default:** ApiError

#### `GET /v5/books/{bookId}/files/{id}` — getFile

**Parameters:**

- `id` (path, string, required) — The file id

**Response 200:** File

**Response default:** ApiError

#### `DELETE /v5/books/{bookId}/files/{id}` — deleteFile

**Parameters:**

- `id` (path, string, required) — The file id

**Response 200:** File

**Response default:** ApiError

### Groups

#### `GET /v5/books/{bookId}/groups` — listGroups

**Response 200:** GroupList

**Response default:** ApiError

#### `POST /v5/books/{bookId}/groups` — createGroup

Group a group

**Request body:** Group

**Response 200:** Group

**Response default:** ApiError

#### `PUT /v5/books/{bookId}/groups` — updateGroup

**Request body:** Group

**Response 200:** Group

**Response default:** ApiError

#### `POST /v5/books/{bookId}/groups/batch` — createGroupsBatch

Batch create groups

**Request body:** GroupList

**Response 200:** GroupList

**Response default:** ApiError

#### `GET /v5/books/{bookId}/groups/{id}` — getGroup

**Parameters:**

- `id` (path, string, required) — The group id or name

**Response 200:** Group

**Response default:** ApiError

#### `DELETE /v5/books/{bookId}/groups/{id}` — deleteGroup

**Parameters:**

- `id` (path, integer (int64), required) — The group id

**Response 200:** Group

**Response default:** ApiError

#### `GET /v5/books/{bookId}/groups/{id}/accounts` — listGroupAccounts

List the accounts of a group

**Parameters:**

- `id` (path, string, required) — The group id or name

**Response 200:** AccountList

**Response default:** ApiError

### Integrations

#### `GET /v5/books/{bookId}/integrations` — listIntegrations

List the integrations of the book

**Response 200:** IntegrationList

**Response default:** ApiError

#### `POST /v5/books/{bookId}/integrations` — createIntegration

**Request body:** Integration

**Response 200:** Integration

**Response default:** ApiError

#### `PUT /v5/books/{bookId}/integrations` — updateIntegration

**Request body:** Integration

**Response 200:** Integration

**Response default:** ApiError

#### `DELETE /v5/books/{bookId}/integrations/{id}` — deleteIntegration

**Parameters:**

- `id` (path, integer (int64), required)

**Response 200:** Integration

**Response default:** ApiError

### Queries

#### `GET /v5/books/{bookId}/queries` — listQueries

**Response 200:** QueryList

**Response default:** ApiError

#### `POST /v5/books/{bookId}/queries` — saveQuery

Create a saved query

**Request body:** Query

**Response 200:** Query

**Response default:** ApiError

#### `PUT /v5/books/{bookId}/queries` — updateQuery

Update a saved query

**Request body:** Query

**Response 200:** Query

**Response default:** ApiError

#### `DELETE /v5/books/{bookId}/queries/{id}` — deleteQuery

Delete a saved query

**Parameters:**

- `id` (path, integer (int64), required) — The query id

**Response 200:** Query

**Response default:** ApiError

### Templates

#### `GET /v5/templates` — listTemplates

**Response 200:** TemplateList

**Response default:** ApiError

### Transactions

#### `GET /v5/books/{bookId}/transactions` — listTransactions

**Parameters:**

- `query` (query, string) — The query to filter transactions
- `limit` (query, integer (int32)) — The dataset limit. Useful for pagination

**Response 200:** TransactionList

**Response default:** ApiError

#### `POST /v5/books/{bookId}/transactions` — createTransaction

**Parameters:**

- `timeZone` (query, string) — Optional time zone for parsing dates when recording from different book time zone

**Request body:** Transaction

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `PUT /v5/books/{bookId}/transactions` — updateTransaction

**Request body:** Transaction

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `POST /v5/books/{bookId}/transactions/batch` — createTransactionsBatch

Batch create transactions

**Parameters:**

- `timeZone` (query, string) — Optional time zone for parsing dates when recording from different book time zone

**Request body:** TransactionList

**Response 200:** TransactionList

**Response default:** ApiError

#### `PUT /v5/books/{bookId}/transactions/batch` — updateTransactionsBatch

Batch update transactions

**Parameters:**

- `updateChecked` (query, boolean) — True to also update checked transactions

**Request body:** TransactionList

**Response 200:** TransactionList

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/check` — checkTransaction

Check a transaction

**Request body:** Transaction

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/check/batch` — checkTransactionsBatch

Batch check transactions

**Request body:** TransactionList

**Response 204:** Successful response with no content.

**Response default:** ApiError

#### `GET /v5/books/{bookId}/transactions/count` — countTransactions

Count transactions

**Parameters:**

- `query` (query, string) — The query to filter transactions

**Response 200:** Count

**Response default:** ApiError

#### `GET /v5/books/{bookId}/transactions/count/posted` — countTransactionsPosted

Count transactions posted

**Parameters:**

- `after` (query, string (date), required) — After date, on yyyy-mm-dd format.
- `before` (query, string (date), required) — Before date, on yyyy-mm-dd format.
- `periodicity` (query, string — `DAILY` | `MONTHLY` | `YEARLY`, required) — Periodicity DAILY or MONTHLY

**Response 200:** Counts

**Response default:** ApiError

#### `POST /v5/books/{bookId}/transactions/load` — loadTransactions

Load transactions by id

**Request body:** TransactionList

**Response 200:** TransactionList

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/merge` — mergeTransactions

Merge two transactions. The first item is primary and the second is secondary. Scalar precedence is submitted primary, submitted secondary, persisted primary, then persisted secondary. Collections are unioned and deduplicated; lifecycle remains server-managed.

**Request body:** TransactionList

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/post` — postTransaction

Post a transaction into accounts

**Request body:** Transaction

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/post/batch` — postTransactionsBatch

Batch post transactions

**Request body:** TransactionList

**Response 204:** Successful response with no content.

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/remove` *(deprecated)* — removeTransaction

Remove a transaction, sending to trash

**Request body:** Transaction

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/restore` *(deprecated)* — restoreTransaction

Restore a transaction from trash

**Request body:** Transaction

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/trash` — trashTransaction

Trash a transaction

**Request body:** Transaction

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/trash/batch` — trashTransactionsBatch

Batch trash transactions

**Parameters:**

- `trashChecked` (query, boolean) — True to also trash checked transactions

**Request body:** TransactionList

**Response 204:** Successful response with no content.

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/uncheck` — uncheckTransaction

Uncheck a transaction

**Request body:** Transaction

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/uncheck/batch` — uncheckTransactionsBatch

Batch uncheck a transactions

**Request body:** TransactionList

**Response 204:** Successful response with no content.

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/untrash` — untrashTransaction

Untrash a transaction

**Request body:** Transaction

**Response 200:** TransactionOperation

**Response default:** ApiError

#### `PATCH /v5/books/{bookId}/transactions/untrash/batch` — untrashTransactionsBatch

Batch untrash transactions

**Request body:** TransactionList

**Response 204:** Successful response with no content.

**Response default:** ApiError

#### `GET /v5/books/{bookId}/transactions/{id}` — getTransaction

**Parameters:**

- `id` (path, string, required) — The transaction id

**Response 200:** Transaction

**Response default:** ApiError

### User

#### `GET /v5/user` — getUser

Retrieve the current user

**Response 200:** User

**Response default:** ApiError

#### `GET /v5/user/billing` — getBilling

Retrieve the user billing information

**Response 200:** Billing

**Response default:** ApiError

#### `GET /v5/user/billing/checkout` — getBillingCheckout

Retrieve the user billing checkout url for a plan

**Parameters:**

- `plan` (query, string, required)
- `cycle` (query, string)
- `successUrl` (query, string, required)
- `cancelUrl` (query, string, required)

**Response 200:** Url

**Response default:** ApiError

#### `GET /v5/user/billing/counts` — listBillingCounts

List user billing transaction counts for last 12 months

**Response 200:** Counts

**Response default:** ApiError

#### `GET /v5/user/billing/portal` — getBillingPortal

Retrieve the user billing portal url

**Parameters:**

- `returnUrl` (query, string, required)

**Response 200:** Url

**Response default:** ApiError

#### `GET /v5/user/connections` — listConnections

**Response 200:** ConnectionList

**Response default:** ApiError

#### `POST /v5/user/connections` — createConnection

**Request body:** Connection

**Response 200:** Connection

**Response default:** ApiError

#### `PUT /v5/user/connections` — updateConnection

**Request body:** Connection

**Response 200:** Connection

**Response default:** ApiError

#### `GET /v5/user/connections/{id}` — getConnection

Retrieve a connection by id

**Parameters:**

- `id` (path, string, required)

**Response 200:** Connection

**Response default:** ApiError

#### `DELETE /v5/user/connections/{id}` — deleteConnection

**Parameters:**

- `id` (path, string, required)

**Response 200:** Connection

**Response default:** ApiError

#### `GET /v5/user/connections/{id}/integrations` — listConnectionIntegrations

List integrations by connection

**Parameters:**

- `id` (path, string, required)

**Response 200:** IntegrationList

**Response default:** ApiError

## Data Models

### Account

- `agentId`: string — The id of agent that created the resource
- `archived`: boolean — Archived accounts are kept for history
- `balance`: string — The running balance of the account at the transaction date. Only present when the account is part of a transaction response filtered by account. NOT the current account balance. To get current balances, use the Balances endpoint: GET /books/{bookId}/balances
- `balanceVerified`: boolean — Whether the account balance has been verified/audited
- `createdAt`: string — The creation timestamp, in milliseconds
- `credit`: boolean — Credit nature or Debit otherwise
- `groups`: Group[] — The groups of the account
- `hasTransactionPosted`: boolean — Whether the account has any transactions posted
- `id`: string — The unique id that identifies the Account in the Book
- `name`: string — The name of the Account
- `normalizedName`: string — The name of the Account, lowercase, without spaces or special characters
- `permanent`: boolean — Permanent are such as bank accounts, customers or the like
- `properties`: Record<string, string> — The key/value custom properties of the Account
- `type`: string — `ASSET` | `LIABILITY` | `INCOMING` | `OUTGOING` — The type of the account
- `updatedAt`: string — The last update timestamp, in milliseconds

### AccountBalances

- `archived`: boolean
- `balances`: Balance[]
- `credit`: boolean
- `cumulativeBalance`: string
- `cumulativeCredit`: string
- `cumulativeDebit`: string
- `empty`: boolean
- `name`: string
- `normalizedName`: string
- `periodBalance`: string
- `periodCredit`: string
- `periodDebit`: string
- `permanent`: boolean
- `properties`: Record<string, string>

### AccountList

- `items`: Account[] — List items

### Agent

- `id`: string — The agent id
- `logo`: string — The agent logo. Public url or Base64 encoded
- `logoDark`: string — The agent logo on dark mode. Public url or Base64 encoded
- `name`: string — The agent name

### App

- `apiVersion`: string — `v0` | `v1` | `v2` | `v3` | `v4` | `v5` — The API version of the event payload
- `clientId`: string — The Google OAuth Client ID
- `clientSecret`: string — The Google OAuth Client Secret
- `connectable`: boolean — Whether this app is connectable by a user
- `deprecated`: boolean — Whether the app is deprecated
- `description`: string — The App description
- `developers`: string — The developers (usernames and domain patterns), comma or space separated
- `events`: string[] — `FILE_CREATED` | `FILE_UPDATED` | `FILE_DELETED` | `TRANSACTION_CREATED` | `TRANSACTION_UPDATED` | `TRANSACTION_DELETED` | `TRANSACTION_POSTED` | `TRANSACTION_CHECKED` | `TRANSACTION_UNCHECKED` | `TRANSACTION_RESTORED` | `ACCOUNT_CREATED` | `ACCOUNT_UPDATED` | `ACCOUNT_DELETED` | `QUERY_CREATED` | `QUERY_UPDATED` | `QUERY_DELETED` | `GROUP_CREATED` | `GROUP_UPDATED` | `GROUP_DELETED` | `COMMENT_CREATED` | `COMMENT_DELETED` | `COLLABORATOR_ADDED` | `COLLABORATOR_UPDATED` | `COLLABORATOR_REMOVED` | `INTEGRATION_CREATED` | `INTEGRATION_UPDATED` | `INTEGRATION_DELETED` | `BOOK_CREATED` | `BOOK_AUDITED` | `BOOK_UPDATED` | `BOOK_DELETED` — Event types the App listen to
- `filePatterns`: string[] — File patterns the App handles - wildcard accepted. E.g. *.pdf, *-bank.csv
- `id`: string — The unique agent id of the App - this can't be changed after created
- `installable`: boolean — Whether this app is installable in a book
- `logoUrl`: string — The App logo url
- `logoUrlDark`: string — The App logo url in dark mode
- `menuOpenMode`: string — `SIDEBAR` | `EXPANDED` | `NEW_TAB` — How the app menu opens. Default to SIDEBAR
- `menuPopupHeight`: string — Deprecated
- `menuPopupWidth`: string — Deprecated
- `menuText`: string — The contex menu text - default to the App name
- `menuUrl`: string — The context menu url
- `menuUrlDev`: string — The context menu url in dev mode
- `name`: string — The App name
- `ownerEmail`: string — The owner user email
- `ownerId`: string — The owner user id
- `ownerLogoUrl`: string — The owner company logo url
- `ownerName`: string — The owner company name
- `ownerWebsite`: string — The owner company website url
- `propertiesSchema`: AppPropertiesSchema
- `published`: boolean — Whether this app is already published
- `readme`: string — The readme.md file as string
- `readmeMd`: string — The readme.md file as raw markdown string
- `repoPrivate`: boolean — Whether the code repository is private
- `repoUrl`: string — The code repository url
- `scopes`: string[] — The Google OAuth Scopes used by the app
- `users`: string — The users (usernames and domain patterns) to enable the App while not yet published
- `webhookUrl`: string — The Webhook endpoint URL to listen for book events
- `webhookUrlDev`: string — The Webhook endpoint URL to listen for book events in dev mode
- `website`: string — The App website url

### AppList

- `items`: App[]

### AppPropertiesSchema

- `account`: AppPropertySchema
- `book`: AppPropertySchema
- `group`: AppPropertySchema
- `transaction`: AppPropertySchema

### AppPropertySchema

- `keys`: string[] — The property keys schema
- `values`: string[] — The property values schema

### Backlog

- `count`: integer (int32)

### Balance

- `cumulativeBalance`: string
- `cumulativeCredit`: string
- `cumulativeDebit`: string
- `day`: integer (int32)
- `fuzzyDate`: integer (int32)
- `month`: integer (int32)
- `periodBalance`: string
- `periodCredit`: string
- `periodDebit`: string
- `year`: integer (int32)

### Balances

- `accountBalances`: AccountBalances[]
- `balancesUrl`: string
- `groupBalances`: GroupBalances[]
- `nextRange`: string
- `periodicity`: string — `DAILY` | `MONTHLY` | `YEARLY`
- `previousRange`: string
- `range`: string
- `rangeBeginLabel`: string
- `rangeEndLabel`: string

### Billing

- `adminEmail`: string — The billing admin email for the user's billing account
- `daysLeftInTrial`: integer (int32) — How many days the user has left in the trial period
- `email`: string — The user's email address
- `enabled`: boolean — True if billing is enabled for the user
- `hostedDomain`: string — The user hosted domain
- `plan`: string — The user's current plan
- `planOverdue`: boolean — True if subscription payment is overdue
- `startedTrial`: boolean — True if the user has started the trial period
- `totalTransactionsThisMonth`: integer (int64) — User-level total transactions this month
- `totalTransactionsThisYear`: integer (int64) — User-level total transactions this year
- `transactionsAverage`: integer (int64) — Authoritative rounded-up rolling monthly average of posted transactions for the current plan
- `transactionsCapacity`: integer (int64) — Confirmed average monthly transaction capacity for the current plan

### Book

- `accounts`: Account[] — The book Accounts
- `agentId`: string — The id of agent that created the resource
- `autoPost`: boolean — Tells if the Book has auto post enabled
- `closingDate`: string — The book closing date, in ISO format yyyy-MM-dd. Transactions on or before this date are closed for the period
- `collection`: Collection
- `createdAt`: string — The creation timestamp, in milliseconds
- `datePattern`: string — The date pattern of the Book. Example: dd/MM/yyyy
- `decimalSeparator`: string — `DOT` | `COMMA` — The decimal separator of the Book
- `fractionDigits`: integer (int32) — The number of fraction digits (decimal places) of the Book. E.g. 2 for ####.##, 4 for ####.####
- `groups`: Group[] — The book account Groups
- `id`: string — The unique id that identifies the Book in the system. Found at bookId url param
- `lastUpdateMs`: string — The last update date of the Book, in milliseconds
- `lockDate`: string — The book lock date, in ISO format yyyy-MM-dd. Transactions on or before this date are locked
- `logoUrl`: string — The logo URL of the book owner's custom domain
- `name`: string — The name of the Book
- `ownerName`: string — The Book owner username
- `pageSize`: integer (int32) — The transactions pagination page size
- `period`: string — `MONTH` | `QUARTER` | `YEAR` — The period slice for balances visualization
- `periodStartMonth`: string — `JANUARY` | `FEBRUARY` | `MARCH` | `APRIL` | `MAY` | `JUNE` | `JULY` | `AUGUST` | `SEPTEMBER` | `OCTOBER` | `NOVEMBER` | `DECEMBER` — The start month when YEAR period set
- `permission`: string — `OWNER` | `EDITOR` | `POSTER` | `RECORDER` | `VIEWER` | `NONE` — The Permission the current user has in the Book
- `properties`: Record<string, string> — The key/value custom properties of the Book
- `timeZone`: string — The time zone of the Book, in IANA format. E.g. America/New_York, Europe/London
- `timeZoneOffset`: integer (int32) — The time zone offset of the Book, in minutes
- `totalTransactions`: integer (int64) — The total transactions posted
- `totalTransactionsCurrentMonth`: integer (int64) — The total transactions posted on current month
- `totalTransactionsCurrentYear`: integer (int64) — The total transactions posted on current year
- `updatedAt`: string — The last update timestamp, in milliseconds
- `visibility`: string — `PUBLIC` | `PRIVATE` — The Visibility of the Book

### BookList

- `items`: Book[] — List items

### BotResponse

- `agentId`: string
- `createdAt`: string
- `message`: string
- `type`: string — `INFO` | `WARNING` | `ERROR`

### Collaborator

- `agentId`: string — The id of agent that created the resource
- `avatarUrl`: string — The Collaborator public avatar url
- `createdAt`: string — The creation timestamp, in milliseconds
- `email`: string — The email of the Collaborator
- `id`: string — The unique id that identifies the Collaborator in the Book
- `permission`: string — `OWNER` | `EDITOR` | `POSTER` | `RECORDER` | `VIEWER` | `NONE` — The permission the Collaborator has in the Book
- `updatedAt`: string — The last update timestamp, in milliseconds

### CollaboratorPayloadCollection

An ordered list of Collaborator

- `items`: Collaborator[]

### Collection

- `agentId`: string — The id of agent that created the resource
- `books`: Book[] — The Books contained in the Collection
- `createdAt`: string — The creation timestamp, in milliseconds
- `id`: string — The unique id of the Collection
- `name`: string — The name of the Collection
- `ownerUsername`: string — The username of the Collection owner
- `permission`: string — `OWNER` | `EDITOR` | `POSTER` | `RECORDER` | `VIEWER` | `NONE` — The permission the current user has in the Collection. E.g. OWNER, EDITOR, NONE
- `updatedAt`: string — The last update timestamp, in milliseconds

### CollectionList

- `items`: Collection[] — List items

### Connection

- `agentId`: string — The id of agent that created the resource
- `createdAt`: string — The creation timestamp, in milliseconds
- `dateAddedMs`: string
- `email`: string
- `id`: string
- `logo`: string
- `name`: string
- `properties`: Record<string, string>
- `type`: string — `APP` | `BANK`
- `updatedAt`: string — The last update timestamp, in milliseconds
- `userId`: string
- `uuid`: string

### ConnectionList

- `items`: Connection[] — List items

### Count

- `day`: integer (int32)
- `fuzzyDate`: integer (int32)
- `month`: integer (int32)
- `total`: integer (int64)
- `year`: integer (int32)

### Counts

- `posted`: Count[]
- `trashed`: Count[]

### Domain

- `id`: string — The unique id of the domain
- `name`: string — The domain name

### Event

- `agent`: Agent
- `book`: Book
- `bookId`: string — The id of the Book associated to the Event
- `botResponses`: BotResponse[] — The list of bot responses associated to the Event
- `createdAt`: string — The creation timestamp, in milliseconds
- `createdOn`: string (date-time) — The creation date time on RFC3339 format
- `data`: EventData
- `id`: string — The unique id that identifies the Event
- `resource`: string — The resource associated to the Event
- `type`: string — `FILE_CREATED` | `FILE_UPDATED` | `FILE_DELETED` | `TRANSACTION_CREATED` | `TRANSACTION_UPDATED` | `TRANSACTION_DELETED` | `TRANSACTION_POSTED` | `TRANSACTION_CHECKED` | `TRANSACTION_UNCHECKED` | `TRANSACTION_RESTORED` | `ACCOUNT_CREATED` | `ACCOUNT_UPDATED` | `ACCOUNT_DELETED` | `QUERY_CREATED` | `QUERY_UPDATED` | `QUERY_DELETED` | `GROUP_CREATED` | `GROUP_UPDATED` | `GROUP_DELETED` | `COMMENT_CREATED` | `COMMENT_DELETED` | `COLLABORATOR_ADDED` | `COLLABORATOR_UPDATED` | `COLLABORATOR_REMOVED` | `INTEGRATION_CREATED` | `INTEGRATION_UPDATED` | `INTEGRATION_DELETED` | `BOOK_CREATED` | `BOOK_AUDITED` | `BOOK_UPDATED` | `BOOK_DELETED` — The type of the Event
- `user`: User

### EventData

- `object`: object
- `previousAttributes`: Record<string, string> — The object previous attributes when updated

### EventList

- `cursor`: string — The cursor, for pagination
- `items`: Event[] — List items

### File

- `agentId`: string — The id of agent that created the resource
- `content`: string — The file content Base64 encoded
- `contentType`: string — The file content type
- `createdAt`: string — The creation timestamp, in milliseconds
- `id`: string — The unique id that identifies the file in the book
- `name`: string — The file name
- `properties`: Record<string, string> — The key/value custom properties of the File
- `size`: integer (int64) — The file size in bytes
- `updatedAt`: string — The last update timestamp, in milliseconds
- `url`: string — The file serving url

### FileList

- `cursor`: string — The cursor, for pagination
- `items`: File[] — List items

### Group

- `agentId`: string — The id of agent that created the resource
- `createdAt`: string — The creation timestamp, in milliseconds
- `credit`: boolean — Whether the group has credit nature
- `hasAccounts`: boolean — Whether the group has any accounts
- `hasGroups`: boolean — Whether the group has any children groups
- `hidden`: boolean — Whether the group is hidden on the transactions main menu
- `id`: string — The unique id that identifies the Group in the Book
- `locked`: boolean — Whether the group is locked by the Book owner
- `mixed`: boolean — Whether the group has mixed types of accounts
- `name`: string — The name of the Group
- `normalizedName`: string — The name of the Group, lowercase, without spaces or special characters
- `parent`: Group
- `permanent`: boolean — Whether the group is permanent
- `properties`: Record<string, string> — The key/value custom properties of the Group
- `type`: string — `ASSET` | `LIABILITY` | `INCOMING` | `OUTGOING` — The type of the accounts in the group. E.g. ASSET, LIABILITY, INCOMING, OUTGOING
- `updatedAt`: string — The last update timestamp, in milliseconds

### GroupBalances

- `accountBalances`: AccountBalances[]
- `balances`: Balance[]
- `credit`: boolean
- `cumulativeBalance`: string
- `cumulativeCredit`: string
- `cumulativeDebit`: string
- `groupBalances`: GroupBalances[]
- `name`: string
- `normalizedName`: string
- `periodBalance`: string
- `periodCredit`: string
- `periodDebit`: string
- `permanent`: boolean
- `properties`: Record<string, string>

### GroupList

- `items`: Group[] — List items

### Integration

- `addedBy`: string
- `agentId`: string — The id of agent that created the resource
- `bookId`: string
- `connectionId`: string
- `createdAt`: string — The creation timestamp, in milliseconds
- `dateAddedMs`: string
- `id`: string
- `lastUpdateMs`: string
- `logo`: string
- `logoDark`: string
- `name`: string
- `normalizedName`: string
- `properties`: Record<string, string>
- `updatedAt`: string — The last update timestamp, in milliseconds
- `userId`: string

### IntegrationList

- `items`: Integration[] — List items

### Query

- `agentId`: string — The id of agent that created the resource
- `createdAt`: string — The creation timestamp, in milliseconds
- `id`: string — The unique id that identifies the saved Query in the Book
- `query`: string — The Query string to be executed
- `title`: string — The title of the saved Query
- `updatedAt`: string — The last update timestamp, in milliseconds

### QueryList

- `items`: Query[] — List items

### Template

- `bookId`: string
- `bookLink`: string
- `category`: string
- `description`: string
- `imageUrl`: string
- `name`: string
- `sheetsLink`: string
- `timesUsed`: integer (int32)

### TemplateList

- `items`: Template[] — List items

### Transaction

- `agentId`: string — The id of agent that created the resource
- `agentLogo`: string — The logo of the agent that created the transaction
- `agentLogoDark`: string — The logo in dark mode, of the agent that created the transaction
- `agentName`: string — The name of the agent that created the transaction
- `amount`: string — The amount on format ####.##
- `checked`: boolean — Whether the transaction is checked
- `createdAt`: string — The creation timestamp, in milliseconds
- `createdBy`: string — The actor username that created the transaction
- `creditAccount`: Account
- `date`: string — The date on ISO format yyyy-MM-dd
- `dateFormatted`: string — The date on format of the Book
- `dateValue`: integer (int32) — The date number representation on format YYYYMMDD
- `debitAccount`: Account
- `description`: string — The transaction description
- `draft`: boolean — Whether the transaction is a draft
- `files`: File[] — The files attached to the transaction
- `id`: string — The unique id that identifies the transaction in the book
- `posted`: boolean — Whether the transaction is already posted on accounts, otherwise is a draft
- `properties`: Record<string, string> — The key/value custom properties of the Transaction
- `remoteIds`: string[] — The transaction remote ids, to avoid duplication
- `tags`: string[] — The transaction #hashtags
- `trashed`: boolean — Whether the transaction is trashed
- `updatedAt`: string — The last update timestamp, in milliseconds
- `urls`: string[] — The transaction urls

### TransactionList

- `account`: string — The account id when filtering by a single account. E.g. account='Bank'
- `cursor`: string — The cursor, for pagination
- `items`: Transaction[] — List items

### TransactionOperation

- `accounts`: Account[] — The affected accounts
- `transaction`: Transaction

### Url

- `url`: string

### User

- `avatarUrl`: string — The user public avatar url
- `bankConnections`: boolean — True if user already had any bank connection
- `billingAdminEmail`: string — The billing admin email for this user's billing account
- `billingEnabled`: boolean — True if billing is enabled for the user
- `daysLeftInTrial`: integer (int32) — How many days left in trial
- `domain`: Domain
- `email`: string — The user email
- `free`: boolean — True if user is in the free plan
- `fullName`: string — The user full name
- `givenName`: string — The user given name
- `hash`: string — The user hash
- `hostedDomain`: string — The user hosted domain
- `id`: string — The user unique id
- `name`: string — The user display name
- `plan`: string — The user plan
- `planAmount`: integer (int64) — The confirmed recurring plan total in currency minor units
- `planCurrency`: string — The confirmed recurring plan currency
- `planCycle`: string — `MONTHLY` | `YEARLY` — The user plan billing cycle
- `planOverdue`: boolean — True if subscription payment is overdue
- `startedTrial`: boolean — True if user started trial
- `totalTransactionsThisMonth`: integer (int64) — User-level total transactions this month
- `totalTransactionsThisYear`: integer (int64) — User-level total transactions this year
- `username`: string — The Bkper username of the user

### UserProfile

- `avatarUrl`: string — The public avatar URL
- `id`: string — The immutable user id
- `name`: string — The public display name
- `username`: string — The current Bkper username

### ApiError

A JSON error response. API operation errors use the nested `error` object. Public API proxy errors use the Problem Details fields.

- `error`: object
- `type`: string
- `title`: string
- `status`: integer (int32)
- `detail`: string
- `instance`: string
- `code`: string

