Developers
API reference

Reconciliation

get/v1/reconciliation/exceptions

List reconciliation exceptions

reconciliation_exceptions.listread tokenidempotent

What is waiting for review, newest first: events with no category, suspected duplicates, and balances that do not match a statement.

Parameters

limit
integer · query
Page size, 1–200.
cursor
string | null · query
The next_cursor of the previous page.
is_resolved
boolean · query
Resolved ones instead of open ones.
exception_type
string | null · query
Only this exception_type.
X-Organization-Id
string | null · header

Returns 200 · ReconciliationExceptionList

data
array of ReconciliationExceptionOut · required
has_more
boolean · required
next_cursor
string | null · required
Example
curl -X GET "https://api.lumaledger.app/v1/reconciliation/exceptions" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN"
post/v1/reconciliation/exceptions/{exception_id}/resolve

Resolve a reconciliation exception

reconciliation_exceptions.resolvewrite tokenidempotent

Mark an exception settled, with a note saying how. Resolving one changes nothing else in the ledger: fix the cause first (categorize the event, delete the duplicate), then resolve it.

Parameters

exception_id
integer · path · required
X-Organization-Id
string | null · header

Body · ExceptionResolve

action
string
What was done, a short word kept with the note: resolved, ignored, merged, … Pattern: ^[a-z_]{1,40}$. Default: "resolved".
note
string · required
Why it is settled.

Returns 200 · ReconciliationExceptionOut

created_at
datetime · required
event_id
integer | null · required
The financial event it is about (events.get), if one.
exception_type
string · required
category_missing, suspected_duplicate or balance_mismatch.
group_id
integer | null · required
The reconciliation group it is about, if one.
id
integer · required
is_resolved
boolean · required
resolution_note
string | null · required
[action] note, as it was resolved.
severity
string · required
info, warning or error.
Example
curl -X POST "https://api.lumaledger.app/v1/reconciliation/exceptions/{exception_id}/resolve" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "note": "…"
  }'
get/v1/reconciliation/review-queue

Count what is waiting for review

review_queue.getread tokenidempotent

The size of the review queue: open exceptions by type, and events still unposted.

Parameters

X-Organization-Id
string | null · header

Returns 200 · ReviewQueue

balance_mismatches
integer · required
Open balance_mismatch exceptions.
duplicates
integer · required
Open suspected_duplicate exceptions.
total_exceptions
integer · required
uncategorized
integer · required
Open category_missing exceptions.
unposted
integer · required
Events not yet posted to the ledger.
Example
curl -X GET "https://api.lumaledger.app/v1/reconciliation/review-queue" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN"
post/v1/reconciliation/run

Run the matchers

reconciliation.runwrite tokenidempotent

Pair transfers, card payments and pending/posted twins, and flag suspected duplicates, across the ledger. Imports and syncs already do this; run it after correcting things by hand. Answers 202 with a Job (kind reconcile); its result: transfers_matched, card_payments_matched, pending_posted_matched, duplicates_flagged. Only rows not matched yet are touched, so running it again is harmless.

Parameters

Idempotency-Key
string | null · header
Any unique string (a UUID is ideal). A retry with the same key returns the first attempt's response instead of doing the work twice. Keys are kept for 24 hours.
X-Organization-Id
string | null · header

Returns 202 · Job

created_at
datetime · required
error
JobError | null · required
Why it failed, once failed.
finished_at
datetime | null · required
id
integer · required
kind
string · required
What the job does: import, categorize, generate_journals, reconcile, run_schedules, plaid_sync or rocket_money_import.
result
object | null · required
What the work produced, once succeeded. Its fields depend on kind and are listed on the operation that started it. Counts are integers.
status
string · required
queued, running, succeeded or failed.
Example
curl -X POST "https://api.lumaledger.app/v1/reconciliation/run" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
post/v1/reconciliation/statements

Reconcile an account against a statement

statement_reconciliations.createwrite tokenidempotent

Check the ledger's balance for an account against the balance a bank statement shows on its closing date. A statement that agrees is recorded as the bank's balance on that date, once per account and date (a second time is a 409 conflict); a difference opens a balance_mismatch exception.

Parameters

Idempotency-Key
string | null · header
Any unique string (a UUID is ideal). A retry with the same key returns the first attempt's response instead of doing the work twice. Keys are kept for 24 hours.
X-Organization-Id
string | null · header

Body · StatementReconcile

account_id
integer · required
The bank, card or loan account the statement is for.
statement_balance
string · required
The closing balance the statement shows, as a decimal string, in the account's currency: "1520.34". Pattern: ^-?\d{1,12}(\.\d{1,2})?$.
statement_date
date · required
The statement's closing date.

Returns 201 · StatementReconciliation

account_id
integer · required
computed_balance
Money · required
The ledger's balance for the account on that date.
difference
Money · required
statement_balance minus computed_balance.
group_id
integer · required
The reconciliation group this check is recorded as.
is_reconciled
boolean · required
They agree to the cent. When not, a balance_mismatch exception is opened.
statement_balance
Money · required
statement_date
date · required
Example
curl -X POST "https://api.lumaledger.app/v1/reconciliation/statements" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": 1,
    "statement_balance": "1520.34",
    "statement_date": "2026-09-01"
  }'

Objects

ExceptionResolve

Fields

action
string
What was done, a short word kept with the note: resolved, ignored, merged, … Pattern: ^[a-z_]{1,40}$. Default: "resolved".
note
string · required
Why it is settled.

Job

Work that outlives the request that started it. Poll jobs.get until status is succeeded or failed.

Fields

created_at
datetime · required
error
JobError | null · required
Why it failed, once failed.
finished_at
datetime | null · required
id
integer · required
kind
string · required
What the job does: import, categorize, generate_journals, reconcile, run_schedules, plaid_sync or rocket_money_import.
result
object | null · required
What the work produced, once succeeded. Its fields depend on kind and are listed on the operation that started it. Counts are integers.
status
string · required
queued, running, succeeded or failed.

JobError

Fields

code
string · required
Stable error code, as in the error envelope.
message
string · required
For people, in the request's language. Never match on it.

Money

An amount and its currency. `amount` is a base-10 string with two decimal places and an optional leading minus sign. Parse it with a decimal type, not a float.

Fields

amount
string · required
Pattern: ^-?\d+\.\d{2}$.
currency
string · required
ISO 4217 code. Pattern: ^[A-Z]{3}$.

ReconciliationExceptionList

A page of reconciliation exceptions, newest first.

Fields

data
array of ReconciliationExceptionOut · required
has_more
boolean · required
next_cursor
string | null · required

ReconciliationExceptionOut

Something the matchers could not settle, waiting for a person.

Fields

created_at
datetime · required
event_id
integer | null · required
The financial event it is about (events.get), if one.
exception_type
string · required
category_missing, suspected_duplicate or balance_mismatch.
group_id
integer | null · required
The reconciliation group it is about, if one.
id
integer · required
is_resolved
boolean · required
resolution_note
string | null · required
[action] note, as it was resolved.
severity
string · required
info, warning or error.

ReviewQueue

How much is waiting for a person.

Fields

balance_mismatches
integer · required
Open balance_mismatch exceptions.
duplicates
integer · required
Open suspected_duplicate exceptions.
total_exceptions
integer · required
uncategorized
integer · required
Open category_missing exceptions.
unposted
integer · required
Events not yet posted to the ledger.

StatementReconcile

Fields

account_id
integer · required
The bank, card or loan account the statement is for.
statement_balance
string · required
The closing balance the statement shows, as a decimal string, in the account's currency: "1520.34". Pattern: ^-?\d{1,12}(\.\d{1,2})?$.
statement_date
date · required
The statement's closing date.

StatementReconciliation

Fields

account_id
integer · required
computed_balance
Money · required
The ledger's balance for the account on that date.
difference
Money · required
statement_balance minus computed_balance.
group_id
integer · required
The reconciliation group this check is recorded as.
is_reconciled
boolean · required
They agree to the cent. When not, a balance_mismatch exception is opened.
statement_balance
Money · required
statement_date
date · required