Developers
API reference

Institutions

get/v1/institutions

List institutions

institutions.listread tokenidempotent

Every bank in the ledger, connected or typed in, by the name the app shows. accounts.list?institution_id= gives the accounts at one.

Parameters

limit
integer · query
Page size, 1–200.
cursor
string | null · query
The next_cursor of the previous page.
X-Organization-Id
string | null · header

Returns 200 · InstitutionList

data
array of Institution · required
has_more
boolean · required
next_cursor
string | null · required
Example
curl -X GET "https://api.lumaledger.app/v1/institutions" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN"
post/v1/institutions

Create an institution

institutions.createwrite tokenidempotent

Add a bank by hand, for one no connection reaches (a credit union, a broker abroad). It starts empty; add accounts to it with institutions.create_account. A bank with the same name already in the ledger is a 409: use that one. Send an Idempotency-Key so a retry cannot create it twice.

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 · InstitutionCreate

name
string · required
url
string | null
The bank's website.

Returns 201 · Institution

id
integer · required
The institution id. Accounts name it as institution_id.
name
string · required
The name to show: your rename if you gave one, else the bank's own.
notes
string | null · required
Free text kept about the bank.
official_name
string | null · required
The bank's own name, present only when a rename is hiding it.
slug
string · required
Stable key of the bank's name (chase), unique in the ledger.
source
string · required
plaid when a connection brought it, manual when typed in.
url
string | null · required
Example
curl -X POST "https://api.lumaledger.app/v1/institutions" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "…"
  }'
delete/v1/institutions/{institution_id}

Delete an institution

institutions.deletewrite tokendestructiveidempotent

Delete a bank nothing points at: a typo, a duplicate, one whose accounts are all gone. A bank that still has an account (closed ones included, whose only record of where they were held is this) or a connection is a 409.

Parameters

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

Returns 204 with no body.

Example
curl -X DELETE "https://api.lumaledger.app/v1/institutions/{institution_id}" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN"
get/v1/institutions/{institution_id}

Get an institution

institutions.getread tokenidempotent

One bank, with the connections that feed it, whether it could be deleted, and who it is (the About card: what the web lookup found and your corrections to it).

Parameters

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

Returns 200 · InstitutionDetail

about
InstitutionAbout | null · required
The web lookup's answer; null when never looked up (institutions.identify).
about_edits
InstitutionAboutEdits | null · required
Your corrections to that answer; null when there are none.
connections
array of Connection · required
deletable
boolean · required
True when no account (closed ones included) and no connection points at it, so institutions.delete would succeed.
id
integer · required
The institution id. Accounts name it as institution_id.
name
string · required
The name to show: your rename if you gave one, else the bank's own.
notes
string | null · required
Free text kept about the bank.
official_name
string | null · required
The bank's own name, present only when a rename is hiding it.
slug
string · required
Stable key of the bank's name (chase), unique in the ledger.
source
string · required
plaid when a connection brought it, manual when typed in.
url
string | null · required
Example
curl -X GET "https://api.lumaledger.app/v1/institutions/{institution_id}" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN"
patch/v1/institutions/{institution_id}

Update an institution

institutions.updatewrite tokenidempotent

Rename a bank, keep notes about it, or correct what its About card says. A rename applies everywhere the ledger names the bank, and survives the connection refreshing the bank's own name. Only the fields sent change.

Parameters

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

Body · InstitutionUpdate

about_address
string | null
about_description
string | null
about_phone
string | null
about_summary
string | null
Correct the About card's one line. Null shows what the lookup found; an empty string shows nothing.
about_website
string | null
http(s) only.
name
string | null
Rename it everywhere the ledger shows it. Null puts the bank's own name back.
notes
string | null
Null clears them.

Returns 200 · Institution

id
integer · required
The institution id. Accounts name it as institution_id.
name
string · required
The name to show: your rename if you gave one, else the bank's own.
notes
string | null · required
Free text kept about the bank.
official_name
string | null · required
The bank's own name, present only when a rename is hiding it.
slug
string · required
Stable key of the bank's name (chase), unique in the ledger.
source
string · required
plaid when a connection brought it, manual when typed in.
url
string | null · required
Example
curl -X PATCH "https://api.lumaledger.app/v1/institutions/{institution_id}" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
get/v1/institutions/{institution_id}/about

Get who an institution is

institutions.get_aboutread tokenidempotent

The stored answer to "who is this bank?", and whether a lookup is still running (poll this after institutions.identify).

Parameters

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

Returns 200 · InstitutionAboutResult

about
InstitutionAbout | null · required
pending
boolean · required
A lookup is running; poll institutions.get_about until this is false.
Example
curl -X GET "https://api.lumaledger.app/v1/institutions/{institution_id}/about" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN"
post/v1/institutions/{institution_id}/accounts

Create an account at an institution

institutions.create_accountwrite tokenidempotent

Open an account at this bank by hand: one no connection returns (a second card, a CD, an account at a bank that cannot be connected). Its type, role and code follow from kind, and with a balance it reads that amount from today, with transfers to it counted on top. Once it exists, transfers to it can be filed as transfers instead of spending. Send an Idempotency-Key so a retry cannot create it twice.

Parameters

institution_id
integer · path · required
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 · ManualAccountCreate

balance
string | null
What it holds (asset) or owes (liability) today, as a decimal string. Omitted, it starts at zero and holds only what transfers put there. Pattern: ^-?\d{1,12}(\.\d{1,2})?$.
kind
string · required
What it is, which decides its type and role: checking, savings, cash, brokerage, retirement, other_asset, credit_card, loan, mortgage, student_loan, other_liability. Pattern: ^(checking|savings|cash|brokerage|retirement|other_asset|credit_card|loan|mortgage|student_loan|other_liability)$.
mask
string | null
The last digits the bank prints.
name
string · required

Returns 201 · Account

balance
Money · required
The account's balance, positive on its normal side: what an asset holds, what a liability owes, what an expense category has spent in total.
code
string · required
Chart-of-accounts code, unique in the ledger (1010, 5190).
created_at
datetime · required
excluded_from_totals
boolean · required
Left out of net worth and other totals.
hidden
boolean · required
Hidden from lists in the app.
id
integer · required
The account id. Transactions and journal lines name it as account_id.
institution_id
integer | null · required
The bank or provider the account belongs to.
is_active
boolean · required
False once the account is closed. Its history stays in the ledger.
is_placeholder
boolean · required
A grouping account that holds no postings of its own.
low_balance_alert
LowBalanceAlert | null · required
The member is told when this account's balance drops below a threshold, and has a to-do until it is back above; null when nobody set one. Only an open asset account can carry one. Set it with accounts.update.
mask
string | null · required
The last digits of the account number, as the bank shows them.
name
string · required
normal_balance
string · required
debit or credit: the side that increases the account.
overdraft_ahead
LowBalanceShortfall | null · required
With no low_balance_alert set: the recurring bills and paychecks expected on this open asset account over the next month, and the payments of the credit cards it pays, take its balance below zero; needed is what to move in to stay at or above zero. The member sees it on their to-do list and the account's page but is never notified of it unasked: setting a low_balance_alert is how they ask. Null when the bills ahead do not, when the balance is already below zero, and whenever an alert is set (its shortfall says it then).
parent_id
integer | null · required
The parent account, for sub-accounts and subcategories.
purpose
string | null · required
business if its transactions count as business by default; null for personal.
role
string | null · required
What the account is for, when known (checking, credit_card, mortgage, …).
type
string · required
asset, liability, equity, income or expense.
unshared_at
datetime | null · required
When the bank stopped sharing this account on its connection (deselected, closed or revoked at the bank) while the connection itself keeps syncing, or null while it is shared. Its balance is frozen at the last number the bank sent. A person fixes it in the app by sharing the account again, or closes it with accounts.close.
Example
curl -X POST "https://api.lumaledger.app/v1/institutions/{institution_id}/accounts" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "…",
    "name": "…"
  }'
post/v1/institutions/{institution_id}/identify

Look up who an institution is

institutions.identifywrite tokenidempotent

Search the web for who a bank, broker or card issuer is, and keep the answer. A bank already identified returns what is stored without searching again, so this is safe to call on every read. When the search runs in the background pending is true: poll institutions.get_about. Answers 503 when lookups are not configured on this server.

Parameters

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

Returns 200 · InstitutionAboutResult

about
InstitutionAbout | null · required
pending
boolean · required
A lookup is running; poll institutions.get_about until this is false.
Example
curl -X POST "https://api.lumaledger.app/v1/institutions/{institution_id}/identify" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN"
post/v1/institutions/{institution_id}/purge

Erase an institution and everything it brought in

institutions.purgewrite tokendestructive

Put the ledger back the way it was before this bank was linked: every account at it, open or closed, is erased with its history (see accounts.purge), every connection to it is revoked, and the bank itself is deleted. The other side of a transfer into one of its accounts is kept and categorized again. An entry that would move an account being kept is a 409 naming it. Needs an admin.

Parameters

institution_id
integer · path · required
dry_run
boolean · query
Report what would go, change nothing.
X-Organization-Id
string | null · header

Returns 200 · Purge

account_ids
array of integer · required
blocker_count
integer · required
blockers
array of PurgeBlocker · required
entries
integer · required
Journal entries deleted outright.
erased
boolean · required
False on a dry run, or when blockers refused it.
released
integer · required
Transactions on accounts that stay, unpaired from a transfer into an erased account and categorized again. Their balances do not move.
transactions
integer · required
Transactions of the erased accounts.
Example
curl -X POST "https://api.lumaledger.app/v1/institutions/{institution_id}/purge" \
  -H "Authorization: Bearer $LUMALEDGER_TOKEN"

Objects

AboutSource

Fields

title
string · required
url
string · required

Account

One account in the ledger's chart of accounts: a bank account, a card, a loan, or a category such as Groceries (an expense account).

Fields

balance
Money · required
The account's balance, positive on its normal side: what an asset holds, what a liability owes, what an expense category has spent in total.
code
string · required
Chart-of-accounts code, unique in the ledger (1010, 5190).
created_at
datetime · required
excluded_from_totals
boolean · required
Left out of net worth and other totals.
hidden
boolean · required
Hidden from lists in the app.
id
integer · required
The account id. Transactions and journal lines name it as account_id.
institution_id
integer | null · required
The bank or provider the account belongs to.
is_active
boolean · required
False once the account is closed. Its history stays in the ledger.
is_placeholder
boolean · required
A grouping account that holds no postings of its own.
low_balance_alert
LowBalanceAlert | null · required
The member is told when this account's balance drops below a threshold, and has a to-do until it is back above; null when nobody set one. Only an open asset account can carry one. Set it with accounts.update.
mask
string | null · required
The last digits of the account number, as the bank shows them.
name
string · required
normal_balance
string · required
debit or credit: the side that increases the account.
overdraft_ahead
LowBalanceShortfall | null · required
With no low_balance_alert set: the recurring bills and paychecks expected on this open asset account over the next month, and the payments of the credit cards it pays, take its balance below zero; needed is what to move in to stay at or above zero. The member sees it on their to-do list and the account's page but is never notified of it unasked: setting a low_balance_alert is how they ask. Null when the bills ahead do not, when the balance is already below zero, and whenever an alert is set (its shortfall says it then).
parent_id
integer | null · required
The parent account, for sub-accounts and subcategories.
purpose
string | null · required
business if its transactions count as business by default; null for personal.
role
string | null · required
What the account is for, when known (checking, credit_card, mortgage, …).
type
string · required
asset, liability, equity, income or expense.
unshared_at
datetime | null · required
When the bank stopped sharing this account on its connection (deselected, closed or revoked at the bank) while the connection itself keeps syncing, or null while it is shared. Its balance is frozen at the last number the bank sent. A person fixes it in the app by sharing the account again, or closes it with accounts.close.

Connection

One bank login (a Plaid item) feeding accounts at this bank.

Fields

bank_refreshed_at
datetime | null · required
When the data provider last reached the bank itself, new data or not (transactions and holdings alike). Same meaning as on plaid_items.list.
created_at
datetime · required
error_code
string | null · required
Why it is not syncing, as a stable code.
item_id
string · required
The connection's id.
last_synced_at
datetime | null · required
new_accounts_available_at
datetime | null · required
When the bank said it has accounts this connection does not share yet, or null. Same meaning as on plaid_items.list.
stale
boolean · required
True when it should be syncing but has delivered no fresh data for over two days.
stale_reason
string | null · required
sync_failing (our syncs fail; sync again), holdings_failing (syncs succeed but the investment positions could not be fetched; sync again), investment_transactions_failing (the same for the investment activity), liabilities_failing (the same for cards' and loans' due dates and rates) or bank_silent (syncs succeed but the bank has not answered since bank_refreshed_at); null when not stale. Same meaning as on plaid_items.list.
status
string · required
active, error, login_required or revoked.

Institution

A bank, card issuer or broker the ledger's accounts are held at.

Fields

id
integer · required
The institution id. Accounts name it as institution_id.
name
string · required
The name to show: your rename if you gave one, else the bank's own.
notes
string | null · required
Free text kept about the bank.
official_name
string | null · required
The bank's own name, present only when a rename is hiding it.
slug
string · required
Stable key of the bank's name (chase), unique in the ledger.
source
string · required
plaid when a connection brought it, manual when typed in.
url
string | null · required

InstitutionAbout

Who a bank is, as looked up on the web.

Fields

address
string | null · required
description
string | null · required
looked_up_at
datetime · required
phone
string | null · required
sources
array of AboutSource · required
status
string · required
found, or unknown when the lookup could not tell.
summary
string | null · required
website
string | null · required

InstitutionAboutEdits

The user's corrections to the About card, field by field. Null shows what the lookup found; an empty string shows nothing.

Fields

address
string | null · required
description
string | null · required
phone
string | null · required
summary
string | null · required
website
string | null · required

InstitutionAboutResult

Fields

about
InstitutionAbout | null · required
pending
boolean · required
A lookup is running; poll institutions.get_about until this is false.

InstitutionCreate

Fields

name
string · required
url
string | null
The bank's website.

InstitutionDetail

An institution with its connections, and who it is.

Fields

about
InstitutionAbout | null · required
The web lookup's answer; null when never looked up (institutions.identify).
about_edits
InstitutionAboutEdits | null · required
Your corrections to that answer; null when there are none.
connections
array of Connection · required
deletable
boolean · required
True when no account (closed ones included) and no connection points at it, so institutions.delete would succeed.
id
integer · required
The institution id. Accounts name it as institution_id.
name
string · required
The name to show: your rename if you gave one, else the bank's own.
notes
string | null · required
Free text kept about the bank.
official_name
string | null · required
The bank's own name, present only when a rename is hiding it.
slug
string · required
Stable key of the bank's name (chase), unique in the ledger.
source
string · required
plaid when a connection brought it, manual when typed in.
url
string | null · required

InstitutionList

A page of institutions, in id order.

Fields

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

InstitutionUpdate

Only the fields sent are changed.

Fields

about_address
string | null
about_description
string | null
about_phone
string | null
about_summary
string | null
Correct the About card's one line. Null shows what the lookup found; an empty string shows nothing.
about_website
string | null
http(s) only.
name
string | null
Rename it everywhere the ledger shows it. Null puts the bank's own name back.
notes
string | null
Null clears them.

LowBalanceAlert

"Tell me when this account drops below …".

Fields

below
boolean · required
The balance is under the threshold right now.
below_since
datetime | null · required
When the balance was seen dropping below the threshold, which is when the member was notified; null while it is at or above it.
shortfall
LowBalanceShortfall | null · required
The recurring bills and paychecks expected on the account over the next month, and the payments of the credit cards it pays (bills first on a day), take the balance under the threshold; the member is notified once and has a to-do while it stands. Null when they do not, and while the balance is already below.
threshold
Money · required
Alert when the balance drops below this.

LowBalanceShortfall

The recurring bills and paychecks expected on the account over the next month take its balance under the alert's threshold.

Fields

bill_amount
Money · required
That bill's usual amount; for a card, what paying it in full takes.
bill_kind
string · required
recurring: a charge the recurring detector found. card_payment: a credit card this account paid last, expected to be paid in full by its due date.
bill_name
string · required
The expected bill that takes it under: a recurring charge's name, or the name of the credit card whose payment it is.
lowest
Money · required
The lowest the balance is projected to reach over the month.
needed
Money · required
What to move in now to stay at or above the threshold all month.
short_on
date · required
The first day the balance is projected under the threshold.

ManualAccountCreate

An account at this bank that no connection feeds.

Fields

balance
string | null
What it holds (asset) or owes (liability) today, as a decimal string. Omitted, it starts at zero and holds only what transfers put there. Pattern: ^-?\d{1,12}(\.\d{1,2})?$.
kind
string · required
What it is, which decides its type and role: checking, savings, cash, brokerage, retirement, other_asset, credit_card, loan, mortgage, student_loan, other_liability. Pattern: ^(checking|savings|cash|brokerage|retirement|other_asset|credit_card|loan|mortgage|student_loan|other_liability)$.
mask
string | null
The last digits the bank prints.
name
string · required

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}$.

Purge

What erasing takes (`dry_run`) or took.

Fields

account_ids
array of integer · required
blocker_count
integer · required
blockers
array of PurgeBlocker · required
entries
integer · required
Journal entries deleted outright.
erased
boolean · required
False on a dry run, or when blockers refused it.
released
integer · required
Transactions on accounts that stay, unpaired from a transfer into an erased account and categorized again. Their balances do not move.
transactions
integer · required
Transactions of the erased accounts.

PurgeBlocker

Fields

date
string | null
id
integer · required
kind
string · required
entry: a journal entry (id is its transaction id) that also moves an account being kept. child_account: a sub-account of one being erased.
label
string · required