jaz-clio 7.0.1 → 9.0.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-382-blue?style=for-the-badge" alt="382 tools">
6
+ <img src="https://img.shields.io/badge/tools-387-blue?style=for-the-badge" alt="387 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>Fastest ledger for agents.</b><br>Jaz accounting on the command line, and inside any AI agent.</p>
11
11
 
12
- 382 tools · 74 command groups · 7 skills · 13 calculators · 12 job playbooks · 148 field-tested API rules.
12
+ 387 tools · 74 command groups · 7 skills · 13 calculators · 12 job playbooks · 148 field-tested API rules.
13
13
 
14
14
  ```bash
15
15
  npm install -g jaz-clio
@@ -109,7 +109,7 @@ that ends up in a journal.
109
109
 
110
110
  ## MCP server
111
111
 
112
- 382 tools for any AI agent that speaks MCP. Runs locally: no cloud, no ports.
112
+ 387 tools for any AI agent that speaks MCP. Runs locally: no cloud, no ports.
113
113
 
114
114
  > **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.
115
115
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-api
3
- version: 7.0.1
3
+ version: 9.0.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, 148 production gotchas, error
@@ -170,7 +170,7 @@ The rest of this skill (field names, gotchas, error catalog, dependency order, s
170
170
  42. **Scheduler GET returns `interval`**; POST uses `repeat`. (Response-side asymmetry remains.)
171
171
  43. **Search sort is an object**: `{ sort: { sortBy: ["valueDate"], order: "DESC" } }`. Required when `offset` is present (even `offset: 0`).
172
172
  44. **Bank records**. **Create**: Multipart CSV/OFX via `POST /magic/importBankStatementFromAttachment` or JSON via `POST /bank-records/:accountResourceId` with `{ records: [{amount, transactionDate, description?, payerOrPayee?, reference?}] }` (positive = cash-in, negative = cash-out, response: `{data: {errors: []}}`). **Search**: `POST /bank-records/:accountResourceId/search`; filter fields: `valueDate` (DateExpression), `status` (StringExpression: UNRECONCILED, RECONCILED, ARCHIVED, POSSIBLE_DUPLICATE), `description`, `extContactName` (payer/payee), `extReference`, `netAmount` (BigDecimalExpression), `extAccountNumber`. Sort by `valueDate` DESC default.
173
- 45. **Withholding tax** on bills/supplier CNs only. Retry pattern: if `WITHHOLDING_CODE_NOT_FOUND`, strip field and retry.
173
+ 45. **Withholding tax (PH) has two sides.** Expanded withholding (EWT) on what you pay sits on each bill / supplier credit note line as `withholdingTax`: copy `code`, `rate`, `type` and `description` from one `list_withholding_codes` row (a field left out is not stored, measured 2026-10-06). Creditable withholding (CWT) a customer deducts is recorded from the customer's BIR Form 2307 with `record_withholding_tax_certificate`, never on the invoice lines (rule 98). On `WITHHOLDING_CODE_NOT_FOUND`, check the code against `list_withholding_codes` (codes contain a space: `WC 158`); never strip the field silently, because the tax disappears from the bill.
174
174
  46. **Known API bugs (500s)**: none on this list today. **Capsules POST, catalogs POST, inventory balances by status GET, contact groups PUT and custom fields PUT are NO LONGER on this list.** Capsules POST creates the capsule and returns its `resourceId`. Catalogs POST returned 201 on a live probe 2026-09-23 (item `unit` omitted, it is optional); its response is counts (`createdCatalogs`, `createdCatalogItems`), not a resourceId, so find the new catalog with `search_catalogs`. Inventory balances by status works (Rule 97). Contact groups PUT and custom fields PUT were re-probed live 2026-09-02 and returned 200 and applied the change. Do not route around any of them.
175
175
  47. **Non-existent endpoints**: `POST /inventory/adjustments` (and `/inventory-adjustments`, `/inventory-items/:id/adjustments`, `/items/:id/inventory-adjustments`; no stock-adjustment write path exists at any spelling), `GET /payments` (list), and `POST /payments/search` return 404; these endpoints are not implemented. For payments, per-payment CRUD is `GET/PUT/DELETE /payments/:resourceId` and there ARE two payment-scoped searches; see Rule 64. `POST /deposits` also 404s, but for a different reason, see Rule 47a; do not read it as a missing feature.
176
176
  47a. **Deposits are not an entity; the 404 on `/deposits` is by design.** A deposit is a **flag on a Chart of Accounts account**, not a document: the account carries `depositContactType` = `CUSTOMER` (advance received, a liability) or `SUPPLIER` (advance paid, an asset). Once flagged, a deposit movement is an **ordinary transaction against that account**: top up with `POST /journals` / `POST /cash-in-entries` / `POST /cash-out-entries` (one leg on the flagged account), draw down with `POST /invoices/:id/payments` or `POST /bills/:id/payments` passing `accountResourceId` = the flagged account **and `paymentMethod` set to something other than BANK_TRANSFER / CASH / CHEQUE** (use `OTHER`; those three force a bank/cash account and 422 here, see Rule 80), read with `POST /cashflow-transactions/search`. **Flagging the account is a web-app action**: `depositContactType` is on no chart-of-accounts request or response model here, and the platform-backend mutation that sets it (`configureDepositAccounts`) is not proxied, so `POST /chart-of-accounts` cannot create a deposit account. Over the API you can only read and post against an account someone already flagged. Full walkthrough: `references/endpoints.md` → Deposits.
@@ -201,7 +201,7 @@ The rest of this skill (field names, gotchas, error catalog, dependency order, s
201
201
  63. **Workflow search tracks all magic uploads**: `POST /magic/workflows/search` searches across BT extractions AND bank statement imports. Filter by `resourceId` (eq), `documentType` (SALE, PURCHASE, SALE_CREDIT_NOTE, PURCHASE_CREDIT_NOTE, SALE_QUOTE, SALE_ORDER, PURCHASE_REQUEST, PURCHASE_ORDER, BANK_STATEMENT), `status` (SUBMITTED, PROCESSING, COMPLETED, FAILED), `fileName` (contains), `fileType`, `createdAt` (date range). Response: paginated `MagicWorkflowItem` with `businessTransactionDetails.businessTransactionResourceId` (the draft BT ID when COMPLETED) or `bankStatementDetails` (for bank imports). Standard search sort: `{ sortBy: ["createdAt"], order: "DESC" }`.
202
202
 
203
203
  ### Cashflow & Unified Ledger
204
- 64. **Four ways to read payments: pick by scope.** `GET /payments` (list) and `POST /payments/search` do NOT exist and never did. What does exist: (a) **per-payment CRUD**: `GET/PUT/DELETE /payments/:resourceId`; (b) **payment-scoped search**: `POST /sales/payments/search` and `POST /purchases/payments/search` (added 2026-08-13), one side of the ledger each, plus `POST /batch-payments/search` for batches; (c) **cross-entity ledger**: `POST /cashflow-transactions/search`, the unified transaction ledger spanning invoices, bills, credit notes, journals, cash entries and payments. Filter it by `businessTransactionType` (e.g. `SALE`, `PURCHASE`) and `direction` (`PAYIN`, `PAYOUT`). Response dates are epoch milliseconds. **Naming trap**: the `search_payments` tool is a wrapper over `/cashflow-transactions/search`, NOT over the sales/purchases payment searches; its name is narrower than what it calls. Reach the per-side searches with a raw request; they have no tool. (d) **Per-document settlements**: `GET /invoices/:id/payments` and `GET /bills/:id/payments`, and for credit notes `GET /customer-credit-notes/:id/refunds` / `GET /supplier-credit-notes/:id/refunds` (the domain distinguishes a refund from a payment; a journal has neither). This is the right call for **one known document's own settlements** and the one to reach for first: no filter to get wrong. All four answer `{ data: [...] }` (measured raw 2026-09-07). It is listed here because it was missing from this rule while (c) sat one line away, and `get_transaction_summary` consequently filtered the ledger by `businessTransactionResourceId`, a field `TransactionsFilter` does not declare, for its entire life, 400ing on every call behind a silent catch.
204
+ 64. **Four ways to read payments: pick by scope.** `GET /payments` (list) and `POST /payments/search` do NOT exist and never did. What does exist: (a) **per-payment CRUD**: `GET/PUT/DELETE /payments/:resourceId`; (b) **payment-scoped search**: `POST /sales/payments/search` and `POST /purchases/payments/search` (added 2026-08-13), one side of the ledger each, plus `POST /batch-payments/search` for batches; (c) **cross-entity ledger**: `POST /cashflow-transactions/search`, the unified transaction ledger spanning invoices, bills, credit notes, journals, cash entries and payments. Filter it by `businessTransactionType` (e.g. `SALE`, `PURCHASE`) and `direction` (`PAYIN`, `PAYOUT`). Response dates are epoch milliseconds. The cashflow ledger tool is `search_cashflow_transactions`; its `resourceId` is a ledger row, not a payment record, so it 404s on `get_payment` / `update_payment`, which take a document's `paymentRecords` id. The per-side payment searches (b) have no tool; reach them with a raw request. (d) **Per-document settlements**: `GET /invoices/:id/payments` and `GET /bills/:id/payments`, and for credit notes `GET /customer-credit-notes/:id/refunds` / `GET /supplier-credit-notes/:id/refunds` (the domain distinguishes a refund from a payment; a journal has neither). This is the right call for **one known document's own settlements** and the one to reach for first: no filter to get wrong. All four answer `{ data: [...] }` (measured raw 2026-09-07). It is listed here because it was missing from this rule while (c) sat one line away, and `get_transaction_summary` consequently filtered the ledger by `businessTransactionResourceId`, a field `TransactionsFilter` does not declare, for its entire life, 400ing on every call behind a silent catch.
205
205
  65. **Contacts search uses `name`**, NOT `billingName`. The filter field for searching contacts by name is `name` (maps to `billingName` internally). Sort field is also `name`. Using `billingName` in a search filter returns zero results.
206
206
 
207
207
  ### Response Shape Gotchas
@@ -334,7 +334,7 @@ Bills, invoices, and credit notes share identical mandatory field specs. Adding
334
334
  97. **Inventory balances: one item or all.** One item: `GET /inventory-item-balance/:itemResourceId` (`get_inventory_balance`) returns `{ itemResourceId, latestAverageCostAmount, baseQty, baseUnit }`; the id is the ITEM resourceId, not an inventory-specific ID. All items: `GET /inventory-balances/:balanceStatus` (`list_inventory_balances`, `clio inventory balances --status`) with `balanceStatus` one of `ALL`, `AVAILABLE`, `FULLY_DRAWN` (anything else is 422); rows carry `itemCode`, `internalName`, `totalQuantity`, `baseUnit`, `averageCostAmount`, `balanceAmount`. The API answers an empty result with 404; the tool and CLI return it as `data: []`. `offset` is a page number here, though the spec says row (probed live 2026-09-23).
335
335
 
336
336
  ### Withholding Tax
337
- 98. **Withholding tax codes via `GET /withholding-tax-codes`**: Returns a flat array of 1,360+ entries (PH PSIC codes). Each entry: `{ code, description, taxRate, ... }`. No pagination; full list in one call. Use for PH/SG tax compliance.
337
+ 98. **Withholding codes are `GET /withholding-codes`** (`list_withholding_codes`, `clio tax-profiles withholding-codes`): the BIR ATCs with `code`, `rate`, `rateType`, `type` (corp, ind, final, wvat), `description` and `resourceId`; filters `countryCode`, `code` (contains, space included) and `type`; `limit` max 100, `offset` is a page. `GET /withholding-tax-codes` is a different list (MSIC/PSIC industry codes) that no withholding field accepts. A customer's 2307 is a sale batch payment with method `WITHHOLDING_TAX_CERTIFICATE` (`record_withholding_tax_certificate`): PH orgs only, sales only, account = the system "Creditable Withholding Tax" account, one allocation per code by `resourceId`, and each allocation's `baseAmount` is the TAX WITHHELD (the dashboard's "Withholding" column; `amount` is the income); the `baseAmount`s must add up to the payment total within 0.01.
338
338
  99. **Duplicate detection fields**. API rejects duplicates with 422: Contacts on `name` (NOT `billingName`), Items on `itemCode`, Accounts on `name`, Tax Profiles on `name`. Agent tools auto-search before creating; if a match is found, the existing entity is returned instead of hitting a 422.
339
339
 
340
340
  ### Tax Profile Scoping
@@ -643,7 +643,7 @@ The `payments` array uses the same 6-field structure as standalone payments. pro
643
643
 
644
644
  ### Withholding Tax on Line Items
645
645
 
646
- Bills and supplier credit notes support withholding tax per line item:
646
+ Bills and supplier credit notes support expanded withholding tax (EWT, Philippines) per line item. Copy `code`, `rate`, `type` and `description` from one `GET /withholding-codes` row (`list_withholding_codes`); a field left out is not stored:
647
647
 
648
648
  ```json
649
649
  {
@@ -653,15 +653,18 @@ Bills and supplier credit notes support withholding tax per line item:
653
653
  "quantity": 1,
654
654
  "accountResourceId": "expense-uuid",
655
655
  "withholdingTax": {
656
- "code": "WC010",
657
- "rate": 10,
658
- "description": "Professional fees"
656
+ "code": "WC 158",
657
+ "rate": 1,
658
+ "type": "corp",
659
+ "description": "Income Payment Made By Top Withholding Agents To Their Local/Resident Supplier Of Goods Other Than Those Covered By Other Rates Of Withholding Tax"
659
660
  }
660
661
  }]
661
662
  }
662
663
  ```
663
664
 
664
- **Retry pattern**: If the organization doesn't support withholding tax, the API returns `WITHHOLDING_CODE_NOT_FOUND`. On this error, remove the `withholdingTax` field from all line items and retry the request.
665
+ **On `WITHHOLDING_CODE_NOT_FOUND`**: check the code against `list_withholding_codes` (codes contain a space). If the organization does not use withholding (non-PH), remove `withholdingTax` and say so; never strip it silently. See errors.md.
666
+
667
+ Customer-side withholding (CWT) is not a line field: record the customer's BIR Form 2307 with `record_withholding_tax_certificate` (`POST /sales/batch-payments`, `paymentMethod: WITHHOLDING_TAX_CERTIFICATE`, `ph2307Details`). SKILL.md rule 98 has the rules.
665
668
 
666
669
  ---
667
670
 
@@ -749,13 +749,7 @@ The same applies on update: `PUT /cash-in-entries/:id` with `saveAsDraft: true`
749
749
  **Request**: POST /api/v1/bills with `withholdingTax` on line items
750
750
  **Error**: `"WITHHOLDING_CODE_NOT_FOUND"` or similar withholding-related error
751
751
  **Cause**: The organization does not have withholding tax enabled, or the code is invalid for this region.
752
- **Fix**: Remove the `withholdingTax` field from ALL line items and retry. This is a common pattern for cross-region compatibility: Singapore orgs typically don't use withholding tax, but Philippines orgs do.
753
-
754
- **Retry pattern** (from production):
755
- 1. Submit bill/credit note with `withholdingTax` fields
756
- 2. If error contains "WITHHOLDING" (case-insensitive), strip `withholdingTax` from all line items
757
- 3. Retry the same request without withholding tax
758
- 4. Log which org doesn't support withholding tax to avoid future retries
752
+ **Fix**: First check the code against `list_withholding_codes` (`GET /withholding-codes`): codes contain a space (`WC 158`, not `WC158`). If the organization does not use withholding (Singapore orgs typically don't; Philippines orgs do), remove `withholdingTax` from the line items, retry, and tell the user the bill was recorded without it. Never strip it silently: the withholding disappears from the bill.
759
753
 
760
754
  ---
761
755
 
@@ -231,7 +231,7 @@ Fixed assets lock their linked line items: cannot edit account, amounts, or exch
231
231
 
232
232
  **User Roles**: Admin (full access), Preparer (create drafts, submit for approval), Member (own drafts only). Granular permissions by module (AR, AP, Treasury, Journals).
233
233
 
234
- **API**: CRUD `GET/POST/PUT/DELETE /chart-of-accounts`, `POST /chart-of-accounts/bulk-upsert`, `POST /chart-of-accounts/search`, `GET /tax-profiles`, `POST /tax-profiles/search`, CRUD `GET/POST/PUT/DELETE /tags`, `POST /tags/search`, CRUD `GET/POST/PUT/DELETE /custom-fields`, `POST /custom-fields/search`, `POST /organization/currencies` (enable), `DELETE /organization/currencies/:code` (disable), `POST /organization/currencies/:code/rates` (set FX rate, CRUD), `GET /organization` (org details), CRUD `GET/POST/PUT/DELETE /organization/bookmarks`, CRUD `GET/POST/PUT/DELETE /nano-classifiers`, `POST /nano-classifiers/search`, `GET /organization-users`, `POST /organization-users/search`. Reference data: `GET /account-classifications`, `GET /withholding-tax-codes`, `GET /tax-types`, `GET /modules`
234
+ **API**: CRUD `GET/POST/PUT/DELETE /chart-of-accounts`, `POST /chart-of-accounts/bulk-upsert`, `POST /chart-of-accounts/search`, `GET /tax-profiles`, `POST /tax-profiles/search`, CRUD `GET/POST/PUT/DELETE /tags`, `POST /tags/search`, CRUD `GET/POST/PUT/DELETE /custom-fields`, `POST /custom-fields/search`, `POST /organization/currencies` (enable), `DELETE /organization/currencies/:code` (disable), `POST /organization/currencies/:code/rates` (set FX rate, CRUD), `GET /organization` (org details), CRUD `GET/POST/PUT/DELETE /organization/bookmarks`, CRUD `GET/POST/PUT/DELETE /nano-classifiers`, `POST /nano-classifiers/search`, `GET /organization-users`, `POST /organization-users/search`. Reference data: `GET /account-classifications`, `GET /withholding-codes` (withholding ATCs), `GET /withholding-tax-codes` (MSIC/PSIC industry codes), `GET /tax-types`, `GET /modules`
235
235
 
236
236
  ---
237
237
 
@@ -208,11 +208,14 @@ COGS maps to `"Direct Costs"`; "Cost of Goods Sold" is the default account name
208
208
  | What You'd Guess | Actual API Field | Notes |
209
209
  |---|---|---|
210
210
  | `tax` | `withholdingTax` | Nested object on each line item |
211
- | `withholdingTaxCode` | `withholdingTax.code` | String code (e.g., "WC010") |
212
- | `withholdingTaxRate` | `withholdingTax.rate` | Numeric percentage (e.g., 10) |
213
- | `withholdingTaxDescription` | `withholdingTax.description` | Optional description |
211
+ | `withholdingTaxCode` | `withholdingTax.code` | The ATC, space included (e.g., "WC 158") |
212
+ | `withholdingTaxRate` | `withholdingTax.rate` | Numeric percentage (e.g., 1) |
213
+ | `withholdingTaxType` | `withholdingTax.type` | corp, ind, final or wvat |
214
+ | `withholdingTaxDescription` | `withholdingTax.description` | The code's description |
214
215
 
215
- **Not supported on**: Invoices, customer credit notes, journals, cash entries. Only bills and supplier credit notes.
216
+ Copy all four from one `list_withholding_codes` row; a field left out is not stored on the line.
217
+
218
+ **Line-level only on**: bills and supplier credit notes (EWT). Customer-side withholding (CWT) on invoices is recorded from the customer's BIR Form 2307 with `record_withholding_tax_certificate`, not on invoice lines.
216
219
 
217
220
  ---
218
221
 
@@ -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 468 spec paths and 599 spec operations and is the authoritative list; check it before concluding
6
+ > carries 475 spec paths and 607 spec 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
  >
@@ -848,11 +848,12 @@ incomplete. Reaching them needs a raw HTTP call.
848
848
  | POST | `/bank-records/:accountResourceId/archive` | Archive bank records |
849
849
  | POST | `/bank-records/:accountResourceId/unarchive` | Unarchive bank records |
850
850
 
851
- ### Withholding (1): 2026-07-31
851
+ ### Withholding (2): 2026-07-31, withholding-codes 2026-10-06
852
852
 
853
853
  | Method | Path | Description |
854
854
  |--------|------|-------------|
855
855
  | POST | `/payments/withholding` | Record withholding on a sale / sale credit note payment (see SKILL.md Rule 45) |
856
+ | GET | `/withholding-codes` | Withholding codes (BIR ATCs) for line `withholdingTax` and 2307 allocations (Rule 98) |
856
857
 
857
858
  ---
858
859
 
@@ -18,7 +18,7 @@ Two MCP namespaces wrap these: **`sale_orders`** (Sale Quotes + Sale Orders) and
18
18
  | `PURCHASE_REQUEST` | DRAFT (default) / ACTIVE (saveAsDraft:false) | **accept** (ACTIVE → ACCEPTED) | VOID | yes (default true) |
19
19
  | `PURCHASE_ORDER` | DRAFT (default) / ACTIVE (saveAsDraft:false) | **confirm** → CONFIRMED | VOID | yes (default true) |
20
20
 
21
- - **Quotes & Requests use `accept`. Orders use `confirm`.** (`transition_*` enforces this via a documentType × action matrix.)
21
+ - **Quotes & Requests use `accept`. Orders use `confirm`.** Each is its own tool: `accept_sale_quote`, `confirm_sale_order`, `accept_purchase_request`, `confirm_purchase_order`.
22
22
  - **`accept` works on the ISSUED state, not DRAFT**: a Sale Quote must be CREATED, a Purchase Request must be ACTIVE. Accepting a DRAFT returns `422 Invalid status` (verified live). **Issue an existing DRAFT in place** with the update tool's flag: `update_sale_order` `isDraftToActiveSaleQuote: true` (→ CREATED), `update_purchase_order` `isDraftToActivePurchaseRequest: true` (→ ACTIVE). Send every stored line with its `resourceId` in the SAME update: a flag-only update is refused with `422 SALE_LINE_ITEMS_REQUIRED` (verified live 2026-09-23 on a sale quote). It keeps the document's number and line ids (verified live: DRAFT → CREATED, same reference, same line `resourceId`; a line without an account issued fine), so never create a second quote/request to issue one. (Update with `saveAsDraft:false` does NOT issue a DRAFT, verified live.) To create one already issued, pass `saveAsDraft:false` on create.
23
23
  - **Sale Orders have no draft state**: `saveAsDraft` is ignored; created directly as `CREATED`.
24
24
  - **PENDING orders.** Jaz Magic creates Sale Orders and Purchase Orders as `PENDING`. Take one live with `update_sale_order` `isPendingToActiveSaleOrder: true` / `update_purchase_order` `isPendingToActivePurchaseOrder: true`. Search accepts `status: PENDING`.
@@ -85,13 +85,13 @@ To change a few fields on some lines without resending the document, use `quick_
85
85
 
86
86
  ## Delete vs Void
87
87
 
88
- - **DELETE is draft-only** (422 on anything non-draft). `transition_* action:DELETE` pre-flights status and returns a `repair` hint to use `VOID` for non-draft records.
89
- - **VOID** cancels any non-draft quote/request/order; optional `internalNotes` reason.
88
+ - **DELETE is draft-only** (422 on anything non-draft). `delete_sale_order` / `delete_purchase_order` pre-flight the status and return a `repair` pointing at the void tool for a non-draft record.
89
+ - **VOID** (`void_sale_order` / `void_purchase_order`) cancels any non-draft quote/request/order; optional `internalNotes` reason.
90
90
 
91
91
  ## MCP tools
92
92
 
93
- `sale_orders`: `create_sale_order`, `get_sale_order`, `search_sale_orders`, `search_sale_order_line_items`, `update_sale_order`, `transition_sale_order` (action: ACCEPT | CONFIRM | VOID | DELETE), `convert_sale_order_to_invoice`.
94
- `purchase_orders`: `create_purchase_order`, `get_purchase_order`, `search_purchase_orders`, `search_purchase_order_line_items`, `update_purchase_order`, `transition_purchase_order`, `convert_purchase_order_to_bill`.
93
+ `sale_orders`: `create_sale_order`, `get_sale_order`, `search_sale_orders`, `search_sale_order_line_items`, `update_sale_order`, `accept_sale_quote`, `confirm_sale_order`, `void_sale_order`, `delete_sale_order`, `convert_sale_order_to_invoice`.
94
+ `purchase_orders`: `create_purchase_order`, `get_purchase_order`, `search_purchase_orders`, `search_purchase_order_line_items`, `update_purchase_order`, `accept_purchase_request`, `confirm_purchase_order`, `void_purchase_order`, `delete_purchase_order`, `convert_purchase_order_to_bill`.
95
95
 
96
96
  PDF downloads for the documents these convert into: `download_bill_pdf` (`bills`), `download_supplier_credit_note_pdf` (`supplier_credit_notes`), alongside the existing `download_invoice_pdf` / `download_credit_note_pdf`.
97
97
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-cli
3
- version: 7.0.1
3
+ version: 9.0.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
- 74 command groups and 382 tools, including employee-expense claims.
11
+ 74 command groups and 387 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. 74 command groups, 13 calculators, 12 job playbooks (jaz-jobs skill), 382 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. 74 command groups, 13 calculators, 12 job playbooks (jaz-jobs skill), 387 tools. Also fully compatible with Juan Accounting (same API, same endpoints).
21
21
 
22
22
  ## When to Use This Skill
23
23
 
@@ -103,11 +103,9 @@ Same subcommands and flags as `cash-in`.
103
103
  | `create` | `--from-account`, `--to-account`, `--amount`, `--date`, `--ref` (generated when omitted), `--input` |
104
104
  | `delete <id>` | |
105
105
 
106
- ### `clio payments`: Cashflow transactions (read-only)
106
+ ### `clio payments`: Payment records (search the ledger with `clio cashflow search`)
107
107
  | Subcommand | Key flags |
108
108
  |------------|-----------|
109
- | `list` | `--limit`, `--offset`, `--all`, `--format`, `--json` |
110
- | `search` | `--from`, `--to`, `--type`, `--direction`, `--ref`, `--sort`, `--order` |
111
109
  | `get <id>` | `--json` |
112
110
  | `update <id>` | `--date`, `--reference`, `--input` |
113
111
  | `delete <id>` | |
@@ -194,7 +192,7 @@ Same subcommands and flags as `cash-in`.
194
192
  | `create` | `--rate`, `--name`, `--tax-type-code` |
195
193
  | `update <id>` | `--name`, `--rate` |
196
194
  | `types` | List available tax type codes |
197
- | `wht-codes` | List withholding tax codes |
195
+ | `withholding-codes` | List withholding codes (BIR ATCs) for a bill line's withholding tax and a Withholding Tax Certificate (2307) |
198
196
 
199
197
  ### `clio filing-submissions`: Tax return filings (read-only, 1 tool)
200
198
  | Subcommand | Key flags |
@@ -727,7 +725,7 @@ Valid entity types: INVOICE, BILL, CUSTOMER_CREDIT_NOTE, SUPPLIER_CREDIT_NOTE, S
727
725
  Universal async tracker: any operation returning a jobId (contacts bulk-upsert, items bulk-upsert, bank import, magic processing) can be polled here.
728
726
 
729
727
  ### `clio mcp`: MCP stdio server
730
- Starts an MCP server for Claude Code / AI tool integration. Exposes all 382 operations.
728
+ Starts an MCP server for Claude Code / AI tool integration. Exposes all 387 operations.
731
729
 
732
730
  ### `clio init`: Skill installer
733
731
  Installs AI agent skills into your project.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-conversion
3
- version: 7.0.1
3
+ version: 9.0.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: 7.0.1
3
+ version: 9.0.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: 7.0.1
3
+ version: 9.0.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: 7.0.1
3
+ version: 9.0.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,
@@ -10,9 +10,9 @@
10
10
  - **`generate_bank_balance_summary(primarySnapshotDate: <cutoff>)`**, used in step 5: confirm cash availability before approving the batch.
11
11
  - **`get_contact(resourceId: <contactResourceId>)`**, used in step 4 (per supplier): pull payment terms / preferred payment method / bank details (especially `taxId`, `bankAccountNumber`, `bicSwift` for GIRO file generation).
12
12
  - **`pay_bill(resourceId: <id>, paymentAmount, transactionAmount, accountResourceId, valueDate, ...)`**, used in step 6: post the payment per bill. NO BATCH PAYMENT ENDPOINT yet; one POST per bill.
13
- - **`search_payments(filter: {businessTransactionReference: {startWith: <run-prefix>}, valueDate: {eq: <run-date>}})`**, used in step 8: idempotency / verification check (re-running the run won't duplicate-pay if all references match).
13
+ - **`search_cashflow_transactions(filter: {businessTransactionReference: {startWith: <run-prefix>}, valueDate: {eq: <run-date>}})`**, used in step 8: idempotency / verification check (re-running the run won't duplicate-pay if all references match).
14
14
 
15
- > **The field and the operator are both exact.** `search_payments` hits `POST /cashflow-transactions/search` → `TransactionsFilter`, which declares no `additionalProperties`, so an undeclared field is rejected outright rather than ignored. It has **no `reference`** (that is `businessTransactionReference`) and `StringExpression` has **no `startsWith`**: the prefix operator is spelled **`startWith`**, no "s". Until 5.55.3 this line asked for both wrong names, so the idempotency check (the step standing between a re-run and paying every supplier twice) could not return anything. Use `startWith`, not `contains`: measured on the sandbox 2026-09-07, `contains: 'PR-'` matched 3 rows that do **not** start with that prefix, and a looser match here silently widens what the run treats as already-paid.
15
+ > **The field and the operator are both exact.** `search_cashflow_transactions` hits `POST /cashflow-transactions/search` → `TransactionsFilter`, which declares no `additionalProperties`, so an undeclared field is rejected outright rather than ignored. It has **no `reference`** (that is `businessTransactionReference`) and `StringExpression` has **no `startsWith`**: the prefix operator is spelled **`startWith`**, no "s". Until 5.55.3 this line asked for both wrong names, so the idempotency check (the step standing between a re-run and paying every supplier twice) could not return anything. Use `startWith`, not `contains`: measured on the sandbox 2026-09-07, `contains: 'PR-'` matched 3 rows that do **not** start with that prefix, and a looser match here silently widens what the run treats as already-paid.
16
16
  - **`finalize_bill(resourceId: <id>)`**, used in step 0 fallback: bills must be `status: APPROVED` (not `DRAFT`) before they accept payments.
17
17
 
18
18
  ### CLI tools (jaz-cli)
@@ -30,7 +30,7 @@
30
30
  Generate a run prefix: `PAYRUN-<YYYY-MM-DD>-<seq>`. Before proceeding:
31
31
 
32
32
  ```
33
- search_payments(filter: {businessTransactionReference: {startWith: 'PAYRUN-2025-02-28-'}})
33
+ search_cashflow_transactions(filter: {businessTransactionReference: {startWith: 'PAYRUN-2025-02-28-'}})
34
34
  ```
35
35
 
36
36
  If results: surface "A payment run with prefix `PAYRUN-2025-02-28-*` already executed on this date (`<n>` payments totalling `<amt>`). Confirm intent; re-run will create duplicate payments." Halt unless practitioner confirms.
@@ -117,13 +117,13 @@ After all `pay_bill` calls succeed:
117
117
 
118
118
  ```
119
119
  generate_aged_payables(endDate: '2025-02-28')
120
- search_payments(filter: {businessTransactionReference: {startWith: 'PAYRUN-2025-02-28-'}, valueDate: {eq: '2025-02-28'}})
120
+ search_cashflow_transactions(filter: {businessTransactionReference: {startWith: 'PAYRUN-2025-02-28-'}, valueDate: {eq: '2025-02-28'}})
121
121
  ```
122
122
 
123
123
  Assert:
124
124
  - AP aging total reduced by `sum(payments.transactionAmount)` (in base currency, FX-converted at value date).
125
125
  - Bills fully paid no longer appear in aging; partials carry the payment in `paymentRecords[]`; derive outstanding from it.
126
- - `search_payments` returns N rows where N = bills paid in step 6.
126
+ - `search_cashflow_transactions` returns N rows where N = bills paid in step 6.
127
127
 
128
128
  ```
129
129
  generate_bank_balance_summary(primarySnapshotDate: '2025-02-28')
@@ -141,7 +141,7 @@ Assert: per-account balance reduced by `sum(paymentAmount per accountResourceId)
141
141
  | `pay_bill` | 422 `currency_mismatch` | `paymentAmount` currency ≠ bank account currency. Either pay from the matching-currency bank account, or model as FX (different `paymentAmount` and `transactionAmount`). |
142
142
  | `pay_bill` | 422 `bill_already_paid` | Bill went `PAID` since step 2. Re-run `search_bills` for fresh state; remove from batch. |
143
143
  | `pay_bill` | 422 `lock_date_violated` | `valueDate` is in a locked period. Either lift the lock via `update_account` lock_date OR adjust `valueDate` to the next open period. |
144
- | `pay_bill` | 500 mid-run | Some payments succeeded; others didn't. NOT idempotent; re-running the loop creates duplicates. Use `search_payments` with the run prefix to identify what succeeded; resume from the next unprocessed bill. Record the judgment: `jot(kind: RECOVERY)` naming the resume point and the bills already paid. |
144
+ | `pay_bill` | 500 mid-run | Some payments succeeded; others didn't. NOT idempotent; re-running the loop creates duplicates. Use `search_cashflow_transactions` with the run prefix to identify what succeeded; resume from the next unprocessed bill. Record the judgment: `jot(kind: RECOVERY)` naming the resume point and the bills already paid. |
145
145
  | `generate_aged_payables` | Total mismatch with `search_bills` | Likely `PARTIALLY_PAID` bills excluded from `search_bills` filter. Add `status: {in: ['UNPAID', 'PARTIALLY_PAID']}` and retry. |
146
146
 
147
147
  ---
@@ -8,7 +8,7 @@
8
8
  - **`search_contacts(filter: {supplier: true, name: {eq: <supplier>}})`** (step 1): resolve the supplier resourceId. Use fuzzy match if exact fails.
9
9
  - **`get_contact(resourceId: <supplier id>)`** (step 1 detail): pull the supplier's payment terms, contact info.
10
10
  - **`search_bills(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: [<period-start>, <period-end>]}}, limit: 200)`** (step 2): pull all bills from this supplier in the period. Paginate.
11
- - **`search_payments(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: [<period-start>, <period-end>]}, direction: {eq: 'PAYOUT'}})`** (step 3): pull all payments to this supplier.
11
+ - **`search_cashflow_transactions(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: [<period-start>, <period-end>]}, direction: {eq: 'PAYOUT'}})`** (step 3): pull all payments to this supplier.
12
12
  - **`search_supplier_credit_notes(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: [<period-start>, <period-end>]}})`** (step 4): pull credit notes that may have been applied.
13
13
 
14
14
  > **A filter value must be an OBJECT, not a bare scalar.** This is the trap these lines fell into:
@@ -17,7 +17,7 @@
17
17
  > **is** declared on bills, supplier credit notes and invoices; it is typed `StringExpression`, so it
18
18
  > needs an operator: `{eq: <id>}`. Measured 2026-09-07: the bare form 400s on both, `{eq: …}` returns
19
19
  > 200 on both. The nested `contact: {resourceId: {eq: <id>}}` form used above also works and is what
20
- > `search_payments` requires, because `TransactionsFilter` is the one of the four that genuinely does
20
+ > `search_cashflow_transactions` requires, because `TransactionsFilter` is the one of the four that genuinely does
21
21
  > **not** declare `contactResourceId`; there, and only there, the field really is absent.
22
22
  >
23
23
  > The amount filter differs by endpoint: `totalAmount` is accepted on bills and on
@@ -67,7 +67,7 @@ For an opening-balance recon: also pull the supplier's pre-period balance via `g
67
67
  ## Step 3: Pull payments
68
68
 
69
69
  ```
70
- search_payments(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: ['2025-01-01', '2025-01-31']}, direction: {eq: 'PAYOUT'}})
70
+ search_cashflow_transactions(filter: {contact: {resourceId: {eq: <supplier id>}}, valueDate: {between: ['2025-01-01', '2025-01-31']}, direction: {eq: 'PAYOUT'}})
71
71
  ```
72
72
 
73
73
  Per payment: `{resourceId, reference, valueDate, paymentAmount, transactionAmount, paymentMethod, billResourceId}`. Save.
@@ -98,7 +98,7 @@ Practitioner provides the supplier's statement (PDF, email, paper). Per-line-ite
98
98
  | Bill in Jaz, not on supplier statement | Supplier hasn't issued / lost the invoice | Verify with supplier; if confirmed bogus, `delete_bill` (DRAFT) OR `create_supplier_credit_note` (if ACTIVE). |
99
99
  | Different amounts on same reference | Pricing dispute | Practitioner contacts supplier for clarification. Possible adjustment journal post-resolution. |
100
100
  | Bill paid per Jaz, supplier says unpaid | Bank reconciliation gap | Pull bank statement for the payment date; verify the wire/cheque cleared. If cleared, send remittance proof to supplier. |
101
- | Bill unpaid per Jaz, supplier says paid | Payment recorded against wrong supplier OR bill | Audit `search_payments(filter: {valueDate: {eq: <date>}, totalAmount: {eq: <amount>}})`; identify mis-routing; post correcting journal OR re-issue payment. |
101
+ | Bill unpaid per Jaz, supplier says paid | Payment recorded against wrong supplier OR bill | Audit `search_cashflow_transactions(filter: {valueDate: {eq: <date>}, totalAmount: {eq: <amount>}})`; identify mis-routing; post correcting journal OR re-issue payment. |
102
102
  | Supplier credit note not in Jaz | Missed credit | `create_supplier_credit_note(...)` per supplier statement. Then `apply_credits_to_bill(...)` to the offsetting bill. |
103
103
  | Currency mismatch | FX bills with different rates | Confirm Jaz used the right rate per `jaz-api/SKILL.md` rule 25; the supplier statement may use spot rate, Jaz uses recorded rate. Document the FX gap. |
104
104
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-recipes
3
- version: 7.0.1
3
+ version: 9.0.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
@@ -4,11 +4,11 @@ Jaz accounting guidance for this workspace. Load the installed Jaz skills for de
4
4
 
5
5
  ## Discovery
6
6
 
7
- Jaz exposes **382 tools across 49 namespaces**. Your tool list shows **3, 49, or 382** entries depending on packaging; **never infer capability from its length.**
7
+ Jaz exposes **387 tools across 49 namespaces**. Your tool list shows **3, 49, or 387** entries depending on packaging; **never infer capability from its length.**
8
8
 
9
9
  - **3**: `search_tools(query)` → `describe_tools(names)` → `execute_tool(name, args)`. Empty query returns the namespace map.
10
10
  - **49**: namespace routers; call one with `{ operation, arguments }`. Its description lists its operations.
11
- - **382**: call operations directly by name.
11
+ - **387**: call operations directly by name.
12
12
 
13
13
  `describe_capabilities` returns the capability map on all three. **Call it before telling the user Jaz cannot do something.**
14
14