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, undoable, and big changes wait for a person. The API never moves money.

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

Start

Create a personal access token in Accountable under Settings › Connected 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

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/northwind"

Books

GET /v1/companies/{company}/accounts

The chart of accounts.

Query: include_inactive

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/northwind/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/northwind/entries"

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

One journal entry with its lines.

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/northwind/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/northwind/periods"

Reports

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

Profit and loss for a period (`period=2026-Q3`, `columns=months`, `basis=cash|accrual`). Also at /reports/pl.

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

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

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

Balance sheet at a period end. Also at /reports/bs.

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

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/northwind/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

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

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

Trial balance at a month end. Also at /reports/tb.

Query: period, from, to, basis

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

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

Every line in a period, by account. Also at /reports/gl.

Query: period, from, to, basis, account

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

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

One account's lines and running balance.

Query: period, from, to, basis, account

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/northwind/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/northwind/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, q, category, funding, method, from, to, limit, offset

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/northwind/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/northwind/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/northwind/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/northwind/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/northwind/reports/planning"

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

Receivables aging.

Query: asOf

curl -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" "https://accountable.im/v1/companies/northwind/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/northwind/reports/ap-aging"

Entries

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

Post a balanced journal entry. Large entries wait for a person's approval.

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/northwind/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/northwind/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/northwind/commands/reverse_entry?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/northwind/commands/reverse_entry" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/commands/categorize?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/commands/set_transaction_fields?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/northwind/commands/set_transaction_fields" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/commands/set_transaction_rate" -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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/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/northwind/commands/link_document?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/northwind/commands/link_document" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

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/northwind/commands/unlink_document?mode=preview" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "content-type: application/json" -d '{"input":{ … }}'
curl -X POST "https://accountable.im/v1/companies/northwind/commands/unlink_document" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

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/northwind/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/northwind/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/northwind/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/northwind/commands/delete_plan" -H "Authorization: Bearer $ACCOUNTABLE_TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "content-type: application/json" -d '{"input":{ … }}'

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/northwind/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/northwind/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/northwind/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/northwind/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 a grouped question was answered.
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 --period 2026-Q3
accountable entries --company northwind --from 2026-09-01 --json
accountable command create_entry --company northwind --input @entry.json --preview
accountable command create_entry --company northwind --input @entry.json --apply
accountable undo aud_123 --company northwind --apply