API reference
Rules
How transactions are filed: written rules first, then the model.
- GET
/v1/rulesList the categorization rules - POST
/v1/rulesWrite a categorization rule - GET
/v1/rules/model_qualityGet how often people agreed with the model - GET
/v1/rules/previewSee what a rule would match before saving it - POST
/v1/rules/runFile undecided transactions by rule, then by model - GET
/v1/rules/{rule_id}Get a rule - PATCH
/v1/rules/{rule_id}Change or pause a rule - DELETE
/v1/rules/{rule_id}Delete a rule - GET
/v1/rules/{rule_id}/unnamedCount what a rule filed that names no department yet - POST
/v1/rules/{rule_id}/unnamed/nameGive what a rule already filed its department
Guides: Automate filing with rules
List the categorization rules
GET/v1/rules
client.rules.list()
Every rule these books file by, newest first.
Parameters
| Name | Type | Description |
|---|---|---|
limitQuery | integer | Page size, 1–200. |
cursorQuery | string or null | The |
originQuery | string or null | Only rules a person wrote, only learned ones, or only those written from an answer. manual, learned, answer |
source_question_idQuery | string or null | An id that starts with |
is_activeQuery | boolean or null | Only rules that are on, or only paused ones. |
counterparty_idQuery | string or null | An id that starts with |
category_account_idQuery | string or null | An id that starts with |
Response
200RulePage
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/rules" \
-H "Authorization: Bearer $LEDGERIT_TOKEN"Write a categorization rule
POST/v1/rules· Idempotent
client.rules.create()
Write a rule. The category is validated now, not when it first fires.
A rule matching exactly what another already matches is refused with
rule_conflict; edit that one instead.
Request body
Response
201RuleOut
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/rules" \
-H "Authorization: Bearer $LEDGERIT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"category_account_id":"…","name":"…","pattern":"…"}'Get how often people agreed with the model
GET/v1/rules/model_quality
client.rules.modelQuality()
Of the model's proposals a person has since filed themselves, how many they filed where the model said. Null until one has been judged.
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/rules/model_quality" \
-H "Authorization: Bearer $LEDGERIT_TOKEN"See what a rule would match before saving it
GET/v1/rules/preview
client.rules.preview()
What a rule with these terms would match, before it is saved.
Looks through the newest transactions with the same matching the feed
uses and answers with how many match and the newest of them. Nothing is
written and nothing is filed: a saved rule files what arrives after it,
and what is already filed stays where it is. Terms that could never match
are refused as saving them would be (rule_invalid).
Parameters
| Name | Type | Description |
|---|---|---|
patternQuery · Required | string | What the rule would look for. |
match_onQuery | string | Which text it is compared to. description, source_description, counterpartyDefault description |
match_typeQuery | string | How it is compared. contains, equals, starts_withDefault contains |
account_idQuery | string or null | An id that starts with |
event_typeQuery | string or null | Only transactions of this event type. expense, income, transfer, fee, interest, refund, sales_refund |
amount_minQuery | number | string or null | Only transactions at least this size. |
amount_maxQuery | number | string or null | Only transactions at most this size. |
memo_patternQuery | string or null | Only transactions whose memo — the description the ledger shows, or the line the bank printed — holds these words. Compared as |
document_kindQuery | string or null | Only transactions with this paper behind them: an invoice, receipt, none |
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/rules/preview" \
-H "Authorization: Bearer $LEDGERIT_TOKEN"File undecided transactions by rule, then by model
POST/v1/rules/run
client.rules.run()
Decide what every undecided transaction is for: rules, then a model.
Categorizes; does not post. Posting stays a separate decision, so a run that produces something surprising can be looked at first.
A run that may call the model counts against the entity's model budget
(MODEL_RUNS); a rules-only run spends nothing and is not counted.
Request body
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 -X POST "https://api.ledgerit.ai/v1/rules/run" \
-H "Authorization: Bearer $LEDGERIT_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Get a rule
GET/v1/rules/{rule_id}
client.rules.get()
One rule, with how often it has fired.
Parameters
| Name | Type | Description |
|---|---|---|
rule_idPath · Required | string | An id that starts with |
Response
200RuleOut
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/rules/{rule_id}" \
-H "Authorization: Bearer $LEDGERIT_TOKEN"Change or pause a rule
PATCH/v1/rules/{rule_id}· Idempotent
client.rules.update()
Change a rule, or pause it with is_active: false.
Held to the same checks as writing one. Transactions it already filed stay as they are: they are in the books, and changing a rule is not a reason to restate them.
Parameters
| Name | Type | Description |
|---|---|---|
rule_idPath · Required | string | An id that starts with |
Request body
Response
200RuleOut
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 PATCH "https://api.ledgerit.ai/v1/rules/{rule_id}" \
-H "Authorization: Bearer $LEDGERIT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{}'Delete a rule
DELETE/v1/rules/{rule_id}
client.rules.delete()
Remove a rule. Transactions it already filed are untouched — they are in
the books, and changing a rule is not a reason to restate them. Pausing it
(is_active: false) keeps it on the record instead.
Parameters
| Name | Type | Description |
|---|---|---|
rule_idPath · Required | string | An id that starts with |
Response
204No content
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 DELETE "https://api.ledgerit.ai/v1/rules/{rule_id}" \
-H "Authorization: Bearer $LEDGERIT_TOKEN"Count what a rule filed that names no department yet
GET/v1/rules/{rule_id}/unnamed
client.rules.unnamed()
How many transactions a rule already filed do not name its department, or any other dimension value it names.
A rule that names a department, or learns one, gives it to what it files from then on; what it filed before stays unnamed until it is given the values. A transaction naming another value of the dimension is not counted: a person chose it.
Parameters
| Name | Type | Description |
|---|---|---|
rule_idPath · Required | string | An id that starts with |
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/rules/{rule_id}/unnamed" \
-H "Authorization: Bearer $LEDGERIT_TOKEN"Give what a rule already filed its department
POST/v1/rules/{rule_id}/unnamed/name· Idempotent
client.rules.nameUnnamed()
Give the transactions a rule already filed the department, and any other dimension value, it names.
Each takes the rule's value for every dimension it does not name yet, as
filing it today would; a value a person chose stands. One already in the
books is reversed and posted again with them, so the change is on the
record and spend by department counts it. Ones in a locked month, and
ones spread over months, are left as they are. A batch a request,
oldest first; unnamed.to_name says how many are still to name.
Parameters
| Name | Type | Description |
|---|---|---|
rule_idPath · Required | string | An id that starts with |
Response
200RuleNamedOut
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/rules/{rule_id}/unnamed/name" \
-H "Authorization: Bearer $LEDGERIT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"Objects
The objects these operations take and return.
RulePage
| Name | Type | Description |
|---|---|---|
dataRequired | array of RuleOut | |
has_moreRequired | boolean | |
next_cursorRequired | string or null |
NewRule
| Name | Type | Description |
|---|---|---|
account_id | string or null | An id that starts with |
amount_max | number | string or null | |
amount_min | number | string or null | |
category_account_idRequired | string | An id that starts with |
dimensions | array of LineDimensionIn | The department, and the value of any other dimension, a matching transaction is to name, at most one per dimension. Refused with |
document_kind | string or null | Only transactions with this paper behind them: an invoice, receipt, none |
event_type | string or null | One of expense, income, transfer, fee, interest, refund, sales_refund |
match_on | string | One of description, source_description, counterpartyDefault description |
match_type | string | One of contains, equals, starts_withDefault contains |
memo_pattern | string or null | Only transactions whose memo — the description the ledger shows, or the line the bank printed — holds these words. Compared as |
nameRequired | string | |
patternRequired | string | |
priority | integer | Default 0 |
RuleOut
| Name | Type | Description |
|---|---|---|
account_idRequired | string or null | An id that starts with |
amount_maxRequired | string or null | |
amount_minRequired | string or null | |
category_account_idRequired | string | An id that starts with |
category_codeRequired | string | |
category_nameRequired | string | |
counterparty_id | string or null | An id that starts with |
created_atRequired | string (date-time) | |
dimensions | array of LineDimensionOut | The department, and the value of any other dimension, a matching transaction names: each one it does not already name, so its lines to |
document_kind | string or null | Only transactions with this paper behind them: an invoice, receipt, none |
event_typeRequired | string or null | One of expense, income, transfer, fee, interest, refund, sales_refund |
idRequired | string | An id that starts with |
is_activeRequired | boolean | |
last_applied_atRequired | string (date-time) or null | |
match_onRequired | string | One of description, source_description, counterparty |
match_typeRequired | string | One of contains, equals, starts_with |
memo_pattern | string or null | Only transactions whose memo — the description the ledger shows, or the line the bank printed — holds these words. Compared as |
nameRequired | string | |
originRequired | string |
manual, learned, answer |
patternRequired | string | |
priorityRequired | integer | |
source_question_id | string or null | An id that starts with |
source_transaction_id | string or null | An id that starts with |
times_appliedRequired | integer |
ModelQualityOut
How often a person agreed with the model, out of how many they judged.
Reported rather than assumed. A product that files transactions with a model and cannot say how often it is right is asking to be trusted rather than earning it.
| Name | Type | Description |
|---|---|---|
agreedRequired | integer | |
agreement_rateRequired | number or null | |
judgedRequired | integer |
RulePreviewOut
| Name | Type | Description |
|---|---|---|
matchedRequired | integer | How many of the transactions looked at the terms match. |
sampleRequired | array of RulePreviewMatch | The newest matches. |
scannedRequired | integer | How many transactions were looked at, newest first. |
truncatedRequired | boolean | True when the books hold more transactions than were looked at. |
CategorizeRequest
| Name | Type | Description |
|---|---|---|
event_ids | array of string or null | |
use_model | boolean | Default true |
CategorizeResponse
| Name | Type | Description |
|---|---|---|
by_modelRequired | integer | |
by_ruleRequired | integer | |
consideredRequired | integer | |
errorsRequired | array of string | |
model_needs_reviewRequired | integer | |
model_unavailableRequired | boolean | |
to_suspenseRequired | integer |
RuleChanges
Only the fields sent change. The narrowing fields (account_id,
event_type, amount_min, amount_max) are cleared by sending null;
the rest cannot be: they are typed without null, and default to None only
so that leaving one out means "unchanged" (hence the ignores).
| Name | Type | Description |
|---|---|---|
account_id | string or null | An id that starts with |
amount_max | number | string or null | |
amount_min | number | string or null | |
category_account_id | string | An id that starts with |
dimensions | array of LineDimensionIn | Every value a matching transaction is to name; the ones left out are taken off, and an empty list clears them. Transactions it already filed keep theirs; |
document_kind | string or null | Only transactions with this paper behind them: an invoice, receipt, none |
event_type | string or null | One of expense, income, transfer, fee, interest, refund, sales_refund |
is_active | boolean | |
match_on | string | One of description, source_description, counterparty |
match_type | string | One of contains, equals, starts_with |
memo_pattern | string or null | Only transactions whose memo — the description the ledger shows, or the line the bank printed — holds these words. Compared as |
name | string | |
pattern | string | |
priority | integer |
RuleUnnamedOut
| Name | Type | Description |
|---|---|---|
lockedRequired | integer | Ones in the books in a locked month: left as they are, since naming them would change a closed month. Reopen the month to include them. |
locked_monthsRequired | array of string (date) | The first day of each month those are in, oldest first. |
spreadRequired | integer | Ones spread over months by a schedule, which takes each month's share out with the values the transaction names: left as they are. |
to_nameRequired | integer | Transactions the rule filed, whose filing still stands, that do not name a dimension the rule names and can be given its values now ( |
RuleNamedOut
| Name | Type | Description |
|---|---|---|
namedRequired | integer | Transactions given the rule's values by this request. |
refusedRequired | integer | Transactions left as they were because posting them again was refused: an account each is filed to now requires a value neither it nor the rule names. |
unnamedRequired | RuleUnnamedOut | What is still unnamed afterwards. |
LineDimensionIn
| Name | Type | Description |
|---|---|---|
dimension_idRequired | string | An id that starts with |
value_idRequired | string | A value of that dimension. |
LineDimensionOut
| Name | Type | Description |
|---|---|---|
dimension_idRequired | string | An id that starts with |
dimension_keyRequired | string | The dimension's key, e.g. |
dimension_nameRequired | string | |
value_codeRequired | string | |
value_idRequired | string | An id that starts with |
value_nameRequired | string |
RulePreviewMatch
| Name | Type | Description |
|---|---|---|
amountRequired | string | |
category_account_idRequired | string or null | An id that starts with |
category_name | string or null | |
currencyRequired | string | |
descriptionRequired | string | |
event_dateRequired | string (date) | |
event_typeRequired | string | |
idRequired | string | An id that starts with |
statusRequired | string |