Ledger API
This page is optional for headless integrations.
Query the deterministic structured records the RobotMoney protocol produces from Raw evidence. The Ledger is the single source of financial truth. Every row carries provenance, evidence references, and a confidence score.
List accounts
GET /v1/ledger/accounts
Account detail (+ latest balance)
GET /v1/ledger/accounts/{account_id}
List balances (point-in-time)
GET /v1/ledger/balances
List counterparties
GET /v1/ledger/counterparties
Create a manual counterparty
POST /v1/ledger/counterparties
Update counterparty identity
PATCH /v1/ledger/counterparties/{counterparty_id}
Grant counterparty trust
POST /v1/ledger/counterparties/{counterparty_id}/trust/grant
Pause counterparty trust
POST /v1/ledger/counterparties/{counterparty_id}/trust/pause
Restore counterparty trust
POST /v1/ledger/counterparties/{counterparty_id}/trust/restore
Acknowledge counterparty review
POST /v1/ledger/counterparties/{counterparty_id}/trust/acknowledge
List invoices
GET /v1/ledger/invoices
Invoice detail
GET /v1/ledger/invoices/{invoice_id}
List obligations
GET /v1/ledger/obligations
Governed resolved views
GET /v1/ledger/{obligations,counterparties,accounts}/{id}/resolved
List transactions
GET /v1/ledger/transactions
Transaction detail
GET /v1/ledger/transactions/{transaction_id}
Promote Raw → Ledger
POST /v1/ledger/normalize
Trigger reconciliation
POST /v1/ledger/reconcile
List reconciliation matches
GET /v1/ledger/reconciliation-matches
List Transactions
Filters: account_id, counterparty_id, direction (inflow | outflow | transfer | adjustment), status (pending | posted | cleared | failed | reversed | disputed), since, until, limit (default 100, max 1000), cursor. amount is a signed decimal string.
Get a Single Transaction
Returns the same Transaction shape. 404 if unknown.
List Accounts
account_type enum: bank_checking | bank_savings | card | loan | line_of_credit | onchain | payment_processor. Filters: status (active | closed | frozen | pending), account_type, limit (default 50, max 500), cursor.
For one account plus its latest balance:
List Balances (Point-in-Time)
Returns the balance row(s) effective at as_of (or the latest if omitted).
List Counterparties
type enum: merchant | vendor | customer | employer | employee | bank | wallet | exchange | tax_authority | agent | other. verified_status: unverified | self_attested | document_verified | sanctions_cleared. trust_status: unreviewed | trusted | paused | acknowledged. Each counterparty carries risk_level (low | medium | high | sanctioned), aliases[], and linked_accounts[]. Filter list results with trust_status when needed.
Create or Update a Counterparty
Create a manual counterparty with ledger:write:
name and type are required. Optional identity fields are display_name, category, contact_email, country, tax_id, and aliases. The route returns 201 for a new record or 200 when its idempotent create result already exists.
Update editable identity fields with a user principal and ledger:write:
The patch cannot modify payment or trust fields. It returns { "counterparty": { ... } }.
Counterparty Trust
Trust transitions apply uniformly to every counterparty type, including vendors and customers. Each route requires a user bearer JWT with ledger:write. Platform shared-secret callers and API keys cannot use these routes.
Grant
POST /v1/ledger/counterparties/{counterparty_id}/trust/grant
unreviewed, acknowledged
trusted
Pause
POST /v1/ledger/counterparties/{counterparty_id}/trust/pause
unreviewed, trusted, acknowledged
paused
Restore
POST /v1/ledger/counterparties/{counterparty_id}/trust/restore
paused
trusted
Acknowledge
POST /v1/ledger/counterparties/{counterparty_id}/trust/acknowledge
unreviewed, paused
acknowledged
Every transition accepts an optional audit-only reason:
Invalid transitions return 409 with ledger_status_invalid. Successful responses return the updated counterparty and previous_trust_status.
Trust state is informational today: payment execution is enforced through verified_status, sanctions screening, and policy checks. Trust state does not gate payment execution.
List Invoices and Obligations
Invoice.status: draft | sent | partial | paid | overdue | cancelled | disputed. Obligation.type: bill | invoice | subscription | loan | rent | payroll | tax | card_statement | other.
Both endpoints use opaque cursor pagination. Pass limit (default 50, max 500) and the preceding response's next_cursor as cursor; a final page returns next_cursor: null. Use direction=receivable on obligations when listing receivable obligations, or scenario=ar to select explicitly AR-marked rows. AR-sourced invoice and receivable-obligation rows carry metadata.scenario: "ar". Clients should use that positive marker for classification rather than treating every non-AP row as receivable.
GET /v1/ledger/invoices is the complete Ledger source for a receivables inventory. GET /v1/ledger/obligations?direction=receivable contains only receivables that have an obligation projection, so it is not an interchangeably complete AR list.
Invoices can include payment_instruction when bank details were extracted from invoice evidence. The object contains display-safe bank_name, routing_last4, swift_last4, account_last4, the comparison status against the latest on-file counterparty payment instruction, and the compared history row id. Full routing, SWIFT, and account values are stored only as hashes and are never returned.
Fetch an individual invoice with:
It returns the tenant-scoped invoice row or 404.
Governed Resolved Views
The resolved views retain all source observations and present the current governed value, field-level authority, and conflicts for one record. Each route requires ledger:read and returns 404 when the record is absent or belongs to another tenant.
Obligation
GET /v1/ledger/obligations/{obligation_id}/resolved
Counterparty
GET /v1/ledger/counterparties/{counterparty_id}/resolved
Account
GET /v1/ledger/accounts/{account_id}/resolved
Promote Raw → Ledger
Normalize a Raw-parsed row into typed Ledger entities. Idempotent. Re-running with the same input returns the same Ledger row ids.
Normalization derives every entity implied by the parsed row. The route accepts an optional target_entities field for forward compatibility, but the current handler ignores it: it reads only raw_parsed_id and produces the full entity set the parsed row supports.
Reconciliation
Trigger an async reconciliation pass:
202 Accepted → { "job_id": "rec_4711" }.
List matches:
match_type enum: transaction_receipt | invoice_payment | statement_balance | wallet_transfer | payroll_bank_debit | subscription_charge | card_charge | onchain_settlement | obligation_duplicate. status: unmatched | matched | partially_matched | duplicate_possible | disputed | cleared | failed | reversed.
Provenance on Every Row
Every Ledger row carries:
| Field | Description | | --------------------------- | ------------------------------------------ | -------- | --------- | --------------- | ------------------ | | source_ids | Raw artifact ids that produced it | | evidence_ids | Raw-parsed row ids the extractor consulted | | provenance | extracted | inferred | ambiguous | human_confirmed | agent_contributed | | confidence | Calibrated 0 to 1 score | | created_at / updated_at | Bitemporal timestamps |
What's Next
Last updated
