jaz-clio 4.33.0 → 4.34.1

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
@@ -235,7 +235,7 @@ Every command supports `--json` for structured output — ideal for piping to ot
235
235
 
236
236
  ## MCP Server
237
237
 
238
- Expose all 235 CLI tools to AI coding and coworking agents via the Model Context Protocol (MCP). The server runs locally on your machine — no cloud, no ports. API calls go directly from your machine to the Jaz API.
238
+ Expose all 240 CLI tools to AI coding and coworking agents via the Model Context Protocol (MCP). The server runs locally on your machine — no cloud, no ports. API calls go directly from your machine to the Jaz API.
239
239
 
240
240
  **Claude Code:**
241
241
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-api
3
- version: 4.33.0
3
+ version: 4.34.1
4
4
  description: Complete reference for the Jaz REST API — the accounting platform backend. Use this skill whenever building, modifying, debugging, or extending any code that calls the API — including API clients, integrations, data seeding, test data, or new endpoint work. Contains every field name, response shape, error, gotcha, and edge case discovered through live production testing.
5
5
  license: MIT
6
6
  compatibility: Requires Jaz API key (x-jk-api-key header). Works with Claude Code, Google Antigravity, OpenAI Codex, GitHub Copilot, Cursor, and any agent that reads markdown.
@@ -284,7 +284,7 @@ Bills, invoices, and credit notes share identical mandatory field specs. Adding
284
284
  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.
285
285
 
286
286
  ### Transfer Trial Balance
287
- 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. Each entry: `{ accountResourceId, type: "DEBIT"|"CREDIT", amount }`.
287
+ 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 }`.
288
288
 
289
289
  ### Scheduler Dynamic Strings
290
290
  109. **Scheduler placeholder strings** — All scheduled transactions (invoices, bills, journals, subscriptions) support dynamic strings in any free text field (`reference`, line item `name`, `notes`). Strings are replaced with values relative to the **transaction date**: `{{Day}}` → day name (Monday), `{{Date}}` → full date (09 Mar 2026), `{{Date+X}}` → date + X days, `{{DateRange:X}}` → date range spanning X days (min 1, max 999), `{{Month}}` → month name (March), `{{Month+X}}` → month + X months, `{{MonthRange:X}}` → month range spanning X months, `{{Year}}` → year (2026), `{{Year+X}}` → year + X years. Example: `reference: "INV-{{Month}}-{{Year}}"` → `"INV-March-2026"` for a March transaction.
@@ -295,6 +295,21 @@ Bills, invoices, and credit notes share identical mandatory field specs. Adding
295
295
  ### Quick Fix Tag Field
296
296
  111. **Quick-fix uses `tags` (string array) — e.g., `"tags": ["Q1"]`** — The `attributes` object in quick-fix transaction endpoints accepts `tags` as a string array (e.g., `"tags": ["Q1"]`). `tag` (singular) is silently ignored. This matches the `tags` array format used on create/update for all transaction types. The CLI `--tag` flag auto-wraps to `tags: [name]`.
297
297
 
298
+ ### Sub-Resource Response Shapes
299
+ 112. **Invoice/bill payment & credit sub-resources return raw arrays** — `GET /invoices/:id/payments` and `GET /bills/:id/payments` return `[{paymentRecord}, ...]` — NOT `{data: [...]}`. Same for `GET /invoices/:id/credits` and `GET /bills/:id/credits`. The CLI wraps these into `{data: [...]}` for consistency. `DELETE /invoices/:id/credits/:creditsAppliedResourceId` reverses a credit application.
300
+
301
+ ### Nano-Classifier API
302
+ 113. **Nano-classifier API gotchas** — CREATE uses `classes: string[]` (NOT `classNames` or `[{className}]`). `printable: boolean` is required — defaults to `false` (most classifiers are not printable). GET single is double-wrapped: `{data: {data: [...], totalElements, totalPages}}` — extract the first element from the inner paginated response. GET/LIST response returns classes as `[{className, resourceId}]` (objects), while CREATE accepts plain `string[]`.
303
+
304
+ ### Scheduler Response Asymmetry
305
+ 114. **Scheduler response uses `interval`, not `repeat`** — POST/PUT uses `repeat` field (values: `WEEKLY`, `MONTHLY`, `QUARTERLY`, `YEARLY`). GET response returns `interval` field (same values). PUT accepts the full transaction template (`invoice`, `bill`, or journal entries at top level), not just schedule metadata — same structure as POST.
306
+
307
+ ### Payment Record CRUD
308
+ 115. **Payment record CRUD** — `GET /payments/:resourceId` returns `{data: PaymentRecord}` (wrapped). Payment resourceIds come from invoice/bill GET response → `paymentRecords[].resourceId`. **Cashflow transaction IDs ≠ payment IDs** — don't mix them. `POST /cashflow-transactions/search` returns cashflow IDs, while payment CRUD uses separate payment IDs from the parent document.
309
+
310
+ 116. **PaymentMethod accepts 11 values** — All payment endpoints (invoices, bills, credit note refunds, payment updates) accept: `CASH`, `BANK_TRANSFER`, `CREDIT_CARD`, `CHEQUE`, `E_WALLET`, `WITHHOLDING_TAX_CERTIFICATE`, `CLEARING_SETTLEMENT`, `DEBT_WRITE_OFF`, `INTER_COMPANY`, `OTHER`, `PAYMENT_GATEWAY`. Default is `BANK_TRANSFER`. The OAS previously listed only 7 — the API runtime already accepted all 11.
311
+ 117. **Fixed asset sale accepts PURCHASE type** — `saleBusinessTransactionType` in mark-as-sold accepts `SALE`, `PURCHASE`, or `JOURNAL_MANUAL`. Use `PURCHASE` when the disposal is linked to a purchase-side transaction (e.g., trade-in).
312
+
298
313
  ## Supporting Files
299
314
 
300
315
  For detailed reference, read these files in this skill directory:
@@ -1971,4 +1971,168 @@ Create opening balance entries for an organization. Used during onboarding to tr
1971
1971
 
1972
1972
  ---
1973
1973
 
1974
- *Last updated: 2026-03-11 Added: Transfer Trial Balance endpoint, cash entry path migration (cash-in-journals → cash-in-entries, cash-out-journals → cash-out-entries, cash-transfer-journals → cash-transfers, cashflow-journals → cash-entries), cash entry request body now uses `lines` (canonical) instead of `journalEntries`.*
1974
+ ## 19. Payment Record CRUD
1975
+
1976
+ ### GET /api/v1/payments/{resourceId}
1977
+
1978
+ Get a single payment record by its payment resourceId (NOT cashflow transaction ID).
1979
+
1980
+ ```json
1981
+ // Response:
1982
+ {
1983
+ "data": {
1984
+ "resourceId": "uuid-payment",
1985
+ "reference": "PAY-001",
1986
+ "paymentAmount": 2250.00,
1987
+ "transactionAmount": 2250.00,
1988
+ "valueDate": "2026-03-01",
1989
+ "paymentMethod": "BANK_TRANSFER",
1990
+ "status": "ACTIVE",
1991
+ "type": "SALE_PAYMENT",
1992
+ "accountResourceId": "uuid-bank",
1993
+ "crossCurrency": false,
1994
+ "currencyCode": "SGD",
1995
+ "feeAmount": 0
1996
+ }
1997
+ }
1998
+ ```
1999
+
2000
+ ### PUT /api/v1/payments/{resourceId}
2001
+
2002
+ Update an existing payment record. All fields optional — only included fields are changed.
2003
+
2004
+ ```json
2005
+ // Request:
2006
+ {
2007
+ "paymentAmount": 2500.00,
2008
+ "reference": "PAY-001-REV",
2009
+ "valueDate": "2026-03-02",
2010
+ "paymentMethod": "BANK_TRANSFER",
2011
+ "accountResourceId": "uuid-bank",
2012
+ "currency": { "sourceCurrency": "USD", "exchangeRate": 1.35 },
2013
+ "transactionFee": 5.00,
2014
+ "transactionFeeCollected": true
2015
+ }
2016
+
2017
+ // Response: same shape as GET
2018
+ { "data": { "resourceId": "uuid", ... } }
2019
+ ```
2020
+
2021
+ **Where to find payment resourceIds**: GET an invoice/bill → `paymentRecords[].resourceId`. These are payment IDs. Do NOT use cashflow transaction IDs from `POST /cashflow-transactions/search`.
2022
+
2023
+ ---
2024
+
2025
+ ## 19b. Invoice/Bill Sub-Resource Endpoints
2026
+
2027
+ ### GET /api/v1/invoices/{resourceId}/payments — Raw array response
2028
+
2029
+ ```json
2030
+ // Response (RAW ARRAY — no {data: [...]} wrapper):
2031
+ [
2032
+ {
2033
+ "resourceId": "uuid-payment",
2034
+ "paymentAmount": 2250.00,
2035
+ "transactionAmount": 2250.00,
2036
+ "valueDate": 1709251200000,
2037
+ "paymentMethod": "BANK_TRANSFER",
2038
+ "reference": "PAY-001"
2039
+ }
2040
+ ]
2041
+ ```
2042
+
2043
+ Same for `GET /bills/{resourceId}/payments`, `GET /invoices/{resourceId}/credits`, `GET /bills/{resourceId}/credits`.
2044
+
2045
+ **CRITICAL**: These sub-resource endpoints return raw arrays, NOT `{data: [...]}`. The CLI wraps them into `{data: [...]}` for consistency.
2046
+
2047
+ ---
2048
+
2049
+ ## 20. Nano-Classifier CRUD
2050
+
2051
+ ### POST /api/v1/nano-classifiers — Create
2052
+
2053
+ ```json
2054
+ // Request:
2055
+ {
2056
+ "type": "Region",
2057
+ "classes": ["North", "South", "East", "West"],
2058
+ "printable": false
2059
+ }
2060
+
2061
+ // Response:
2062
+ { "data": { "resourceId": "uuid" } }
2063
+ ```
2064
+
2065
+ **CRITICAL**: `classes` is a `string[]` (NOT `classNames`, NOT `[{className}]`). `printable` is required — defaults to `false`.
2066
+
2067
+ ### GET /api/v1/nano-classifiers/{resourceId} — Double-wrapped response
2068
+
2069
+ ```json
2070
+ // Response (DOUBLE-WRAPPED):
2071
+ {
2072
+ "data": {
2073
+ "data": [
2074
+ {
2075
+ "resourceId": "uuid",
2076
+ "type": "Region",
2077
+ "printable": false,
2078
+ "classes": [
2079
+ { "className": "North", "resourceId": "uuid-class-1" },
2080
+ { "className": "South", "resourceId": "uuid-class-2" }
2081
+ ]
2082
+ }
2083
+ ],
2084
+ "totalElements": 1,
2085
+ "totalPages": 1
2086
+ }
2087
+ }
2088
+ ```
2089
+
2090
+ **CRITICAL**: GET single is double-wrapped — `{data: {data: [...], totalElements, totalPages}}`. Extract `res.data.data[0]` to get the classifier. Classes in response are objects (`{className, resourceId}`), not strings.
2091
+
2092
+ ---
2093
+
2094
+ ## 21. Scheduler GET/PUT/DELETE
2095
+
2096
+ ### GET /api/v1/scheduled/invoices/{resourceId}
2097
+
2098
+ ```json
2099
+ // Response — uses `interval`, NOT `repeat`:
2100
+ {
2101
+ "data": {
2102
+ "resourceId": "uuid",
2103
+ "status": "ACTIVE",
2104
+ "interval": "MONTHLY",
2105
+ "startDate": "2026-03-01",
2106
+ "endDate": "2026-12-01",
2107
+ "nextScheduleDate": "2026-04-01",
2108
+ "businessTransactionType": "SALE"
2109
+ }
2110
+ }
2111
+ ```
2112
+
2113
+ ### PUT /api/v1/scheduled/invoices/{resourceId}
2114
+
2115
+ Accepts scheduling fields AND the full invoice template (same structure as POST):
2116
+
2117
+ ```json
2118
+ // Request:
2119
+ {
2120
+ "repeat": "QUARTERLY",
2121
+ "startDate": "2026-03-01",
2122
+ "endDate": "2027-03-01",
2123
+ "invoice": {
2124
+ "contactResourceId": "uuid",
2125
+ "saveAsDraft": false,
2126
+ "reference": "SCH-INV-001-UPDATED",
2127
+ "valueDate": "2026-03-01",
2128
+ "dueDate": "2026-03-31",
2129
+ "lineItems": [{ "name": "Quarterly retainer", "unitPrice": 9000, "quantity": 1, "accountResourceId": "uuid" }]
2130
+ }
2131
+ }
2132
+ ```
2133
+
2134
+ Same pattern for `PUT /scheduled/bills/:id` (uses `bill` wrapper) and `PUT /scheduled/journals/:id` (flat structure with `schedulerEntries`, same as POST).
2135
+
2136
+ ---
2137
+
2138
+ *Last updated: 2026-03-13 — Added: Payment record CRUD (section 19), invoice/bill sub-resource raw array responses (19b), nano-classifier CRUD with double-wrapped GET (20), scheduler GET/PUT/DELETE with `interval` vs `repeat` (21). Previous: Transfer Trial Balance, cash entry path migration.*
@@ -833,4 +833,28 @@ Journals support a top-level `currency` object to create entries in a foreign cu
833
833
 
834
834
  ---
835
835
 
836
- *Last updated: 2026-03-11 — Cash entry path migration (cash-in-journals → cash-in-entries, etc.), cash entry `lines` canonical. Previous: Quick Fix errors.*
836
+ ### Nano-Classifier Errors
837
+
838
+ **"classes must be an array"** or **400 Invalid request body** — Sending `classNames` or `[{className: "..."}]` instead of `classes: ["..."]`. CREATE expects `classes` as a flat `string[]`.
839
+
840
+ **`printable` field missing** — `printable: boolean` is required on CREATE. Omitting it defaults to `false` on the API side, but explicitly sending `false` or `true` is recommended.
841
+
842
+ **GET returns `undefined` / empty** — GET single nano-classifier is double-wrapped: `{data: {data: [...], totalElements, totalPages}}`. If you read `res.data` directly expecting a single classifier, you get the inner paginated object. Extract `res.data.data[0]`.
843
+
844
+ ---
845
+
846
+ ### Payment Record Errors
847
+
848
+ **404 on payment GET** — Using a cashflow transaction ID (`POST /cashflow-transactions/search` returns these) instead of a payment ID. Payment resourceIds come from the parent document: `GET /invoices/:id` → `paymentRecords[].resourceId`.
849
+
850
+ **Cashflow transaction ID ≠ payment ID** — These are different entities. Cashflow transactions are a ledger view; payment records are the actual payment objects attached to invoices/bills.
851
+
852
+ ---
853
+
854
+ ### Sub-Resource Response Errors
855
+
856
+ **`Cannot read property 'data'` / TypeError** — Invoice/bill sub-resource endpoints (`GET /invoices/:id/payments`, `GET /invoices/:id/credits`, etc.) return raw arrays `[{...}]`, NOT `{data: [...]}`. Trying to access `.data` on the response fails. Wrap the raw array yourself.
857
+
858
+ ---
859
+
860
+ *Last updated: 2026-03-13 — Added: Nano-classifier errors (classes field, double-wrapped GET), payment record errors (cashflow vs payment IDs), sub-resource raw array errors. Previous: Cash entry path migration, Quick Fix errors.*
@@ -283,7 +283,7 @@ DELETE → expects "A" (parentEntityResourceId, via /cash-entries/:id)
283
283
  | `amount` | `paymentAmount` | **Bank account currency** — actual cash moved. NOT `amount`. |
284
284
  | (none) | `transactionAmount` | **Transaction document currency (invoice/bill/credit note)** — amount applied to balance. Equal to `paymentAmount` for same-currency. For FX: differs (e.g., USD invoice paid from SGD bank at 1.35 → `paymentAmount: 1350`, `transactionAmount: 1000`). |
285
285
  | `bankAccountResourceId` | `accountResourceId` | Canonical is `accountResourceId`. **Alias `bankAccountResourceId` now accepted on POST.** |
286
- | (none) | `paymentMethod` | Required: `"BANK_TRANSFER"` |
286
+ | (none) | `paymentMethod` | Default: `"BANK_TRANSFER"`. Full enum: `CASH`, `BANK_TRANSFER`, `CREDIT_CARD`, `CHEQUE`, `E_WALLET`, `WITHHOLDING_TAX_CERTIFICATE`, `CLEARING_SETTLEMENT`, `DEBT_WRITE_OFF`, `INTER_COMPANY`, `OTHER`, `PAYMENT_GATEWAY` |
287
287
  | (none) | `reference` | Required: payment reference string |
288
288
  | `date` / `paymentDate` | `valueDate` | NOT `paymentDate`, NOT `date`. Must be `YYYY-MM-DD` |
289
289
  | (flat object) | `{ payments: [...] }` | Must be wrapped in array |
@@ -578,4 +578,41 @@ Battle-tested patterns from production Jaz API clients:
578
578
 
579
579
  ---
580
580
 
581
- *Last updated: 2026-03-11 — Cash entry path migration (cash-in-journals → cash-in-entries, cash-out-journals → cash-out-entries, cash-transfer-journals → cash-transfers, cashflow-journals → cash-entries). `lines` is now canonical for cash entry request bodies (`journalEntries` accepted as alias). Previous: Quick Fix field mapping.*
581
+ ### Payment Record Fields
582
+
583
+ | What You'd Guess | Actual API Field | Notes |
584
+ |------------------|-------------------|-------|
585
+ | `amount` | `paymentAmount` | Bank account currency amount (actual cash moved) |
586
+ | `appliedAmount` | `transactionAmount` | Document currency amount (applied to invoice/bill balance) |
587
+ | `paymentId` | `resourceId` | From parent document: `GET /invoices/:id` → `paymentRecords[].resourceId` |
588
+ | `cashflowId` | ≠ `resourceId` | Cashflow transaction IDs are NOT payment IDs — different entities |
589
+ | `bankAccountId` | `accountResourceId` | Bank account for the payment |
590
+ | `fee` | `feeAmount` (response) / `transactionFee` (update) | Response field is `feeAmount`, update field is `transactionFee` |
591
+ | `isCrossCurrency` | `crossCurrency` | Boolean, no `is` prefix |
592
+ | `currency` (string) | `currencyCode` (response) / `currency` (update: `{ sourceCurrency, exchangeRate }`) | Response is flat string, update is object |
593
+
594
+ ---
595
+
596
+ ### Scheduler Fields (Request vs Response Asymmetry)
597
+
598
+ | What You'd Guess | Actual API Field | Notes |
599
+ |------------------|-------------------|-------|
600
+ | `frequency` | `repeat` (request) / `interval` (response) | POST/PUT uses `repeat`, GET returns `interval` — same values |
601
+ | `nextDate` | `nextScheduleDate` | Next scheduled execution date |
602
+ | `type` | `businessTransactionType` | `SALE`, `PURCHASE`, etc. |
603
+ | `schedule` (update) | full template | PUT accepts the full transaction template (`invoice`/`bill`/flat journal), not just schedule metadata |
604
+
605
+ ---
606
+
607
+ ### Nano-Classifier Fields
608
+
609
+ | What You'd Guess | Actual API Field | Notes |
610
+ |------------------|-------------------|-------|
611
+ | `classNames` | `classes` | CREATE: `string[]`. GET response: `[{className, resourceId}]` (objects) |
612
+ | `name` | `type` | The classifier name/label is `type`, not `name` |
613
+ | `isPrintable` | `printable` | Boolean, no `is` prefix. Default `false` — most classifiers are not printable |
614
+ | `categories` | `classes` | The "categories" or "options" are called `classes` |
615
+
616
+ ---
617
+
618
+ *Last updated: 2026-03-13 — Added: Payment record fields (paymentAmount vs transactionAmount, feeAmount vs transactionFee), scheduler field asymmetry (repeat vs interval), nano-classifier fields (classes, type, printable). Previous: Cash entry path migration, Quick Fix field mapping.*
@@ -42,9 +42,9 @@
42
42
  | DELETE | `/invoices/:resourceId` | Delete invoice |
43
43
  | GET | `/invoices/:resourceId/download` | Download PDF |
44
44
  | POST | `/invoices/:resourceId/payments` | Record payment(s) |
45
- | GET | `/invoices/:resourceId/payments` | List recorded payments |
45
+ | GET | `/invoices/:resourceId/payments` | List recorded payments — **raw array response** |
46
46
  | POST | `/invoices/:resourceId/credits` | Apply credit note(s) |
47
- | GET | `/invoices/:resourceId/credits` | List applied credits |
47
+ | GET | `/invoices/:resourceId/credits` | List applied credits — **raw array response** |
48
48
  | DELETE | `/invoices/:resourceId/credits/:creditsAppliedResourceId` | Reverse credit |
49
49
  | GET | `/invoices/:resourceId/attachments` | List attachments |
50
50
  | POST | `/invoices/:resourceId/attachments` | Upload attachment |
@@ -138,10 +138,12 @@
138
138
  ### Payments (Generic)
139
139
  | Method | Path | Description |
140
140
  |--------|------|-------------|
141
- | GET | `/payments/:resourceId` | Get payment record |
142
- | PUT | `/payments/:resourceId` | Update payment |
141
+ | GET | `/payments/:resourceId` | Get payment record — returns `{data: PaymentRecord}` |
142
+ | PUT | `/payments/:resourceId` | Update payment — returns `{data: PaymentRecord}` |
143
143
  | DELETE | `/payments/:resourceId` | Delete/void payment |
144
144
 
145
+ **Note**: Payment resourceIds come from parent documents (`GET /invoices/:id` → `paymentRecords[].resourceId`). Cashflow transaction IDs from `POST /cashflow-transactions/search` are NOT the same.
146
+
145
147
  ### Bank Records
146
148
  | Method | Path | Description |
147
149
  |--------|------|-------------|
@@ -320,6 +322,8 @@
320
322
  |--------|------|-------------|
321
323
  | POST | `/scheduled-transaction/search` | Search all scheduled items |
322
324
 
325
+ **Response shape note**: Scheduler GET returns `interval` field (not `repeat`). POST/PUT uses `repeat`. PUT accepts the full transaction template (not just schedule metadata).
326
+
323
327
  ---
324
328
 
325
329
  ## Reports & Exports
@@ -455,13 +459,15 @@
455
459
  ### Nano Classifiers (Tracking Categories)
456
460
  | Method | Path | Description |
457
461
  |--------|------|-------------|
458
- | POST | `/nano-classifiers` | Create classifier |
462
+ | POST | `/nano-classifiers` | Create `classes: string[]`, `printable: boolean` (default `false`) |
459
463
  | GET | `/nano-classifiers` | List |
460
- | GET | `/nano-classifiers/:resourceId` | Get by ID |
464
+ | GET | `/nano-classifiers/:resourceId` | Get by ID — **double-wrapped**: `{data: {data: [...], totalElements, totalPages}}` |
461
465
  | PUT | `/nano-classifiers/:resourceId` | Update |
462
466
  | DELETE | `/nano-classifiers/:resourceId` | Delete |
463
467
  | POST | `/nano-classifiers/search` | Search |
464
468
 
469
+ **Response shape note**: GET single is double-wrapped. GET/LIST response returns classes as `[{className, resourceId}]` objects, while CREATE accepts plain `string[]`.
470
+
465
471
  ### Organization Report Templates
466
472
  | Method | Path | Description |
467
473
  |--------|------|-------------|
@@ -693,4 +699,4 @@ Response: `{ updated: [...], failed: [{ resourceId, error, errorCode }] }`. HTTP
693
699
 
694
700
  ---
695
701
 
696
- *Last updated: 2026-03-11Cash entry path migration + Transfer Trial Balance endpoint. Previous: 20 Quick Fix endpoints (bulk update).*
702
+ *Last updated: 2026-03-13Added response shape annotations: payment record wrapped response, nano-classifier double-wrapped GET and classes field, scheduler interval vs repeat asymmetry, invoice/bill sub-resource raw array responses. Previous: Cash entry path migration, Transfer Trial Balance, Quick Fix.*
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-conversion
3
- version: 4.33.0
3
+ version: 4.34.1
4
4
  description: Accounting data conversion skill — migrates customer data from Xero, QuickBooks, Sage, MYOB, and Excel exports to Jaz. Covers config, quick, and full conversion workflows, Excel parsing, CoA/contact/tax/items mapping, clearing accounts, TTB, and TB verification.
5
5
  ---
6
6
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-jobs
3
- version: 4.33.0
3
+ version: 4.34.1
4
4
  description: 12 accounting jobs for SMB bookkeepers and accountants — month-end, quarter-end, and year-end close playbooks plus 9 ad-hoc operational jobs (bank recon, document collection, GST/VAT filing, payment runs, credit control, supplier recon, audit prep, fixed asset review, statutory filing). Jobs can have paired tools as nested subcommands (e.g., `clio jobs bank-recon match`, `clio jobs document-collection ingest`, `clio jobs statutory-filing sg-cs`). Paired with an interactive CLI blueprint generator (clio jobs).
5
5
  license: MIT
6
6
  compatibility: Works with Claude Code, Claude Cowork, Claude.ai, and any agent that reads markdown. For API payloads, load the jaz-api skill. For individual transaction patterns, load the jaz-recipes skill.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-recipes
3
- version: 4.33.0
3
+ version: 4.34.1
4
4
  description: 16 IFRS-compliant recipes for complex multi-step accounting in Jaz — prepaid amortization, deferred revenue, loan schedules, IFRS 16 leases, hire purchase, fixed deposits, asset disposal, FX revaluation, ECL provisioning, IAS 37 provisions, dividends, intercompany, and capital WIP. Each recipe includes journal entries, capsule structure, and verification steps. Paired with 13 financial calculators that produce execution-ready blueprints with workings.
5
5
  license: MIT
6
6
  compatibility: Works with Claude Code, Claude Cowork, Claude.ai, and any agent that reads markdown. For API payloads, load the jaz-api skill alongside this one.
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { listContactGroups, getContactGroup, searchContactGroups, createContactGroup, } from '../core/api/contact-groups.js';
2
+ import { listContactGroups, getContactGroup, searchContactGroups, createContactGroup, updateContactGroup, deleteContactGroup, } from '../core/api/contact-groups.js';
3
3
  import { apiAction } from './api-action.js';
4
4
  import { outputList } from './output.js';
5
5
  import { parsePositiveInt, parseNonNegativeInt, requireFields } from './parsers.js';
@@ -74,4 +74,36 @@ export function registerContactGroupsCommand(program) {
74
74
  console.log(chalk.green(`Contact group "${opts.name}" created.`));
75
75
  console.log(chalk.bold('ID:'), res.data.resourceId);
76
76
  }));
77
+ cmd
78
+ .command('update <resourceId>')
79
+ .description('Update a contact group')
80
+ .option('--name <name>', 'New group name')
81
+ .option('--api-key <key>', 'API key')
82
+ .option('--format <type>', 'Output format: table, json, csv, yaml')
83
+ .option('--json', 'JSON output')
84
+ .action((resourceId, opts) => apiAction(async (client) => {
85
+ const data = {};
86
+ if (opts.name)
87
+ data.name = opts.name;
88
+ const res = await updateContactGroup(client, resourceId, data);
89
+ if (opts.json) {
90
+ console.log(JSON.stringify(res.data, null, 2));
91
+ return;
92
+ }
93
+ console.log(chalk.green(`Contact group updated.`));
94
+ console.log(chalk.bold('ID:'), res.data.resourceId);
95
+ })(opts));
96
+ cmd
97
+ .command('delete <resourceId>')
98
+ .description('Delete a contact group')
99
+ .option('--api-key <key>', 'API key')
100
+ .option('--json', 'JSON output')
101
+ .action((resourceId, opts) => apiAction(async (client) => {
102
+ await deleteContactGroup(client, resourceId);
103
+ if (opts.json) {
104
+ console.log(JSON.stringify({ deleted: true, resourceId }));
105
+ return;
106
+ }
107
+ console.log(chalk.green(`Contact group ${resourceId} deleted.`));
108
+ })(opts));
77
109
  }
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
- import { listInventoryItems, getInventoryBalance } from '../core/api/inventory.js';
2
+ import { listInventoryItems, createInventoryItem, getInventoryBalance } from '../core/api/inventory.js';
3
3
  import { apiAction } from './api-action.js';
4
- import { parsePositiveInt, parseNonNegativeInt } from './parsers.js';
4
+ import { parsePositiveInt, parseNonNegativeInt, readBodyInput, requireFields } from './parsers.js';
5
5
  import { paginatedFetch } from './pagination.js';
6
6
  import { outputList } from './output.js';
7
7
  import { formatId } from './format-helpers.js';
@@ -45,4 +45,38 @@ export function registerInventoryCommand(program) {
45
45
  console.log(chalk.bold('Qty:'), `${b.baseQty} ${b.baseUnit}`);
46
46
  console.log(chalk.bold('Avg Cost:'), b.latestAverageCostAmount);
47
47
  })(opts));
48
+ cmd
49
+ .command('create')
50
+ .description('Create an inventory-tracked item (use --input for full JSON body)')
51
+ .option('--item-code <code>', 'Item code (SKU)')
52
+ .option('--name <name>', 'Item name')
53
+ .option('--unit <unit>', 'Unit of measure')
54
+ .option('--costing-method <method>', 'FIXED or WAC')
55
+ .option('--input <file>', 'Read full request body from JSON file (or pipe via stdin)')
56
+ .option('--api-key <key>', 'API key')
57
+ .option('--format <type>', 'Output format: table, json, csv, yaml')
58
+ .option('--json', 'JSON output')
59
+ .action(apiAction(async (client, opts) => {
60
+ const body = readBodyInput(opts);
61
+ if (!body) {
62
+ requireFields(opts, [
63
+ { flag: '--item-code', key: 'itemCode' },
64
+ { flag: '--name', key: 'name' },
65
+ ]);
66
+ }
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- user-provided JSON, API validates
68
+ const data = body ?? {
69
+ itemCode: opts.itemCode,
70
+ name: opts.name,
71
+ unit: opts.unit,
72
+ costingMethod: opts.costingMethod,
73
+ };
74
+ const res = await createInventoryItem(client, data);
75
+ if (opts.json) {
76
+ console.log(JSON.stringify(res.data, null, 2));
77
+ return;
78
+ }
79
+ console.log(chalk.green(`Inventory item created.`));
80
+ console.log(chalk.bold('ID:'), res.data.resourceId);
81
+ }));
48
82
  }
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { listTags, getTag, searchTags, createTag, deleteTag, } from '../core/api/tags.js';
2
+ import { listTags, getTag, searchTags, createTag, updateTag, deleteTag, } from '../core/api/tags.js';
3
3
  import { findExistingTag } from '../core/api/guards.js';
4
4
  import { apiAction } from './api-action.js';
5
5
  import { outputList } from './output.js';
@@ -104,6 +104,25 @@ export function registerTagsCommand(program) {
104
104
  console.log(chalk.bold('ID:'), res.data.resourceId);
105
105
  }
106
106
  }));
107
+ // ── clio tags update ─────────────────────────────────────────
108
+ tags
109
+ .command('update <resourceId>')
110
+ .description('Rename a tag')
111
+ .option('--name <name>', 'New tag name')
112
+ .option('--api-key <key>', 'API key (overrides stored/env)')
113
+ .option('--format <type>', 'Output format: table, json, csv, yaml')
114
+ .option('--json', 'Output as JSON')
115
+ .action((resourceId, opts) => apiAction(async (client) => {
116
+ requireFields(opts, [{ flag: '--name', key: 'name' }]);
117
+ const res = await updateTag(client, resourceId, { name: opts.name });
118
+ if (opts.json) {
119
+ console.log(JSON.stringify(res.data, null, 2));
120
+ }
121
+ else {
122
+ console.log(chalk.green(`Tag renamed to "${opts.name}".`));
123
+ console.log(chalk.bold('ID:'), res.data.resourceId);
124
+ }
125
+ })(opts));
107
126
  // ── clio tags delete ──────────────────────────────────────────
108
127
  tags
109
128
  .command('delete <resourceId>')
@@ -10,3 +10,9 @@ export async function searchContactGroups(client, params) {
10
10
  export async function createContactGroup(client, data) {
11
11
  return client.post('/api/v1/contact-groups', data);
12
12
  }
13
+ export async function updateContactGroup(client, resourceId, data) {
14
+ return client.put(`/api/v1/contact-groups/${resourceId}`, data);
15
+ }
16
+ export async function deleteContactGroup(client, resourceId) {
17
+ await client.delete(`/api/v1/contact-groups/${resourceId}`);
18
+ }
@@ -1,6 +1,12 @@
1
1
  export async function listInventoryItems(client, params) {
2
2
  return client.list('/api/v1/inventory-items', params);
3
3
  }
4
+ export async function searchInventoryItems(client, params) {
5
+ return client.search('/api/v1/inventory-items/search', params);
6
+ }
7
+ export async function createInventoryItem(client, data) {
8
+ return client.post('/api/v1/inventory-items', data);
9
+ }
4
10
  export async function getInventoryBalance(client, itemResourceId) {
5
11
  return client.get(`/api/v1/inventory-item-balance/${itemResourceId}`);
6
12
  }
@@ -10,6 +10,9 @@ export async function searchTags(client, params) {
10
10
  export async function createTag(client, data) {
11
11
  return client.post('/api/v1/tags', data);
12
12
  }
13
+ export async function updateTag(client, resourceId, data) {
14
+ return client.put(`/api/v1/tags/${resourceId}`, data);
15
+ }
13
16
  export async function deleteTag(client, resourceId) {
14
17
  await client.delete(`/api/v1/tags/${resourceId}`);
15
18
  }
@@ -8,7 +8,7 @@ import { listJournals, searchJournals, getJournal, createJournal, deleteJournal,
8
8
  import { generateTrialBalance, generateBalanceSheet, generateProfitAndLoss, generateCashflow, generateArSummary, generateApSummary, generateCashBalance, generateGeneralLedger, generateVatLedger, generateEquityMovement, generateBankBalanceSummary, generateBankReconSummary, generateBankReconDetails, generateFaSummary, generateFaReconSummary, generateArReport, } from '../api/reports.js';
9
9
  import { listBankAccounts, addBankRecords, importBankStatement } from '../api/bank.js';
10
10
  import { listItems, searchItems, getItem, createItem, updateItem, deleteItem, } from '../api/items.js';
11
- import { listTags, searchTags, createTag, deleteTag, } from '../api/tags.js';
11
+ import { listTags, getTag, searchTags, createTag, updateTag, deleteTag, } from '../api/tags.js';
12
12
  import { listCapsuleTypes, listCapsules, searchCapsules, getCapsule, createCapsule, updateCapsule, deleteCapsule, } from '../api/capsules.js';
13
13
  import { listCustomerCreditNotes, searchCustomerCreditNotes, getCustomerCreditNote, createCustomerCreditNote, deleteCustomerCreditNote, updateCustomerCreditNote, finalizeCustomerCreditNote, createCustomerCreditNoteRefund, listCustomerCreditNoteRefunds, downloadCustomerCreditNotePdf, } from '../api/customer-cn.js';
14
14
  import { listSupplierCreditNotes, searchSupplierCreditNotes, getSupplierCreditNote, createSupplierCreditNote, deleteSupplierCreditNote, updateSupplierCreditNote, finalizeSupplierCreditNote, createSupplierCreditNoteRefund, listSupplierCreditNoteRefunds, } from '../api/supplier-cn.js';
@@ -36,8 +36,8 @@ import { handlePagination, buildCnFilter, buildBankRecordFilter, buildInvoiceBil
36
36
  import { listBankRules, getBankRule, searchBankRules, createBankRule, updateBankRule, deleteBankRule, } from '../api/bank-rules.js';
37
37
  import { listFixedAssets, getFixedAsset, searchFixedAssets, createFixedAsset, updateFixedAsset, deleteFixedAsset, discardFixedAsset, markFixedAssetSold, transferFixedAsset, undoFixedAssetDisposal, } from '../api/fixed-assets.js';
38
38
  import { listSubscriptions, getSubscription, createSubscription, updateSubscription, deleteSubscription, cancelSubscription, searchScheduledTransactions, } from '../api/subscriptions.js';
39
- import { listContactGroups, getContactGroup, searchContactGroups, createContactGroup, } from '../api/contact-groups.js';
40
- import { listInventoryItems, getInventoryBalance } from '../api/inventory.js';
39
+ import { listContactGroups, getContactGroup, searchContactGroups, createContactGroup, updateContactGroup, deleteContactGroup, } from '../api/contact-groups.js';
40
+ import { listInventoryItems, createInventoryItem, getInventoryBalance } from '../api/inventory.js';
41
41
  import { universalSearch } from '../api/search.js';
42
42
  import { listCustomFields, getCustomField, searchCustomFields, createCustomField, updateCustomField, deleteCustomField } from '../api/custom-fields.js';
43
43
  import { quickFix, quickFixLineItems, QUICK_FIX_ENTITIES } from '../api/quick-fix.js';
@@ -136,6 +136,15 @@ const LINE_ITEM_PARAM = {
136
136
  },
137
137
  description: 'Line items — include accountResourceId on each line when finalizing (saveAsDraft: false)',
138
138
  };
139
+ const PAYMENT_METHOD_PARAM = {
140
+ type: 'string',
141
+ enum: [
142
+ 'CASH', 'BANK_TRANSFER', 'CREDIT_CARD', 'CHEQUE', 'E_WALLET',
143
+ 'WITHHOLDING_TAX_CERTIFICATE', 'CLEARING_SETTLEMENT',
144
+ 'DEBT_WRITE_OFF', 'INTER_COMPANY', 'OTHER', 'PAYMENT_GATEWAY',
145
+ ],
146
+ description: 'Payment method (default BANK_TRANSFER)',
147
+ };
139
148
  // ── Helper to extract common input fields ────────────────────────
140
149
  function extractPaginationInput(input) {
141
150
  const limit = input.limit;
@@ -604,11 +613,7 @@ export const TOOL_DEFINITIONS = [
604
613
  accountResourceId: { type: 'string', description: 'Bank/cash account resourceId for payment' },
605
614
  valueDate: { type: 'string', description: 'Payment date (YYYY-MM-DD)' },
606
615
  reference: { type: 'string', description: 'Payment reference' },
607
- paymentMethod: {
608
- type: 'string',
609
- enum: ['CASH', 'BANK_TRANSFER', 'CREDIT_CARD', 'CHEQUE', 'E_WALLET', 'OTHER'],
610
- description: 'Payment method (default BANK_TRANSFER)',
611
- },
616
+ paymentMethod: PAYMENT_METHOD_PARAM,
612
617
  customFields: CUSTOM_FIELDS_PARAM,
613
618
  },
614
619
  required: ['resourceId', 'paymentAmount', 'accountResourceId', 'valueDate'],
@@ -806,7 +811,7 @@ Steps: 1) search_customer_credit_notes with status UNAPPLIED for the same contac
806
811
  accountResourceId: { type: 'string' },
807
812
  valueDate: { type: 'string' },
808
813
  reference: { type: 'string' },
809
- paymentMethod: { type: 'string' },
814
+ paymentMethod: PAYMENT_METHOD_PARAM,
810
815
  customFields: CUSTOM_FIELDS_PARAM,
811
816
  },
812
817
  required: ['resourceId', 'paymentAmount', 'accountResourceId', 'valueDate'],
@@ -1230,6 +1235,19 @@ Steps: 1) search_customer_credit_notes with status UNAPPLIED for the same contac
1230
1235
  return createTag(ctx.client, { name });
1231
1236
  },
1232
1237
  },
1238
+ getTool('get_tag', 'Get a tag by resourceId.', 'tags', (client, id) => getTag(client, id)),
1239
+ {
1240
+ name: 'update_tag',
1241
+ description: 'Rename a tag.',
1242
+ params: {
1243
+ resourceId: { type: 'string', description: 'Tag resourceId' },
1244
+ name: { type: 'string', description: 'New tag name' },
1245
+ },
1246
+ required: ['resourceId', 'name'],
1247
+ group: 'tags',
1248
+ readOnly: false,
1249
+ execute: async (ctx, input) => updateTag(ctx.client, input.resourceId, { name: input.name }),
1250
+ },
1233
1251
  {
1234
1252
  name: 'delete_tag',
1235
1253
  description: 'Delete a tag.',
@@ -1470,11 +1488,7 @@ Steps: 1) search_customer_credit_notes with status UNAPPLIED for the same contac
1470
1488
  accountResourceId: { type: 'string', description: 'Bank/cash account resourceId' },
1471
1489
  valueDate: { type: 'string', description: 'Payment date (YYYY-MM-DD)' },
1472
1490
  reference: { type: 'string', description: 'Payment reference' },
1473
- paymentMethod: {
1474
- type: 'string',
1475
- enum: ['CASH', 'BANK_TRANSFER', 'CREDIT_CARD', 'CHEQUE', 'E_WALLET', 'OTHER'],
1476
- description: 'Payment method (default BANK_TRANSFER)',
1477
- },
1491
+ paymentMethod: PAYMENT_METHOD_PARAM,
1478
1492
  },
1479
1493
  required: ['creditNoteId', 'paymentAmount', 'accountResourceId', 'valueDate'],
1480
1494
  group: 'customer_credit_notes',
@@ -1645,11 +1659,7 @@ Steps: 1) search_customer_credit_notes with status UNAPPLIED for the same contac
1645
1659
  accountResourceId: { type: 'string', description: 'Bank/cash account resourceId' },
1646
1660
  valueDate: { type: 'string', description: 'Payment date (YYYY-MM-DD)' },
1647
1661
  reference: { type: 'string', description: 'Payment reference' },
1648
- paymentMethod: {
1649
- type: 'string',
1650
- enum: ['CASH', 'BANK_TRANSFER', 'CREDIT_CARD', 'CHEQUE', 'E_WALLET', 'OTHER'],
1651
- description: 'Payment method (default BANK_TRANSFER)',
1652
- },
1662
+ paymentMethod: PAYMENT_METHOD_PARAM,
1653
1663
  },
1654
1664
  required: ['creditNoteId', 'paymentAmount', 'accountResourceId', 'valueDate'],
1655
1665
  group: 'supplier_credit_notes',
@@ -3315,7 +3325,7 @@ Dynamic strings for name/reference: {{bankReference}} (e.g., INV-03/01/2025-01),
3315
3325
  resourceId: { type: 'string', description: 'Fixed asset resourceId' },
3316
3326
  depreciationEndDate: { type: 'string', description: 'Final depreciation date (YYYY-MM-DD)' },
3317
3327
  assetDisposalGainLossAccountResourceId: { type: 'string', description: 'Gain/loss account resourceId' },
3318
- saleBusinessTransactionType: { type: 'string', enum: ['SALE', 'JOURNAL_MANUAL'], description: 'Sale transaction type' },
3328
+ saleBusinessTransactionType: { type: 'string', enum: ['SALE', 'PURCHASE', 'JOURNAL_MANUAL'], description: 'Sale transaction type' },
3319
3329
  saleItemResourceId: { type: 'string', description: 'Sale item resourceId' },
3320
3330
  },
3321
3331
  required: ['resourceId', 'depreciationEndDate', 'assetDisposalGainLossAccountResourceId', 'saleBusinessTransactionType', 'saleItemResourceId'],
@@ -3627,6 +3637,23 @@ Dynamic strings for reference/line item name/notes: {{Day}}, {{Date}}, {{Date+X}
3627
3637
  contactResourceIds: input.contactResourceIds,
3628
3638
  }),
3629
3639
  },
3640
+ {
3641
+ name: 'update_contact_group',
3642
+ description: 'Update a contact group name or members. NOTE: Update endpoint has a known 500 bug on some orgs — retry or recreate if it fails.',
3643
+ params: {
3644
+ resourceId: { type: 'string', description: 'Contact group resourceId' },
3645
+ name: { type: 'string', description: 'New group name' },
3646
+ contactResourceIds: { type: 'array', items: { type: 'string' }, description: 'Contact IDs to set as group members (replaces existing)' },
3647
+ },
3648
+ required: ['resourceId'],
3649
+ group: 'contact_groups',
3650
+ readOnly: false,
3651
+ execute: async (ctx, input) => updateContactGroup(ctx.client, input.resourceId, {
3652
+ name: input.name,
3653
+ contactResourceIds: input.contactResourceIds,
3654
+ }),
3655
+ },
3656
+ deleteTool('delete_contact_group', 'Delete a contact group. Does not delete the contacts themselves.', 'contact_groups', (client, id) => deleteContactGroup(client, id)),
3630
3657
  // ══════════════════════════════════════════════════════════════
3631
3658
  // ── Custom Fields ──────────────────────────────────────────
3632
3659
  // ══════════════════════════════════════════════════════════════
@@ -3789,6 +3816,45 @@ Dynamic strings for reference/line item name/notes: {{Day}}, {{Date}}, {{Date+X}
3789
3816
  readOnly: true,
3790
3817
  execute: async (ctx, input) => getInventoryBalance(ctx.client, input.itemResourceId),
3791
3818
  },
3819
+ {
3820
+ name: 'create_inventory_item',
3821
+ description: 'Create a new inventory-tracked item. Requires itemCode, name, costingMethod (FIXED or WAC), cogsResourceId, and account links. Use --input for full JSON body.',
3822
+ params: {
3823
+ itemCode: { type: 'string', description: 'Unique item code (SKU)' },
3824
+ name: { type: 'string', description: 'Item name' },
3825
+ unit: { type: 'string', description: 'Unit of measure (e.g., "pcs", "kg")' },
3826
+ costingMethod: { type: 'string', description: 'Costing method: FIXED or WAC' },
3827
+ cogsResourceId: { type: 'string', description: 'COGS account resourceId (required)' },
3828
+ purchaseAccountResourceId: { type: 'string', description: 'Purchase account resourceId (required if cogsResourceId set)' },
3829
+ saleAccountResourceId: { type: 'string', description: 'Sale account resourceId (required if cogsResourceId set)' },
3830
+ appliesToSale: { type: 'boolean', description: 'Whether item applies to sales (required if cogsResourceId set)' },
3831
+ appliesToPurchase: { type: 'boolean', description: 'Whether item applies to purchases (required if cogsResourceId set)' },
3832
+ blockInsufficientDeductions: { type: 'boolean', description: 'Block transactions when insufficient stock (default: false)' },
3833
+ },
3834
+ required: ['itemCode', 'name', 'costingMethod', 'cogsResourceId'],
3835
+ group: 'inventory',
3836
+ readOnly: false,
3837
+ execute: async (ctx, input) => {
3838
+ const data = {
3839
+ itemCode: input.itemCode,
3840
+ name: input.name,
3841
+ costingMethod: input.costingMethod,
3842
+ cogsResourceId: input.cogsResourceId,
3843
+ blockInsufficientDeductions: input.blockInsufficientDeductions ?? false,
3844
+ };
3845
+ if (input.unit)
3846
+ data.unit = input.unit;
3847
+ if (input.purchaseAccountResourceId)
3848
+ data.purchaseAccountResourceId = input.purchaseAccountResourceId;
3849
+ if (input.saleAccountResourceId)
3850
+ data.saleAccountResourceId = input.saleAccountResourceId;
3851
+ if (input.appliesToSale !== undefined)
3852
+ data.appliesToSale = input.appliesToSale;
3853
+ if (input.appliesToPurchase !== undefined)
3854
+ data.appliesToPurchase = input.appliesToPurchase;
3855
+ return createInventoryItem(ctx.client, data);
3856
+ },
3857
+ },
3792
3858
  // ══════════════════════════════════════════════════════════════
3793
3859
  // ── CRUD Gaps (missing from existing tools) ────────────────
3794
3860
  // ══════════════════════════════════════════════════════════════
@@ -4339,7 +4405,7 @@ Response: { updated: string[], failed: [{ resourceId, error, errorCode }] }. On
4339
4405
  endDate: { type: 'string', description: 'Last occurrence date (YYYY-MM-DD)' },
4340
4406
  status: { type: 'string', description: 'Status: ACTIVE or PAUSED' },
4341
4407
  valueDate: { type: 'string', description: 'Journal date (YYYY-MM-DD)' },
4342
- schedulerEntries: { type: 'array', description: 'Journal entries: [{ accountResourceId, type: CREDIT|DEBIT, amount, ... }]' },
4408
+ schedulerEntries: { type: 'array', items: { type: 'object' }, description: 'Journal entries: [{ accountResourceId, type: CREDIT|DEBIT, amount, ... }]' },
4343
4409
  reference: { type: 'string', description: 'Journal reference' },
4344
4410
  notes: { type: 'string', description: 'Journal notes' },
4345
4411
  },
@@ -4378,7 +4444,7 @@ Response: { updated: string[], failed: [{ resourceId, error, errorCode }] }. On
4378
4444
  paymentAmount: { type: 'number', description: 'Corrected payment amount (bank currency)' },
4379
4445
  reference: { type: 'string', description: 'Payment reference' },
4380
4446
  valueDate: { type: 'string', description: 'Payment date (YYYY-MM-DD)' },
4381
- paymentMethod: { type: 'string', description: 'Payment method (BANK_TRANSFER, CASH, CHEQUE, etc.)' },
4447
+ paymentMethod: PAYMENT_METHOD_PARAM,
4382
4448
  accountResourceId: { type: 'string', description: 'Bank/cash account resourceId' },
4383
4449
  transactionFee: { type: 'number', description: 'Transaction fee amount' },
4384
4450
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaz-clio",
3
- "version": "4.33.0",
3
+ "version": "4.34.1",
4
4
  "description": "Clio — Command Line Interface Orchestrator for Jaz AI.",
5
5
  "type": "module",
6
6
  "bin": {