jaz-clio 5.59.1 → 5.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,13 +3,13 @@
3
3
  <p align="center">
4
4
  <a href="https://www.npmjs.com/package/jaz-clio"><img src="https://img.shields.io/npm/v/jaz-clio?style=for-the-badge&logo=npm" alt="npm"></a>
5
5
  <a href="https://www.npmjs.com/package/jaz-clio"><img src="https://img.shields.io/npm/dm/jaz-clio?style=for-the-badge&label=downloads" alt="npm downloads"></a>
6
- <img src="https://img.shields.io/badge/tools-369-blue?style=for-the-badge" alt="369 tools">
6
+ <img src="https://img.shields.io/badge/tools-371-blue?style=for-the-badge" alt="371 tools">
7
7
  <a href="https://github.com/teamtinvio/jaz-ai/blob/main/LICENSE"><img src="https://img.shields.io/github/license/teamtinvio/jaz-ai?style=for-the-badge&color=green" alt="License"></a>
8
8
  </p>
9
9
 
10
10
  <p align="center"><b>Jaz accounting on the command line, and inside any AI agent.</b></p>
11
11
 
12
- 369 tools · 72 command groups · 7 skills · 13 calculators · 12 close playbooks · 159 field-tested API rules.
12
+ 371 tools · 73 command groups · 7 skills · 13 calculators · 12 close playbooks · 159 field-tested API rules.
13
13
 
14
14
  ```bash
15
15
  npm install -g jaz-clio
@@ -48,9 +48,10 @@ clio calc lease --payment 5000 --term 36 --rate 5 # IFRS 16, offline, insta
48
48
  clio jobs month-end --period 2026-03 # step-by-step close playbook
49
49
  clio magic create --file receipt.pdf # AI extracts, drafts the transaction
50
50
  clio invoices search --query 'status:unpaid AND $500+' # structured per-entity search
51
+ clio ledger-find-fix preview --level TRANSACTIONS --input recode.json # find & fix (recode) across record types
51
52
  ```
52
53
 
53
- 72 command groups, 16 report types, 13 calculators, 12 job playbooks. Every command takes `--json`. Run `clio --help` for the full list.
54
+ 73 command groups, 16 report types, 13 calculators, 12 job playbooks. Every command takes `--json`. Run `clio --help` for the full list.
54
55
 
55
56
  ### Foreign currency
56
57
 
@@ -77,7 +78,7 @@ that ends up in a journal.
77
78
 
78
79
  ## MCP server
79
80
 
80
- 369 tools for any AI agent that speaks MCP. Runs locally: no cloud, no ports.
81
+ 371 tools for any AI agent that speaks MCP. Runs locally: no cloud, no ports.
81
82
 
82
83
  > **No install at all?** Claude.ai, ChatGPT, Cowork, and Microsoft Copilot Studio can use Jaz through the hosted connector. Add `https://mcp.jaz.ai/mcp` as a custom connector and sign in with OAuth, no key. The local setup below is for terminal use, scripting, and editors that run MCP servers as local processes.
83
84
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-api
3
- version: 5.59.1
3
+ version: 5.60.0
4
4
  description: >-
5
5
  Use this skill whenever you call, debug, or review code that touches the Jaz
6
6
  REST API. Covers field names, response shapes, 159 production gotchas, error
@@ -31,7 +31,7 @@ The rest of this skill — field names, gotchas, error catalog, dependency order
31
31
 
32
32
  **Core fundamentals (read first, every integration):** Identifiers & Dates 1–3; Names & Fields 9–13; Transaction Creation 14–16; Chart of Accounts 17–22; Payments / Cross-Currency 4–8; Journals & Cash 23–26; Credit Notes & Refunds 27–28; Reports 36–37; Tax Profile Scoping 100; Transaction References 104; Draft Finalization Pipeline 81–88; Jaz Magic / PDF-JPG 57–63; Currency Rates 39, 49, 105; Withholding Tax 45, 98.
33
33
 
34
- **Integration depth (API clients, pipelines, batch jobs, MCP/CLI):** Bulk Upsert (Items/Contacts/Rates); Background Jobs (filter `resourceId` not `jobId`); Export Records; Pagination (38); Search & Filter (50–56); Response Shape Gotchas (66–73); Cash Entry Response Shape (74–77); Entity Resolution (78–80); Bank Rules (89–90c); Fixed Assets (91–92c); Subscriptions & Scheduled (93–94); niche endpoints (95–102); Journals balance (103); Quick Fix (107, 111); TTB (108); Dynamic Strings (109–110); Sub-Resource Shapes (112); Nano-Classifier (113); Scheduler Asymmetry (114); Payment Record CRUD (115–117); Bulk Upserts transactions (118–122); Reconciliation write-side (123–127); Drafts lifecycle (128–135); Orders — Sale Quotes / Sale Orders / Purchase Requests / Purchase Orders (`references/orders.md`); Claims — records / lifecycle / bulk + conversion + payouts + Employees + Claim Settings (`references/claims.md`).
34
+ **Integration depth (API clients, pipelines, batch jobs, MCP/CLI):** Bulk Upsert (Items/Contacts/Rates); Background Jobs (filter `resourceId` not `jobId`); Export Records; Pagination (38); Search & Filter (50–56); Response Shape Gotchas (66–73); Cash Entry Response Shape (74–77); Entity Resolution (78–80); Bank Rules (89–90d); Fixed Assets (91–92c); Subscriptions & Scheduled (93–94); niche endpoints (95–102); Journals balance (103); Quick Fix (107, 111); TTB (108); Dynamic Strings (109–110); Sub-Resource Shapes (112); Nano-Classifier (113); Scheduler Asymmetry (114); Payment Record CRUD (115–117); Bulk Upserts transactions (118–122); Reconciliation write-side (123–127); Drafts lifecycle (128–135); Orders — Sale Quotes / Sale Orders / Purchase Requests / Purchase Orders (`references/orders.md`); Claims — records / lifecycle / bulk + conversion + payouts + Employees + Claim Settings (`references/claims.md`).
35
35
 
36
36
  ## When to Use This Skill
37
37
 
@@ -359,6 +359,7 @@ Bills, invoices, and credit notes share identical mandatory field specs. Adding
359
359
 
360
360
  ### Quick Fix (Bulk Update)
361
361
  107. **20 Quick Fix endpoints for bulk-updating transactions and line items** — `POST /api/v1/quick-fix/{entity}` with `{ resourceIds: [...], attributes: {...} }`. Only included fields are changed — omitted fields are left unchanged. Response: `{ updated: string[], failed: [{ resourceId, error, errorCode }] }`. **HTTP status codes**: 200 = complete success (`failed` always empty). **207 Multi-Status** = partial or total failure with per-item detail (same response shape as 200 — check `failed` array). 422 = total failure with no per-item breakdown (rare). On 207, retry only `failed` resourceIds. Entities: **ARAP**: invoices, bills, customer-credit-notes, supplier-credit-notes. **Accounting**: journals, cash-entries. **Schedulers**: sale-schedules, purchase-schedules, subscription-schedules, journal-schedules. **Line-item request patterns**: ARAP + accounting use `{ lineItemResourceIds, attributes }`. Schedulers (sale/purchase/subscription) use Pattern C: `{ schedulerUpdates: [{ schedulerResourceId, lineItemUpdates: [{ arrayIndex, ...attrs }] }] }`. **Journal-schedules use Pattern D**: `lineItemResourceId` (UUID) instead of `arrayIndex`. **Field gotchas**: cash entries use `currencySetting` (singular: `{ rateFunctionalToSource, exchangeToken }`), NOT `currencySettings`. Journal schedules have `startDate` in addition to `endDate`/`interval`. Tags: string array, max 50 items, max 50 chars each.
362
+ 107a. **Ledger Find & Fix: find and fix (recode) records across types with one filter, preview one change, apply it once.** Use it when a user asks to find & fix, recode, reclassify, retag, re-date or move records to another account across many records or several types. `POST /api/v1/ledger/find-fix/transactions/preview` (sets contact, date, capsule, tags) or `POST /api/v1/ledger/find-fix/line-items/preview` (sets account, classifiers), each with `{ filter, change }`, then `POST /api/v1/ledger/find-fix/apply` with `{ previewId }`; conditions, bodies and every code are in endpoints.md section 17a. `JOURNAL` covers manual and cashflow journals only: transfer and trial-balance journals and cash transfers never match, so their ids come back `NOT_FOUND`. **A filter with no condition besides `types` is a 422, and a condition with no operator is ignored.** **The API refuses a key it does not take, at any level, with 400 `invalid_filter` naming the key**; the tools and the CLI refuse a field of the other level before the request, naming the level that takes it. `tags` `{ add, remove }` keeps the record's other tags, so setting tags to X means removing the current ones and adding X. A classifier removal needs only `{ resourceId, deleted: true }`, even for a classifier the organization no longer has. **Preview** writes nothing, matches at most 500 records, and returns `previewId` (valid 30 minutes; absent when nothing is eligible). **A blocked field is left as it is while the record's other fields still change.** **Apply** is single use and saves the preview-time values, so a field edited between preview and apply, tags included, is overwritten. Once it has taken the preview it runs to the end even if the caller leaves, and starts no new call 3 minutes after the request arrived. 207 lists the `failed` records with an `errorCode`; `OUTCOME_UNKNOWN` means that record may have changed. 404 `PREVIEW_NOT_FOUND` (expired, used, being applied, or another caller's): preview again, never resend. **Any other 5xx, or a timeout, on apply means the outcome is unknown: if the connection drops, the apply keeps running for up to 4 minutes. Wait that long before previewing or applying again on the same records, then preview again or re-read them. Never apply this previewId again.** Several applies can run at the same time. When two applies change records on one document at once, the one saved last can undo the other's changes, including fields and line items it did not set. Preview again to check the result. Lock dates, filed tax periods and claims-backed documents fail per record, and e-invoice filings may be re-submitted. Rule 107's per-type routes stay for one document, for fields this does not change (due date, tax profile, notes, amounts, custom fields) and for scheduled transactions.
362
363
 
363
364
  ### Transfer Trial Balance
364
365
  108. **Transfer Trial Balance** (`POST /api/v1/transfer-trial-balance`) creates opening balance entries. Uses `journalEntries` (NOT `lines` — this is a journal type). Always ACTIVE (no draft mode), reference auto-generated as "Transfer Trial Balance", minimum 1 entry, entries cannot have 0 amounts, skips lock date validation. **`valueDate` must be today or in the past** — future dates are rejected with "Opening data cannot be future date". Each entry: `{ accountResourceId, type: "DEBIT"|"CREDIT", amount }`.
@@ -2039,6 +2039,131 @@ Note: journal-schedules use `lineItemResourceId` (UUID), NOT `arrayIndex`.
2039
2039
 
2040
2040
  ---
2041
2041
 
2042
+ ## 17a. Ledger Find & Fix
2043
+
2044
+ Find and fix (recode) records across invoices, bills, both credit notes, journals and cash entries with one filter: preview one change, then apply the stored preview once. SKILL.md rule 107a carries the rules an agent must follow; the conditions, shapes and codes are here.
2045
+
2046
+ | Filter condition | Operators |
2047
+ |------------------|-----------|
2048
+ | `types` (required) | `INVOICE`, `BILL`, `CUSTOMER_CREDIT_NOTE`, `SUPPLIER_CREDIT_NOTE`, `JOURNAL` (manual and cashflow journals only), `CASH_ENTRY` |
2049
+ | `resourceIds` | Up to 500; line item ids at line level |
2050
+ | `reference` | `eq`, `in`, `contains`, `startWith` |
2051
+ | `valueDate` | `eq`, `gte`, `lte`, `between: [from, to]` |
2052
+ | `contactResourceId` | `eq`, `in` |
2053
+ | `organizationAccountResourceId` | `eq`, `in`; line level only |
2054
+
2055
+ A filter needs a condition besides `types`, or the preview answers 422. A condition with no operator is ignored. A key or operator the API does not take, at any level of the request, is a 400 `invalid_filter` whose message names it. At line level, `resourceIds` are line item ids, and reference, date and contact conditions match the line's document.
2056
+
2057
+ ### POST /api/v1/ledger/find-fix/transactions/preview
2058
+
2059
+ Finds records and plans one change: `contactResourceId`, `valueDate` (at most a year ahead), `capsuleResourceId` or `tags` (`{ add, remove }`; the record's other tags stay). A cash entry that is not void is always listed as changing its capsule, since its current capsule is not shown.
2060
+
2061
+ ```json
2062
+ {
2063
+ "filter": { "types": ["INVOICE", "BILL"], "valueDate": { "between": ["2026-04-01", "2026-06-30"] } },
2064
+ "change": { "contactResourceId": "new-contact-uuid", "tags": { "add": ["Q2"] } }
2065
+ }
2066
+ ```
2067
+
2068
+ ### POST /api/v1/ledger/find-fix/line-items/preview
2069
+
2070
+ Finds and recodes line items: `organizationAccountResourceId` (not a bank, cash or control account) or `classifierConfig` (max 50 entries, unique by resourceId, at most 100 classes each; unlisted classifiers stay, and `{ "resourceId": "classifier-uuid", "deleted": true }` removes one, with type and printable filled in by the API; a set needs type, printable and at least one class). On a set entry, a classifier the organization lacks, or a class it lacks or has deleted, is 422 `CLASSIFIER_NOT_FOUND` / `CLASS_NOT_FOUND`. A removal is not checked: removing a classifier the organization lacks is `NO_CHANGE`, so stored bad IDs can be cleaned up. A selection drawn from a record list (`entityResourceId`) is not checked either.
2071
+
2072
+ ```json
2073
+ {
2074
+ "filter": { "types": ["JOURNAL", "CASH_ENTRY"], "organizationAccountResourceId": { "eq": "old-account-uuid" } },
2075
+ "change": { "organizationAccountResourceId": "new-account-uuid" }
2076
+ }
2077
+ ```
2078
+
2079
+ Preview response (both levels). The contact change below reaches the invoice; on the bill the contact is blocked, so only its tags change. `after` holds only the fields that will change:
2080
+
2081
+ ```json
2082
+ {
2083
+ "previewId": "Q2rX8vK1mZ4p",
2084
+ "expiresAt": "2026-09-15T10:30:00Z",
2085
+ "level": "TRANSACTIONS",
2086
+ "counts": {
2087
+ "matched": 3, "eligible": 2, "excluded": 1,
2088
+ "byType": { "INVOICE": 2, "BILL": 1 },
2089
+ "excludedByCode": { "VOID": 1 },
2090
+ "blockedByCode": { "CONTACT_NOT_SUPPLIER": 1 }
2091
+ },
2092
+ "data": [
2093
+ {
2094
+ "type": "INVOICE", "resourceId": "invoice-uuid", "reference": "INV-12", "valueDate": "2026-04-01", "status": "ELIGIBLE",
2095
+ "before": { "contactResourceId": "old-contact-uuid", "tags": [] },
2096
+ "after": { "contactResourceId": "new-contact-uuid", "tags": ["Q2"] }
2097
+ },
2098
+ {
2099
+ "type": "BILL", "resourceId": "bill-uuid", "reference": "BILL-7", "valueDate": "2026-04-02", "status": "ELIGIBLE",
2100
+ "blocked": [{ "field": "contactResourceId", "code": "CONTACT_NOT_SUPPLIER" }],
2101
+ "before": { "contactResourceId": "old-contact-uuid", "tags": [] },
2102
+ "after": { "tags": ["Q2"] }
2103
+ }
2104
+ ]
2105
+ }
2106
+ ```
2107
+
2108
+ No `previewId` means nothing is eligible and nothing was stored. A row is `EXCLUDED` only for these codes:
2109
+
2110
+ | Row `code` | Meaning |
2111
+ |------------|---------|
2112
+ | `NOT_FOUND` | A listed id matched no record of the listed types; transfer and trial-balance journals and cash transfers never match |
2113
+ | `VOID` | The record, or the line's document, is void |
2114
+ | `NO_CHANGE` | Every field the change sets already has that value |
2115
+ | `BLOCKED` | Every field the change sets is blocked on this record |
2116
+
2117
+ A blocked field is left as it is while the record's other fields still change, and the row stays `ELIGIBLE`:
2118
+
2119
+ | `blocked[].code` | Field | Why |
2120
+ |------------------|-------|-----|
2121
+ | `CONTACT_NOT_CUSTOMER`, `CONTACT_NOT_SUPPLIER` | contact | The new contact is not the customer or supplier the document needs |
2122
+ | `HAS_CREDIT_OFFSETS` | contact | Credits applied to the document would stay with the old contact |
2123
+ | `FOREIGN_CURRENCY_VALUE_DATE` | date | A new date on a foreign currency record would take a new exchange rate |
2124
+ | `VALUE_DATE_AFTER_DUE_DATE` | date | The new date is after the document's due date |
2125
+ | `TOO_MANY_TAGS` | tags | The record would end with more than 50 tags |
2126
+ | `CONTROL_LINE` | account | A journal line on a bank, cash or control account |
2127
+
2128
+ ### POST /api/v1/ledger/find-fix/apply
2129
+
2130
+ ```json
2131
+ { "previewId": "Q2rX8vK1mZ4p" }
2132
+ ```
2133
+
2134
+ Single use. Saves the preview-time values, so a field edited between preview and apply, tags included, is overwritten. Once it has taken the preview, the apply runs to the end even if the caller leaves, sends calls of about 100 records (a document's lines stay together, so one call can carry more), and starts no new call 3 minutes after the request arrived. Lock dates are checked when a change is saved, so a record in a locked period comes back in `failed`. 200 when every record changed, 207 otherwise:
2135
+
2136
+ ```json
2137
+ {
2138
+ "failed": [{ "type": "INVOICE", "resourceId": "invoice-uuid", "error": "…", "errorCode": "OUTCOME_UNKNOWN" }],
2139
+ "updated": [{ "type": "BILL", "resourceId": "bill-uuid" }]
2140
+ }
2141
+ ```
2142
+
2143
+ | `failed[].errorCode` | Meaning |
2144
+ |----------------------|---------|
2145
+ | `OUTCOME_UNKNOWN` | The answer for this record was lost, so it may or may not have changed |
2146
+ | `NOT_ATTEMPTED` | The apply reached its 3-minute limit before sending this record, so it did not change |
2147
+ | `UPSTREAM_REJECTED` | The platform refused the update before this record changed |
2148
+ | `UNSUPPORTED_RECORD_TYPE` | The stored preview names a record type this version cannot change |
2149
+
2150
+ Several applies can run at the same time. When two applies change records on one document at once, the one saved last can undo the other's changes, including fields and line items it did not set. Preview again to check the result.
2151
+
2152
+ | Status | `error_details.code` | Meaning |
2153
+ |--------|----------------------|---------|
2154
+ | 404 | `PREVIEW_NOT_FOUND` | Expired, already applied or being applied, or another caller's preview. Preview again, never resend. |
2155
+ | 400 | none; `error_type` is `invalid_filter` | A key or operator the request may not carry; the message names it |
2156
+ | 422 | `CONTACT_NOT_FOUND`, `CAPSULE_NOT_FOUND` | Transactions preview: the contact or capsule the change sets does not exist; `resourceId` names it |
2157
+ | 422 | `ACCOUNT_NOT_FOUND`, `ACCOUNT_NOT_ALLOWED` | Line items preview: the account the change sets does not exist, is inactive, or is a bank, cash or control account; `resourceId` names it |
2158
+ | 422 | `CLASSIFIER_NOT_FOUND`, `CLASS_NOT_FOUND` | Line items preview, set entries only: a classifier the change sets does not exist, or a class it selects is not a current class of that classifier; `resourceId` names the classifier or class. A removal and a record-list selection (`entityResourceId`) are not checked |
2159
+ | 422 | `TOO_MANY_RECORDS` | Either preview: at least `count` records or line items match, more than `limit` |
2160
+ | 422 | `TOO_MANY_CALLS` | Transactions preview: the change needs `count` separate updates, more than `limit`, because records whose resulting values differ need separate updates. A line items preview never answers it |
2161
+ | 503 | `PREVIEW_STORE_UNAVAILABLE` | Nothing applied |
2162
+
2163
+ Any other 5xx, or a timeout, on apply: the outcome is unknown. If the connection drops, apply keeps running for up to 4 minutes. Wait that long before previewing or applying again on the same records, then preview again or re-read them. Never apply this previewId again. A service restart can stop an apply; preview again to check.
2164
+
2165
+ ---
2166
+
2042
2167
  ## 18b. Transfer Trial Balance
2043
2168
 
2044
2169
  ### POST /api/v1/transfer-trial-balance
@@ -2535,4 +2660,82 @@ Append one review verb to a jot (append-only: annotates, never mutates).
2535
2660
 
2536
2661
  ---
2537
2662
 
2538
- *Last updated: 2026-07-11 (added Jots judgment journal, section 25). Previous: 2026-04-09 — Added: Contacts bulk-upsert (22), Background Jobs search (23), Export Records (24). 2026-03-13 — Payment record CRUD, nano-classifier, scheduler GET/PUT/DELETE.*
2663
+ ## 26. Bank Rules CRUD
2664
+
2665
+ A bank rule has two halves: the **WHEN** (`searchFilter`, the condition deciding which statement lines it applies to) and the **THEN** (`configuration.reconcileWithDirectCashEntry`, the allocation). **A rule with no `searchFilter` is never suggested** — auto-reconciliation only considers rules whose stored condition is non-null, so it exists, lists, and can be applied by hand, but is never offered. See jaz-api rules 90a-90d for the full payload.
2666
+
2667
+ ### GET /api/v1/bank-rules
2668
+
2669
+ Lists bank rules. Standard pagination (`limit`, `offset`).
2670
+
2671
+ ### GET /api/v1/bank-rules/:resourceId
2672
+
2673
+ Returns one rule, including its `searchFilter`.
2674
+
2675
+ ```json
2676
+ // Response (data):
2677
+ {
2678
+ "resourceId": "uuid",
2679
+ "name": "Grab rides",
2680
+ "actionType": "RECONCILE_WITH_DIRECT_CASH_ENTRY",
2681
+ "appliesToReconciliationAccount": { "code": "1001", "currencyCode": "SGD", "name": "Business Bank Account" },
2682
+ "searchFilter": {
2683
+ "version": 1,
2684
+ "raw": "description:grab",
2685
+ "parsed": { "description": { "contains": "grab" } }
2686
+ },
2687
+ "configuration": { "reconcileWithDirectCashEntry": { "...": "..." } }
2688
+ }
2689
+ ```
2690
+
2691
+ `appliesToReconciliationAccount` comes back as an OBJECT on read but is sent as a bare UUID on write, so a rule cannot be round-tripped without substituting it.
2692
+
2693
+ ### POST /api/v1/bank-rules
2694
+
2695
+ Creates a rule. `searchFilter` is optional on the wire and effectively required in practice.
2696
+
2697
+ ```json
2698
+ // Request:
2699
+ {
2700
+ "name": "Grab rides",
2701
+ "appliesToReconciliationAccount": "<bank-account-uuid>",
2702
+ "searchFilter": {
2703
+ "version": 1,
2704
+ "raw": "description:grab",
2705
+ "parsed": { "description": { "contains": "grab" } }
2706
+ },
2707
+ "configuration": {
2708
+ "reconcileWithDirectCashEntry": {
2709
+ "amountAllocationType": "PERCENTAGE",
2710
+ "reference": "AUTO-{{bankReference}}",
2711
+ "percentageAllocation": [{ "organizationAccountResourceId": "<acct-uuid>", "amount": 100 }]
2712
+ }
2713
+ }
2714
+ }
2715
+ ```
2716
+
2717
+ `searchFilter` rules: `version` must be `1`; `raw` must be PRESENT but **may be the empty string** (the app itself saves conditions that way); `parsed` must be a non-empty object. Condition fields are `description`, `extReference`, `extContactName`, `netAmount`, `valueDate`, plus the account's active custom Bank Fields. An unsupported field path does NOT error — the rule saves and then never fires.
2718
+
2719
+ ### PUT /api/v1/bank-rules/:resourceId
2720
+
2721
+ Full replacement: send `resourceId`, `appliesToReconciliationAccount` and the whole `configuration` every time.
2722
+
2723
+ **`searchFilter` is the one exception to full replacement.** Omit the key and the stored condition is KEPT; send `null` to remove it; send an object to replace it. This matters because the obvious read-modify-write (GET, change the name, PUT) drops the condition unless you carry it across — which silently stops the rule ever being suggested again.
2724
+
2725
+ ### DELETE /api/v1/bank-rules/:resourceId
2726
+
2727
+ Deletes a rule.
2728
+
2729
+ ### POST /api/v1/bank-rules/search
2730
+
2731
+ Searches rules. Filter fields: `name`, `resourceId`, `actionType`, `appliesToReconciliationAccount`, `businessTransactionType`, `reference`, plus `and`/`or`.
2732
+
2733
+ ```json
2734
+ { "filter": { "name": { "contains": "grab" } }, "sort": { "sortBy": ["name"], "order": "ASC" }, "limit": 100 }
2735
+ ```
2736
+
2737
+ **There is no filter on `searchFilter`**, so "which of my rules have no condition" cannot be asked server-side — list the rules and check the field client-side.
2738
+
2739
+ ---
2740
+
2741
+ *Last updated: 2026-09-13 (added Bank Rules CRUD, section 26). Previous: 2026-07-11 — added Jots judgment journal, section 25. Previous: 2026-04-09 — Added: Contacts bulk-upsert (22), Background Jobs search (23), Export Records (24). 2026-03-13 — Payment record CRUD, nano-classifier, scheduler GET/PUT/DELETE.*
@@ -167,7 +167,7 @@ Match bank statement lines to Jaz transactions to verify cash balances. This is
167
167
 
168
168
  **Bank Feeds**: Connect Airwallex, Aspire, Stripe, Wise, or Xendit for automated statement sync (up to 12 months history, daily auto-sync).
169
169
 
170
- **Bank Rules**: Auto-allocate amounts using percentage-only or fixed+percentage splits (max 10 fixed + 10 percentage lines). Support dynamic strings like `#{{bankReference}}`, `#{{payeeName}}`.
170
+ **Bank Rules**: Two halves. The WHEN is the inline `searchFilter` condition deciding which statement lines the rule applies to — without one the rule is never suggested under Apply Rule, only applied by hand. The THEN auto-allocates amounts using percentage-only or fixed+percentage splits (max 10 fixed + 10 percentage lines). Support dynamic strings `{{bankReference}}`, `{{bankPayee}}`, `{{bankDescription}}`.
171
171
 
172
172
  Statement amounts are recorded in the bank account's currency — no auto-conversion. Cross-currency transactions prompt for cash received/spent in statement currency. Reconciled transactions become uneditable (must reset to edit).
173
173
 
@@ -255,6 +255,12 @@ Mass-edit transactions and line items in a single operation. Replaces the need t
255
255
 
256
256
  **API**: `POST /api/v1/quick-fix/{entity}` (transaction-level) + `POST /api/v1/quick-fix/{entity}/line-items` (line-item-level). 20 endpoints total.
257
257
 
258
+ ### Ledger Find & Fix
259
+
260
+ Find and fix, or recode, records across record types in one pass: find invoices, bills, credit notes, journals and cash entries by a condition (reference, date range, contact, current account), preview one change to their contact, date, capsule, tags, account or classifiers, and apply it once the user has checked the preview. Users ask for it as "find & fix", "recode", "reclassify", "retag", "re-date" or "move these to account X". Quick Fix stays for a known set of records of one type and for the fields this does not change.
261
+
262
+ **API**: `POST /api/v1/ledger/find-fix/transactions/preview` or `POST /api/v1/ledger/find-fix/line-items/preview`, then `POST /api/v1/ledger/find-fix/apply`. See rule 107a.
263
+
258
264
  ---
259
265
 
260
266
  *Maintained alongside [help.jaz.ai](https://help.jaz.ai).*
@@ -3,7 +3,7 @@
3
3
  > **The endpoints clio wraps — the REST surface is larger.** This file catalogues roughly 200
4
4
  > paths, organized by resource, including undocumented endpoints, magic AI features, admin
5
5
  > APIs, and advanced search/filter syntax. The committed OpenAPI spec (`spec/openapi.yaml`)
6
- > carries 454 paths / 369 operations and is the authoritative list; check it before concluding
6
+ > carries 454 paths / 371 operations and is the authoritative list; check it before concluding
7
7
  > an endpoint does not exist. For request/response examples of core endpoints, see
8
8
  > endpoints.md.
9
9
  >
@@ -404,6 +404,9 @@ Body for all three: `{ items: [{btResourceId: "<uuid>", btType: "SALE|PURCHASE|S
404
404
  | POST | `/generate-reports/fixed-assets-recon-summary` |
405
405
  | POST | `/generate-reports/templated-*` | Templated versions of above |
406
406
  | GET | `/ledger/highlights` | GL summary metadata (counts, date range, currencies) |
407
+ | POST | `/ledger/find-fix/transactions/preview` | Ledger Find & Fix: find records across types, plan a contact, date, capsule or tag change (rule 107a) |
408
+ | POST | `/ledger/find-fix/line-items/preview` | Ledger Find & Fix for line items: plan an account or classifier change |
409
+ | POST | `/ledger/find-fix/apply` | Apply a Ledger Find & Fix preview once |
407
410
 
408
411
  ### Data Exports (downloadable)
409
412
  | Method | Path |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-cli
3
- version: 5.59.1
3
+ version: 5.60.0
4
4
  description: >-
5
5
  Use this skill when running Clio CLI commands, building shell scripts with
6
6
  Clio, debugging auth issues, understanding --json output, paginating results,
@@ -8,7 +8,7 @@ description: >-
8
8
  precedence, output formats, entity resolution, and common workflow patterns.
9
9
  Also use when the user asks how to use clio, what commands are available, or
10
10
  how to automate accounting tasks from the command line. Covers all
11
- 72 command groups and 369 tools, including employee-expense claims.
11
+ 73 command groups and 371 tools, including employee-expense claims.
12
12
  license: MIT
13
13
  compatibility: Requires Node.js >= 18.0.0. Install via npm install -g jaz-clio.
14
14
  ---
@@ -17,7 +17,7 @@ compatibility: Requires Node.js >= 18.0.0. Install via npm install -g jaz-clio.
17
17
 
18
18
  > **Audience note:** for power users and CI/automation. Load this skill only when you're scripting from a terminal, building shell pipelines, or debugging from `clio --json` output. For day-to-day accounting inside Claude Desktop / Cowork, the MCP tools cover the common flows without dropping to the CLI.
19
19
 
20
- You are working with **Clio** (`jaz-clio`) — the CLI for the Jaz accounting platform. 72 command groups, 13 calculators, 12 job blueprints, 369 tools. Also fully compatible with Juan Accounting (same API, same endpoints).
20
+ You are working with **Clio** (`jaz-clio`) — the CLI for the Jaz accounting platform. 73 command groups, 13 calculators, 12 job blueprints, 371 tools. Also fully compatible with Juan Accounting (same API, same endpoints).
21
21
 
22
22
  ## When to Use This Skill
23
23
 
@@ -259,7 +259,7 @@ Sending `lineItems[]` to the FLAT endpoint silently ignores them and creates a $
259
259
 
260
260
  **Contacts & Configuration**: `contacts`, `contact-groups`, `accounts`, `items`, `tags`, `currencies`, `currency-rates`, `tax-profiles`, `custom-fields`, `bookmarks`, `nano-classifiers`
261
261
 
262
- **Bank & Reconciliation**: `bank` (accounts, get, records, add-records, import, auto-recon), `bank-rules`
262
+ **Bank & Reconciliation**: `bank` (accounts, get, records, add-records, import, auto-recon), `bank-rules` (a rule needs `--search-filter` or auto-reconciliation never suggests it; on `update`, omitting the flag keeps the stored condition and `--clear-search-filter` removes it)
263
263
 
264
264
  **Employee Claims & Settings**: `claims` (lifecycle + `create` + `from-attachment` + convert + payout), `employees`, `claim-types`, `claim-profiles`, `posting-rules`
265
265
 
@@ -269,7 +269,7 @@ Sending `lineItems[]` to the FLAT endpoint silently ignores them and creates a $
269
269
 
270
270
  **Reports & Exports**: `reports` (16 report types), `exports`
271
271
 
272
- **AI & Automation**: `magic` (create, status), `quick-fix`, `capsules`, `capsule-transaction` (alias: `ct`, 13 recipe types)
272
+ **AI & Automation**: `magic` (create, status), `quick-fix`, `ledger-find-fix` (preview, apply), `capsules`, `capsule-transaction` (alias: `ct`, 13 recipe types)
273
273
 
274
274
  **Judgment journal**: `jots` (create, recall, dispose). Every write command also takes `--jot "<one line>"` to log the judgment behind that specific write inline, no extra call (see `--jot` in Common Flags).
275
275
 
@@ -382,7 +382,7 @@ clio ct loan --principal 100000 --rate 5 --term 60 --start-date 2026-01-01 \
382
382
  3. **Multi-org scripts**: `clio invoices list --org acme-sg --json && clio invoices list --org acme-ph --json`
383
383
  4. **Draft-then-finalize**: The CLI defaults to saving as draft (overrides the API default of `saveAsDraft: false`). Use `--finalize` to create a finalized transaction immediately. Note: `cash-in`, `cash-out` and `cash-transfer` have no draft state and so take no `--finalize` — they always post ACTIVE.
384
384
  5. **Idempotent creates**: Use `--input` with the same JSON to get consistent results. The API dedup guards catch duplicate contacts, items, and accounts.
385
- 6. **Check before bulk ops**: Always preview with `--json | jq length` before piping IDs into `quick-fix`.
385
+ 6. **Check before bulk ops**: Always preview with `--json | jq length` before piping IDs into `quick-fix`. To find & fix (recode, retag, re-date) records found by a condition, across record types, `clio ledger-find-fix preview` lists what would change and why anything is excluded, and `clio ledger-find-fix apply -- <previewId>` runs exactly that, once.
386
386
  7. **Offline calculators for exploration**: `clio calc` commands need no auth -- use them to explore scenarios before committing with `clio ct`.
387
387
  8. **Help center for guidance**: `clio hc "how to reconcile"` searches the full Jaz help center locally (hybrid: embeddings + keyword).
388
388
 
@@ -1,6 +1,6 @@
1
1
  # Clio Command Catalog
2
2
 
3
- Complete reference for all 72 command groups. Organized by domain.
3
+ Complete reference for all 73 command groups. Organized by domain.
4
4
 
5
5
  ---
6
6
 
@@ -318,14 +318,16 @@ EmploymentType: `FULL_TIME` · `PART_TIME` · `CONTRACTOR` · `INTERN` · `TEMPO
318
318
  | Subcommand | Key flags |
319
319
  |------------|-----------|
320
320
  | `list` | `--limit`, `--offset`, `--all`, `--format`, `--json` |
321
- | `get <id>` | `--json` |
322
- | `search <query>` | `--limit`, `--offset` |
323
- | `create` | `--input` (JSON body with rule definition) |
324
- | `update <id>` | `--input` |
321
+ | `get <id>` | `--json`. Prints the rule's condition, or says it has none |
322
+ | `search <query>` | `--limit`, `--offset`, `--account` |
323
+ | `create` | `--name`, `--account`, `--config`, `--search-filter <json>`, `--input` |
324
+ | `update <id>` | `--account` (required), `--name`, `--config`, `--search-filter <json>`, `--clear-search-filter`, `--input` |
325
325
  | `delete <id>` | |
326
326
 
327
327
  Dynamic strings in rules: `{{bankReference}}`, `{{bankPayee}}`, `{{bankDescription}}`
328
328
 
329
+ **A rule without a condition is never suggested.** `--search-filter` is the rule's WHEN side; auto-reconciliation only considers rules whose stored condition is non-null, so a rule created without one exists, lists and applies by hand but is never offered. On `update` the condition is the one field a full-replacement PUT need not resend: **omit `--search-filter` and the stored condition is kept**, pass `--clear-search-filter` to remove it. Shape: `{"version":1,"raw":"description:grab","parsed":{"description":{"contains":"grab"}}}` — `raw` may be blank.
330
+
329
331
  ---
330
332
 
331
333
  ## Fixed Assets & Inventory
@@ -544,6 +546,14 @@ Entities: `invoices`, `bills`, `customer-credit-notes`, `supplier-credit-notes`,
544
546
  | `--date`, `--due`, `--tag`, `--contact`, `--account`, `--tax-profile` | Shorthand flags |
545
547
  | `--input <file>` | Full request body from file |
546
548
 
549
+ ### `clio ledger-find-fix` — Find & fix (recode) records across types, preview one change, apply it once
550
+ Types: `INVOICE`, `BILL`, `CUSTOMER_CREDIT_NOTE`, `SUPPLIER_CREDIT_NOTE`, `JOURNAL`, `CASH_ENTRY`
551
+
552
+ | Subcommand | Key flags |
553
+ |------------|-----------|
554
+ | `preview` | `--level` (`TRANSACTIONS`: contact, date, capsule, tags; `LINE_ITEMS`: account, classifiers; required), `--filter <json>`, `--change <json>`, `--input <file>` (`{"filter": …, "change": …}`; the flags replace its keys), `--json` |
555
+ | `apply <previewId>` | `--jot`, `--json`. Runs the preview once, within 30 minutes. Type it as `apply -- <previewId>`: a previewId can start with `-`, which would read as an option. Options go before `--`: `apply --json -- <previewId>`. Exits 1 unless every record changed (PARTIAL, FAILED, UNKNOWN) |
556
+
547
557
  ### `clio capsules` — Transaction grouping
548
558
  | Subcommand | Key flags |
549
559
  |------------|-----------|
@@ -693,7 +703,7 @@ Valid entity types: INVOICE, BILL, CUSTOMER_CREDIT_NOTE, SUPPLIER_CREDIT_NOTE, S
693
703
  Universal async tracker — any operation returning a jobId (contacts bulk-upsert, items bulk-upsert, bank import, magic processing) can be polled here.
694
704
 
695
705
  ### `clio mcp` — MCP stdio server
696
- Starts an MCP server for Claude Code / AI tool integration. Exposes all 369 operations.
706
+ Starts an MCP server for Claude Code / AI tool integration. Exposes all 371 operations.
697
707
 
698
708
  ### `clio serve` — HTTP daemon
699
709
  Starts the HTTP daemon for ChatKit and email channel integrations.
@@ -193,6 +193,15 @@ clio quick-fix invoices --ids "$DRAFT_IDS" --tag "Q1-Review" --due 2026-04-30
193
193
  # Bulk-update line items (e.g., reassign account)
194
194
  clio quick-fix invoices --line-items --ids "$LINE_ITEM_IDS" \
195
195
  --account "<target-account-resourceId>"
196
+
197
+ # Find & fix (recode) across record types: no ID list needed. Preview moves every
198
+ # journal and cash entry line on the old account to the new one, writing nothing
199
+ clio ledger-find-fix preview --level LINE_ITEMS \
200
+ --filter '{"types":["JOURNAL","CASH_ENTRY"],"organizationAccountResourceId":{"eq":"<old-account-resourceId>"}}' \
201
+ --change '{"organizationAccountResourceId":"<new-account-resourceId>"}'
202
+
203
+ # Apply the preview once you have checked it (-- because a previewId can start with "-")
204
+ clio ledger-find-fix apply -- "<previewId>"
196
205
  ```
197
206
 
198
207
  ## 7. Multi-Org Management
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-conversion
3
- version: 5.59.1
3
+ version: 5.60.0
4
4
  description: >-
5
5
  Use this skill when migrating accounting data into Jaz — importing from Xero,
6
6
  QuickBooks, Sage, MYOB, or Excel exports. Covers the full conversion pipeline:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-kit
3
- version: 5.59.1
3
+ version: 5.60.0
4
4
  description: >-
5
5
  Use this skill when an accountant, bookkeeper, or owner is running real books
6
6
  in Jaz across one or more organizations from the terminal — setting up a
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-pseudo-sql
3
- version: 5.59.1
3
+ version: 5.60.0
4
4
  description: >-
5
5
  Use this skill when answering ad-hoc data questions that aren't covered by
6
6
  download_export (canonical reports — anomaly, audit, aging, P&L, BS, GL,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-jobs
3
- version: 5.59.1
3
+ version: 5.60.0
4
4
  description: >-
5
5
  Use this skill for recurring accounting workflows — month/quarter/year-end
6
6
  close, bank reconciliation, GST/VAT filing, payment runs, credit control,
@@ -9,7 +9,7 @@
9
9
  - **`search_tax_profiles(filter: {})`** — step 2 setup verification: confirm all expected tax profiles exist (`SR`, `ZR`, `ES`, `IES`, `OS`, `TX`, `BL`, `OP`, `EP`, `RC` for SG; `VAT-RC`, `VAT-EXP`, `VAT-ZR`, `VAT-EXM`, `VAT-EXC` for PH).
10
10
  - **`search_invoices(filter: {valueDate: {between: [<period-start>, <period-end>]}}, limit: 200)`** — step 3 output-tax detail: per-invoice GST cross-check against tax ledger.
11
11
  - **`search_bills(filter: {valueDate: {between: [<period-start>, <period-end>]}, status: {neq: 'DRAFT'}}, limit: 200)`** — step 4 input-tax detail: per-bill GST cross-check, with blocked-input filter.
12
- - **`quick_fix_invoices(...)` / `quick_fix_bills(...)`** — step 5 corrections: bulk-update tax-profile / tax-vat-applicable across multiple transactions if errors found.
12
+ - **`quick_fix_line_items(entity: 'invoices' | 'bills', lineItemResourceIds, attributes)`** — step 5 corrections: re-assign the tax profile on the affected lines if errors are found. The tax profile sits on each line, so the fix is at line level.
13
13
  - **`download_export(exportType: 'analysis-exchange-rate-audit', startDate, endDate)`** — step 6 pre-filing check: FX rates outside expected band can shift GST on FX invoices.
14
14
  - **`generate_trial_balance(period_end: <period-end>)`** — step 7 GST account reconciliation: `GST Control` / `Input Tax Recoverable` / `Output Tax Payable` accounts.
15
15
 
@@ -97,23 +97,17 @@ Flag bills where:
97
97
 
98
98
  ## Step 5 — Corrections (if errors found)
99
99
 
100
- For tax-profile errors detected in steps 3-4:
100
+ For tax-profile errors detected in steps 3-4. The tax profile sits on each line item, so correct the lines:
101
101
 
102
102
  ```
103
- quick_fix_invoices({
104
- resourceIds: [<list of invoice ids>],
103
+ quick_fix_line_items({
104
+ entity: 'invoices',
105
+ lineItemResourceIds: [<line item ids from the step 3 invoices>],
105
106
  attributes: { taxProfileResourceId: <correct profile id> }
106
107
  })
107
108
  ```
108
109
 
109
- Mirror for bills via `quick_fix_bills`. For line-item-level fixes:
110
-
111
- ```
112
- quick_fix_invoices({
113
- lineItemResourceIds: [<list of line item ids>],
114
- attributes: { taxProfileResourceId: <correct profile> }
115
- })
116
- ```
110
+ Mirror for bills with `entity: 'bills'`. Ledger Find & Fix (`preview_ledger_find_fix`) does not change tax profiles, so these per-type calls are the route for this correction.
117
111
 
118
112
  Per `jaz-api/SKILL.md` rule 107: Quick Fix returns 207 Multi-Status on partial failures; retry only failed resourceIds.
119
113
 
@@ -176,7 +170,7 @@ Save the filing summary for the quarter. The user files via the appropriate port
176
170
  | Step 2 | Tax profile missing for jurisdiction | `create_tax_profile(...)` per IRAS / BIR spec. Halt and surface to practitioner — practitioner judgment on rate. |
177
171
  | Step 3 | Per-invoice GST ≠ tax-ledger output total | Investigate per-invoice tax-profile assignment. Quick Fix typically resolves. |
178
172
  | Step 4 | BL bills coded as TX | Quick Fix re-assigns to BL. Practitioner approval required (changes input tax claim). |
179
- | Step 5 | `quick_fix_invoices` 207 Multi-Status | Retry only failed resourceIds (per rule 107). Likely cause: invoice in locked period. |
173
+ | Step 5 | `quick_fix_line_items` 207 Multi-Status | Retry only failed resourceIds (per rule 107). Likely cause: invoice in locked period. |
180
174
  | Step 7 | TB GST Control ≠ tax-ledger net | Surface to practitioner. Investigate manual journals against GST accounts. Auditor will catch this if unresolved. |
181
175
  | Step 8 | Box 13 Revenue ≠ P&L Operating Revenue | Box 13 includes ALL revenue (zero-rated + exempt + standard); P&L may show split. Re-confirm Box 13 definition with IRAS. |
182
176
  | Filing rejected by myTax / BIR | (post-filing) | Pull rejection reason. Amend filing summary; refile within allowed window. Practitioner judgment on penalty exposure. |
@@ -155,7 +155,7 @@ update_account(resourceId: <CoA root>, lockDate: '2025-03-31')
155
155
  | Source | Error | Recovery |
156
156
  |--------|-------|----------|
157
157
  | Phase 1-5 (standalone) | Months not all closed | Months incomplete. Route to missing `month-end-close.md`. Run quarterly extras only once all 3 months are locked. |
158
- | Q1 verification | Tax ledger ≠ sum of GST per invoice/bill | Likely tax-profile assignment errors. Audit each invoice / bill for correct tax profile. Quick Fix: `quick_fix_invoices(...)` / `quick_fix_bills(...)`. |
158
+ | Q1 verification | Tax ledger ≠ sum of GST per invoice/bill | Likely tax-profile assignment errors. Audit each invoice / bill for correct tax profile. Quick Fix: `quick_fix_line_items(entity: 'invoices' \| 'bills', ...)` on the affected lines, since the tax profile sits on each line. |
159
159
  | Q2 ECL recipe | 422 `account_not_found` | `Allowance for Doubtful Debts` missing. Create via `create_account(accountType: 'Current Asset')`. |
160
160
  | Q3 | YTD accrual mismatches monthly recipe expectations | Likely a manual journal posted directly to Bonus Liability (not via recipe). Audit `generate_general_ledger(accountResourceId: <Bonus Liability>, period_start: <FY-start>, period_end: <today>)`. |
161
161
  | Q4 IC recon | Entity A IC Receivable ≠ Entity B IC Payable (sign-flipped) | See the `intercompany` recipe error table. Common causes: timing, FX confusion, posting skipped in one entity. |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-recipes
3
- version: 5.59.1
3
+ version: 5.60.0
4
4
  description: >-
5
5
  Use this skill when modeling complex multi-step accounting transactions —
6
6
  anything that spans multiple periods, involves changing amounts, or requires
@@ -6,11 +6,11 @@ Source of truth lives in the installed skills (`.claude/skills/jaz-*/SKILL.md` o
6
6
 
7
7
  ## Discovery
8
8
 
9
- Jaz exposes **369 tools across 45 namespaces**. Your tool list shows **3, 45, or 369** entries depending on packaging — **never infer capability from its length.**
9
+ Jaz exposes **371 tools across 45 namespaces**. Your tool list shows **3, 45, or 371** entries depending on packaging — **never infer capability from its length.**
10
10
 
11
11
  - **3** — `search_tools(query)` → `describe_tools(names)` → `execute_tool(name, args)`. Empty query returns the namespace map.
12
- - **43** — namespace routers; call one with `{ operation, arguments }`. Its description lists its operations.
13
- - **369** — call operations directly by name.
12
+ - **45** — namespace routers; call one with `{ operation, arguments }`. Its description lists its operations.
13
+ - **371** — call operations directly by name.
14
14
 
15
15
  `describe_capabilities` returns the capability map on all three. **Call it before telling the user Jaz cannot do something.**
16
16
 
@@ -36,6 +36,7 @@ Exception: `fx-reval` is verification-only — Jaz auto-handles period-end IAS 2
36
36
 
37
37
  ## Bulk operations
38
38
 
39
+ - Find & fix (recode) many records: `preview_ledger_find_fix`, then apply once the user confirms.
39
40
  - `bulk_upsert_*` tools accept up to 500 rows per call. Async tools return a `jobId` — poll `search_background_jobs(filter:{resourceId:{eq:jobId}})` until SUCCESS / FAILED / PARTIAL_SUCCESS.
40
41
  - On `PARTIAL_SUCCESS`: succeeded rows are committed. Inspect `errorDetails[].rowIndex` and re-submit only failed rows.
41
42
  - Sync `bulk_upsert_chart_of_accounts` returns `failedRows[]` inline — no polling.