jaz-clio 4.2.1 → 4.3.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 +6 -0
- package/assets/skills/api/SKILL.md +61 -6
- package/assets/skills/api/references/endpoints.md +74 -5
- package/assets/skills/api/references/full-api-surface.md +2 -1
- package/assets/skills/conversion/SKILL.md +1 -1
- package/assets/skills/jobs/SKILL.md +1 -1
- package/assets/skills/jobs/references/document-collection.md +58 -12
- package/assets/skills/transaction-recipes/SKILL.md +1 -1
- package/dist/commands/accounts.js +18 -10
- package/dist/commands/bank.js +43 -1
- package/dist/commands/bills.js +240 -12
- package/dist/commands/capsules.js +18 -10
- package/dist/commands/cash-entry.js +18 -10
- package/dist/commands/cash-transfer.js +18 -10
- package/dist/commands/contacts.js +18 -10
- package/dist/commands/currency-rates.js +9 -5
- package/dist/commands/customer-credit-notes.js +18 -10
- package/dist/commands/draft-helpers.js +276 -0
- package/dist/commands/invoices.js +18 -10
- package/dist/commands/items.js +18 -10
- package/dist/commands/jobs.js +52 -2
- package/dist/commands/journals.js +18 -10
- package/dist/commands/magic.js +262 -0
- package/dist/commands/pagination.js +44 -10
- package/dist/commands/payments.js +18 -10
- package/dist/commands/reports.js +18 -1
- package/dist/commands/resolve.js +52 -0
- package/dist/commands/supplier-credit-notes.js +18 -10
- package/dist/commands/tags.js +18 -10
- package/dist/core/api/attachments.js +7 -12
- package/dist/core/api/bills.js +10 -0
- package/dist/core/api/magic.js +78 -0
- package/dist/core/api/reports.js +3 -0
- package/dist/core/jobs/document-collection/tools/ingest/classify.js +38 -8
- package/dist/core/jobs/document-collection/tools/ingest/decrypt.js +111 -0
- package/dist/core/jobs/document-collection/tools/ingest/format.js +6 -3
- package/dist/core/jobs/document-collection/tools/ingest/scanner.js +17 -2
- package/dist/core/jobs/document-collection/tools/ingest/upload.js +20 -7
- package/dist/index.js +2 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -12,6 +12,12 @@ CLI for the [Jaz](https://jaz.ai) accounting platform. Create invoices, record b
|
|
|
12
12
|
|
|
13
13
|
> Also fully compatible with [Juan Accounting](https://juan.ac).
|
|
14
14
|
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
**Node.js 18 or later** is required. If `node --version` works, skip ahead.
|
|
18
|
+
|
|
19
|
+
Otherwise: download the LTS installer from [nodejs.org](https://nodejs.org). It includes `npm`.
|
|
20
|
+
|
|
15
21
|
## Install
|
|
16
22
|
|
|
17
23
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-api
|
|
3
|
-
version: 4.
|
|
3
|
+
version: 4.3.0
|
|
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.
|
|
@@ -94,7 +94,7 @@ You are working with the **Jaz REST API** — the accounting platform backend. A
|
|
|
94
94
|
| Trial balance | `startDate`, `endDate` |
|
|
95
95
|
| Balance sheet | `primarySnapshotDate` |
|
|
96
96
|
| P&L | `primarySnapshotDate`, `secondarySnapshotDate` |
|
|
97
|
-
| General ledger | `startDate`, `endDate`, `groupBy: "ACCOUNT"` |
|
|
97
|
+
| General ledger | `startDate`, `endDate`, `groupBy: "ACCOUNT"` (also `TRANSACTION`, `CAPSULE`) |
|
|
98
98
|
| Cashflow | `primaryStartDate`, `primaryEndDate` |
|
|
99
99
|
| Cash balance | `reportDate` |
|
|
100
100
|
| AR/AP report | `endDate` |
|
|
@@ -105,7 +105,7 @@ You are working with the **Jaz REST API** — the accounting platform backend. A
|
|
|
105
105
|
37. **Data exports use simpler field names**: P&L export uses `startDate`/`endDate` (NOT `primarySnapshotDate`). AR/AP export uses `endDate`.
|
|
106
106
|
|
|
107
107
|
### Pagination
|
|
108
|
-
38. **All list/search endpoints use `limit`/`offset` pagination** — NOT `page`/`size`. Default limit=100, offset=0. Max limit=1000, max offset=65536. `page`/`size` params are silently ignored. Response shape: `{ totalPages, totalElements, data: [...] }`.
|
|
108
|
+
38. **All list/search endpoints use `limit`/`offset` pagination** — NOT `page`/`size`. Default limit=100, offset=0. Max limit=1000, max offset=65536. `page`/`size` params are silently ignored. Response shape: `{ totalPages, totalElements, truncated, data: [...] }`. When `truncated: true`, a `_meta: { fetchedRows, maxRows }` field explains why (offset cap or `--max-rows` soft cap — default 10,000). Use `--max-rows <n>` to override. Always check `truncated` before assuming the full dataset was returned.
|
|
109
109
|
|
|
110
110
|
### Other
|
|
111
111
|
39. **Currency rates use `/organization-currencies/:code/rates`** — note the HYPHENATED path (NOT `/organization/currencies`). Enable currencies first via `POST /organization/currencies`, then set rates via `POST /organization-currencies/:code/rates` with body `{ "rate": 0.74, "rateApplicableFrom": "YYYY-MM-DD" }` (see Rule 49 for direction). Cannot set rates for org base currency. Full CRUD: POST (create), GET (list), GET/:id, PUT/:id, DELETE/:id.
|
|
@@ -132,11 +132,12 @@ You are working with the **Jaz REST API** — the accounting platform backend. A
|
|
|
132
132
|
### Jaz Magic — Extraction & Autofill
|
|
133
133
|
57. **When the user starts from an attachment, always use Jaz Magic** — if the input is a PDF, JPG, or any document image (invoice, bill, receipt), the correct path is `POST /magic/createBusinessTransactionFromAttachment`. Do NOT manually construct a `POST /invoices` or `POST /bills` payload from an attachment — Jaz Magic handles the entire extraction-and-autofill pipeline server-side: OCR, line item detection, contact matching, CoA auto-mapping via ML learning, and draft creation with all fields pre-filled. Only use `POST /invoices` or `POST /bills` when building transactions from structured data (JSON, CSV, database rows) where the fields are already known.
|
|
134
134
|
58. **Two upload modes with different content types** — `sourceType: "FILE"` requires **multipart/form-data** with `sourceFile` blob (JSON body fails with 400 "sourceFile is a required field"). `sourceType: "URL"` accepts **application/json** with `sourceURL` string. The OAS only documents URL mode — FILE mode (the common case) is undocumented.
|
|
135
|
-
59. **Three required fields**: `sourceFile` (multipart blob — NOT `file`), `businessTransactionType` (`"INVOICE"` or `"
|
|
136
|
-
60. **Response maps transaction types**: Request `BILL` → response `
|
|
137
|
-
61. **Extraction is asynchronous** — the API response is immediate (file upload confirmation only). The actual Magic pipeline — OCR, line item extraction, contact matching, CoA learning, and autofill — runs asynchronously.
|
|
135
|
+
59. **Three required fields**: `sourceFile` (multipart blob — NOT `file`), `businessTransactionType` (`"INVOICE"`, `"BILL"`, `"CUSTOMER_CREDIT_NOTE"`, or `"SUPPLIER_CREDIT_NOTE"` — `EXPENSE` rejected), `sourceType` (`"FILE"` or `"URL"`). All three are validated server-side. **CRITICAL: multipart form field names are camelCase** — `businessTransactionType`, `sourceType`, `sourceFile`, NOT snake_case. Using `business_transaction_type` returns 422 "businessTransactionType is a required field". The File blob must include a filename and correct MIME type (e.g. `application/pdf`, `image/jpeg`) — bare `application/octet-stream` blobs are rejected with 400 "Invalid file type".
|
|
136
|
+
60. **Response maps transaction types**: Request `INVOICE` → response `SALE`. Request `BILL` → response `PURCHASE`. Request `CUSTOMER_CREDIT_NOTE` → response `SALE_CREDIT_NOTE`. Request `SUPPLIER_CREDIT_NOTE` → response `PURCHASE_CREDIT_NOTE`. S3 paths follow the response type. The response `validFiles[]` array contains `workflowResourceId` for tracking extraction progress via `POST /magic/workflows/search`.
|
|
137
|
+
61. **Extraction is asynchronous** — the API response is immediate (file upload confirmation only). The actual Magic pipeline — OCR, line item extraction, contact matching, CoA learning, and autofill — runs asynchronously. Use `POST /magic/workflows/search` with `filter.resourceId.eq: "<workflowResourceId>"` to check status (SUBMITTED → PROCESSING → COMPLETED/FAILED). When COMPLETED, `businessTransactionDetails.businessTransactionResourceId` contains the created draft BT ID. The `subscriptionFBPath` in the response is a Firebase Realtime Database path for real-time status updates (alternative to polling).
|
|
138
138
|
62. **Accepts PDF and JPG/JPEG** — both file types confirmed working. Handwritten documents are accepted at upload stage (extraction quality varies). `fileType` in response reflects actual format: `"PDF"`, `"JPEG"`.
|
|
139
139
|
63. **Never use magic-search endpoints** — `GET /invoices/magic-search` and `GET /bills/magic-search` require a separate `x-magic-api-key` (not available to agents). Always use `POST /invoices/search` or `POST /bills/search` with standard `x-jk-api-key` auth instead.
|
|
140
|
+
63b. **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, 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" }`.
|
|
140
141
|
|
|
141
142
|
### Cashflow & Unified Ledger
|
|
142
143
|
64. **No standalone payments list/search** — `GET /payments`, `POST /payments/search`, and `GET /payments` do NOT exist. Per-payment CRUD (`GET/PUT/DELETE /payments/:resourceId`) exists for individual payment records, but to **list or search** payments, use `POST /cashflow-transactions/search` — the unified transaction ledger that spans invoices, bills, credit notes, journals, cash entries, and payments. Filter by `businessTransactionType` (e.g., `SALE`, `PURCHASE`) and `direction` (`PAYIN`, `PAYOUT`). Response dates are epoch milliseconds.
|
|
@@ -163,6 +164,60 @@ You are working with the **Jaz REST API** — the accounting platform backend. A
|
|
|
163
164
|
79. **`capsule-transaction` recipes auto-resolve accounts** — when `--input` is omitted, the CLI searches the org's chart of accounts for each blueprint account name (e.g., "Interest Expense", "Loan Payable"). If all accounts resolve with high confidence, no JSON mapping file is needed. If any fail, the error message shows exactly which accounts could not be found and suggests close matches. `--contact` and `--bank-account` on recipes also accept names.
|
|
164
165
|
80. **Payment/refund account filter is conditional on `--method`** — for BANK_TRANSFER, CASH, and CHEQUE, the `--account` resolver filters to bank/cash accounts only. For other payment methods, all account types are considered.
|
|
165
166
|
|
|
167
|
+
### Draft Finalization Pipeline (Convert & Next)
|
|
168
|
+
|
|
169
|
+
The `clio bills draft` subcommand group enables the full "review → fill missing → convert" workflow that mirrors the Jaz UI's "Convert and Next" button. Designed for AI agents processing a queue of draft bills.
|
|
170
|
+
|
|
171
|
+
#### Commands
|
|
172
|
+
|
|
173
|
+
| Command | Purpose |
|
|
174
|
+
|---------|---------|
|
|
175
|
+
| `clio bills draft list [--ids <ids>] [--json]` | Queue view: all drafts with per-field validation + attachment count |
|
|
176
|
+
| `clio bills draft finalize <id> [flags] [--json]` | Fill missing fields + convert DRAFT → UNPAID in one PUT |
|
|
177
|
+
| `clio bills draft attachments <id> [--json]` | List attachments with download URLs for agent inspection |
|
|
178
|
+
|
|
179
|
+
#### Mandatory Fields for Bill Finalization
|
|
180
|
+
|
|
181
|
+
| Field | JSON Path | CLI Flag | Resolver |
|
|
182
|
+
|-------|-----------|----------|----------|
|
|
183
|
+
| Contact | `contactResourceId` | `--contact <name/UUID>` | Fuzzy resolved |
|
|
184
|
+
| Bill date | `valueDate` | `--date <YYYY-MM-DD>` | Literal |
|
|
185
|
+
| Due date | `dueDate` | `--due <YYYY-MM-DD>` | Literal |
|
|
186
|
+
| Line items | `lineItems` (non-empty) | `--lines <json>` | — |
|
|
187
|
+
| Item name | `lineItems[i].name` | via `--lines` | — |
|
|
188
|
+
| Item price | `lineItems[i].unitPrice` | via `--lines` | — |
|
|
189
|
+
| Item account | `lineItems[i].accountResourceId` | `--account <name/UUID>` (bulk) | Fuzzy resolved |
|
|
190
|
+
|
|
191
|
+
Optional: `--ref`, `--notes`, `--tag`, `--tax-profile <name/UUID>` (bulk, fuzzy resolved), `--tax`, `--tax-inclusive`, `--dry-run`, `--input <file>`.
|
|
192
|
+
|
|
193
|
+
#### Agent Workflow Pattern
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
Step 1: clio bills draft list --json
|
|
197
|
+
→ Batch queue: every DRAFT with per-field validation + attachment count
|
|
198
|
+
|
|
199
|
+
Step 2: For each draft where ready = false:
|
|
200
|
+
a) Read validation.missingFields from Step 1 output
|
|
201
|
+
b) Optional: clio bills draft attachments <id> --json
|
|
202
|
+
→ Download fileUrl, read PDF/image, extract or verify values
|
|
203
|
+
c) Resolve values (ask user, or infer from attachment + context)
|
|
204
|
+
d) clio bills draft finalize <id> --contact "Acme" --date 2025-01-15 ... --json
|
|
205
|
+
→ Updates + converts to UNPAID in one PUT (Rule 67: bills/invoices → UNPAID, journals → APPROVED)
|
|
206
|
+
|
|
207
|
+
Step 3: For each draft where ready = true:
|
|
208
|
+
clio bills draft finalize <id> --json
|
|
209
|
+
→ Converts directly (all mandatory fields already present)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
81. **`--account` bulk patches line items** — when used with `clio bills draft finalize`, `--account` resolves the name to a UUID then sets `accountResourceId` on EVERY line item where it's currently null. Existing accounts are NOT overwritten. Same for `--tax-profile`. `--lines` takes priority (full replacement).
|
|
213
|
+
82. **`--dry-run` validates without modifying** — returns the same validation structure as `draft list` (per-field status/hint), so agents can preview what would happen before committing. No API write occurs.
|
|
214
|
+
83. **Finalization is a single PUT** — `updateBill()` with `saveAsDraft: false` transitions DRAFT → UNPAID (per Rule 67) and updates all fields in one call. No delete-and-recreate.
|
|
215
|
+
84. **Draft list attachment count** — `draft list` includes `attachmentCount` per draft (from `GET /bills/:id/attachments`). Use `draft attachments <id>` for full details including `fileUrl` download links.
|
|
216
|
+
|
|
217
|
+
#### DRY Extension Pattern
|
|
218
|
+
|
|
219
|
+
Bills, invoices, and credit notes share identical mandatory field specs. Adding `clio invoices draft` or `clio customer-credit-notes draft` later reuses all validation, formatting, and CLI flag logic from `draft-helpers.ts` — only the API calls differ.
|
|
220
|
+
|
|
166
221
|
## Supporting Files
|
|
167
222
|
|
|
168
223
|
For detailed reference, read these files in this skill directory:
|
|
@@ -919,6 +919,12 @@ Valid `datatypeCode`: `TEXT`, `NUMBER`, `BOOLEAN`, `DATE`, `LINK`.
|
|
|
919
919
|
|
|
920
920
|
Processing is **asynchronous** — the API response confirms file upload immediately. The extraction pipeline runs server-side and pushes status updates via Firebase Realtime Database.
|
|
921
921
|
|
|
922
|
+
**Supported document types:**
|
|
923
|
+
- `INVOICE` → creates a draft sale (response type: `SALE`)
|
|
924
|
+
- `BILL` → creates a draft purchase (response type: `PURCHASE`)
|
|
925
|
+
- `CUSTOMER_CREDIT_NOTE` → creates a draft customer CN (response type: `SALE_CREDIT_NOTE`)
|
|
926
|
+
- `SUPPLIER_CREDIT_NOTE` → creates a draft supplier CN (response type: `PURCHASE_CREDIT_NOTE`)
|
|
927
|
+
|
|
922
928
|
**Two modes** — content type depends on `sourceType`:
|
|
923
929
|
|
|
924
930
|
#### FILE mode (multipart/form-data) — most common
|
|
@@ -929,7 +935,7 @@ Content-Type: multipart/form-data
|
|
|
929
935
|
|
|
930
936
|
Fields:
|
|
931
937
|
- sourceFile: PDF or JPG file blob (NOT "file")
|
|
932
|
-
- businessTransactionType: "INVOICE"
|
|
938
|
+
- businessTransactionType: "INVOICE", "BILL", "CUSTOMER_CREDIT_NOTE", or "SUPPLIER_CREDIT_NOTE"
|
|
933
939
|
- sourceType: "FILE"
|
|
934
940
|
```
|
|
935
941
|
|
|
@@ -941,6 +947,7 @@ Fields:
|
|
|
941
947
|
"filename": "NB64458.pdf",
|
|
942
948
|
"invalidFiles": [],
|
|
943
949
|
"validFiles": [{
|
|
950
|
+
"workflowResourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
944
951
|
"subscriptionFBPath": "magic_transactions/{orgId}/purchase/{fileId}",
|
|
945
952
|
"errorCode": null,
|
|
946
953
|
"errorMessage": null,
|
|
@@ -980,12 +987,74 @@ Content-Type: application/json
|
|
|
980
987
|
|
|
981
988
|
**Key gotchas:**
|
|
982
989
|
- `sourceFile` is the field name (NOT `file`) — same pattern as bank statement endpoint
|
|
983
|
-
-
|
|
984
|
-
- Response maps types: `INVOICE` → `SALE`, `BILL` → `PURCHASE`
|
|
990
|
+
- `EXPENSE` returns 422 — use one of the 4 valid types above
|
|
991
|
+
- Response maps types: `INVOICE` → `SALE`, `BILL` → `PURCHASE`, `CUSTOMER_CREDIT_NOTE` → `SALE_CREDIT_NOTE`, `SUPPLIER_CREDIT_NOTE` → `PURCHASE_CREDIT_NOTE`
|
|
985
992
|
- JSON body with `sourceType: "FILE"` always fails (400) — MUST use multipart
|
|
986
|
-
- `
|
|
993
|
+
- `workflowResourceId` in `validFiles[]` is for tracking via `POST /magic/workflows/search`
|
|
994
|
+
- `subscriptionFBPath` is the Firebase path for real-time status updates
|
|
987
995
|
- All three fields (`sourceFile`/`sourceURL`, `businessTransactionType`, `sourceType`) are required — omitting any returns 422
|
|
988
|
-
- File types confirmed: PDF, JPG/JPEG
|
|
996
|
+
- File types confirmed: PDF, JPG/JPEG, PNG, HEIC, XLS, XLSX, EML (max 1 MB)
|
|
997
|
+
|
|
998
|
+
---
|
|
999
|
+
|
|
1000
|
+
### POST /api/v1/magic/workflows/search
|
|
1001
|
+
|
|
1002
|
+
Search across magic BT extraction workflows and bank statement imports. Use this to track the status of uploads and retrieve the created draft BT resource ID.
|
|
1003
|
+
|
|
1004
|
+
```json
|
|
1005
|
+
/ Request:
|
|
1006
|
+
POST /api/v1/magic/workflows/search
|
|
1007
|
+
Content-Type: application/json
|
|
1008
|
+
|
|
1009
|
+
{
|
|
1010
|
+
"filter": {
|
|
1011
|
+
"resourceId": { "eq": "f47ac10b-58cc-4372-a567-0e02b2c3d479" },
|
|
1012
|
+
"documentType": ["SALE", "PURCHASE"],
|
|
1013
|
+
"status": ["COMPLETED"],
|
|
1014
|
+
"fileName": { "contains": "invoice" },
|
|
1015
|
+
"createdAt": { "gte": "2025-01-01", "lte": "2025-12-31" }
|
|
1016
|
+
},
|
|
1017
|
+
"limit": 20,
|
|
1018
|
+
"offset": 0,
|
|
1019
|
+
"sort": { "sortBy": ["createdAt"], "order": "DESC" }
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
/ Response (200):
|
|
1023
|
+
{
|
|
1024
|
+
"data": [{
|
|
1025
|
+
"resourceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
|
1026
|
+
"documentType": "SALE",
|
|
1027
|
+
"status": "COMPLETED",
|
|
1028
|
+
"fileName": "invoice.pdf",
|
|
1029
|
+
"fileType": "PDF",
|
|
1030
|
+
"fileUrl": "https://s3...",
|
|
1031
|
+
"fileId": "6e999313...",
|
|
1032
|
+
"createdAt": "2025-01-15",
|
|
1033
|
+
"updatedAt": "2025-01-15",
|
|
1034
|
+
"businessTransactionDetails": {
|
|
1035
|
+
"businessTransactionResourceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
|
1036
|
+
"ocrJobType": "SYNC",
|
|
1037
|
+
"workflowStatus": "TRANSACTION_CREATED"
|
|
1038
|
+
}
|
|
1039
|
+
}],
|
|
1040
|
+
"totalElements": 1,
|
|
1041
|
+
"totalPages": 1
|
|
1042
|
+
}
|
|
1043
|
+
```
|
|
1044
|
+
|
|
1045
|
+
**Filter fields:**
|
|
1046
|
+
- `resourceId`: StringExpression (eq, contains) — workflow ID from magic create response
|
|
1047
|
+
- `documentType`: Array — SALE, PURCHASE, SALE_CREDIT_NOTE, PURCHASE_CREDIT_NOTE, BANK_STATEMENT
|
|
1048
|
+
- `status`: Array — SUBMITTED, PROCESSING, COMPLETED, FAILED
|
|
1049
|
+
- `fileName`: StringExpression — original uploaded filename
|
|
1050
|
+
- `fileType`: Array — PDF, PNG, JPEG, JPG, HEIC, CSV, XLS, XLSX, EML
|
|
1051
|
+
- `createdAt`: DateExpression (eq, gte, lte) — workflow creation date
|
|
1052
|
+
|
|
1053
|
+
**Workflow for agents:**
|
|
1054
|
+
1. Upload via `POST /magic/createBusinessTransactionFromAttachment` → get `workflowResourceId`
|
|
1055
|
+
2. Search with `filter.resourceId.eq` → check `status`
|
|
1056
|
+
3. When `COMPLETED` → read `businessTransactionDetails.businessTransactionResourceId`
|
|
1057
|
+
4. Use the BT resource ID with `GET /invoices/:id`, `GET /bills/:id`, `GET /customer-credit-notes/:id`, or `GET /supplier-credit-notes/:id`
|
|
989
1058
|
|
|
990
1059
|
---
|
|
991
1060
|
|
|
@@ -381,7 +381,8 @@
|
|
|
381
381
|
|
|
382
382
|
| Method | Path | Description |
|
|
383
383
|
|--------|------|-------------|
|
|
384
|
-
| POST | `/magic/createBusinessTransactionFromAttachment` | **Jaz Magic: Extraction & Autofill.** Upload PDF/JPG → full extraction pipeline (OCR, line items, contact matching, CoA ML learning) → draft
|
|
384
|
+
| POST | `/magic/createBusinessTransactionFromAttachment` | **Jaz Magic: Extraction & Autofill.** Upload PDF/JPG → full extraction pipeline (OCR, line items, contact matching, CoA ML learning) → draft transaction with all fields autofilled. Supports `INVOICE`, `BILL`, `CUSTOMER_CREDIT_NOTE`, `SUPPLIER_CREDIT_NOTE`. FILE mode = multipart (`sourceFile` blob), URL mode = JSON (`sourceURL`). Async — returns `workflowResourceId` for tracking via workflow search. Request maps: `INVOICE`→`SALE`, `BILL`→`PURCHASE`, `CUSTOMER_CREDIT_NOTE`→`SALE_CREDIT_NOTE`, `SUPPLIER_CREDIT_NOTE`→`PURCHASE_CREDIT_NOTE`. |
|
|
385
|
+
| POST | `/magic/workflows/search` | **Workflow search.** Track magic upload status across BT extractions and bank imports. Filter by `resourceId`, `documentType` (SALE/PURCHASE/SALE_CREDIT_NOTE/PURCHASE_CREDIT_NOTE/BANK_STATEMENT), `status` (SUBMITTED/PROCESSING/COMPLETED/FAILED), `fileName`, `fileType`, `createdAt`. Response includes `businessTransactionDetails.businessTransactionResourceId` (the draft BT ID) when COMPLETED. |
|
|
385
386
|
| POST | `/magic/importBankStatementFromAttachment` | Convert bank statement → entries |
|
|
386
387
|
| PUT | `/invoices/magic-update` | AI-enhanced invoice update |
|
|
387
388
|
| PUT | `/bills/magic-update` | AI-enhanced bill update |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-conversion
|
|
3
|
-
version: 4.
|
|
3
|
+
version: 4.3.0
|
|
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.
|
|
3
|
+
version: 4.3.0
|
|
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,31 +1,34 @@
|
|
|
1
1
|
# Document Collection
|
|
2
2
|
|
|
3
|
-
Scan and classify client documents (invoices, bills, bank statements) from local directories or cloud share links (Dropbox, Google Drive, OneDrive). Outputs classified file paths with metadata
|
|
3
|
+
Scan and classify client documents (invoices, bills, credit notes, bank statements) from local directories or cloud share links (Dropbox, Google Drive, OneDrive). Outputs classified file paths with metadata. Supports encrypted PDF detection and decryption via `qpdf`. The AI agent handles uploads via the api skill.
|
|
4
4
|
|
|
5
5
|
## When to Use
|
|
6
6
|
|
|
7
|
-
- Client sends a folder of PDFs (invoices, bills, receipts) for bulk processing
|
|
7
|
+
- Client sends a folder of PDFs (invoices, bills, credit notes, receipts) for bulk processing
|
|
8
8
|
- Processing bank statement CSVs/OFX files for import
|
|
9
9
|
- Migrating documents from file dumps (Dropbox, shared folders, email attachments)
|
|
10
10
|
- Processing documents from a shared Dropbox, Google Drive, or OneDrive link
|
|
11
11
|
- Batch-processing scanned documents during onboarding
|
|
12
|
+
- Handling password-protected bank statement PDFs (auto-detection + decryption)
|
|
12
13
|
|
|
13
14
|
## How It Works
|
|
14
15
|
|
|
15
16
|
```
|
|
16
17
|
Source (local or cloud) CLI Output (IngestPlan)
|
|
17
18
|
┌───────────────┐ ┌──────────────────────────────────────────┐
|
|
18
|
-
│ invoices/ │── scan + classify ─►
|
|
19
|
+
│ invoices/ │── scan + classify ─► documentType: INVOICE │
|
|
19
20
|
│ inv-001.pdf │ │ sizeBytes: 45230 │
|
|
20
|
-
│
|
|
21
|
-
│
|
|
21
|
+
│ credit-notes/ │── scan + classify ─► documentType: CUSTOMER_CREDIT_NOTE │
|
|
22
|
+
│ cn-001.pdf │ │ │
|
|
23
|
+
│ bills/ │── scan + classify ─► documentType: BILL │
|
|
22
24
|
│ acme-jan.pdf│ │ │
|
|
23
|
-
│ bank/ │── scan + classify ─►
|
|
24
|
-
│ dbs-jan.csv │ │
|
|
25
|
+
│ bank/ │── scan + classify ─► documentType: BANK_STATEMENT │
|
|
26
|
+
│ dbs-jan.csv │ │ encrypted: true (if password-protected) │
|
|
27
|
+
│ dbs-feb.pdf │ │ │
|
|
25
28
|
└───────────────┘ └──────────────────────────────────────────┘
|
|
26
29
|
│
|
|
27
30
|
AI Agent reads plan,
|
|
28
|
-
uploads via api skill
|
|
31
|
+
uploads via api skill / clio magic
|
|
29
32
|
```
|
|
30
33
|
|
|
31
34
|
Cloud links are downloaded to a temp directory first, then scanned through the same pipeline.
|
|
@@ -36,14 +39,18 @@ The tool auto-classifies documents by **folder name** (case-insensitive prefix m
|
|
|
36
39
|
|
|
37
40
|
| Folder name pattern | Classification |
|
|
38
41
|
|---|---|
|
|
39
|
-
| `invoice*`, `sales*`, `ar*`, `receivable*`, `revenue*` | INVOICE |
|
|
42
|
+
| `invoice*`, `sales*`, `ar*`, `receivable*`, `revenue*`, `customer*` | INVOICE |
|
|
43
|
+
| `credit-note*`, `cn*`, `customer-credit*`, `sales-credit*` | CUSTOMER_CREDIT_NOTE |
|
|
44
|
+
| `debit-note*`, `dn*`, `supplier-credit*`, `vendor-credit*`, `purchase-credit*` | SUPPLIER_CREDIT_NOTE |
|
|
40
45
|
| `bill*`, `purchase*`, `expense*`, `ap*`, `payable*`, `supplier*`, `vendor*`, `cost*` | BILL |
|
|
41
|
-
| `bank*`, `statement*`, `recon*` | BANK_STATEMENT |
|
|
46
|
+
| `bank*`, `statement*`, `recon*`, `payment*`, `transaction*` | BANK_STATEMENT |
|
|
42
47
|
| (unknown) | UNKNOWN — skipped unless `--type` forced |
|
|
43
48
|
|
|
49
|
+
Multilingual support: Filipino/Tagalog, Bahasa Indonesia/Malay, Vietnamese, and Mandarin (pinyin) folder names are also recognized for all five document types.
|
|
50
|
+
|
|
44
51
|
### File Extension Filters
|
|
45
52
|
|
|
46
|
-
- **Invoices/Bills**: `.pdf`, `.jpg`, `.jpeg`, `.png`
|
|
53
|
+
- **Invoices/Bills/Credit Notes**: `.pdf`, `.jpg`, `.jpeg`, `.png`
|
|
47
54
|
- **Bank Statements**: `.csv`, `.ofx`
|
|
48
55
|
- **Skipped** (with warning): `.xlsx`, `.xls`, `.doc`, `.docx`, `.txt`, `.zip`, `.rar`, `.7z`
|
|
49
56
|
|
|
@@ -88,6 +95,10 @@ clio jobs document-collection ingest --source "https://www.dropbox.com/..." --ti
|
|
|
88
95
|
|
|
89
96
|
# Force classification (skip auto-detect)
|
|
90
97
|
clio jobs document-collection ingest --source ./scans/ --type invoice [--json]
|
|
98
|
+
clio jobs document-collection ingest --source ./scans/ --type credit-note-customer [--json]
|
|
99
|
+
|
|
100
|
+
# Scan + upload (decrypt encrypted PDFs with password)
|
|
101
|
+
clio jobs document-collection ingest --source ./bank-docs/ --upload --bank-account "DBS Checking" --pdf-password "mypass" --json
|
|
91
102
|
```
|
|
92
103
|
|
|
93
104
|
### Options
|
|
@@ -95,7 +106,11 @@ clio jobs document-collection ingest --source ./scans/ --type invoice [--json]
|
|
|
95
106
|
| Flag | Description |
|
|
96
107
|
|------|-------------|
|
|
97
108
|
| `--source <path\|url>` | Local directory path or public cloud share link — Dropbox, Google Drive, OneDrive (required) |
|
|
98
|
-
| `--type <type>` | Force all files to: `invoice`, `bill`, or `bank-statement` |
|
|
109
|
+
| `--type <type>` | Force all files to: `invoice`, `bill`, `credit-note-customer`, `credit-note-supplier`, or `bank-statement` |
|
|
110
|
+
| `--upload` | Upload classified files to Jaz after scanning (requires auth) |
|
|
111
|
+
| `--bank-account <name-or-id>` | Bank account name or resourceId (required for bank statements) |
|
|
112
|
+
| `--pdf-password <password>` | Password for encrypted PDFs — same password applied to all. Requires `qpdf` installed (`brew install qpdf`) |
|
|
113
|
+
| `--api-key <key>` | API key for upload (or use `JAZ_API_KEY` env var) |
|
|
99
114
|
| `--timeout <ms>` | Download timeout in milliseconds (default: 30000 for files, 120000 for folders) |
|
|
100
115
|
| `--currency <code>` | Functional/reporting currency label |
|
|
101
116
|
| `--json` | Structured JSON output with absolute file paths |
|
|
@@ -129,6 +144,7 @@ The `--json` output includes absolute file paths, classification, and size for e
|
|
|
129
144
|
"uploadable": 1,
|
|
130
145
|
"needClassification": 0,
|
|
131
146
|
"skipped": 0,
|
|
147
|
+
"encrypted": 0,
|
|
132
148
|
"byType": { "INVOICE": 1 }
|
|
133
149
|
}
|
|
134
150
|
}
|
|
@@ -136,6 +152,36 @@ The `--json` output includes absolute file paths, classification, and size for e
|
|
|
136
152
|
|
|
137
153
|
For cloud sources, `localPath` points to the temp directory where files were downloaded.
|
|
138
154
|
|
|
155
|
+
## Encrypted PDF Support
|
|
156
|
+
|
|
157
|
+
Bank statements and some government documents are often delivered as password-protected PDFs. The Magic API cannot process encrypted PDFs, so the tool detects them during scan and decrypts before upload.
|
|
158
|
+
|
|
159
|
+
### Detection
|
|
160
|
+
|
|
161
|
+
During scan, each `.pdf` file is checked for a `/Encrypt` dictionary entry in the PDF binary. Encrypted files are flagged with `encrypted: true` in the plan and shown with a `(encrypted)` tag in the output.
|
|
162
|
+
|
|
163
|
+
### Decryption
|
|
164
|
+
|
|
165
|
+
Decryption requires `qpdf` (a system CLI tool):
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# Install qpdf
|
|
169
|
+
brew install qpdf # macOS
|
|
170
|
+
sudo apt install qpdf # Ubuntu/Debian
|
|
171
|
+
choco install qpdf # Windows
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
When `--upload` is used with `--pdf-password`, encrypted PDFs are decrypted to a temp file, uploaded, then cleaned up. The same password is applied to all encrypted files in the batch.
|
|
175
|
+
|
|
176
|
+
### Error Handling (JSON mode)
|
|
177
|
+
|
|
178
|
+
If encrypted PDFs are found during `--upload` without the required dependencies, the tool outputs structured errors for agent consumption:
|
|
179
|
+
|
|
180
|
+
| Error Code | Condition | Action |
|
|
181
|
+
|------------|-----------|--------|
|
|
182
|
+
| `ENCRYPTED_PDF_NO_QPDF` | qpdf not installed | Install qpdf, then retry |
|
|
183
|
+
| `ENCRYPTED_PDF_NO_PASSWORD` | No `--pdf-password` provided | Retry with `--pdf-password <password>` |
|
|
184
|
+
|
|
139
185
|
## Phases (Blueprint)
|
|
140
186
|
|
|
141
187
|
When run without `ingest` subcommand, produces a 4-phase blueprint:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-recipes
|
|
3
|
-
version: 4.
|
|
3
|
+
version: 4.3.0
|
|
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 10 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.
|
|
@@ -2,7 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { listAccounts, searchAccounts, createAccount, deleteAccount } from '../core/api/chart-of-accounts.js';
|
|
3
3
|
import { apiAction } from './api-action.js';
|
|
4
4
|
import { parsePositiveInt, parseNonNegativeInt, readBodyInput, requireFields } from './parsers.js';
|
|
5
|
-
import { paginatedFetch } from './pagination.js';
|
|
5
|
+
import { paginatedFetch, paginatedJson, displaySlice } from './pagination.js';
|
|
6
6
|
export function registerAccountsCommand(program) {
|
|
7
7
|
const accounts = program
|
|
8
8
|
.command('accounts')
|
|
@@ -14,18 +14,22 @@ export function registerAccountsCommand(program) {
|
|
|
14
14
|
.option('--limit <n>', 'Max results (default 100)', parsePositiveInt)
|
|
15
15
|
.option('--offset <n>', 'Offset for pagination', parseNonNegativeInt)
|
|
16
16
|
.option('--all', 'Fetch all pages')
|
|
17
|
+
.option('--max-rows <n>', 'Max rows for --all (default 10000)', parsePositiveInt)
|
|
17
18
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
18
19
|
.option('--json', 'Output as JSON')
|
|
19
20
|
.action(apiAction(async (client, opts) => {
|
|
20
|
-
const
|
|
21
|
+
const result = await paginatedFetch(opts, (p) => listAccounts(client, p), { label: 'Fetching accounts' });
|
|
21
22
|
if (opts.json) {
|
|
22
|
-
console.log(
|
|
23
|
+
console.log(paginatedJson(result, opts));
|
|
23
24
|
}
|
|
24
25
|
else {
|
|
25
|
-
console.log(chalk.bold(`Accounts (${data.length} of ${totalElements}):\n`));
|
|
26
|
-
|
|
26
|
+
console.log(chalk.bold(`Accounts (${result.data.length} of ${result.totalElements}):\n`));
|
|
27
|
+
const { items, overflow } = displaySlice(result.data);
|
|
28
|
+
for (const a of items) {
|
|
27
29
|
console.log(` ${chalk.cyan(a.resourceId)} ${a.code ?? ''} ${a.name} ${chalk.dim(a.accountType)}`);
|
|
28
30
|
}
|
|
31
|
+
if (overflow > 0)
|
|
32
|
+
console.log(chalk.dim(` ... and ${overflow.toLocaleString()} more (use --json for full output)`));
|
|
29
33
|
}
|
|
30
34
|
}));
|
|
31
35
|
// ── clio accounts search ────────────────────────────────────────
|
|
@@ -37,24 +41,28 @@ export function registerAccountsCommand(program) {
|
|
|
37
41
|
.option('--limit <n>', 'Max results (default 20)', parsePositiveInt)
|
|
38
42
|
.option('--offset <n>', 'Offset for pagination', parseNonNegativeInt)
|
|
39
43
|
.option('--all', 'Fetch all pages')
|
|
44
|
+
.option('--max-rows <n>', 'Max rows for --all (default 10000)', parsePositiveInt)
|
|
40
45
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
41
46
|
.option('--json', 'Output as JSON')
|
|
42
47
|
.action((query, opts) => apiAction(async (client) => {
|
|
43
48
|
const filter = { or: { name: { contains: query }, code: { contains: query } } };
|
|
44
49
|
const sort = { sortBy: [opts.sort ?? 'code'], order: (opts.order ?? 'ASC') };
|
|
45
|
-
const
|
|
50
|
+
const result = await paginatedFetch(opts, ({ limit, offset }) => searchAccounts(client, { filter, limit, offset, sort }), { label: 'Searching accounts', defaultLimit: 20 });
|
|
46
51
|
if (opts.json) {
|
|
47
|
-
console.log(
|
|
52
|
+
console.log(paginatedJson(result, opts));
|
|
48
53
|
}
|
|
49
54
|
else {
|
|
50
|
-
if (data.length === 0) {
|
|
55
|
+
if (result.data.length === 0) {
|
|
51
56
|
console.log(chalk.yellow('No accounts found.'));
|
|
52
57
|
return;
|
|
53
58
|
}
|
|
54
|
-
console.log(chalk.bold(`Found ${data.length} account(s):\n`));
|
|
55
|
-
|
|
59
|
+
console.log(chalk.bold(`Found ${result.data.length} account(s):\n`));
|
|
60
|
+
const { items, overflow } = displaySlice(result.data);
|
|
61
|
+
for (const a of items) {
|
|
56
62
|
console.log(` ${chalk.cyan(a.resourceId)} ${a.code ?? ''} ${a.name} ${chalk.dim(a.accountType)}`);
|
|
57
63
|
}
|
|
64
|
+
if (overflow > 0)
|
|
65
|
+
console.log(chalk.dim(` ... and ${overflow.toLocaleString()} more (use --json for full output)`));
|
|
58
66
|
}
|
|
59
67
|
})(opts));
|
|
60
68
|
// ── clio accounts create ──────────────────────────────────────
|
package/dist/commands/bank.js
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { basename, extname, resolve } from 'node:path';
|
|
4
|
+
import { listBankAccounts, getBankAccount, searchBankRecords, importBankStatement, } from '../core/api/bank.js';
|
|
3
5
|
import { apiAction } from './api-action.js';
|
|
4
6
|
import { parsePositiveInt } from './parsers.js';
|
|
7
|
+
const BANK_MIME_MAP = {
|
|
8
|
+
'.csv': 'text/csv',
|
|
9
|
+
'.ofx': 'application/x-ofx',
|
|
10
|
+
'.xls': 'application/vnd.ms-excel',
|
|
11
|
+
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
12
|
+
};
|
|
5
13
|
export function registerBankCommand(program) {
|
|
6
14
|
const bank = program
|
|
7
15
|
.command('bank')
|
|
@@ -92,4 +100,38 @@ export function registerBankCommand(program) {
|
|
|
92
100
|
}
|
|
93
101
|
}
|
|
94
102
|
})(opts));
|
|
103
|
+
// ── clio bank import ──────────────────────────────────────────
|
|
104
|
+
bank
|
|
105
|
+
.command('import')
|
|
106
|
+
.description('Import a bank statement file (CSV, OFX, XLS, XLSX)')
|
|
107
|
+
.requiredOption('--file <path>', 'Bank statement file path')
|
|
108
|
+
.requiredOption('--account <resourceId>', 'Bank account resourceId')
|
|
109
|
+
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
110
|
+
.option('--json', 'Output as JSON')
|
|
111
|
+
.action(apiAction(async (client, opts) => {
|
|
112
|
+
const filePath = resolve(opts.file);
|
|
113
|
+
const ext = extname(filePath).toLowerCase();
|
|
114
|
+
const mime = BANK_MIME_MAP[ext];
|
|
115
|
+
if (!mime) {
|
|
116
|
+
console.error(chalk.red(`Error: unsupported file type "${ext}". Supported: ${Object.keys(BANK_MIME_MAP).join(', ')}`));
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
const buffer = readFileSync(filePath);
|
|
120
|
+
const blob = new Blob([buffer], { type: mime });
|
|
121
|
+
const fileName = basename(filePath);
|
|
122
|
+
const res = await importBankStatement(client, {
|
|
123
|
+
businessTransactionType: 'BANK_STATEMENT',
|
|
124
|
+
accountResourceId: opts.account,
|
|
125
|
+
sourceFile: blob,
|
|
126
|
+
sourceFileName: fileName,
|
|
127
|
+
});
|
|
128
|
+
if (opts.json) {
|
|
129
|
+
console.log(JSON.stringify(res.data, null, 2));
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
console.log(chalk.green('Bank statement uploaded — processing started.'));
|
|
133
|
+
console.log(chalk.bold('File:'), fileName);
|
|
134
|
+
console.log(chalk.dim('Check status: clio magic search --type bank-statement'));
|
|
135
|
+
}
|
|
136
|
+
}));
|
|
95
137
|
}
|