Tool catalog

Tool catalog #

Classification: Restricted (describes source code, infrastructure, and access control).

Generated file — do not hand-edit. Regenerate with mise run mcp-tools-doc-gen after adding, renaming or removing a tool in libs/typescript/mcp-tool/src/tool-groups/. A test fails when this file drifts from the catalog.

Every stable tool in the catalog (138 tools), grouped by category. A tool is only served when apps/tofu-external-mcp registers it for the caller’s environment and agent. read tools change nothing; write tools change data and need the matching BonsAI permission. “destructive hint” is the catalog’s destructiveHint annotation, not a guarantee. For input/output details of the most-used tools see the Tools guide.

Document #

Tool Effect Endpoint Description
download_document_file read GET /api/v1/documents/{documentId}/download Download the original uploaded document file (e.g. the source PDF or image) as inline bytes, scoped to the given entity. The response is a binary stream (Content-Type set by the file’s media type).
get_document read GET /api/v1/documents/{documentId} Fetch a single document’s data (status, extraction types, metadata) by its id, scoped to the given entity. Does not include the raw file bytes — use download_document_file for that. Requires DocumentUpload:Read permission.
get_document_metadata read GET /api/v1/documents/{documentId}/metadata Fetch a document’s ingestion-source-specific metadata (e.g. inbound-email headers, integration/trigger-sync origin details), scoped to the given entity. Distinct from get_document, which covers status/extraction/page data but not source metadata. Requires DocumentUpload:Read permission.
get_document_page read GET /api/v1/document-pages/{documentPageId} Fetch a single document page’s data (type, page number, rotation, bounding box, public_metadata, is_linked, etc.), scoped to the given entity. Requires DocumentUpload:Read permission.
get_document_page_image read GET /api/v1/document-pages/{documentPageId}/download Fetch a document page’s rendered image as inline bytes, scoped to the given entity. The response is a binary stream (Content-Type image/png). Requires DocumentUpload:Read permission.
get_document_page_signed_urls read GET /api/v1/document-pages/{documentPageId}/signed-urls Get short-lived, signed CDN URLs (one per size: xs/sm/md/lg/xl) for a single document page, valid for a few minutes. Requests beyond the TTL get a fresh URL. Requires DocumentUpload:Read permission.
get_stale_documents read GET /api/v1/documents/stale List documents that are stale — older than 2 months and not yet DONE — for an entity. Paginated (n_per_page 1-100, default 20; page_number, default 0). Useful for finding documents stuck in processing/review that may need cleanup or a reprocess. Requires DocumentUpload:Read permission.
list_documents read GET /api/v1/documents List documents for an entity, filtered only by upload/update time — there is no filter by extraction type, status, etc. Sorted by creation date (newest first). Requires DocumentUpload:Read permission.
patch_document_page write (destructive hint) PATCH /api/v1/document-pages/{documentPageId} Partially update a document page — only the fields provided are changed (at least one of name, rotation, public_metadata, is_multi_snippet is required). Every field replaces its existing value outright except public_metadata, whose keys are deep-merged into the existing object instead of replacing it wholesale. Requires DocumentUpload:Write permission.
reprocess_document write (destructive hint) POST /api/v1/documents/{documentId}/reprocess Re-run the conversion pipeline for a document that failed before producing any pages (e.g. the virus scanner was unavailable) — moves it back to PENDING and re-queues it. Only eligible if the document is in ERROR with no pages and error_type is UNEXPECTED or unset; failures describing a fixed property of the file itself (MALICIOUS, PASSWORD_PROTECTED, EMPTY_FILE, INVALID_FILE, UNSUPPORTED_FILE, TOO_MANY_PAGES) are rejected with a 400 since reprocessing would reach the same verdict. If the document has a source extraction type, extraction re-runs automatically when quota allows — the original upload was already counted against usage, so this never charges twice; with no quota left the document lands in a limit-reached state instead of extracting. Requires DocumentUpload:Write permission.
update_document write (destructive hint) PATCH /api/v1/documents/{documentId} Update a document’s status directly (one of PENDING/PROCESSING/NEEDS_REVIEW/DONE/ERROR), scoped to the given entity. status is required — this endpoint has no other updatable fields. Requires DocumentUpload:Write permission.
upload_document write (destructive hint) POST /api/v1/documents Upload one or more document files (e.g. an invoice and its supporting attachments) as multipart/form-data. All files are added to one document record and will be extracted together as a multi-page document. Requires DocumentUpload:Write permission.
upsert_document_page write (destructive hint) PUT /api/v1/document-pages Update a document page if id is provided and already exists, or create a new one otherwise (omit id to have bonsapi assign one). Rejects (400) creating a new page with type PAGE (only SNIPPET pages can be created this way), a SNIPPET missing its bounding box or original_document_page_id, a PAGE with a bounding box set, or any attempt to change an existing page’s type/entity_id/document_id. Requires DocumentUpload:Write permission.

Invoice #

Tool Effect Endpoint Description
create_invoice_data write (destructive hint) POST /api/v1/invoices/{invoiceId}/data Append a new invoice_data version to an invoice’s history (e.g. an edit). Set is_placeholder true to skip syncing this version to the connected accounting software. Requires EntityExtractions:Write permission.
get_invoice read GET /api/v1/invoices/{invoiceId} Fetch a single invoice (status, publish/import state, and its current invoice_data version, which is the live published/imported version), scoped to the entity. Invoices are created only during extraction processing (no separate create_invoice endpoint). Requires EntityExtractions:Read permission.
get_invoice_data read GET /api/v1/invoices/{invoiceId}/data List the version history of an invoice’s invoice_data (each edit/publish/import/verification event creates a new version). Returns all versions, each with extracted data (amount, date, vendor, etc.) and metadata (who/when). Requires EntityExtractions:Read permission.
import_invoice write (destructive hint) POST /api/v1/invoices/{invoiceId}/import Sync the invoice’s data and attachments in from the connected accounting software (the reverse direction of publish). Requires EntityExtractions:Write permission.
publish_invoice write (destructive hint) POST /api/v1/invoices/{invoiceId}/publish Publish the invoice’s current data and attachments to the connected accounting software (create-only — republishing an already-published invoice is not this call’s job). Requires EntityExtractions:Write permission.
search_invoice_data read POST /api/v1/invoices/search-data Batch-fetch up to 50 invoices at once by the id of a specific invoice_data version — useful when you have a batch of invoice_data ids and want to fetch all their extracted data in one call. Requires EntityExtractions:Read permission.

Direct expense #

Tool Effect Endpoint Description
create_direct_expense write (destructive hint) POST /api/v1/direct-expenses Create a new direct expense with an extraction, scoped to the entity. Requires EntityDirectExpenses:Manage permission.
create_direct_expense_data write (destructive hint) POST /api/v1/direct-expenses/{directExpenseId}/data Create a new version of a direct expense’s data with line items. Requires EntityDirectExpenses:Manage permission.
delete_direct_expense write (destructive hint) DELETE /api/v1/direct-expenses/{directExpenseId} Soft-delete a direct expense by its id, scoped to the entity. Returns no content on success (204). Requires EntityDirectExpenses:Manage permission.
get_direct_expense_by_extraction read GET /api/v1/direct-expenses/{extractionId} Fetch a single direct expense (status, publish/import state, and its current direct_expense_data version, which is the live published/imported version). Direct expenses are created only during extraction processing (no separate create_direct_expense endpoint). Requires EntityExtractions:Read permission.
get_direct_expense_data read GET /api/v1/direct-expenses/{directExpenseId}/data List the version history of a direct expense’s data (each edit/publish/import/verification event creates a new version). Returns all versions, each with extracted data (amount, date, category, etc.) and metadata (who/when). Requires EntityExtractions:Read permission.
import_direct_expense write (destructive hint) POST /api/v1/direct-expenses/{directExpenseId}/import Sync the direct expense’s data and attachments in from the connected accounting software. Requires EntityDirectExpenses:Create permission.
list_direct_expenses read GET /api/v1/direct-expenses List direct expenses for an entity — pagination only (n_per_page/page_number). Requires EntityDirectExpenses:Read permission.
publish_direct_expense write (destructive hint) POST /api/v1/direct-expenses/{directExpenseId}/publish Publish the direct expense’s current data and attachments to the connected accounting software. Requires EntityDirectExpenses:Update permission.
search_direct_expense_data read POST /api/v1/direct-expenses/search-data Batch-fetch direct expenses by the id of a specific direct_expense_data version — useful when you have a batch of direct_expense_data ids and want to fetch all their extracted data in one call. Requires EntityDirectExpenses:Read permission.

Extraction #

Tool Effect Endpoint Description
confirm_classification write POST /api/v1/extractions/classifications Confirm the AI-classified page types for one or more extractions currently held in CLASSIFY_AND_REVIEW mode and enqueue their extraction jobs. Collection-style — a single confirmation is a one-element list; duplicate ids are deduplicated. Ids that are unknown, not awaiting confirmation, missing a primary page, or blocked by the billing limit are returned in the response’s skipped list with a reason instead of failing the whole batch. Requires EntityExtractions:Write permission.
create_extraction write (destructive hint) POST /api/v1/extractions Create a brand-new extraction from already-uploaded document pages AND immediately trigger its processing in the background — a wrapper around create + trigger combined. Requires DocumentUpload:Read and EntityExtractions:Write permissions. Returns the created extraction and its status (DRAFT).
create_extraction_page write (destructive hint) POST /api/v1/extractions/{extractionId}/pages Add a single document page to an existing extraction — creates the extraction-page mapping (document_page_id, its role PRIMARY/SUPPORTING, and its display order). To replace the entire page set at once, use replace_extraction_pages instead. Requires EntityExtractions:Write permission.
create_soybean write (destructive hint) POST /api/v1/extractions/{extractionId}/soybean Trigger an AIOps Hub data-collection job for an extraction — PII masking, extraction-data snapshotting, and related AIOps tasks. Runs asynchronously; this call only queues the job and returns immediately. The extraction should be VERIFIED for the job to process meaningful data. Optionally carries flag metadata (label, reason, reporter_org_role, reporter_initial) recorded as an extraction issue when a tofu member is flagging a problematic extraction. Requires EntityExtractions:Write permission.
delete_extraction write (destructive hint) DELETE /api/v1/extractions/{extractionId} Permanently delete an extraction, scoped to the entity. Returns no content on success (204). Requires EntityExtractions:Write permission.
delete_extraction_page write (destructive hint) DELETE /api/v1/extractions/{extractionId}/pages/{documentPageId} Remove a single page from an extraction by deleting its extraction-page mapping — this does not delete the underlying document page or its data, just this extraction’s link to it. Requires EntityExtractions:Write permission.
get_extraction read GET /api/v1/extractions/{extractionId} Fetch one extraction in full (the shared model across invoices, direct expenses and bank statements), scoped to the entity. This is how you read what was extracted from a document: the response carries the extracted data itself — the invoice number, the counterparty, the dates, the currency, the total, the line items — alongside the title, the pages, the status (DRAFT/PROCESSING/READY), any error, and which version of the data is current (published/imported/verified). list_extractions returns the status-level rows without that data, so it is the wrong tool for reading values: take an id from it and come here. Requires EntityExtractions:Read permission.
get_stale_extractions read GET /api/v1/extractions/stale List stale extractions for an entity — extractions older than 2 months that are still not done. Pagination only (n_per_page/page_number). Requires EntityExtractions:Read permission.
list_extractions read GET /api/v1/extractions List extractions for an entity: the status-level rows only, without the extracted field values — use get_extraction with an id from here to read those. (The shared status model across invoices, direct expenses, and bank statements.) Supports filtering by types, statuses, timestamp_from/timestamp_to (date range, max 3 months, defaults to last month), and updated_after, plus pagination (n_per_page/page_number). When listing drafts, include both DRAFT and legacy NEEDS_REVIEW statuses. Sorted by creation date (newest first). Requires EntityExtractions:Read permission.
replace_extraction_pages write (destructive hint) PUT /api/v1/extractions/{extractionId}/pages Replace the full set of pages on an extraction in one call — every existing extraction-page mapping for this extraction is overwritten with the pages provided. Returns the new set of extraction pages. Requires EntityExtractions:Write permission.
switch_extraction_type write (destructive hint) POST /api/v1/extractions/{extractionId}/switch-type Switch an extraction from one type to another (e.g. AP_BILL to AR_INVOICE): marks the original extraction DELETED and creates a new extraction with the same pages under the target type, returning the newly created extraction. If the original extraction had synced to an external accounting integration, that deletion is synced too — if that sync fails, this call still succeeds but the response’s warning_message reports it. Fails if target_type equals the extraction’s current type, or if the target type isn’t enabled for this entity. Requires EntityExtractions:Write permission.
trigger_extraction write (destructive hint) PATCH /api/v1/extractions/{extractionId} Trigger (or re-trigger) processing on an extraction that already exists, regardless of its current status — not DRAFT-only; bonsapi accepts most statuses (including NEEDS_REVIEW) and only rejects a few specific ones (e.g. VERIFIED must be unverified first; a deleted extraction cannot be re-triggered; an already-PROCESSING extraction is a same-status no-op, not an error). After triggering, the extraction moves to PROCESSING; when background work completes, it moves to READY (or ERROR if something failed). Requires EntityExtractions:Write permission.

Bank statement #

Tool Effect Endpoint Description
create_bank_statement write (destructive hint) POST /api/v1/bank-statements Create a new bank statement with pending extraction status, scoped to the entity. Requires EntityExtractions:Write permission. No v2 equivalent exists — this is create-only regardless of statement version.
delete_bank_statement write (destructive hint) DELETE /api/v1/bank-statements/{bankStatementId} Delete a bank statement by its id, scoped to the entity. Returns no content on success (204). No v2 equivalent exists. Requires EntityExtractions:Write permission.
get_bank_statement read GET /api/v2/bank-statements/{extractionId} Fetch a single bank statement by its extraction id (bank statements have a 1:1 relationship with extractions, like invoices and direct expenses). Bank statements are created only during extraction processing (no separate create_bank_statement endpoint). Requires EntityExtractions:Read permission.
get_bank_statement_data_activities read GET /api/v1/bank-statements/{bankStatementId}/data/activities Get the activity history for a bank statement’s data, scoped to the entity. No v2 equivalent exists. Requires EntityExtractions:Read permission.
list_bank_statements read GET /api/v1/bank-statements List bank statements for an entity — pagination only (n_per_page/page_number); there is no filtering by date/status/etc. Sorted by creation date (newest first). Requires EntityExtractions:Read permission.
publish_bank_statement write (destructive hint) POST /api/v2/bank-statements/{bankStatementId}/publish Publish every account group of a verified v2 (multi-account) bank statement to the connected accounting software’s bank feed in a single batch, returning a per-group result (the v1 single-account endpoint is superseded by this one). Already-published groups are skipped; groups failing local validation are excluded and marked. 4xx is reserved for whole-statement precondition failures (not verified, integration unavailable, or not a v2 statement) — otherwise 200 is returned even for partial or all-failed outcomes. Requires EntityExtractions:Write permission.
search_bank_statement_data read POST /api/v1/bank-statements/search-data Batch-fetch bank statements by the id of a specific bank_statement_data version — useful when you have a batch of bank_statement_data ids and want to fetch all their extracted data in one call. No v2 equivalent exists. Requires EntityExtractions:Read permission.
upsert_bank_statement_data write (destructive hint) POST /api/v2/bank-statements/{bankStatementId}/data Persist the multi-account data list into a bank statement’s data and transactions (v2, multi-account model — the v1 single-account endpoint is superseded by this one). Requires EntityExtractions:Write permission.

Entity #

Tool Effect Endpoint Description
add_entity_member write (destructive hint) POST /api/v1/entities/{entityId}/members Add an existing organization member to an entity with a specific role. Requires the caller to hold the entity’s Member:Write permission — checked by bonsapi before the member is added; a caller without it (e.g. the built-in Viewer role) gets a clean permission-denied error. app_user_id is the target’s Clerk external user id (the organization member’s own id, NOT the entity-membership id that update_entity_member/remove_entity_member take) — bonsapi looks the member up by their live Clerk membership in the caller’s organization, so app_user_id must belong to someone who is already an organization member, not merely any UUID. Fails with a clean 400 if they’re already a member of this entity.
create_entity write (destructive hint) POST /api/v1/entities Create a new entity in the caller organization. Requires the caller to hold the Organization:Admin role — members with lower roles (e.g. Entity Admin, Member) get a clean permission-denied error. Returns the created entity, including the caller’s own role in it (always Manager).
create_entity_knowledge write (destructive hint) POST /api/v1/entities/{entityId}/knowledge Kick off knowledge learning for an entity, either from free-form text content or — with contents omitted — from its historical extraction data, which nothing else does. Returns as soon as the job is queued, so the knowledge is not there yet; poll list_knowledge to see the cards appear. Writes whichever knowledge version the entity is on, so its output is what list_knowledge returns. Supports one or more extraction_types (processed sequentially) — pass extraction_types over the deprecated singular extraction_type. Unlike create_knowledge, which writes one card synchronously, this learns a whole set. Requires entity-level entity-knowledge create permission.
delete_entity write (destructive hint) DELETE /api/v1/entities/{entityId} Delete an entity. Returns no content on success (204). Requires the caller to hold the entity’s (or organization’s) entity-delete permission.
get_entity read GET /api/v1/entities/{entityId} Fetch a single entity’s data (name, slug, organization, the caller’s own role, and when it was created/updated), scoped to the entity. Does not return members list — use list_entities for that context. Requires Read permission on the entity (not just membership).
list_entities read GET /api/v1/entities List every entity the caller can access, each with the caller’s own role in it (not roles of other members). Sorted by creation date (oldest first). Paginated via page_number/n_per_page (defaults to 20 per page, max 100).
list_entity_members read GET /api/v1/entities/{entityId}/members List members of an entity, including their roles and permissions — pagination only (n_per_page/page_number).
remove_entity_member write (destructive hint) DELETE /api/v1/entities/{entityId}/members/{appUserId} Remove a member from an entity by deleting their role assignment — they keep their organization membership (they can rejoin the entity later). Requires the caller to hold the entity’s Member:Write permission. Fails with a clean 400 if the member is not in the entity.
update_entity_member write (destructive hint) PATCH /api/v1/entities/{entityId}/members/{appUserId} Change an existing entity member’s role. Requires the caller to hold the entity’s Member:Write permission. The member must already be in the entity — use add_entity_member to add new members. Fails with a clean 400 if the member is not in the entity.
update_entity_settings write (destructive hint) PATCH /api/v1/entities/{entityId} Update an entity’s name, slug, or write-flow settings (auto-publish/import for AI extraction data when processing completes). At least one field is required in the body. Requires the caller to hold the entity’s Admin role.

Integration setup #

Tool Effect Endpoint Description
check_integration_connection write POST /api/v1/integrations/{integrationId}/check-connection Call a lightweight accounting-provider API endpoint once to verify whether the integration is currently available or rate limited. Disabled in production (403). Requires EntityIntegrations:Write permission.
get_integration read GET /api/v1/integrations/{integrationId} Fetch a single entity integration (accounting connection like Xero/QuickBooks, or trigger-sync integration like Sharepoint). Returns status, installation warnings, and connection metadata. Requires EntityIntegrations:Read permission.
get_integration_details read GET /api/v1/integrations/{integrationId}/details Fetch an entity integration’s installation_warnings only (each a key/tooltip_key pair). A new/reinstalled integration may have warnings; resolving them ensures triggering data is safe (e.g. Sharepoint folder found). Requires EntityIntegrations:Read permission.
get_integration_oauth_authorize_url write POST /api/v1/integrations/oauth/authorize Get the OAuth authorization URL for a provider (XERO, QUICK_BOOKS, FREEE, MYOB, MONEY_FORWARD, SHAREPOINT, GOOGLE_DRIVE, DROPBOX) instead of being redirected — useful for frontends that need to avoid CORS issues with redirects. redirect_url is where the OAuth flow returns to afterward.
list_integrations read GET /api/v1/integrations List every integration (accounting connections like Xero/QuickBooks, and trigger-sync integrations like Sharepoint) for an entity. Sorted by creation date (newest first). Requires EntityIntegrations:Read permission.
setup_integration write (destructive hint) PUT /api/v1/integrations/{integrationId} Set up or update an existing integration — e.g. choose which Xero organization/tenant or QuickBooks company to use, set Sharepoint/Google Drive/Dropbox source and sub-source and directories, or activate a PENDING WhatsApp integration by setting status to ACTIVE. public_metadata is a discriminated union keyed by provider — see get_integration for the current shape before replacing it, since fields you omit are not preserved from the existing value. Requires EntityIntegrations:Write permission.

Integration trigger #

Tool Effect Endpoint Description
activate_integration_submitter write POST /api/v1/integrations/{integrationId}/submitters/{submitterId}/activate Reactivate a previously deactivated WhatsApp submitter — no new OTP or messages are sent, this is purely an admin trust signal. Only valid from DEACTIVATED status; other states return 409. Requires EntityIntegrations:Write permission.
add_integration_submitter write (destructive hint) POST /api/v1/integrations/{integrationId}/submitters Invite a submitter to a WhatsApp integration: generates a verification code, creates an INVITED submitter row, and emails the code. phone_number must be E.164-parseable; first_name/last_name/email are trimmed 1..N chars. By default each phone number can only link to one integration — set multi_entity true to allow linking to more, as long as all links stay within the same organization (cross-organization is always rejected, 422, regardless of multi_entity). Fails 409 if the phone is already linked to this integration, 422 if it is linked elsewhere without multi_entity or in another organization, and 400 if the target integration is not WhatsApp. Requires EntityIntegrations:Write permission.
deactivate_integration_submitter write POST /api/v1/integrations/{integrationId}/submitters/{submitterId}/deactivate Soft-disable a verified WhatsApp submitter — the row is preserved and can later be re-enabled via activate_integration_submitter. Only valid from ACTIVE status; other states return 409. Requires EntityIntegrations:Write permission.
delete_integration_submitter write (destructive hint) DELETE /api/v1/integrations/{integrationId}/submitters/{submitterId} Hard-delete a WhatsApp submitter’s entity-integration link — valid from any status (INVITED/ACTIVE/DEACTIVATED), no state guard. Returns no content on success (204). Requires EntityIntegrations:Write permission.
get_integration_trigger_sources read GET /api/v1/integrations/{integrationId}/trigger-sources List the trigger sources available for a trigger-sync integration (e.g. sites in Sharepoint) — used to pick a source_id when calling setup_integration. Requires EntityIntegrations:Read permission.
get_integration_trigger_sub_sources read GET /api/v1/integrations/{integrationId}/trigger-sources/{sourceId}/sub-sources List the sub-sources under a given trigger source (e.g. document libraries under a Sharepoint site) — used to pick a sub_source_id when calling setup_integration. Requires EntityIntegrations:Read permission.
list_integration_submitter_logs read GET /api/v1/integrations/{integrationId}/submitter-logs List a WhatsApp integration’s submitter activity log (invitations, OTP verifications, inbound user documents, bot replies), newest first — pagination only (n_per_page/page_number), optionally filtered to one submitter_integration_id. Fails 400 if the target integration is not a WhatsApp integration. Requires EntityIntegrations:Read permission.
list_integration_submitters read GET /api/v1/integrations/{integrationId}/submitters List the submitters attached to a WhatsApp trigger integration — pagination only (n_per_page/page_number), optionally filtered by submitter_channel. Fails 400 if the target integration is not a WhatsApp integration. Requires EntityIntegrations:Read permission.
resend_integration_submitter_invitation write (destructive hint) POST /api/v1/integrations/{integrationId}/submitters/{submitterId}/resend Regenerate the OTP for an INVITED WhatsApp submitter and re-dispatch both the email and WhatsApp invitation template — status stays INVITED. email is required in the body since it isn’t persisted on the submitter row. Fails 409 if the submitter isn’t currently INVITED, 502 on an email/WhatsApp provider failure (safe to retry — the submitter row is unchanged). Requires EntityIntegrations:Write permission.

Entity accounting account #

Tool Effect Endpoint Description
create_entity_accounting_account write (destructive hint) POST /api/v1/entities/{entityId}/accounting/accounts Create a single accounting account for an entity — code, name, and type are required; compatibility flags control which document line items (AP bill, AR invoice, direct expense, bank statement) can use it. Requires EntityAccounting:Write permission.
delete_entity_accounting_account write (destructive hint) DELETE /api/v1/entities/{entityId}/accounting/accounts/{id} Archive (soft-delete) a single accounting account by id — recoverable via update_entity_accounting_account with unarchive true. Returns no content on success (204). Requires EntityAccounting:Write permission.
delete_entity_accounting_accounts write (destructive hint) DELETE /api/v1/entities/{entityId}/accounting/accounts Delete every accounting account owned by an entity in one call. Returns no content on success (204). Requires EntityAccounting:Write permission.
list_entity_accounting_accounts read GET /api/v1/entities/{entityId}/accounting/accounts List every accounting account owned by an entity — no pagination in bonsapi; page_number/n_per_page here slice the full result client-side. Requires EntityAccounting:Read permission.
replace_entity_accounting_accounts write (destructive hint) PUT /api/v1/entities/{entityId}/accounting/accounts/collection Replace the entity’s entire accounting account list in one call — the existing list is overwritten outright, not merged. Returns no content on success (204). Requires EntityAccounting:Write permission.
update_entity_accounting_account write (destructive hint) PATCH /api/v1/entities/{entityId}/accounting/accounts/{id} Replace a single accounting account by id — code, name, and type are required (full replace, not a partial patch). Set unarchive true to restore an account previously archived via delete_entity_accounting_account; works whether the account is currently active or archived. Returns 404 if the account does not exist. Requires EntityAccounting:Write permission.

Entity accounting currency #

Tool Effect Endpoint Description
create_entity_accounting_currencies write (destructive hint) POST /api/v1/entities/{entityId}/accounting/currencies Add one or more currencies (ISO 4217 code, e.g. USD, JPY) to an entity in a single batch, each with an optional tax_decimal_places (0-5). Returns no content on success (204). Requires EntityAccounting:Write permission.
delete_entity_accounting_currency write (destructive hint) DELETE /api/v1/entities/{entityId}/accounting/currencies/{currencyId} Archive a single accounting currency on an entity by its currency id. Returns no content on success (204). Requires EntityAccounting:Write permission.
list_entity_accounting_currencies read GET /api/v1/entities/{entityId}/accounting/currencies List every accounting currency owned by an entity, each with its tax_decimal_places — no pagination in bonsapi; page_number/n_per_page here slice the full result client-side. Requires EntityAccounting:Read permission.
replace_entity_accounting_currencies write (destructive hint) PUT /api/v1/entities/{entityId}/accounting/currencies/collection Replace the entity’s entire accounting currency list in one call — the existing list is overwritten outright, not merged. Returns no content on success (204). Requires EntityAccounting:Write permission.
update_entity_accounting_currency write (destructive hint) PATCH /api/v1/entities/{entityId}/accounting/currencies/{currencyId} Update the tax_decimal_places (0-5, nullable) for a single accounting currency on an entity. Requires EntityAccounting:Write permission.

Entity accounting tax rate #

Tool Effect Endpoint Description
bulk_update_entity_accounting_tax_rates write (destructive hint) PATCH /api/v1/entities/{entityId}/accounting/tax-rates/collection Update multiple existing tax rates for an entity in one call, each identified by id (name and rate required per item; unlike replace_entity_accounting_tax_rates this only touches the ids you pass). Returns no content on success (204). Requires EntityAccounting:Write permission.
create_entity_accounting_tax_rate write (destructive hint) POST /api/v1/entities/{entityId}/accounting/tax-rates Create a single tax rate for an entity — name and rate (decimal, e.g. 0.10 for 10%) are required; type (Purchase/Sales) is optional. Requires EntityAccounting:Write permission.
delete_entity_accounting_tax_rate write (destructive hint) DELETE /api/v1/entities/{entityId}/accounting/tax-rates/{id} Archive (soft-delete) a single tax rate by id — recoverable via update_entity_accounting_tax_rate with unarchive true. Returns no content on success (204). Requires EntityAccounting:Write permission.
delete_entity_accounting_tax_rates write (destructive hint) DELETE /api/v1/entities/{entityId}/accounting/tax-rates Delete every tax rate owned by an entity in one call. Returns no content on success (204). Requires EntityAccounting:Write permission.
list_entity_accounting_tax_rates read GET /api/v1/entities/{entityId}/accounting/tax-rates List every tax rate owned by an entity — no pagination in bonsapi; page_number/n_per_page here slice the full result client-side. Requires EntityAccounting:Read permission.
replace_entity_accounting_tax_rates write (destructive hint) PUT /api/v1/entities/{entityId}/accounting/tax-rates/collection Replace the entity’s entire tax-rate list in one call — the existing list is overwritten outright, not merged. Returns no content on success (204). Requires EntityAccounting:Write permission.
update_entity_accounting_tax_rate write (destructive hint) PATCH /api/v1/entities/{entityId}/accounting/tax-rates/{id} Replace a single tax rate by id — name and rate are required (full replace, not a partial patch). Set unarchive true to restore a tax rate previously archived via delete_entity_accounting_tax_rate; works whether the tax rate is currently active or archived. Returns 404 if the tax rate does not exist. Requires EntityAccounting:Write permission.

Entity accounting contact #

Tool Effect Endpoint Description
create_entity_accounting_contact write (destructive hint) POST /api/v1/entities/{entityId}/accounting/contacts Create a single accounting contact for an entity — code and name are required; is_supplier/is_customer/default_currency/tax_identification_number are optional. Requires EntityAccounting:Write permission.
delete_entity_accounting_contact write (destructive hint) DELETE /api/v1/entities/{entityId}/accounting/contacts/{id} Archive (soft-delete) a single accounting contact by id — recoverable via update_entity_accounting_contact with unarchive true. Returns no content on success (204). Requires EntityAccounting:Write permission.
delete_entity_accounting_contacts write (destructive hint) DELETE /api/v1/entities/{entityId}/accounting/contacts Delete every accounting contact owned by an entity in one call. Returns no content on success (204). Requires EntityAccounting:Write permission.
list_entity_accounting_contacts read GET /api/v1/entities/{entityId}/accounting/contacts List every accounting contact owned by an entity — no pagination in bonsapi; page_number/n_per_page here slice the full result client-side. Requires EntityAccounting:Read permission.
replace_entity_accounting_contacts write (destructive hint) PUT /api/v1/entities/{entityId}/accounting/contacts/collection Replace the entity’s entire accounting contact list in one call — the existing list is overwritten outright, not merged. Returns no content on success (204). Requires EntityAccounting:Write permission.
update_entity_accounting_contact write (destructive hint) PATCH /api/v1/entities/{entityId}/accounting/contacts/{id} Replace a single accounting contact by id — code and name are required (full replace, not a partial patch). Set unarchive true to restore a contact previously archived via delete_entity_accounting_contact; works whether the contact is currently active or archived. Returns 404 if the contact does not exist. Requires EntityAccounting:Write permission.

Entity accounting tag #

Tool Effect Endpoint Description
create_entity_accounting_tag write (destructive hint) POST /api/v1/entities/{entityId}/accounting/tags Create a single accounting tag (tracking category/option) for an entity — name and is_selectable are required; parent_id (null for a root category) and code are optional. Requires EntityAccounting:Write permission.
update_entity_accounting_tag write (destructive hint) PATCH /api/v1/entities/{entityId}/accounting/tags/{id} Replace a single accounting tag by id — name and is_selectable are required (full replace, not a partial patch); parent_id null moves it to root. To archive/reactivate a tag instead, use update_entity_accounting_tag_status. Requires EntityAccounting:Write permission.
update_entity_accounting_tag_status write (destructive hint) PATCH /api/v1/entities/{entityId}/accounting/tags/{id}/status Archive or reactivate a single accounting tag by id — set active false to archive it, true to reactivate. Requires EntityAccounting:Write permission.

Entity accounting item #

Tool Effect Endpoint Description
create_entity_accounting_item write (destructive hint) POST /api/v1/entities/{entityId}/accounting/items Create a single accounting item for an entity — type is required; code, name, sales_price, description, default_account_id, and default_tax_rate_id are optional. Requires EntityAccounting:Write permission.
delete_entity_accounting_item write (destructive hint) DELETE /api/v1/entities/{entityId}/accounting/items/{id} Archive (soft-delete) a single accounting item by id — recoverable via update_entity_accounting_item with unarchive true. Returns no content on success (204). Requires EntityAccounting:Write permission.
delete_entity_accounting_items write (destructive hint) DELETE /api/v1/entities/{entityId}/accounting/items Delete every accounting item owned by an entity in one call. Returns no content on success (204). Requires EntityAccounting:Write permission.
list_entity_accounting_items read GET /api/v1/entities/{entityId}/accounting/items List every accounting item (product/service) owned by an entity — no pagination in bonsapi; page_number/n_per_page here slice the full result client-side. Requires EntityAccounting:Read permission.
replace_entity_accounting_items write (destructive hint) PUT /api/v1/entities/{entityId}/accounting/items/collection Replace the entity’s entire accounting item list in one call — the existing list is overwritten outright, not merged. Returns no content on success (204). Requires EntityAccounting:Write permission.
update_entity_accounting_item write (destructive hint) PATCH /api/v1/entities/{entityId}/accounting/items/{id} Replace a single accounting item by id — code, name, and type are required (full replace, not a partial patch). Set unarchive true to restore an item previously archived via delete_entity_accounting_item; works whether the item is currently active or archived. Returns 404 if the item does not exist. Requires EntityAccounting:Write permission.

Reference data #

Tool Effect Endpoint Description
accounting_tag_usage read GET /api/v1/entities/{entityId}/accounting/tags/{id}/usage Get invoice and direct-expense usage counts for a single accounting tag on an entity — read the description in the accounting_tags tool for context. Requires EntityAccounting:Read permission.
accounting_tags read GET /api/v1/entities/{entityId}/accounting/tags List every accounting tag (tracking category/option, e.g. Xero’s tracking categories) configured for an entity and extraction type — the fields that accounting-sync uses when publishing to Xero/QuickBooks. Requires EntityAccounting:Read permission.
apply_knowledge_templates write (destructive hint) POST /api/v1/knowledge/templates Apply pre-built country-specific knowledge templates to an entity. Templates provide field-mapping guidance for the country’s invoicing, direct-expense, and bank-statement extractions. Returns the merged knowledge set after applying templates (some cards may be duplicates or updates to existing ones). Requires EntityKnowledge:Write permission.
get_accounting_target_config read GET /api/v1/accounting/targets/{key}/config Fetch extraction config defaults and configurable constraints for a single accounting target (e.g. CSV export field options and limits for that target software). key must be one of the values returned by get_accounting_targets. Returns 404 if the key is not a supported target.
get_accounting_targets read GET /api/v1/accounting/targets List every supported accounting-target software key (e.g. Xero, QuickBooks) as an enum value — used to populate target_accounting_software on update_entity_settings and to know which keys get_accounting_target_config accepts.
get_countries read GET /api/v1/countries List every country bonsapi recognizes (ISO 3166-1 alpha-2 code only, e.g. US, JP). Used by create_knowledge_card and other endpoints that validate country-specific fields.
get_currencies read GET /api/v1/currencies List every currency bonsapi recognizes (ISO 4217 code and its tax rounding decimal places, e.g. USD: 2, JPY: 0). Used when creating knowledge cards and other currency-specific fields.
get_priority_fields read GET /api/v1/priority-fields List the priority fields configured for an entity and extraction type — the fields that appear at the top of the UI and are validated/extracted first. Priority fields are set via entity knowledge (knowledge cards). Requires EntityKnowledge:Read permission.
replace_priority_fields write (destructive hint) PUT /api/v1/priority-fields Replace the full set of priority fields for an entity and extraction type in one call — the existing list is overwritten outright, not merged. Requires extraction_type and fields (max 3 field names) in the body. Requires EntityKnowledge:Write permission.

Organization #

Tool Effect Endpoint Description
get_organization_analytics read GET /api/v1/organization/analytics Fetch the caller’s organization’s usage analytics: usage_metrics (daily per-entity extraction counts, split tofu-vs-external, for invoices/direct-expenses/bank-statements), review_analytics (per-entity counts of extractions/documents currently in review), and entity_usage_summary (per-entity integration/extraction/verification totals). No per-user or unique-user breakdown is included anywhere in the response. Used by billing and usage-tracking dashboards.
get_organization_by_external_id read GET /api/v1/organizations/{externalId} Fetch organization details (id, name, slug, created_at/updated_at) by its external ID (e.g. Stripe subscription id, Xero tenant id). Used by integrations to look up the organization in Bonsai from external systems.
get_organization_members read GET /api/v1/organization/members List all members of the organization with their roles. Requires Organization:Read permission.
get_organization_roles read GET /api/v1/organization/roles List every entity role available in the caller’s organization (id, name, created_at). Roles are custom per-organization; each role has a set of permissions (read/write/admin/etc.). Used by add_entity_member and update_entity_member to populate role dropdowns.
get_organization_settings read GET /api/v1/organization/settings Fetch the caller’s organization’s settings: whether integration-trigger emails are disabled, whether the org is in read-only/archival mode, and organization-level field configuration defaults. Requires Organization:Admin role.
get_public_organization_settings read GET /api/v1/organization/public-settings Fetch the same email-domain-whitelist and knowledge-sharing settings as get_organization_settings, but exposed to any authenticated member — no Organization:Admin role check, JWT authentication alone is sufficient. Useful when a lower-privileged caller needs to read these settings (e.g. to render a banner) without being able to fetch or change the admin-only settings resource.
update_organization_settings write (destructive hint) PATCH /api/v1/organization/settings Update the caller’s organization’s settings: whether integration-trigger emails require an email-domain whitelist, and whether the organization has opted in to share knowledge data. Both fields are optional and independent — pass only what you want to change; an omitted field keeps its current value. Returns the full updated settings object (same shape as get_organization_settings), including the new updated_at timestamp. Requires Organization:Admin role.

User account #

Tool Effect Endpoint Description
get_billings read GET /api/v1/billings Fetch the caller’s organization’s current billing plan, AI extraction usage/limits (monthly/annual), and usage so far this billing period — invoice/direct-expense/bank-statement counts and invoice verification count.
get_my_prompt_usage read GET /api/v1/users/me/prompt-usage Fetch the caller’s own all-time prompt usage: self_prompt_count (number of unique invoices/direct expenses/bank statements the caller has manually verified), and organization-wide context (org_prompt_limit, org_prompt_usage_count — the aggregated counts).
get_my_verification_count read GET /api/v1/users/me/verification-count Fetch the caller’s own invoice verification counts for the last 90 days: total_verified (count of invoices the caller verified), and total_in_organization (count of invoices verified by anyone in the organization). Used by the verify buttons to show progress towards the monthly limit.
list_coupons read GET /api/v1/billings/coupons List the coupons in Stripe’s product catalog that sales can offer a prospect — not a customer’s already-applied discount, and never the welcome or referral coupons tofu applies itself. Each entry includes id (the code to quote/apply), name, either amount_off + currency or percent_off, duration (forever/once/repeating, with duration_in_months for repeating), max_redemptions and times_redeemed so far, redeem_by (Unix seconds; absent means no expiry), and valid — Stripe’s own up-to-date ‘can this still be redeemed’ flag. Always check valid before offering a coupon: an expired or maxed-out one is still returned so the record is auditable, but should not be quoted to a prospect.
list_pricing_plans read GET /api/v1/billings/pricing-plans List active Stripe pricing plans (basic catalog data, no per-org sales overrides). Pass country (ISO 3166-1 alpha-2, e.g. ‘GB’, ‘JP’) to resolve pricing to that market the same way the webapp does from the caller’s IP — ask which country the caller is in if you don’t already know; omitted or unrecognized defaults to USD. Each price’s amount is localized to that market’s currency when Stripe has one, else USD, else its own base currency. Each plan includes id, name, description, tagline, and its prices (amount, currency, billing interval, any AI-extraction allowance with its limit interval, any entity cap via max_entities — absent means unlimited for either — and an optional per-price tagline distinct from the plan-level one). Normally only the prices shown on the billing page are returned (the price’s own is_in_app metadata set to true). When onboarding v2 is enabled, a caller who can manage billing in an organization that is still onboarding gets the onboarding catalog instead (is_self_serve set to true): it can include prices the billing page doesn’t show, which can only be bought during onboarding. Either way, every other price is withheld and a plan with none left is omitted, so anything you get back here is safe to quote to this caller. Each returned price still carries its own billing interval (monthly or yearly) and its own allowance reset interval, which are independent: quote both from the price itself rather than assuming.

Knowledge #

Tool Effect Endpoint Description
create_knowledge write (destructive hint) POST /api/v1/knowledge Create a new knowledge item for an entity. Requires entity_id, extraction_type, and content. Optional fields: title, knowledge_type (defaults to EXTRACTION), target_fields. Requires EntityKnowledge:Create permission.
delete_knowledge write (destructive hint) DELETE /api/v1/knowledge/{entityKnowledgeId} Delete a knowledge item permanently. Requires EntityKnowledge:Update permission. Returns no content on success (204).
get_contact_learnings read GET /api/v1/contact-knowledge/learnings Get the most recent contact-knowledge learning for every contact on an entity, aggregated by contact name. Contact learning is tofie’s in-flight learning for individual contacts (e.g. preferred email, phone number format) that overrides or augments entity-level knowledge. Requires EntityKnowledge:Read permission.
list_knowledge read GET /api/v1/knowledge List knowledge items for an entity, optionally filtered by extraction_type, target_external_contact_id, version (entity_knowledge_version), and/or knowledge_type (EXTRACTION or PAGE_CLASSIFICATION, defaults to EXTRACTION). Supports client-side pagination (limit/offset) on top of the full filtered result set. Requires EntityKnowledge:Read permission.
list_knowledge_conflicts read GET /api/v1/knowledge/conflicts List pending entity-knowledge conflicts for an entity and extraction type — cases where an existing knowledge card is about to be overwritten or deleted. Caller can resolve them with resolve_knowledge_conflict (keep new or discard new). Requires EntityKnowledge:Read permission.
list_knowledge_history read GET /api/v1/knowledge/history List the version history for a knowledge card, or for an entire entity. If entity_knowledge_id is provided, returns history for that card only; if omitted, returns all history for the entity filtered by version (version defaults to the entity’s current entity_knowledge_version when not given). Requires EntityKnowledge:Read permission.
list_knowledge_templates read GET /api/v1/knowledge/templates List pre-built knowledge templates available to apply to an entity via apply_knowledge_templates — distinct from that tool, this one only lists candidates and applies nothing. Optionally filter by country (comma-separated ISO 3166-1 alpha-2 codes, e.g. “SG,MY” — templates with an empty countries list are global and always included regardless of this filter) and scope (comma-separated; COUNTRY is the only scope today). Requires EntityKnowledge:Read permission.
resolve_knowledge_conflict write (destructive hint) PATCH /api/v1/knowledge/conflicts/{conflictId} Resolve a pending knowledge card conflict by either keeping or discarding the conflicting new version. Send {resolution: “keep”} to accept the conflicting version or {resolution: “discard”} to reject it and keep the existing one. Requires EntityKnowledge:Update permission.
revert_knowledge write (destructive hint) POST /api/v1/knowledge/{entityKnowledgeId}/revert Revert a knowledge item to a specific previous version using its history ID. The tool returns all versions of the knowledge item after reverting so the caller can confirm or revert again. Requires EntityKnowledge:Update permission.
update_knowledge_card write (destructive hint) PATCH /api/v1/knowledge/{entityKnowledgeId} Update a single knowledge card’s contents, title, target_fields, or preferred language via a genuine single-item PATCH. Pass only the fields you want to change; omitted fields keep their old values (at least one of contents/title/target_fields is required — preferred_language alone does not count as an update). Infer preferred_language from the language the user is writing to you in (as an English language name, e.g. “Japanese”), not just an explicit language request, and pass it explicitly whenever you can — it is never inferred from a previously-stored value (bonsapi does not persist or return preferred_language). If omitted, it resolves to the caller’s own UI locale, then is left unset. The resolved value is echoed back in the response. Requires EntityKnowledge:Update permission.
upsert_knowledge_cards write (destructive hint) PUT /api/v1/knowledge Create or update multiple knowledge cards in a single batch operation — an upsert matched by id: items with an existing card id are updated, items without one are created new. Existing cards not referenced in this call are left untouched; this does not replace or wipe the entity’s knowledge base. For an update item, contents/title/target_fields are each independently patchable: omit a field to leave that card’s existing value unchanged, or pass an empty string/array to explicitly clear title/target_fields. A new item requires both contents and extraction_type (or extraction_types). Infer each item’s preferred_language from the language the user is writing to you in (as an English language name, e.g. “Japanese”), not just an explicit language request, and pass it explicitly whenever you can. If an item omits preferred_language, it resolves to the caller’s own UI locale, then is left unset. The resolved value is echoed back in the response. Requires EntityKnowledge:Write permission. Returns the created/updated items from this batch.