API reference
Exceptions
What blocks a month from closing, and how each one is resolved.
- GET
/v1/exceptionsList what the automation could not finish - GET
/v1/exceptions/countsCount the open items by whom they wait on - POST
/v1/exceptions/{exception_id}/approveApprove what the books recommend for an item - POST
/v1/exceptions/{exception_id}/assignAssign a close exception to a member - POST
/v1/exceptions/{exception_id}/escalateHand an open item to the business owner - POST
/v1/exceptions/{exception_id}/resolveResolve a close exception - POST
/v1/exceptions/{exception_id}/send_to_reviewerHand an open item to the books' accountant or firm
Guides: Close the month, Work the inbox
List what the automation could not finish
GET/v1/exceptions
client.exceptions.list()
Everything the automation could not finish, across every month, newest first: what it is, how much it matters and the record it is about. A month's close lists the same items for that month; this is the whole queue, for working it without opening each month.
Parameters
| Name | Type | Description |
|---|---|---|
limitQuery | integer | Page size, 1–200. |
cursorQuery | string or null | The |
statusQuery | string |
open, resolved, dismissedDefault open |
kindQuery | string or null | Only this kind, such as |
assigned_toQuery | string or null | Only items assigned to this member's user id; |
waiting_onQuery | string or null | Only items waiting on this: agent, reviewer, owner, third_party |
Response
Errors
- 400
- The request was malformed or a parameter is invalid.
- 401
- No valid credential was sent.
- 403
- The credential or the member's role does not allow this.
- 404
- No such resource in this ledger.
- 409
- A conflicting request, e.g. one with the same Idempotency-Key still running.
- 422
- A well-formed request a business rule refused.
- 429
- Too many requests; retry after the Retry-After header.
- 500
- Something failed on our side; the request_id identifies it.
Example
curl "https://api.ledgerit.ai/v1/exceptions" \
-H "Authorization: Bearer $LEDGERIT_TOKEN"Count the open items by whom they wait on
GET/v1/exceptions/counts
client.exceptions.counts()
How many open items wait on the owner, the reviewer and someone outside the books, and the money at stake in each, per currency; and whether the books have a reviewer to send items to. The agent's own items are not counted: nobody is asked about them yet.
Response
Errors
- 400
- The request was malformed or a parameter is invalid.
- 401
- No valid credential was sent.
- 403
- The credential or the member's role does not allow this.
- 404
- No such resource in this ledger.
- 409
- A conflicting request, e.g. one with the same Idempotency-Key still running.
- 422
- A well-formed request a business rule refused.
- 429
- Too many requests; retry after the Retry-After header.
- 500
- Something failed on our side; the request_id identifies it.
Example
curl "https://api.ledgerit.ai/v1/exceptions/counts" \
-H "Authorization: Bearer $LEDGERIT_TOKEN"Approve what the books recommend for an item
POST/v1/exceptions/{exception_id}/approve
client.exceptions.approve()
Approve what the books recommend for an item asking for a category —
or file it under account_id — and resolve it. The transaction is filed
exactly as filing it by hand files it (POST /transactions/{id}/categorize),
so the same refusals apply: account_not_usable, and period_closed for
a transaction in a closed month.
With always, a rule files every later transaction with the same
counterparty here, with no model asked.
A missing_accrual item from the books' daily check is approved by
accruing the vendor's month: its usual amount (or amount) to the
account its charges are filed to (or account_id), as
POST /schedules/accruals would, settled by the vendor's next charge
even if it lands later in the month. The accrual's id is kept on the
item's detail as schedule_id.
A payroll_accrual item, the days of a month no payroll run paid by its
end, is approved by accruing each account's share as the item shows it,
reversed on the next month's first day when the run paying those days
lands; it takes no account_id, amount, always or dimensions. The
accruals' ids are kept on the item's detail as schedule_ids.
A payroll_department item, a team the payroll provider names and the
books' department dimension lacks, is approved by adding it under
parent_id (else the department the item proposes); the next payroll
run files its people there. The new value's id is kept on the item's
detail as value_id. parent_id is taken by no other kind.
A payment_match item, a bank or card line that pays an open invoice or
bill, is approved by settling the line as the item's detail.parts
propose, as POST /transactions/{id}/settle would; it takes no
account_id, amount, always or dimensions.
Naturally idempotent: approving an item already approved under the same
account returns it unchanged. Refused with conflict for one closed some
other way, and unprocessable for one that asks for something else.
Parameters
| Name | Type | Description |
|---|---|---|
exception_idPath · Required | string | An id that starts with |
Request body
Response
200ExceptionOut
Errors
- 400
- The request was malformed or a parameter is invalid.
- 401
- No valid credential was sent.
- 403
- The credential or the member's role does not allow this.
- 404
- No such resource in this ledger.
- 409
- A conflicting request, e.g. one with the same Idempotency-Key still running.
- 422
- A well-formed request a business rule refused.
- 429
- Too many requests; retry after the Retry-After header.
- 500
- Something failed on our side; the request_id identifies it.
Example
curl -X POST "https://api.ledgerit.ai/v1/exceptions/{exception_id}/approve" \
-H "Authorization: Bearer $LEDGERIT_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Assign a close exception to a member
POST/v1/exceptions/{exception_id}/assign· Idempotent
client.exceptions.assign()
Give an item on the exception queue to a member to work, or hand it
back with null. Refused with unprocessable for someone who does not
open these books.
Parameters
| Name | Type | Description |
|---|---|---|
exception_idPath · Required | string | An id that starts with |
Request body
Response
200ExceptionOut
Errors
- 400
- The request was malformed or a parameter is invalid.
- 401
- No valid credential was sent.
- 403
- The credential or the member's role does not allow this.
- 404
- No such resource in this ledger.
- 409
- A conflicting request, e.g. one with the same Idempotency-Key still running.
- 422
- A well-formed request a business rule refused.
- 429
- Too many requests; retry after the Retry-After header.
- 500
- Something failed on our side; the request_id identifies it.
Example
curl -X POST "https://api.ledgerit.ai/v1/exceptions/{exception_id}/assign" \
-H "Authorization: Bearer $LEDGERIT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"assigned_to":"…"}'Hand an open item to the business owner
POST/v1/exceptions/{exception_id}/escalate
client.exceptions.escalate()
Hand an open item to the business owner, with a note: what only they can answer. It leaves the reviewer's queue for the owner's "Needs you".
Naturally idempotent: an item already waiting on the owner is returned as
it is. Refused with conflict for an item no longer open.
Parameters
| Name | Type | Description |
|---|---|---|
exception_idPath · Required | string | An id that starts with |
Request body
Response
200ExceptionOut
Errors
- 400
- The request was malformed or a parameter is invalid.
- 401
- No valid credential was sent.
- 403
- The credential or the member's role does not allow this.
- 404
- No such resource in this ledger.
- 409
- A conflicting request, e.g. one with the same Idempotency-Key still running.
- 422
- A well-formed request a business rule refused.
- 429
- Too many requests; retry after the Retry-After header.
- 500
- Something failed on our side; the request_id identifies it.
Example
curl -X POST "https://api.ledgerit.ai/v1/exceptions/{exception_id}/escalate" \
-H "Authorization: Bearer $LEDGERIT_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Resolve a close exception
POST/v1/exceptions/{exception_id}/resolve
client.exceptions.resolve()
Resolve (or dismiss) one item on a month's exception queue, with the reason on the record.
Parameters
| Name | Type | Description |
|---|---|---|
exception_idPath · Required | string | An id that starts with |
Request body
Response
200ExceptionOut
Errors
- 400
- The request was malformed or a parameter is invalid.
- 401
- No valid credential was sent.
- 403
- The credential or the member's role does not allow this.
- 404
- No such resource in this ledger.
- 409
- A conflicting request, e.g. one with the same Idempotency-Key still running.
- 422
- A well-formed request a business rule refused.
- 429
- Too many requests; retry after the Retry-After header.
- 500
- Something failed on our side; the request_id identifies it.
Example
curl -X POST "https://api.ledgerit.ai/v1/exceptions/{exception_id}/resolve" \
-H "Authorization: Bearer $LEDGERIT_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Hand an open item to the books' accountant or firm
POST/v1/exceptions/{exception_id}/send_to_reviewer
client.exceptions.sendToReviewer()
Hand an open item to the books' accountant or firm, with a note: the
owner's way of saying "you take this one". The inverse of escalating: it
leaves the owner's "Needs you" for the reviewer's queue, and the note is
kept on the item as its latest hand-over (escalation_note), for the
reviewer to read there.
Naturally idempotent: an item already waiting on the reviewer is returned
as it is. Refused with no_reviewer when nobody reviews these books, and
with conflict for an item no longer open.
Parameters
| Name | Type | Description |
|---|---|---|
exception_idPath · Required | string | An id that starts with |
Request body
Response
200ExceptionOut
Errors
- 400
- The request was malformed or a parameter is invalid.
- 401
- No valid credential was sent.
- 403
- The credential or the member's role does not allow this.
- 404
- No such resource in this ledger.
- 409
- A conflicting request, e.g. one with the same Idempotency-Key still running.
- 422
- A well-formed request a business rule refused.
- 429
- Too many requests; retry after the Retry-After header.
- 500
- Something failed on our side; the request_id identifies it.
Example
curl -X POST "https://api.ledgerit.ai/v1/exceptions/{exception_id}/send_to_reviewer" \
-H "Authorization: Bearer $LEDGERIT_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Objects
The objects these operations take and return.
ExceptionPage
| Name | Type | Description |
|---|---|---|
dataRequired | array of ExceptionItemOut | |
has_moreRequired | boolean | |
next_cursorRequired | string or null |
ExceptionCountsOut
The open queue in totals: one per whom it waits on. Items the agent is still working are in none of them.
| Name | Type | Description |
|---|---|---|
has_reviewerRequired | boolean | Whether someone other than the business reviews these books: an accountant member, or an accounting firm the organization let in. Only then can an item be sent to the reviewer. |
viewsRequired | array of ExceptionViewCountOut | One per whom open items wait on, always all three, in the order |
ApproveException
| Name | Type | Description |
|---|---|---|
account_id | string or null | An id that starts with |
always | boolean | Also file every later transaction with this counterparty here: writes a rule matching the counterparty's name exactly. |
amount | number | string or null | A missing accrual: the estimate to accrue, in the books' currency, instead of the vendor's usual month (the item's |
dimensions | array of LineDimensionIn or null | A missing accrual: the department, and the value of any other dimension, the accrual carries, at most one per dimension. Left out, the values the vendor's charges to the account agree on. |
note | string or null | Kept with the filing. |
parent_id | string or null | An id that starts with |
ExceptionOut
| Name | Type | Description |
|---|---|---|
amount | string or null | The money at stake: the amount of the transaction it is about. |
ask_reasonRequired | string | Why it needs a person: needs_category, needs_receipt, needs_match, needs_business_intent, needs_approval, data_problem |
assigned_at | string (date-time) or null | |
assigned_to | string or null | An id that starts with |
created_atRequired | string (date-time) | |
currency | string or null | That amount's currency. |
detailRequired | object or null | |
escalated_at | string (date-time) or null | When it was last handed between the owner and the reviewer, either way ( |
escalated_by | string or null | An id that starts with |
escalation_note | string or null | What they wrote with it, to the owner or to the reviewer. |
idRequired | string | An id that starts with |
kindRequired | string | |
recommendation | RecommendationOut or null | What the books would file it as. Null when they have no answer. |
researched_at | string (date-time) or null | When the books last researched it before asking; null until they have. |
severityRequired | string | |
statusRequired | string | |
subject_idRequired | string | An id. Which resource it names is given by the field beside it. |
subject_typeRequired | string | |
waiting_onRequired | string | Whose answer it waits for: agent, reviewer, owner, third_party |
AssignException
| Name | Type | Description |
|---|---|---|
assigned_toRequired | string or null | An id that starts with |
EscalateException
| Name | Type | Description |
|---|---|---|
note | string or null | What the owner should know: the question only they can answer. |
ResolveException
| Name | Type | Description |
|---|---|---|
dismiss | boolean | Default false |
note | string or null | What was done, or why nothing was. Required unless a dismissal gives a |
reason | string or null | Why an item the books' daily check raised is dismissed: vendor_varies, expected |
SendExceptionToReviewer
| Name | Type | Description |
|---|---|---|
note | string or null | What the reviewer should know: the answer, or what to look at. |
ExceptionItemOut
An exception as the queue lists it: with what it is about, by name.
| Name | Type | Description |
|---|---|---|
amount | string or null | The money at stake: the amount of the transaction it is about. |
ask_reasonRequired | string | Why it needs a person: needs_category, needs_receipt, needs_match, needs_business_intent, needs_approval, data_problem |
assigned_at | string (date-time) or null | |
assigned_to | string or null | An id that starts with |
counterparty_id | string or null | An id that starts with |
counterparty_logo_url | string or null | The logo of whoever it is about: the counterparty it names, the transaction's or the counterparty itself. Null for none, or initials. |
created_atRequired | string (date-time) | |
currency | string or null | That amount's currency. |
detailRequired | object or null | |
escalated_at | string (date-time) or null | When it was last handed between the owner and the reviewer, either way ( |
escalated_by | string or null | An id that starts with |
escalation_note | string or null | What they wrote with it, to the owner or to the reviewer. |
idRequired | string | An id that starts with |
kindRequired | string | |
occurred_on | string (date) or null | The day the transaction it is about happened. Null when it is not about a transaction. |
paid_with | string or null | The name of the bank account or card the transaction came from, as its provider names it. Null when it is not about a transaction, or nothing connected reported it. |
paid_with_account_id | string or null | An id that starts with |
paid_with_mask | string or null | The last digits of that account or card, when its provider gives them. |
recommendation | RecommendationOut or null | What the books would file it as. Null when they have no answer. |
researched_at | string (date-time) or null | When the books last researched it before asking; null until they have. |
resolution_note | string or null | What whoever resolved or dismissed it wrote. |
resolved_at | string (date-time) or null | |
resolved_by | string or null | An id that starts with |
severityRequired | string | |
statusRequired | string | |
subject_idRequired | string | An id. Which resource it names is given by the field beside it. |
subject_label | string or null | The record as a person names it: a transaction's description, an account's code and name. Null for the books as a whole, or a record that is gone. |
subject_typeRequired | string | |
waiting_onRequired | string | Whose answer it waits for: agent, reviewer, owner, third_party |
ExceptionViewCountOut
| Name | Type | Description |
|---|---|---|
amountsRequired | array of ExceptionAmountOut | The money at stake in them, summed per currency, in currency order. Items with no amount are counted but add nothing. |
countRequired | integer | How many open items wait on this. |
waiting_onRequired | string | Whom these items wait on: owner, reviewer, third_party |
LineDimensionIn
| Name | Type | Description |
|---|---|---|
dimension_idRequired | string | An id that starts with |
value_idRequired | string | A value of that dimension. |
RecommendationOut
What the books would file an item's transaction as.
| Name | Type | Description |
|---|---|---|
account_codeRequired | string | Its code, such as |
account_idRequired | string | The GL account recommended. |
account_nameRequired | string | Its name. |
confidence | string or null | 0 to 1: the model's confidence, or the share of the payee's earlier filings that went to this account. Null when nothing measures it. |
counterparty_id | string or null | An id that starts with |
counterparty_name | string or null | Their name. |
department_id | string or null | An id that starts with |
department_name | string or null | That department's name. |
evidence | array of EvidenceOut | What the books found when they researched the item: the payee's earlier filings, its default account, rules that nearly matched, the receipt, similar transactions. Empty until it is researched. |
proposal_id | string or null | An id that starts with |
reasoning | string or null | One line on why. |
sourceRequired | string | Where it came from: rule, model, history |
spread | SpreadOut or null | The prepaid spread proposed, when the payment buys more than a month. |
times_filed | integer | How many of the payee's earlier transactions were filed here. |
ExceptionAmountOut
| Name | Type | Description |
|---|---|---|
amountRequired | string | What the open items in this currency add up to. |
currencyRequired | string | The currency, as an ISO 4217 code. |
EvidenceOut
One thing the books knew about a transaction when it was researched.
| Name | Type | Description |
|---|---|---|
account_code | string or null | The account it points to: its code. |
account_name | string or null | That account's name. |
count | integer or null | For |
kindRequired | string | What it is: prior_filings, counterparty_default, rule_near_miss, document, source_record, similar_transaction |
noteRequired | string | The line the model was shown, in English. |
ref | string or null | The record it is about, by kind: a GL account, a rule, a document, a source record or a transaction. |
since | string or null | For |
text | string or null | The words quoted: what a receipt says, the card program's category, the rule's name or the other transaction's description. |
SpreadOut
A prepaid spread: the payment covers this many months from start.
| Name | Type | Description |
|---|---|---|
monthsRequired | integer | How many months the payment covers. |
startRequired | string (date) | The first month it covers (its first day). |