Accounting Ledger API · ledgers
The trial balance over the ledger's range beside what its journals not refused carry
GET /ledgers/{ledgerId}/reconciliation
The trial balance over the ledger's range (from the opening stocktake — opening — to the end of today in the books' zone; empty, and waiting says why, before it) beside what its journals not refused carry, per account, debits and credits apart: inStep when every account matches; pending counts journals not yet answered; waiting says what holds the rest back — settings not saved, accounts not placed, recent refusals, more sent than the ledger holds (a person's to look at; nothing sent is ever undone).
unplaced names, structured, the accounts with movement not yet sent that have nowhere to land (neither mapped nor kept by the app) — empty in create mode and before settings are saved. unmapped names the accounts the chart's roles need (each SKU-role or control-account default) that have no place, whether or not anything has posted to them yet — every one, in map mode with nothing mapped; empty in create mode and before settings are saved. The setup walk calls an accounting app's step done only when both are empty.
Access
Requires financials:read.
How scopes come from roles: Scopes and roles. Getting a token: Authentication and app tokens.
AI agent tool
Agents call this as accounting_ledger_reconciliation (Accounting: Ledger reconciliation), in the accounting toolset. It only reads.
Connecting an agent: AI agents.
Example
curl -X GET 'https://accounting.getmanifold.io/ledgers/lgr_01a0f6b2-1c00-7f71-8a82-465768798a9b/reconciliation' \
-H "Authorization: Bearer $MANIFOLD_TOKEN"const response = await fetch("https://accounting.getmanifold.io/ledgers/lgr_01a0f6b2-1c00-7f71-8a82-465768798a9b/reconciliation", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.MANIFOLD_TOKEN}` },
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const answer = await response.json();{
"opening": {
"stocktakeId": "stk_01a0f6b0-9c40-7e61-8f72-021324354657",
"at": "2026-10-01T00:30:00.000Z"
},
"from": "2026-10-01T00:30:00.000Z",
"to": "2026-10-21T13:00:00.000Z",
"accounts": [
{
"account": "1200",
"ledgerDebitCents": 10560,
"ledgerCreditCents": 0,
"sentDebitCents": 10560,
"sentCreditCents": 0
},
{
"account": "1400",
"ledgerDebitCents": 150000,
"ledgerCreditCents": 3400,
"sentDebitCents": 150000,
"sentCreditCents": 3400
},
{
"account": "2100",
"ledgerDebitCents": 0,
"ledgerCreditCents": 102000,
"sentDebitCents": 0,
"sentCreditCents": 102000
},
{
"account": "2200",
"ledgerDebitCents": 0,
"ledgerCreditCents": 960,
"sentDebitCents": 0,
"sentCreditCents": 960
},
{
"account": "3900",
"ledgerDebitCents": 0,
"ledgerCreditCents": 48000,
"sentDebitCents": 0,
"sentCreditCents": 48000
},
{
"account": "4000",
"ledgerDebitCents": 0,
"ledgerCreditCents": 9600,
"sentDebitCents": 0,
"sentCreditCents": 9600
},
{
"account": "5000",
"ledgerDebitCents": 3400,
"ledgerCreditCents": 0,
"sentDebitCents": 3400,
"sentCreditCents": 0
}
],
"inStep": true,
"pending": 0,
"waiting": [
"no place yet for the chart's default accounts: 1110, 1120, 1130, 1170, 1180, 1190, 1195, 1350, 2000, 2150, 2160, 2300, 2400, 2410, 4100, 4200, 4300, 5100, 5200, 6100, 6200, 7100, 7110"
],
"unplaced": [],
"unmapped": [
"1110",
"1120",
"1130",
"1170",
"1180",
"1190",
"1195",
"1350",
"2000",
"2150",
"2160",
"2300",
"2400",
"2410",
"4100",
"4200",
"4300",
"5100",
"5200",
"6100",
"6200",
"7100",
"7110"
]
}The panel writes this call in other languages. It does not send it: Manifold's APIs do not take calls from a web
page on another site, so run the call from your own code or terminal. The whole API as OpenAPI: accounting-manager.openapi.json. Base URL https://accounting.getmanifold.io.
Errors
Every refusal is a status and a JSON body whose _tag names it. A refused call changes nothing.
401
| Refusal | What it means | What to do |
|---|---|---|
Unauthorized reason | The token is missing, expired or not one Manifold issued. | Get a fresh token and send the call again. |
TokenAlreadyUsed tokenId | A single-use app token was already spent. | Mint a new token for this call. |
402
| Refusal | What it means | What to do |
|---|---|---|
SubscriptionRequired status | The organization's subscription has lapsed, so writes are refused. | An owner settles billing. Reads still work meanwhile. |
403
| Refusal | What it means | What to do |
|---|---|---|
TenantRequired userId | The token names no organization. | Choose the organization, then get a new token. |
ScopeRequired required | The token's roles do not grant the scope this call needs. | Ask an owner or admin for a role that grants it. |
404
| Refusal | What it means | What to do |
|---|---|---|
LedgerNotFound ledgerId | No such record in this organization. | Check the id in the path or the body. |
409
| Refusal | What it means | What to do |
|---|---|---|
MirroredFromSource source | This area is fed by your source system until the organization goes live. | Make the change in the source system, or go live first. |
503
| Refusal | What it means | What to do |
|---|---|---|
ChartUnreadable reason | The accounting software's chart of accounts could not be read. | Try again shortly. |
RequestLogUnavailable tokenId, reason | The service could not record the request, so it did nothing. | Try again shortly. |
How refusals work everywhere: Errors.