API Reference
The current LedgerHQ partner REST API contract.
LedgerHQ serves the public integration API from the same deployed app that users sign into. The current public contract is the partner accounting surface: firm-level OAuth, company-scoped bookkeeping routes, accounts, posting resources, entries, Plaid-connected bank activity, reconciliation actions, reports, MCP, and webhooks.
New third-party apps should start with the
Partner Bookkeeping API. It uses
/api/v1/companies/{companyId}/... routes so apps can connect once at the
firm level and then choose the company they need.
OpenAPI
Machine-readable contract:
https://ledgerhq.pro/api/openapi.jsonThe OpenAPI document covers the validated partner integration surface first. Routes outside that contract are not public partner docs yet.
Base URL
https://ledgerhq.pro/api/v1Authentication
Partner apps should connect once with Authorization Code + PKCE from a LedgerHQ firm owner/admin account. The access token is anchored to the firm account and can then discover client files managed by that firm.
GET /api/oauth/authorize
POST /api/oauth/tokenClient discovery does not require an organization header:
Authorization: Bearer mcp_at_your_tokenNew partner routes scope requests through the path:
GET /api/v1/companies/company_id/accounts
Authorization: Bearer mcp_at_your_tokenLegacy organization-scoped routes include the mapped company as a header:
Authorization: Bearer mcp_at_your_token
x-organization-id: org_idServer-to-server requests can also use a LedgerHQ API key:
Authorization: Bearer dk_live_your_key
x-organization-id: org_idBrowser-session requests can call the same routes with the signed-in user's
cookies. Include x-organization-id when the user has access to more than
one organization.
Response Shape
Legacy endpoints may return simple errors:
{ "error": "Message" }Posting endpoints return structured errors:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed.",
"retryable": false,
"requestId": "req_..."
}
}Money values in the documented integration contract are integer cents unless a
field says otherwise. Example: 1250 means $12.50.
Supported REST Surface
Health
| Method | Path | Purpose |
|---|---|---|
GET | /api/health | Public deployment health check |
Organizations
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/organizations | List firm-managed client organizations for account-level OAuth mapping |
Partner Companies
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/companies | List firm-managed companies for a connected firm |
GET | /api/v1/companies/:companyId | Get company details |
GET | /api/v1/companies/:companyId/accounts | List company chart accounts |
GET | /api/v1/companies/:companyId/journal-entries | List company journal entries |
GET | /api/v1/companies/:companyId/journal-lines | List company journal lines |
GET | /api/v1/companies/:companyId/bank-accounts | List company bank/register accounts |
GET | /api/v1/companies/:companyId/bank-transactions | List company bank transactions |
GET | /api/v1/companies/:companyId/reconciliations | List company reconciliation sessions |
GET | /api/v1/companies/:companyId/reports/profit-and-loss | Run profit and loss |
GET | /api/v1/companies/:companyId/reports/balance-sheet | Run balance sheet |
GET | /api/v1/companies/:companyId/reports/trial-balance | Run trial balance |
GET | /api/v1/companies/:companyId/reports/general-ledger | Run general ledger |
Accounts
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/accounts | List accounts for classification and reporting |
POST | /api/v1/accounts | Create an account |
GET | /api/v1/accounts/:id | Get account and ledger detail |
PATCH | /api/v1/accounts/:id | Update account metadata |
DELETE | /api/v1/accounts/:id | Delete an unused account |
Journal Entries
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/entries | List entries |
POST | /api/v1/entries | Create a draft entry |
GET | /api/v1/entries/:id | Get an entry with lines |
POST | /api/v1/entries/:id/post | Post a draft entry |
POST | /api/v1/entries/:id/void | Void a posted entry |
Posting Resources
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/purchases | Create a posted purchase and bank-register activity when source account is bank-linked |
POST | /api/v1/deposits | Create a posted deposit and bank-register activity when destination account is bank-linked |
POST | /api/v1/transfers | Create a posted transfer between two balance-sheet accounts |
POST | /api/v1/bill-payments | Pay an existing bill and allocate the payment |
POST | /api/v1/journal-entries | Create a balanced posted journal entry |
Posting routes require Idempotency-Key and return a posting receipt with the
created journalEntryId, optional bankTransactionIds, status, and
createdAt.
Company-path aliases are also available and are recommended for partner apps:
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/companies/:companyId/purchases | Create a posted purchase |
POST | /api/v1/companies/:companyId/deposits | Create a posted deposit |
POST | /api/v1/companies/:companyId/transfers | Create a posted transfer |
POST | /api/v1/companies/:companyId/bill-payments | Pay an existing bill |
POST | /api/v1/companies/:companyId/journal-entries | Create a balanced posted journal entry |
Bank Activity
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/bank-accounts | List bank accounts that hold bank/card activity |
POST | /api/v1/bank-accounts | Create a bank account |
GET | /api/v1/bank-accounts/:id/transactions | List bank transactions for an account |
GET | /api/v1/bank-transactions | List organization bank transaction history for rules and review |
GET | /api/v1/bank-feeds | List connected bank feeds |
GET | /api/v1/bank-feeds/health | Per-connection and per-account Plaid feed health |
Bank and card activity arrives through Plaid-connected feeds, which sync
internally on a webhook-driven basis. There is no public "import rows" endpoint;
synced rows land as bank transactions with sourceType: "plaid_bank_feed",
which you then classify, reclassify, and reconcile.
Bank Transaction Actions
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/bank-transactions/:id/reclassify | Update account/contact/tax classification and linked editable journal line |
POST | /api/v1/bank-transactions/:id/match | Match a transaction to an invoice or bill payment |
POST | /api/v1/bank-transactions/:id/split | Split a transaction across invoices or bills |
POST | /api/v1/bank-transactions/:id/reconcile | Mark a transaction reconciled |
POST | /api/v1/bank-transactions/:id/exclude | Mark a transaction excluded |
Reports
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/reports/financial-packet | Financial packet JSON |
GET | /api/v1/reports/trial-balance | Trial balance |
GET | /api/v1/reports/balance-sheet | Balance sheet |
GET | /api/v1/reports/profit-and-loss | Profit and loss |
GET | /api/v1/reports/general-ledger | General ledger |
GET | /api/v1/reports/bank-reconciliation-status | Bank reconciliation status |
Webhooks
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/webhooks | List webhook subscriptions |
POST | /api/v1/webhooks | Create webhook subscription |
Example: Post A Purchase
curl -X POST \
-H "Authorization: Bearer mcp_at_your_token" \
-H "Idempotency-Key: ledgerhq-purchase-1001" \
-H "Content-Type: application/json" \
-d '{
"date": "2026-06-08",
"sourceAccountId": "checking_gl_account_id",
"amountCents": 4299,
"categoryAccountId": "office_supplies_expense_id",
"description": "Office supplies",
"reference": "office-depot-1001"
}' \
https://ledgerhq.pro/api/v1/companies/company_uuid/purchasesExample: Reclassify Transaction
curl -X POST \
-H "Authorization: Bearer mcp_at_your_token" \
-H "x-organization-id: org_id" \
-H "Content-Type: application/json" \
-d '{ "accountId": "expense_account_id", "reason": "Category review" }' \
https://ledgerhq.pro/api/v1/bank-transactions/bank_transaction_id/reclassifyExample: Fetch A Company Report
curl -H "Authorization: Bearer mcp_at_your_token" \
"https://ledgerhq.pro/api/v1/companies/company_uuid/reports/profit-and-loss?startDate=2026-01-01&endDate=2026-06-30"