Accountable

Accountable API

Read your books and fix them from your own code. Every write goes through the same preview → policy → apply pipeline as the app and MCP: it is idempotent, audited and undoable. Under the default rules it applies at once, and entries of $5,000 or more wait for an owner. The API never moves money.

Base URL https://accountable.im/v1 · OpenAPI 3.1 spec · 67 routes

Start

Create a personal access token in Accountable under Settings › AI and agents (read, or read and write, for the companies you pick). The same token works for MCP and this API. Send it as a bearer token.

export ACCOUNTABLE_TOKEN=acc_pat_…
curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" https://accountable.im/v1/companies
export ACCOUNTABLE_COMPANY=…   # an id from that list, or the company's exact name (URL-encoded)

The examples below use $ACCOUNTABLE_COMPANY for the company.

Writes. POST …/commands/<name>?mode=preview returns the exact diff and the policy decision and changes nothing. Without mode (or with mode=apply) it applies and returns 201 {status: "applied", change_id}, or 202 {status: "pending_approval", proposal_id} when your company's approval rules want a person. No token can approve anything.

Idempotency. Every apply needs an Idempotency-Key header. Sending the same key and body again returns the first response with Idempotent-Replay: true; the same key with a different body returns 409 idempotency_mismatch.

Errors are {"error": {"type", "code", "message", "request_id"}}. Types: invalid_request, authentication, permission, not_found, conflict, rate_limited, server. A company your token cannot open is a 404.

Limits. 120 reads and 30 writes a minute per token, with RateLimit-* headers; over the limit you get 429 and Retry-After.

Pagination. Lists return {data, next_cursor, has_more}; pass cursor for the next page.

Companies

GET /v1/companies

Companies this token can open, with your role in each.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies"

GET /v1/companies/{company}

One company: legal name, closed-through month and open months.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY"

Books

GET /v1/companies/{company}/accounts

The chart of accounts.

Query: include_inactive

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/accounts"

GET /v1/companies/{company}/entries

Journal entries, newest first, with cursor pagination (`{data, next_cursor, has_more}`).

Query: from, to, limit, cursor

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/entries"

GET /v1/companies/{company}/entries/{entryId}

One journal entry with its lines.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/entries/je_123"

GET /v1/companies/{company}/periods

Months and whether each is open or closed.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/periods"

POST /v1/companies/{company}/entries

Post a balanced journal entry (as commands/create_entry).

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: the fields, as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/entries?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{"date":"2026-09-30","memo":"September legal accrual","lines":[{"accountId":"acc_6300","debit":1250000},{"accountId":"acc_2300","credit":1250000}]}}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/entries" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{"date":"2026-09-30","memo":"September legal accrual","lines":[{"accountId":"acc_6300","debit":1250000},{"accountId":"acc_2300","credit":1250000}]}}'

POST /v1/companies/{company}/entries/{entryId}/reverse

Reverse an entry: post its mirror and link the two (optional `date`, `memo`).

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: the fields, as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/entries/je_123/reverse?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/entries/je_123/reverse" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{}'

Reports

GET /v1/companies/{company}/reports/profit-and-loss

Profit and loss for a period (`period=2026-Q3`, `period=2026-07-08..2026-08-20` for exact days, `period=all`; or `from`/`to` as months or days; `columns=months`, `basis=cash|accrual`). Also at /reports/pl.

Query: period, from, to, basis, columns, compare, pct, tag, tagGroup

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/profit-and-loss?period=2026-Q3"

GET /v1/companies/{company}/reports/balance-sheet

Balance sheet at a period's last day (a month's end, or an exact day like `to=2026-08-20`). Also at /reports/bs.

Query: period, from, to, basis, columns, compare, pct, tag, tagGroup

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/balance-sheet"

GET /v1/companies/{company}/reports/cash-flow

Cash flow statement (indirect method). Also at /reports/cf.

Query: period, from, to, basis, columns, compare, pct, tag, tagGroup

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/cash-flow"

GET /v1/companies/{company}/reports/trial-balance

Trial balance at a month end or an exact day. Also at /reports/tb.

Query: period, from, to, basis

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/trial-balance"

GET /v1/companies/{company}/reports/general-ledger

Every line in a period (whole months or exact days), by account. Also at /reports/gl.

Query: period, from, to, basis, account, limit, perAccount, budget, undone

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/general-ledger"

GET /v1/companies/{company}/reports/account-detail

One account's lines and running balance.

Query: period, from, to, basis, account, undone

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/account-detail"

GET /v1/companies/{company}/reports/metrics

Cash, net burn, gross burn, runway, revenue and net income, each with its formula.

Query: period, from, to, today, burnMethod, fixedBurn, basis

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/metrics"

GET /v1/companies/{company}/reports/transaction-list

Transactions with filters (tab, q, category, from, to) and limit/offset. Also at /reports/transactions.

Query: tab, tag, tagGroup, q, category, funding, method, party, amountMin, amountMax, direction, review, period, from, to, limit, offset, cursor

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/transaction-list"

GET /v1/companies/{company}/reports/transaction-detail

One transaction with its lines, rule and activity.

Query: id

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/transaction-detail"

GET /v1/companies/{company}/reports/transaction-review

Grouped questions and the light-look queue.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/transaction-review"

GET /v1/companies/{company}/reports/close-overview

Close history, the oldest open month and days to close.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/close-overview"

GET /v1/companies/{company}/reports/planning

The planning baseline and saved scenarios.

Query: today

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/planning"

GET /v1/companies/{company}/reports/ar-aging

Receivables aging.

Query: asOf

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/ar-aging"

GET /v1/companies/{company}/reports/ap-aging

Payables aging.

Query: asOf

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/reports/ap-aging"

Entries

POST /v1/companies/{company}/commands/create_entry

Post a balanced journal entry. Entries at or over the owner's limit ($5,000 unless changed) wait for an owner.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/create_entry?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{"date":"2026-09-30","memo":"September legal accrual","lines":[{"accountId":"acc_6300","debit":1250000},{"accountId":"acc_2300","credit":1250000}]}}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/create_entry" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{"date":"2026-09-30","memo":"September legal accrual","lines":[{"accountId":"acc_6300","debit":1250000},{"accountId":"acc_2300","credit":1250000}]}}'

POST /v1/companies/{company}/commands/reverse_entry

Post the mirror of an entry and link the two. Posted entries are never edited.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/reverse_entry?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/reverse_entry" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{}'

Accounts

POST /v1/companies/{company}/commands/create_account

Add an account to the chart of accounts.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/create_account?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/create_account" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/update_account

Rename or renumber an account.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/update_account?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/update_account" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/deactivate_account

Hide an account from new postings.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/deactivate_account?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/deactivate_account" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/activate_account

Use a deactivated account again.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/activate_account?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/activate_account" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

Transactions

POST /v1/companies/{company}/commands/categorize

Categorize one or many transactions, optionally saving a rule.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/categorize?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/categorize" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/answer_question

Answer a grouped question: categorize the group and save the rule.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/answer_question?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/answer_question" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/split_transaction

Split one transaction across categories.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/split_transaction?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/split_transaction" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/set_transaction_fields

Set the vendor name or memo.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/set_transaction_fields?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"memo":"Team offsite"}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/set_transaction_fields" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"memo":"Team offsite"}'

POST /v1/companies/{company}/commands/mark_reviewed

Mark transactions reviewed (or not).

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/mark_reviewed?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/mark_reviewed" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/match_transfer

Match two transactions as a transfer between your own accounts.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/match_transfer?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/match_transfer" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/unmatch_transfer

Undo a transfer match.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/unmatch_transfer?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/unmatch_transfer" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/set_transaction_rate

Change the exchange rate behind a foreign-currency transaction. A closed month stays closed: the difference posts in the first open month.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/set_transaction_rate?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/set_transaction_rate" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

GET /v1/companies/{company}/transactions

Transactions, newest first, with the filters of the Transactions page (tab, q, category, party, amountMin, amountMax, direction, from, to) and cursor pagination.

Query: tab, q, category, party, from, to, limit, cursor

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/transactions"

GET /v1/companies/{company}/transactions/{id}

One transaction with its lines, rule, documents and activity.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/transactions/txn_123"

POST /v1/companies/{company}/transactions/{id}/categorize

Categorize this transaction (`accountId`), optionally saving a rule (`rule: {}`).

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: the fields, as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/transactions/txn_123/categorize?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"accountId":"acc_6100","rule":{}}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/transactions/txn_123/categorize" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"accountId":"acc_6100","rule":{}}'

POST /v1/companies/{company}/transactions/{id}/split

Split this transaction across categories (`lines: [{accountId, amount, memo?}]`).

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: the fields, as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/transactions/txn_123/split?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/transactions/txn_123/split" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

PATCH /v1/companies/{company}/transactions/{id}

Set the vendor name (`description`) or `memo`, or mark it `reviewed`.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: the fields, as in the OpenAPI schema.

curl -X PATCH "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/transactions/txn_123?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"memo":"Team offsite"}'
curl -X PATCH "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/transactions/txn_123" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"memo":"Team offsite"}'

GET /v1/companies/{company}/questions

Grouped questions waiting for an answer, and the light-look queue.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/questions"

POST /v1/companies/{company}/questions/answer

Answer a grouped question: categorize its transactions (`transactionIds`, `accountId`) and save the rule.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: the fields, as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/questions/answer?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/questions/answer" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

Rules

POST /v1/companies/{company}/commands/create_rule

Create a categorization rule.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/create_rule?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/create_rule" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/update_rule

Change a rule.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/update_rule?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/update_rule" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/delete_rule

Delete a rule.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/delete_rule?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/delete_rule" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

Close

POST /v1/companies/{company}/commands/record_statement_balance

Record a statement's ending balance for an account and month.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/record_statement_balance?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/record_statement_balance" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/close_period

Close and lock a month once its checklist passes.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/close_period?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/close_period" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/reopen_period

Reopen a closed month, with a reason.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/reopen_period?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/reopen_period" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

Documents

POST /v1/companies/{company}/commands/link_document

Link a document to what it proves.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/link_document?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"objectType":"transaction","objectId":"txn_123"}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/link_document" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"objectType":"transaction","objectId":"txn_123"}'

POST /v1/companies/{company}/commands/unlink_document

Remove a document link.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/unlink_document?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"objectType":"transaction","objectId":"txn_123"}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/unlink_document" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"objectType":"transaction","objectId":"txn_123"}'

GET /v1/companies/{company}/documents

Documents in the vault (`folder`, `filter`, `kind`, `q`, `from`, `to`).

Query: folder, filter, kind, q

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/documents"

GET /v1/companies/{company}/documents/{id}

One document with what it reads and what it is linked to.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/documents/doc_123"

POST /v1/companies/{company}/documents

Upload a file (multipart, field `file`, up to 10 MB): it is read and linked to its payment when the match is certain. The same file twice answers with the first copy.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/documents" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -F "file=@receipt.pdf"

POST /v1/companies/{company}/documents/{id}/links

Link the document to what it proves (`objectType`, `objectId`: a transaction, bill, invoice, entry or account month).

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: the fields, as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/documents/doc_123/links?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"objectType":"transaction","objectId":"txn_123"}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/documents/doc_123/links" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"objectType":"transaction","objectId":"txn_123"}'

POST /v1/companies/{company}/documents/{id}/unlink

Remove one of the document's links (`objectType`, `objectId`).

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: the fields, as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/documents/doc_123/unlink?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"objectType":"transaction","objectId":"txn_123"}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/documents/doc_123/unlink" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"objectType":"transaction","objectId":"txn_123"}'

Planning

POST /v1/companies/{company}/commands/save_plan

Create or replace a planning scenario. Never posts entries.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/save_plan?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/save_plan" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

POST /v1/companies/{company}/commands/delete_plan

Delete a planning scenario.

Write: ?mode=preview first, then apply with an Idempotency-Key header. Body: {"input": …} as in the OpenAPI schema.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/delete_plan?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/commands/delete_plan" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

Parties

GET /v1/companies/{company}/parties

Vendors and customers with what was paid or received in a period (`from`, `to`, `q`, `kind`).

Query: from, to, q, kind

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/parties"

GET /v1/companies/{company}/parties/{name}

One vendor or customer by name: categories, recent payments, W-9 status and spellings.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/parties/Cooley%20LLP"

Exports

POST /v1/companies/{company}/exports

Start the full data export (every report, the ledger and the documents in one ZIP), or get the one already running.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/exports" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN"

GET /v1/companies/{company}/exports/{id}

An export's status and progress; once done, `downloadUrl` (a link that works for 15 minutes).

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/exports/exp_123"

Changes

GET /v1/companies/{company}/proposals

Changes waiting for (or decided by) a person, newest first (`status`).

Query: status, limit, cursor

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/proposals"

GET /v1/companies/{company}/changes

The audit log, newest first (`command` to filter).

Query: command, limit, cursor

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/changes"

GET /v1/companies/{company}/changes/{changeId}

One change from the audit log: who, what, before and after.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/changes/aud_123"

POST /v1/companies/{company}/changes/{changeId}/undo

Undo a change. Posted entries are reversed, never deleted.

Write: ?mode=preview first, then apply with an Idempotency-Key header.

curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/changes/aud_123/undo?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{}'
curl -X POST "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/changes/aud_123/undo" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{}'

GET /v1/companies/{company}/proposals/{proposalId}

A change waiting for a person's approval, and its decision. No token can approve.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/$ACCOUNTABLE_COMPANY/proposals/prp_123"

Webhooks

Add endpoints in Settings › Developers (owners and admins). Each delivery is a POST with a JSON body {id, type, created_at, company, data} and the headers Accountable-Event, Accountable-Event-Id (the same on every retry and resend: dedupe on it), Accountable-Delivery and Accountable-Signature: t=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 of t + "." + body with the endpoint's signing secret. Any 2xx within 10 seconds counts as delivered. Failed deliveries retry after 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h, 24 h (about 3 days); after the last failure the endpoint is turned off and its creator gets an email. Each event is delivered once per endpoint; a retry or a resend carries the same event id.

entry.postedA journal entry was posted.
entry.reversedA journal entry was reversed (posted entries are never edited).
period.closedA month was closed and locked.
period.reopenedA closed month was reopened, with a reason.
transaction.categorizedOne or more transactions were categorized or split, or a grouped question was answered.
transaction.createdNew bank, card or payment transactions arrived from a connection or an import.
transaction.excludedTransactions were set aside as duplicates or personal, with a reason.
document.uploadedA receipt, statement or other file was added to the books.
invoice.sentAn invoice was issued to a customer.
invoice.paidA payment was recorded against an invoice (by card, bank or by hand).
invoice.voidedAn invoice was voided.
bill.createdA bill was added, from the bill inbox or by hand.
bill.approvedA bill was approved.
bill.paidA payment was recorded against a bill.
alert.createdAccountable raised an alert about the books (a balance off, an unusual charge, a feed problem).
pingA test event sent from Settings › Developers.
// Node or Bun: verify a delivery
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(secret, header, rawBody) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

CLI

The accountable command line wraps this API. From the repository today (bun run cli); the npm package follows.

accountable login --key acc_pat_…              # saved to ~/.config/accountable/credentials.json (mode 600)
accountable companies
accountable report pl --company "Northwind Labs" --period 2026-Q3
accountable entries --company "Northwind Labs" --from 2026-09-01 --json
accountable command create_entry --company "Northwind Labs" --input @entry.json --preview
accountable command create_entry --company "Northwind Labs" --input @entry.json --apply
accountable undo aud_123 --company "Northwind Labs" --apply