jaz-clio 5.39.3 → 5.40.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 +2 -2
- package/assets/skills/api/SKILL.md +5 -3
- package/assets/skills/api/references/endpoints.md +38 -2
- package/assets/skills/api/references/errors.md +16 -0
- package/assets/skills/api/references/feature-glossary.md +2 -2
- package/assets/skills/api/references/field-map.md +1 -0
- package/assets/skills/cli/SKILL.md +1 -1
- package/assets/skills/conversion/SKILL.md +1 -1
- package/assets/skills/jaz-kit/SKILL.md +1 -1
- package/assets/skills/jaz-pseudo-sql/SKILL.md +1 -1
- package/assets/skills/jobs/SKILL.md +1 -1
- package/assets/skills/transaction-recipes/SKILL.md +3 -3
- package/cli.mjs +427 -427
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
<p align="center"><b>Jaz accounting on the command line, and inside any AI agent.</b></p>
|
|
11
11
|
|
|
12
|
-
358 tools · 66 command groups · 7 skills · 13 calculators · 12 close playbooks ·
|
|
12
|
+
358 tools · 66 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
|
|
@@ -109,7 +109,7 @@ Several companies at once: comma-separate the keys, or use a personal access tok
|
|
|
109
109
|
|
|
110
110
|
## Skills
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
159 API rules from production testing: field-name maps, error-recovery patterns, response-shape quirks, plus 12 job playbooks. Installable into any agent project, no server involved.
|
|
113
113
|
|
|
114
114
|
```bash
|
|
115
115
|
clio init # auto-detect the agent, install skills + agent-rules
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-api
|
|
3
|
-
version: 5.
|
|
3
|
+
version: 5.40.1
|
|
4
4
|
description: >-
|
|
5
5
|
Use this skill whenever you call, debug, or review code that touches the Jaz
|
|
6
|
-
REST API. Covers field names, response shapes,
|
|
6
|
+
REST API. Covers field names, response shapes, 159 production gotchas, error
|
|
7
7
|
recovery (422/400/404/500), search filters, pagination, and edge cases for
|
|
8
8
|
every endpoint — invoices, bills, credit notes, journals, cash entries,
|
|
9
9
|
payments, contacts, CoA, items, tax profiles, bank records, fixed assets,
|
|
@@ -447,7 +447,7 @@ Bills, invoices, and credit notes share identical mandatory field specs. Adding
|
|
|
447
447
|
|
|
448
448
|
142. **`capsuleRecipe` payload is mutually exclusive with `capsuleResourceId`** on trigger mutations (create/update of invoice, bill, journal, cash_in, cash_out). Use `capsuleRecipe` to CREATE a new capsule via the recipe engine; use `capsuleResourceId` to ATTACH a base-trx to an existing capsule. Sending both returns 422 (`excluded_with` validator).
|
|
449
449
|
|
|
450
|
-
143. **Capsule recipe publish is best-effort post-commit — silent-null failure mode.** On success the trigger-mutation response carries `capsuleRecipeJob: { jobResourceId, capsuleResourceId, subscriptionFBPath, totalRecords, idempotentHit, recipeKey }` (verified live 2026-05-27). **Note `jobResourceId` (NOT `resourceId`)** on the trigger-mutation payload — this is the polling key. **On publish failure, `capsuleRecipeJob` is absent (or null) from the response, the trigger mutation STILL returns 201, the base-trx is committed, and NO error reason is surfaced to the caller.** The response echoes `capsuleRecipe.{recipeName, inputs}` back unchanged, which can look like success at a glance. **Three known causes** of silent null `capsuleRecipeJob` (must pre-validate before sending):
|
|
450
|
+
143. **Capsule recipe publish is best-effort post-commit — silent-null failure mode.** On success the trigger-mutation response carries `capsuleRecipeJob: { jobResourceId, capsuleResourceId, subscriptionFBPath, totalRecords, idempotentHit, recipeKey }` (verified live 2026-05-27). **Note `jobResourceId` (NOT `resourceId`)** on the trigger-mutation payload — this is the polling key. **On publish failure, `capsuleRecipeJob` is absent (or null) from the response, the trigger mutation STILL returns its normal success status (201 on create, 200 on update — see endpoints.md "Success Status Codes"), the base-trx is committed, and NO error reason is surfaced to the caller.** The response echoes `capsuleRecipe.{recipeName, inputs}` back unchanged, which can look like success at a glance. **Three known causes** of silent null `capsuleRecipeJob` (must pre-validate before sending):
|
|
451
451
|
- **(a) Wrong `recipeName` for the base trx type** — every recipe is locked to `allowedBaseTransactionTypes` (e.g. PREPAID_AMORTIZATION = PURCHASE only; DEFERRED_REVENUE = SALE only; ACCRUAL_REVERSAL, IFRS16_LEASE = JOURNAL_MANUAL only; LOAN_AMORTIZATION = JOURNAL_DIRECT_CASH_IN or JOURNAL_MANUAL). On `preview_capsule_recipe`, mismatch surfaces as 422 `RECIPE_INVALID_BASE_TRANSACTION_TYPE`. **On the trigger mutation, it silently nulls the job** — the validation happens post-commit in customer-service and arap catches the exception. Always check `get_capsule_recipe(name).allowedBaseTransactionTypes` matches the trigger mutation you're calling.
|
|
452
452
|
- **(b) Currency mismatch** — see Rule 156 (single-currency v1 recipes — recipe `currency`, every `*AccountResourceId` account's `currencyCode`, and the base trx currency MUST all match). Mismatch surfaces as 422 `ERR_RECIPE_ACCOUNT_CURRENCY_MISMATCH` on `preview_capsule_recipe` but silently nulls on the trigger mutation.
|
|
453
453
|
- **(c) Wrong `x-accountClass` on an input field** — see Rule 157 (each `*AccountResourceId` slot has a required account class). Mismatch silently nulls; preview returns the matching `RECIPE_FIELDS_*` 422.
|
|
@@ -547,3 +547,5 @@ When the user wants to OPEN, SEE, or SHARE something in the Jaz dashboard ("open
|
|
|
547
547
|
- **jaz-jobs** — 12 accounting job playbooks (month-end close, bank recon, GST/VAT filing, etc.)
|
|
548
548
|
- **jaz-conversion** — Data migration workflows from Xero, QuickBooks, Sage, MYOB, and Excel
|
|
549
549
|
- **jaz-cli** — CLI command reference, auth, output formats, pagination, and workflow patterns
|
|
550
|
+
|
|
551
|
+
160. **Payment `adjustment` is a CASH-LEG-only correction — it never moves the document balance.** Records an overpayment or a rounding difference on the bank side of a payment: `netCash = paymentAmount -/+ fees +/- adjustmentValue` (fees are deducted from cash received on an invoice and added to cash spent on a bill). AR/AP is untouched, so an overpaid invoice stays PAID with the excess sitting on the account you chose and NO credit note is created. Shape: `adjustment: { adjustmentValue, adjustmentAccountResourceId, adjustmentDescription? }` — signed, non-zero, max 2dp, always FLAT (never a percentage), never taxed. Accepted on `pay_invoice` / `pay_bill` / both credit-note refunds / `update_payment` / both receipt reconciliations. **NOT** on batch payments, and not for `DEBT_WRITE_OFF` / `CLEARING_SETTLEMENT` / `INTER_COMPANY` / `WITHHOLDING_TAX_CERTIFICATE` (those record a settlement, so there is no cash leg). The account must be non-controlled: not AR/AP, not the VAT or FX accounts, not bank/cash, not deposit-linked. **Write/read asymmetry:** you WRITE the nested `adjustment.adjustmentValue` but READ a flat `adjustmentAmount` on the payment record, alongside `adjustmentOrganizationAccountResourceId`. Don't confuse either with `lineItems[].taxVatAdjustment.adjustmentAmount`, which is line-item tax and unrelated. **SET THE ADJUSTMENT WHEN RECORDING THE PAYMENT. On `update_payment` the field is inert.** Verified against production on 2026-08-10: adding one to a payment that has none, changing an existing one, and removing one all return **200 and change nothing**. Omitting it also changes nothing. There is no request shape that works, including `"adjustment": null`. So never tell a user you added, changed or removed an adjustment on an existing payment, and never rely on a 200 here as evidence that it applied. If the value is wrong, the only route today is to delete the payment record and record it again with the correct adjustment. Read the payment back before reporting any adjustment change as done. This is an upstream regression introduced in arap `v10.7.19` on 2026-08-10 and is with the accounting service owner. Before that release an omitted adjustment CLEARED it, so any guidance saying omit-to-clear is doubly stale. One knock-on: `PAYMENT_ADJUSTMENT_CANNOT_CHANGE_WHEN_RECONCILED` can no longer fire through this API at all, so editing the reference on a reconciled adjusted payment now succeeds.
|
|
@@ -54,6 +54,23 @@ All GET list endpoints and POST `/search` endpoints use **`limit`/`offset` pagin
|
|
|
54
54
|
|
|
55
55
|
---
|
|
56
56
|
|
|
57
|
+
## Success Status Codes (All Endpoints)
|
|
58
|
+
|
|
59
|
+
**Never branch on the exact 2xx — check `response.ok` (or `status < 300`) and read the body.** Every success carries the same `{ data: ... }` envelope regardless of code.
|
|
60
|
+
|
|
61
|
+
| Shape | Code |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `POST` that creates a NEW record — `/invoices`, `/bills`, `/journals`, `/contacts`, `/items`, `/chart-of-accounts`, `/tags`, `/tax-profiles`, `/capsules`, `/bookmarks`, `/bank-records/:acct`, `/:type/:id/payments`, `/:type/:id/refunds`, `/organization[-]currencies/:code/rates`, `/scheduled/*`, `/magic/*`, `/sale-orders/:id/convert-to-invoice` (and the other `convert-to-*`), the fixed-asset disposal actions (`/discard-fixed-assets/:id`, `/mark-as-sold/fixed-assets`, `/transfer-fixed-assets`) | **201** |
|
|
64
|
+
| `PUT` (update) — all 40 of them, no exceptions | **200** |
|
|
65
|
+
| `GET` (all), `DELETE` (all) | **200** |
|
|
66
|
+
| `POST /search`, `POST /bulk-upsert`, and action POSTs that mutate an EXISTING record (`/:id/request-changes`, `/:id/credits`, `/:id/attachments`) | **200** |
|
|
67
|
+
| Async batch kickoff (`/bulk-request-changes`, claims `bulk/*`) | **202** |
|
|
68
|
+
| Quick Fix / bulk partial failure | **207** (body shape identical to 200 — check `failed[]`) |
|
|
69
|
+
|
|
70
|
+
**Changed 2026-08-10**: seven `PUT` endpoints moved 201 → 200 — `/bills/{id}`, `/contacts/{id}`, `/nano-classifiers/{id}`, `/items/{id}`, `/journals/{id}`, `/scheduled/journals/{id}`, `/organization-currencies/{code}/rates/{id}`. Request shapes and response bodies are byte-identical; only the status changed. The same release corrected 114 published success codes that disagreed with what the endpoints actually returned, so the API reference now matches runtime everywhere. A client that asserted `status === 201` on an update breaks; one that checks `response.ok` does not.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
57
74
|
## 1. Organization
|
|
58
75
|
|
|
59
76
|
### GET /api/v1/organization
|
|
@@ -2081,8 +2098,27 @@ Update an existing payment record. All fields optional — only included fields
|
|
|
2081
2098
|
"paymentMethod": "BANK_TRANSFER",
|
|
2082
2099
|
"accountResourceId": "uuid-bank",
|
|
2083
2100
|
"currency": { "sourceCurrency": "USD", "exchangeRate": 0.74 },
|
|
2084
|
-
|
|
2085
|
-
"
|
|
2101
|
+
// Both fees are OBJECTS, not a number and not a boolean. A bare value is rejected.
|
|
2102
|
+
"transactionFee": {
|
|
2103
|
+
"feeAccountResourceId": "uuid-fee-expense",
|
|
2104
|
+
"feeType": "FLAT",
|
|
2105
|
+
"feeValue": 5.00,
|
|
2106
|
+
"feeTaxVatApplicable": false
|
|
2107
|
+
},
|
|
2108
|
+
"transactionFeeCollected": {
|
|
2109
|
+
"feeAccountResourceId": "uuid-fee-income",
|
|
2110
|
+
"feeType": "FLAT",
|
|
2111
|
+
"feeValue": 2.00,
|
|
2112
|
+
"feeTaxVatApplicable": false
|
|
2113
|
+
},
|
|
2114
|
+
// Cash-leg adjustment: overpayment or rounding. Bank leg only, never AR/AP.
|
|
2115
|
+
// Only applies when RECORDING a payment. On update it is inert: add, change
|
|
2116
|
+
// and remove all return 200 and do nothing. See rule 160.
|
|
2117
|
+
"adjustment": {
|
|
2118
|
+
"adjustmentValue": -0.03,
|
|
2119
|
+
"adjustmentAccountResourceId": "uuid-rounding-account",
|
|
2120
|
+
"adjustmentDescription": "rounding difference"
|
|
2121
|
+
}
|
|
2086
2122
|
}
|
|
2087
2123
|
|
|
2088
2124
|
// Response: same shape as GET
|
|
@@ -851,6 +851,22 @@ Journals support a top-level `currency` object to create entries in a foreign cu
|
|
|
851
851
|
|
|
852
852
|
**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.
|
|
853
853
|
|
|
854
|
+
#### Payment adjustment errors (422)
|
|
855
|
+
|
|
856
|
+
The `adjustment` object on a payment is validated server-side. The API returns the code as `error_type` with a human message. Do NOT pre-validate any of these — surface the 422.
|
|
857
|
+
|
|
858
|
+
Two of the seven never reach you through this path: a zero `adjustmentValue` and a missing `adjustmentAccountResourceId` are caught by the API layer's own field validation first and come back as a `validation_error`, not as the code below. `INVALID_PAYMENT_ADJUSTMENT_AMOUNT` still reaches you via the decimal-scale rule.
|
|
859
|
+
|
|
860
|
+
| `error_type` | Cause | Fix |
|
|
861
|
+
|---|---|---|
|
|
862
|
+
| `INVALID_PAYMENT_ADJUSTMENT_AMOUNT` | `adjustmentValue` is zero, or has more than 2 decimal places | Send a non-zero value rounded to 2dp. Zero is the absence of an adjustment, not an adjustment of nothing — omit the object instead |
|
|
863
|
+
| `PAYMENT_ADJUSTMENT_ACCOUNT_REQUIRED` | No `adjustmentAccountResourceId` | Supply one |
|
|
864
|
+
| `INVALID_PAYMENT_ADJUSTMENT_ACCOUNT` | Account is a control account (AR, AP, the VAT pair, the FX accounts, Retained Earnings, withholding tax), a bank or cash account, deposit-linked, missing, or deleted | Pick an ordinary postable account. Most seeded accounts qualify — Rounding, Other Income, Bank Charges |
|
|
865
|
+
| `PAYMENT_ADJUSTMENT_MAKES_NET_CASH_INVALID` | Net cash would not remain above zero | Reduce the magnitude of a negative adjustment |
|
|
866
|
+
| `PAYMENT_ADJUSTMENT_NOT_APPLICABLE_FOR_PAYMENT_METHOD` | Method is `DEBT_WRITE_OFF`, `CLEARING_SETTLEMENT`, `INTER_COMPANY` or `WITHHOLDING_TAX_CERTIFICATE` | Those record a settlement, not a bank movement, so there is no cash leg to adjust. Drop the adjustment |
|
|
867
|
+
| `PAYMENT_ADJUSTMENT_CANNOT_CHANGE_WHEN_RECONCILED` | The payment is matched to a bank statement entry and the request would change its adjustment | **Unreachable through this API since 2026-08-10.** The update path never reads the caller's adjustment, so nothing can present a changed value for this rule to reject. Editing the `reference` on a reconciled adjusted payment now succeeds. Still listed because it fires for other clients and will return here when the upstream regression is fixed |
|
|
868
|
+
| `PAYMENT_ADJUSTMENT_NOT_APPLICABLE_FOR_BATCH_PAYMENT` | Batch payments do not support adjustments | Record the adjustment on an individual payment |
|
|
869
|
+
|
|
854
870
|
---
|
|
855
871
|
|
|
856
872
|
### Sub-Resource Response Errors
|
|
@@ -12,7 +12,7 @@ Sales documents sent to customers for goods/services rendered. Track Accounts Re
|
|
|
12
12
|
|
|
13
13
|
Key capabilities: draft/approval workflows, multi-currency (auto-fetch ECB rates or custom org rates), scheduled/recurring invoices with dynamic scheduler strings, delivery slips, sales subscriptions with proration, bulk import (up to 1,000), Quick Fix for bulk field edits, GST/VAT adjustments.
|
|
14
14
|
|
|
15
|
-
If payment date equals invoice date, it's recorded as a cash transaction (not AR). Transaction fees are deducted from cash received. RGL = `(Invoice payment / Transaction Rate) - (Cash received / Payment Rate)`.
|
|
15
|
+
If payment date equals invoice date, it's recorded as a cash transaction (not AR). Transaction fees are deducted from cash received, and a payment `adjustment` shifts the cash leg further (net cash = paymentAmount - feesCharged + feesCollected +/- adjustmentValue) without touching AR. RGL = `(Invoice payment / Transaction Rate) - (Cash received / Payment Rate)`.
|
|
16
16
|
|
|
17
17
|
**API**: CRUD `GET/POST/PUT/DELETE /invoices`, `POST /invoices/search`, `POST /invoices/:id/payments`, `GET /invoices/:id/payments`, `POST /invoices/:id/credits`, `GET /invoices/:id/download`, `POST/GET/DELETE /invoices/:id/attachments`, `PUT /invoices/:id/approve`, `POST /scheduled/invoices` (CRUD), `POST /scheduled/subscriptions` (recurring). Generic payment ops: `GET/PUT/DELETE /payments/:id`. **Starting from a PDF/JPG attachment?** Use `POST /magic/createBusinessTransactionFromAttachment` instead — Jaz Magic handles extraction & autofill (see AI Agents section).
|
|
18
18
|
|
|
@@ -38,7 +38,7 @@ Purchase documents from suppliers for goods/services received. Track Accounts Pa
|
|
|
38
38
|
|
|
39
39
|
Key capabilities: bill receipts (short-form template creating bill + payment together), purchase order PDFs from drafts, scheduled/recurring bills, WHT certificate payments (always credited to WHT Payable account), bulk import.
|
|
40
40
|
|
|
41
|
-
Transaction fees are added to cash spent (not deducted like invoices). RGL = `(Cash spent / Payment rate) - (Bill payment / Transaction rate)`.
|
|
41
|
+
Transaction fees are added to cash spent (not deducted like invoices), and a payment `adjustment` shifts the cash leg further without touching AP. RGL = `(Cash spent / Payment rate) - (Bill payment / Transaction rate)`.
|
|
42
42
|
|
|
43
43
|
**API**: CRUD `GET/POST/PUT/DELETE /bills`, `POST /bills/search`, `POST /bills/:id/payments`, `GET /bills/:id/payments`, `POST /bills/:id/credits`, `POST/GET/DELETE /bills/:id/attachments`, `PUT /bills/:id/approve`, `POST /scheduled/bills` (CRUD). Generic payment ops: `GET/PUT/DELETE /payments/:id`. **Starting from a PDF/JPG attachment?** Use `POST /magic/createBusinessTransactionFromAttachment` instead — Jaz Magic handles extraction & autofill (see AI Agents section).
|
|
44
44
|
|
|
@@ -636,6 +636,7 @@ Battle-tested patterns from production Jaz API clients:
|
|
|
636
636
|
| `cashflowId` | ≠ `resourceId` | Cashflow transaction IDs are NOT payment IDs — different entities |
|
|
637
637
|
| `bankAccountId` | `accountResourceId` | Bank account for the payment |
|
|
638
638
|
| `fee` | `feeAmount` (response) / `transactionFee` (update) | Response field is `feeAmount`, update field is `transactionFee` |
|
|
639
|
+
| `adjustment` (cash-leg over/underpayment) | `adjustment: { adjustmentValue, adjustmentAccountResourceId, adjustmentDescription }` | Write nested; READ back flat as `adjustmentAmount` + `adjustmentOrganizationAccountResourceId`. Bank leg only |
|
|
639
640
|
| `isCrossCurrency` | `crossCurrency` | Boolean, no `is` prefix |
|
|
640
641
|
| `currency` (string) | `currencyCode` (response) / `currency` (update: `{ sourceCurrency, exchangeRate }`) | Response is flat string, update is object |
|
|
641
642
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-recipes
|
|
3
|
-
version: 5.
|
|
3
|
+
version: 5.40.1
|
|
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
|
|
@@ -307,7 +307,7 @@ A second path: 5 IFRS recipes (Loan Amortization, Accrual Reversal, Prepaid Amor
|
|
|
307
307
|
|
|
308
308
|
### Three pre-flight gates BEFORE sending `capsuleRecipe` (else the response silently nulls)
|
|
309
309
|
|
|
310
|
-
The trigger mutation is **best-effort post-commit**: if the recipe publish fails inside customer-service, the base-trx still commits, the response still returns 201, but `capsuleRecipeJob` is null and **no error reason is surfaced on the response body**. Three causes of silent null — gate every one of them before sending:
|
|
310
|
+
The trigger mutation is **best-effort post-commit**: if the recipe publish fails inside customer-service, the base-trx still commits, the response still returns its normal success status (201 on create, 200 on update), but `capsuleRecipeJob` is null and **no error reason is surfaced on the response body**. Three causes of silent null — gate every one of them before sending:
|
|
311
311
|
|
|
312
312
|
| Gate | Constraint | Pre-flight check |
|
|
313
313
|
|---|---|---|
|
|
@@ -315,7 +315,7 @@ The trigger mutation is **best-effort post-commit**: if the recipe publish fails
|
|
|
315
315
|
| **Currency** | Recipe `currency`, every `*AccountResourceId` account's `currencyCode`, and base trx `currencyCode` ALL must match (v1 recipes are single-currency) | `get_account(<id>).currencyCode` for every input account |
|
|
316
316
|
| **Account class** | Each `*AccountResourceId` slot has an `x-accountClass` constraint in the recipe inputSchema (Asset/Liability/Expense/Revenue) | `get_capsule_recipe(name).versions[0].inputSchema.properties.<field>['x-accountClass']` vs `get_account(<id>).accountClass` |
|
|
317
317
|
|
|
318
|
-
**The canonical pre-flight is one call**: `preview_capsule_recipe(recipeName, inputs)`. Pure-compute (no side effects). Surfaces every input/class/currency violation as a clean 422 with a concrete `error_type`. The trigger mutation does NOT surface these — it just returns
|
|
318
|
+
**The canonical pre-flight is one call**: `preview_capsule_recipe(recipeName, inputs)`. Pure-compute (no side effects). Surfaces every input/class/currency violation as a clean 422 with a concrete `error_type`. The trigger mutation does NOT surface these — it just returns its normal success status with no `capsuleRecipeJob`. Always preview first if you can't trust the inputs.
|
|
319
319
|
|
|
320
320
|
See `jaz-api` Rule 143 (silent-null failure mode + diagnosis sequence), Rule 144 (closed enum on `recipeName`), Rule 150 (RECIPE_INVALID_BASE_TRANSACTION_TYPE — preview-only, NOT trigger), Rule 156 (ERR_RECIPE_ACCOUNT_CURRENCY_MISMATCH), Rule 157 (x-accountClass slot constraint).
|
|
321
321
|
|