jaz-cli 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,216 @@
1
+ # Feature Glossary
2
+
3
+ Business context for Jaz platform features — what they are, when to use them, and which API endpoints correspond. This supplements the API-focused reference files with product knowledge that helps AI agents understand the *purpose* behind API calls.
4
+
5
+ For full help center content split by section, see [help-center-mirror/](../help-center-mirror/) or [help.jaz.ai](https://help.jaz.ai). For the complete endpoint catalog (80+), see [full-api-surface.md](./full-api-surface.md).
6
+
7
+ ---
8
+
9
+ ## Invoices
10
+
11
+ Sales documents sent to customers for goods/services rendered. Track Accounts Receivable, support multi-currency with FX gain/loss, and integrate with payments, customer credits, delivery slips, and recurring schedules. Statuses: draft, payment due, overdue, partially paid, fully paid.
12
+
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
+
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)`.
16
+
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`
18
+
19
+ ---
20
+
21
+ ## Bills
22
+
23
+ Purchase documents from suppliers for goods/services received. Track Accounts Payable with multi-currency FX. Bills follow the same lifecycle as invoices but with reversed RGL logic and admin-only approval workflows. Supports withholding tax (WHT) on line items.
24
+
25
+ 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.
26
+
27
+ Transaction fees are added to cash spent (not deducted like invoices). RGL = `(Cash spent / Payment rate) - (Bill payment / Transaction rate)`.
28
+
29
+ **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`
30
+
31
+ ---
32
+
33
+ ## Customer Credits
34
+
35
+ Credit notes that reduce amounts owed by customers — issued for returns, discounts, or corrections. Can be applied to invoices (same currency only) or refunded to customers. Statuses: draft, credit available, fully applied.
36
+
37
+ Active credits only can be applied to invoices. Application has no additional ledger impact (already accounted at creation). Refunds use `refundAmount` + `refundMethod` (NOT `paymentAmount`/`paymentMethod`). Voiding a credit deletes associated refunds and unapplies from invoices.
38
+
39
+ **API**: CRUD `GET/POST/PUT/DELETE /customer-credit-notes`, `POST /customer-credit-notes/search`, `POST /customer-credit-notes/:id/refunds`, `GET /customer-credit-notes/:id/refunds`, `POST /customer-credit-notes/:id/credits` (apply to invoice), `GET /customer-credit-notes/:id/download`
40
+
41
+ ---
42
+
43
+ ## Supplier Credits
44
+
45
+ Credit notes that reduce amounts owed to suppliers — issued by suppliers for returns, discounts, or corrections. Can be applied to bills (same currency only) or refunded from suppliers. Same lifecycle as customer credits.
46
+
47
+ Supports withholding tax on credit line items. Supplier credit note PDFs are NOT available for download (internal records only). Import supports credit notes but NOT refunds.
48
+
49
+ **API**: CRUD `GET/POST/PUT/DELETE /supplier-credit-notes`, `POST /supplier-credit-notes/search`, `POST /supplier-credit-notes/:id/refunds`, `GET /supplier-credit-notes/:id/refunds`, `POST /supplier-credit-notes/:id/credits` (apply to bill)
50
+
51
+ ---
52
+
53
+ ## Deposits
54
+
55
+ Track advance payments and prepaid balances. Customer deposits are liabilities (money received before goods/services delivered). Supplier deposits are assets (money paid before goods/services received). Support multi-currency, top-ups, drawdowns, and integration with invoice/bill payment workflows.
56
+
57
+ Can block payments if deposit balance is insufficient. View all contacts with deposits and filter by balance status. Managed via dedicated deposit accounts in the Chart of Accounts.
58
+
59
+ There is no dedicated `/deposits` endpoint (returns 404). Deposits are managed through deposit-designated CoA accounts, with transactions recorded as journal entries and payments on invoices/bills drawing from those deposit accounts.
60
+
61
+ **API**: `POST /journals` (record deposit top-ups/drawdowns via deposit CoA accounts), `POST /chart-of-accounts` (create deposit accounts), `POST /invoices/:id/payments` / `POST /bills/:id/payments` (draw from deposit account via `accountResourceId`)
62
+
63
+ ---
64
+
65
+ ## Journal Entries
66
+
67
+ Manual accounting entries for non-payment transactions. Three types: Manual Journals (multi-line debit/credit entries), Cash Journals (2-line cash transfers between bank accounts with cross-currency support), and Transfer Journals (year-end trial balance transfers, non-editable).
68
+
69
+ Minimum 2 balanced entries required. Cash journals are restricted to exactly 2 lines. Bank/cash/current asset/equity/liability accounts cannot have tax profiles applied. Supports scheduled/recurring journals with dynamic scheduler strings (`{{YEAR}}`, `{{MONTH}}`).
70
+
71
+ Cash transfer FX logic: if either side is base currency, keep as-is; if both non-base, fetch rate for cash-out and derive cash-in. Transfer rate = `Cash-in amount / Cash-out amount`.
72
+
73
+ **API**: CRUD `GET/POST/PUT/DELETE /journals`, `POST /journals/search`, `POST/GET/DELETE /journals/:id/attachments`, `POST /cash-in-journals`, `POST /cash-out-journals`, `POST /cash-transfer-journals`, `POST /cashflow-transactions/search`, `DELETE /cashflow-journals/:id`, `POST /scheduled/journals` (CRUD)
74
+
75
+ ---
76
+
77
+ ## Capsules
78
+
79
+ Containers that group related transactions for complex accounting scenarios. Use cases: prepaid expenses (annual insurance amortization), deferred revenue, accrued expenses, fixed asset acquisitions (CIP), intercompany transactions, renovation projects.
80
+
81
+ A capsule links invoices, bills, journals, and schedulers into a single logical unit. The ledger can be filtered and grouped by capsule. Capsule Types are customizable labels. A capsule must be empty before deletion. Clio (AI assistant) can auto-detect complex transactions and suggest capsule creation with linked schedulers.
82
+
83
+ **API**: CRUD `GET/POST/PUT/DELETE /capsules`, `POST /capsules/search`, `POST /move-transaction-capsules`, CRUD `GET/POST/PUT/DELETE /capsuleTypes`, `POST /capsuleTypes/search` (also available as `/capsule-types/*` kebab-case aliases)
84
+
85
+ ---
86
+
87
+ ## Reports
88
+
89
+ Financial statements and accounting reports for compliance, analysis, and audit. All reports support multi-currency display, exchange rate transparency, and Excel/PDF export.
90
+
91
+ | Report | What it shows |
92
+ |--------|--------------|
93
+ | **Trial Balance** | Debit/credit verification worksheet — if unbalanced, arithmetic error exists |
94
+ | **Balance Sheet** | Assets/liabilities/equity snapshot at a point in time |
95
+ | **Profit & Loss** | Revenue/costs/expenses over a period; supports tracking tag filters |
96
+ | **Cashflow Statement** | Cash inflows/outflows categorized as operating/investing/financing |
97
+ | **General Ledger** | Complete record of all transactions; group by accounts/contacts/transactions/relationships/tax profiles/capsules |
98
+ | **Aged Receivables** | Outstanding invoices by overdue periods; summary and detail views |
99
+ | **Aged Payables** | Outstanding bills by overdue periods; summary and detail views |
100
+ | **Cash Balance** | Bank/cash account balances at a specific date |
101
+ | **Equity Movement** | Changes in equity accounts over a period |
102
+ | **Bank Balance Summary** | Consolidated bank account balances with lock dates and currencies |
103
+
104
+ FX-related accounts auto-created: FX Bank Revaluation, FX Realized, FX Unrealized, FX Rounding (each with Gains and Loss variants). Retained Earnings auto-updates at financial year-end via CYE rollover.
105
+
106
+ **API**: `POST /generate-reports/trial-balance`, `POST /generate-reports/balance-sheet`, `POST /generate-reports/profit-and-loss`, `POST /generate-reports/general-ledger`, `POST /generate-reports/cashflow`, `POST /generate-reports/cash-balance`, `POST /generate-reports/ar-report`, `POST /generate-reports/ap-report`, `POST /generate-reports/bank-balance-summary`, `POST /generate-reports/equity-movement`, and more. Data exports: `POST /data-exports/trial-balance`, `POST /data-exports/profit-and-loss`, `POST /data-exports/general-ledger`, etc. Also: `POST /generate-report-packs-pdf`, `POST /statement-of-account-export`
107
+
108
+ ---
109
+
110
+ ## Contacts
111
+
112
+ Customer and supplier records. A single contact can be both customer AND supplier simultaneously. Each contact has transaction settings (default payment terms, currency, GST profile, WHT codes, PDF/email templates) that auto-fill when creating transactions.
113
+
114
+ Contact Groups organize contacts for report filtering (Aged Receivables/Payables, Ledger). Contact Relationships use pre-defined types (Associate Company, Director/Shareholder, Parent Company, etc.) for related-party reporting. Sales Activity PDFs show statement of balances and accounts per currency.
115
+
116
+ **API**: CRUD `GET/POST/PUT/DELETE /contacts`, `POST /contacts/search`, CRUD `GET/POST/PUT/DELETE /contact-groups`, `POST /contact-groups/search`
117
+
118
+ ---
119
+
120
+ ## Products & Items
121
+
122
+ Items for sales (revenue accounts) and purchases (expense accounts). Each item has Internal Name (org use), Sale Name (invoice PDF), and Purchase Name (bill PDF). Items support default tax profiles, COGS tracking, and unique item codes.
123
+
124
+ Inventory items use Fixed Cost (non-GAAP, for fully-landed costs) or Weighted Average Cost (recalculates on each stock addition). Costing method cannot be changed after selection. "Block insufficient deductions" prevents sales reducing stock below zero.
125
+
126
+ Catalogs group items for bulk application to invoices/credits/scheduled invoices/subscriptions. Catalogs can be assigned to contact groups.
127
+
128
+ **API**: CRUD `GET/POST/PUT/DELETE /items`, `POST /items/search`, `DELETE /items/:id` (also deletes inventory items), `POST /inventory-items`, `GET /inventory-items`, `GET /inventory-item-balance/:id`, CRUD `GET/POST/PUT/DELETE /catalogs`, `POST /catalogs/search`, `POST /purchase-items/search`
129
+
130
+ ---
131
+
132
+ ## Bank Reconciliations
133
+
134
+ Match bank statement lines to Jaz transactions to verify cash balances. This is where most day-to-day bookkeeping happens — reconciling what the bank shows vs what Jaz has recorded.
135
+
136
+ **Auto-Reconciliation**: Runs daily at midnight with configurable rules — Match (existing transactions), Quick Reconcile (create journals), Apply Rule (bank rules), Cash Transfer. Three magic thresholds: Strict, Balanced, Lenient. Can exclude specific records via Saved Search.
137
+
138
+ **Magic Match**: Auto-suggests transaction matches within 30 days (with contact) or 3 days (payments only), matching by amount + contact name.
139
+
140
+ **Bank Feeds**: Connect Airwallex, Aspire, Stripe, Wise, or Xendit for automated statement sync (up to 12 months history, daily auto-sync).
141
+
142
+ **Bank Rules**: Auto-allocate amounts using percentage-only or fixed+percentage splits (max 10 fixed + 10 percentage lines). Support dynamic strings like `#{{bankReference}}`, `#{{payeeName}}`.
143
+
144
+ Statement amounts are recorded in the bank account's currency — no auto-conversion. Cross-currency transactions prompt for cash received/spent in statement currency. Reconciled transactions become uneditable (must reset to edit).
145
+
146
+ **API**: `POST /bank-records/:accountResourceId` (JSON import), `POST /bank-records/:accountResourceId/search`, `POST /magic/importBankStatementFromAttachment` (multipart CSV/OFX), CRUD `GET/POST/PUT/DELETE /bank-rules`, `POST /bank-rules/search`, `GET /bank-accounts`, `POST /view-auto-reconciliation`
147
+
148
+ ---
149
+
150
+ ## Approvals
151
+
152
+ Workflow for draft invoices and bills requiring admin sign-off before activation. Three user roles: Admins (approve + create active), Preparers (submit drafts for approval), Members (submit own drafts only). Status progression: Draft → For Approval → Approved (active). Approval PDFs capture Submitted By / Approved By audit trail.
153
+
154
+ **API**: `PUT /invoices/:id/approve`, `PUT /bills/:id/approve`
155
+
156
+ ---
157
+
158
+ ## Fixed Assets
159
+
160
+ Fixed asset register with straight-line depreciation. Register assets from invoice/bill line items or standalone. Auto-posts monthly depreciation journal entries. Formula: `(Cost - Salvage Value) / Useful Life`.
161
+
162
+ Fixed assets lock their linked line items — cannot edit account, amounts, or exchange rates on a line item with an active fixed asset. Must delete the asset before modifying the line item. Fixed asset journals can be grouped in capsules for CIP, renovations, and disposals.
163
+
164
+ **API**: CRUD `GET/POST/PUT/DELETE /fixed-assets`, `POST /fixed-assets/search`, `POST /mark-as-sold/fixed-assets`, `POST /undo-disposal/fixed-assets/:id`, `POST /discard-fixed-assets/:id`, `POST /transfer-fixed-assets`, `POST /fixed-assets-types/search`
165
+
166
+ ---
167
+
168
+ ## AI Agents
169
+
170
+ **Clio**: AI assistant for accounting tasks. Auto-extracts invoice/bill data from PDF/image attachments (OCR), detects multi-step transactions (prepaid expenses, deferred revenue, accruals), and suggests capsule creation with linked schedulers. Creates draft transactions for user review. Session-based (no persistent chat history). Available on web and Android (iOS coming).
171
+
172
+ **Agent Builder**: Configure custom AI agents in Settings > Agent Builder with name, email (a-z, 0-9, + symbol), and workflow preferences.
173
+
174
+ **Jaz Magic**: Contact-level setting controlling auto-extraction behavior — line items (detailed extraction), summary totals (single amount), or none. Up to 10 images can be merged into a single PDF.
175
+
176
+ **API**: `POST /magic/createBusinessTransactionFromAttachment` (OCR PDF → draft transaction), `POST /magic/importBankStatementFromAttachment`, `PUT /invoices/magic-update`, `PUT /bills/magic-update`, `PUT /journals/magic-update`, `GET /invoices/magic-search`, `GET /bills/magic-search` (all magic endpoints use `x-magic-api-key`)
177
+
178
+ ---
179
+
180
+ ## Settings & Configuration
181
+
182
+ **Chart of Accounts**: Account codes, names, types (Revenue, Expense, Asset, Liability, Equity), subtypes, lock dates per account. System accounts (AR, AP, FX) are auto-created and cannot be deleted.
183
+
184
+ **Tax Profiles**: GST/VAT codes with rates, scoped to sales-only, purchases-only, or both. Pre-provisioned per org — discover via GET, never create.
185
+
186
+ **Currencies & FX Rates**: Enable currencies before use. Rate priority: transaction-level custom rate > org-level custom rate > ECB/Frankfurter auto-fetch. Rate direction: `rate` = functionalToSource (1 base = X foreign).
187
+
188
+ **Tracking Tags**: Custom labels for reporting. Apply to line items or transaction headers. Filter reports by tags but cannot group by them (except capsules in ledger).
189
+
190
+ **Custom Fields**: Text/number/date/dropdown fields. Apply to invoices/bills/journals/contacts. Can show on PDFs and be made mandatory.
191
+
192
+ **Lock Dates**: Prevent edits to transactions before a date (org-wide or per-account). Prevents backdated entries.
193
+
194
+ **User Roles**: Admin (full access), Preparer (create drafts, submit for approval), Member (own drafts only). Granular permissions by module (AR, AP, Treasury, Journals).
195
+
196
+ **API**: CRUD `GET/POST/PUT/DELETE /chart-of-accounts`, `POST /chart-of-accounts/bulk-upsert`, `POST /chart-of-accounts/search`, `GET /tax-profiles`, `POST /tax-profiles/search`, CRUD `GET/POST/PUT/DELETE /tags`, `POST /tags/search`, CRUD `GET/POST/PUT/DELETE /custom-fields`, `POST /custom-fields/search`, `POST /organization/currencies` (enable), `DELETE /organization/currencies/:code` (disable), `POST /organization-currencies/:code/rates` (set FX rate, CRUD), `GET /organization` (org details), CRUD `GET/POST/PUT/DELETE /organization/bookmarks`, CRUD `GET/POST/PUT/DELETE /nano-classifiers`, `POST /nano-classifiers/search`, `GET /organization-users`, `POST /organization-users/search`. Reference data: `GET /account-classifications`, `GET /withholding-tax-codes`, `GET /tax-types`, `GET /modules`, `GET /search` (Typesense full-text)
197
+
198
+ ---
199
+
200
+ ## Collaboration
201
+
202
+ Threaded comments on transactions for team communication and audit trails. Add comments to invoices, bills, journals, and credit notes. Tag team members with @mentions to trigger notifications.
203
+
204
+ ---
205
+
206
+ ## Data Import
207
+
208
+ Bulk import for all entity types. All imports use .xlsx templates with error review before finalizing. Limits: 1,000 rows (invoices/bills/journals/credits/items), 2MB (items), 12 files (bank statements). Imports create active transactions (not drafts) for invoices/bills. Items can update existing records based on item code.
209
+
210
+ Bank statement import supports CSV and PDF with configurable column mapping. Statement amounts recorded in bank account currency (no auto-conversion). Auto-detects date format.
211
+
212
+ **API**: `POST /magic/importBankStatementFromAttachment` (multipart: `sourceFile`, `accountResourceId`, `businessTransactionType: "BANK_STATEMENT"`, `sourceType: "FILE"`)
213
+
214
+ ---
215
+
216
+ *Maintained alongside [help.jaz.ai](https://help.jaz.ai).*
@@ -0,0 +1,428 @@
1
+ # Jaz API Field Name Map
2
+
3
+ > Complete mapping of intuitive/guessed field names to actual Jaz API field names.
4
+ > Organized by resource type. Every field verified against production API.
5
+
6
+ ---
7
+
8
+ ## Universal Fields
9
+
10
+ | What You'd Guess | Actual API Field | Context |
11
+ |------------------|-------------------|---------|
12
+ | `id` | `resourceId` | Every resource, every response |
13
+ | `contactId` | `contactResourceId` | POST body reference |
14
+ | `accountId` | `accountResourceId` | POST body reference |
15
+ | `bankAccountId` | `accountResourceId` | Payments, cash entries. **Alias `bankAccountResourceId` now accepted on POST.** |
16
+ | `taxProfileId` | `taxProfileResourceId` | POST body reference |
17
+ | `itemId` | `itemResourceId` | POST body reference |
18
+ | `creditNoteId` | `creditNoteResourceId` | POST body reference |
19
+
20
+ **Pattern**: References always use `<resource>ResourceId` suffix.
21
+ **Exception**: Bank account references in payments and cash entries use `accountResourceId` (NOT `bankAccountResourceId`).
22
+
23
+ ---
24
+
25
+ ## Date Fields
26
+
27
+ | What You'd Guess | Actual API Field | Used In |
28
+ |------------------|-------------------|---------|
29
+ | `issueDate` | `valueDate` | Invoices, bills, credit notes, journals, cash entries. **Alias `issueDate` now accepted on POST.** |
30
+ | `invoiceDate` | `valueDate` | Invoices. **Alias accepted on POST.** |
31
+ | `billDate` | `valueDate` | Bills |
32
+ | `journalDate` | `valueDate` | Journals |
33
+ | `paymentDate` | `valueDate` | Invoice/bill payments (NOT `paymentDate`!) |
34
+ | `date` (payment) | `valueDate` | Invoice/bill payments |
35
+ | `date` (bank) | `transactionDate` | Bank records |
36
+ | `asAtDate` | `endDate` | Reports (trial balance) |
37
+
38
+ **Pattern**: Transaction documents AND payments use `valueDate`. Bank records use `transactionDate`. Reports use `startDate`/`endDate`.
39
+ **CORRECTION**: Payments use `valueDate` (NOT `paymentDate` as previously documented).
40
+ **FORMAT**: All dates MUST be `YYYY-MM-DD` strings (e.g., `"2026-02-08"`). ISO datetime and epoch ms are rejected. OAS may declare `integer/int64` but strings work.
41
+
42
+ ### Date Format Matrix (Request vs Response)
43
+
44
+ | Context | Direction | Format | Example |
45
+ |---------|-----------|--------|---------|
46
+ | Create/update requests | Inbound | `YYYY-MM-DD` string | `"valueDate": "2026-02-14"` |
47
+ | Search filter dates (`DateExpression`) | Inbound | `YYYY-MM-DD` string | `{ "valueDate": { "gte": "2026-01-01" } }` |
48
+ | Search filter datetimes (`DateTimeExpression`) | Inbound | RFC3339 string | `{ "createdAt": { "gte": "2026-01-01T00:00:00Z" } }` |
49
+ | **ALL response dates** | **Outbound** | **`int64` epoch milliseconds** | `"valueDate": 1707868800000` |
50
+
51
+ **CRITICAL**: ALL dates in API responses are `int64` epoch milliseconds — including `valueDate`, `createdAt`, `updatedAt`, `approvedAt`, `submittedAt`, `matchDate`, `startDate`, `endDate`, `lastScheduleDate`, `nextScheduleDate`. To convert: `new Date(epochMs).toISOString().slice(0, 10)` → `"2026-02-14"`.
52
+
53
+ **Which fields use DateExpression (YYYY-MM-DD) vs DateTimeExpression (RFC3339)**:
54
+ - `DateExpression`: `valueDate`, `dueDate`, `startDate`, `endDate`, `purchaseDate`, `matchDate`, `approvedAt`, `submittedAt`, `depreciationStartDate`, `depreciationEndDate`, `disposalValueDate`, `proratedStartDate`, `lastScheduleDate`, `nextScheduleDate`
55
+ - `DateTimeExpression`: `createdAt`, `updatedAt` (on invoices, bills, journals, custom fields)
56
+
57
+ ---
58
+
59
+ ### Middleware Alias Table (Complete)
60
+
61
+ These aliases are applied by middleware on POST/PUT endpoints. The alias is only used if the canonical field is absent from the request body.
62
+
63
+ | Alias | Canonical | Middleware | Applied To |
64
+ |-------|-----------|------------|-----------|
65
+ | `issueDate` | `valueDate` | `txnDateAliases` | POST/PUT: invoices, bills, customer-credit-notes, supplier-credit-notes, journals, cash-in-journals, cash-out-journals, cash-transfer-journals, scheduled/invoices, scheduled/bills, scheduled/journals, scheduled/subscriptions |
66
+ | `date` | `valueDate` | `txnDateAliases` | Same as above (all transaction and scheduled create/update endpoints) |
67
+ | `paymentDate` | `valueDate` | `paymentAliases` | POST: invoice payments, bill payments. PUT: payments |
68
+ | `bankAccountResourceId` | `accountResourceId` | `paymentAliases` | Same as above |
69
+ | `paymentAmount` | `refundAmount` | `refundAliases` | POST: customer-credit-notes refunds, supplier-credit-notes refunds |
70
+ | `paymentMethod` | `refundMethod` | `refundAliases` | Same as above |
71
+ | `name` | `tagName` | `tagAliases` | POST/PUT: tags |
72
+ | `name` | `internalName` | `itemAliases` | POST: items, inventory-items |
73
+ | `accountType` | `classificationType` | Code-level alias | POST/PUT: chart-of-accounts, bulk-upsert |
74
+ | `currencyCode` | `currency` | Code-level alias | POST: chart-of-accounts bulk-upsert |
75
+
76
+ ---
77
+
78
+ ## Organization & Auth
79
+
80
+ | What You'd Guess | Actual API Field | Notes |
81
+ |------------------|-------------------|-------|
82
+ | `apiKey` header | `x-jk-api-key` | Custom header (not Authorization: Bearer) |
83
+ | `org.id` | `data[0].resourceId` | Org endpoint returns a LIST |
84
+ | `org.baseCurrency` | `data[0].currency` | Not `baseCurrency` |
85
+ | `org.country` | `data[0].countryCode` | ISO 2-letter code |
86
+
87
+ ---
88
+
89
+ ## Chart of Accounts
90
+
91
+ | What You'd Guess | Actual API Field | Context |
92
+ |------------------|-------------------|---------|
93
+ | `chartOfAccounts` (upsert body) | `accounts` | POST bulk-upsert wrapper |
94
+ | `currencyCode` (in POST) | `currency` | POST body (GET returns `currencyCode`!) |
95
+ | `accountClass` or `accountType` | `classificationType` | POST body — uses `accountType` values |
96
+ | `type` | `accountType` | GET response field |
97
+ | `class` | `accountClass` | GET response field |
98
+ | `accountNumber` | `code` | String, can be null. **Codes differ between orgs — match by name, not code** |
99
+
100
+ ### classificationType → accountType Mapping
101
+
102
+ When POSTing, `classificationType` must be one of these exact strings (same as `accountType` from GET):
103
+
104
+ | classificationType Value | accountClass (GET) |
105
+ |-------------------------|-------------------|
106
+ | `"Bank Accounts"` | Asset |
107
+ | `"Cash"` | Asset |
108
+ | `"Current Asset"` | Asset |
109
+ | `"Fixed Asset"` | Asset |
110
+ | `"Inventory"` | Asset |
111
+ | `"Current Liability"` | Liability |
112
+ | `"Non-current Liability"` | Liability |
113
+ | `"Shareholders Equity"` | Equity |
114
+ | `"Operating Revenue"` | Revenue |
115
+ | `"Other Revenue"` | Revenue |
116
+ | `"Operating Expense"` | Expense |
117
+ | `"Direct Costs"` | Expense |
118
+
119
+ ---
120
+
121
+ ## Contacts
122
+
123
+ | What You'd Guess | Actual API Field | Notes |
124
+ |------------------|-------------------|-------|
125
+ | `contactType: "customer"` | `customer: true` | Boolean, not enum |
126
+ | `contactType: "supplier"` | `supplier: true` | Boolean, not enum |
127
+ | `defaultCurrencyCode` | `currency` | ISO code string |
128
+ | `taxRegistrationNumber` | `taxNumber` | UEN (SG), TIN (PH) |
129
+ | `address.line1` | `addressLine1` | Top-level, NOT nested |
130
+ | `address.line2` | `addressLine2` | Top-level |
131
+ | `address.city` | `city` | Top-level |
132
+ | `address.postalCode` | `postalCode` | Top-level |
133
+ | `address.country` | `countryCode` | ISO 2-letter code, top-level |
134
+ | `displayName` | `billingName` | Required, set = name |
135
+
136
+ ---
137
+
138
+ ## Items
139
+
140
+ | What You'd Guess | Actual API Field | Notes |
141
+ |------------------|-------------------|-------|
142
+ | `name` | `internalName` | Display name. **Alias `name` now accepted on POST; GET returns both `internalName` and `name`.** |
143
+ | `sku` | `itemCode` | Unique code |
144
+ | `type` | `type` | `"PRODUCT"` or `"SERVICE"` |
145
+ | `sellPrice` | `salePrice` | Decimal |
146
+ | `buyPrice` | `purchasePrice` | Decimal |
147
+ | `sellAccountId` | `saleAccountResourceId` | CoA UUID |
148
+ | `buyAccountId` | `purchaseAccountResourceId` | CoA UUID |
149
+ | `sellTaxId` | `saleTaxProfileResourceId` | Tax profile UUID |
150
+ | `buyTaxId` | `purchaseTaxProfileResourceId` | Tax profile UUID |
151
+ | `sellable` | `appliesToSale` | Boolean |
152
+ | `purchasable` | `appliesToPurchase` | Boolean |
153
+ | `sellName` | `saleItemName` | REQUIRED when `appliesToSale: true` |
154
+ | `buyName` | `purchaseItemName` | REQUIRED when `appliesToPurchase: true` |
155
+
156
+ ---
157
+
158
+ ## Invoices / Bills
159
+
160
+ | What You'd Guess | Actual API Field | Notes |
161
+ |------------------|-------------------|-------|
162
+ | `invoiceNumber` | `reference` | User-visible number |
163
+ | `referenceNumber` | `reference` | Same field |
164
+ | `issueDate` | `valueDate` | THE invoice date |
165
+ | `description` (line item) | `name` | Line item description |
166
+ | `price` (line item) | `unitPrice` | Per-unit price |
167
+ | `qty` (line item) | `quantity` | Count |
168
+ | `taxId` (line item) | `taxProfileResourceId` | Tax profile UUID |
169
+ | `accountId` (line item) | `accountResourceId` | CoA UUID (required if !saveAsDraft) |
170
+ | `isDraft` | `saveAsDraft` | Boolean — defaults to `false`. Omitting creates a finalized transaction. |
171
+ | `currencyCode: "USD"` (string for FX) | SILENTLY IGNORED | Creates invoice in base currency! No error returned |
172
+ | `currency: "USD"` (string for FX) | CAUSES 400 ERROR | "Invalid request body" — string form rejected |
173
+ | `currency` (object form) | `currency: { sourceCurrency, exchangeRate }` | **ONLY working form** for FX transactions |
174
+
175
+ ---
176
+
177
+ ## Withholding Tax (Bills & Supplier Credit Notes Only)
178
+
179
+ | What You'd Guess | Actual API Field | Notes |
180
+ |---|---|---|
181
+ | `tax` | `withholdingTax` | Nested object on each line item |
182
+ | `withholdingTaxCode` | `withholdingTax.code` | String code (e.g., "WC010") |
183
+ | `withholdingTaxRate` | `withholdingTax.rate` | Numeric percentage (e.g., 10) |
184
+ | `withholdingTaxDescription` | `withholdingTax.description` | Optional description |
185
+
186
+ **Not supported on**: Invoices, customer credit notes, journals, cash entries. Only bills and supplier credit notes.
187
+
188
+ ---
189
+
190
+ ## Journals
191
+
192
+ | What You'd Guess | Actual API Field | Notes |
193
+ |------------------|-------------------|-------|
194
+ | `lineItems` | `journalEntries` | Array of entries |
195
+ | `lines` | `journalEntries` | Same |
196
+ | `entries` | `journalEntries` | Same |
197
+ | `debit` / `credit` (entry) | `amount` + `type` | `amount`: number, `type`: `"DEBIT"` or `"CREDIT"` (UPPERCASE) |
198
+ | `currency` (top level) | DO NOT SEND | Causes "Invalid request body" |
199
+
200
+ ---
201
+
202
+ ## Cash Entries
203
+
204
+ | What You'd Guess | Actual API Field | Notes |
205
+ |------------------|-------------------|-------|
206
+ | `bankAccountResourceId` | `accountResourceId` (top level) | The BANK account UUID — NOT `bankAccountResourceId` |
207
+ | `amount` (flat) | `journalEntries[].amount` | Cash entries use `journalEntries` array, same as journals |
208
+ | `description` | NOT USED | Cash entries do not have a flat `description` field |
209
+ | `bankAccount` | `accountResourceId` (top level) | Same as above |
210
+ | offset account | `journalEntries[].accountResourceId` | The offsetting account goes in `journalEntries` |
211
+ | (omit saveAsDraft) | `saveAsDraft` | **REQUIRED** — must be included on cash-in and cash-out journals |
212
+
213
+ ---
214
+
215
+ ## Payments
216
+
217
+ | What You'd Guess | Actual API Field | Notes |
218
+ |------------------|-------------------|-------|
219
+ | `amount` | `paymentAmount` | **Bank account currency** — actual cash moved. NOT `amount`. |
220
+ | (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`). |
221
+ | `bankAccountResourceId` | `accountResourceId` | Canonical is `accountResourceId`. **Alias `bankAccountResourceId` now accepted on POST.** |
222
+ | (none) | `paymentMethod` | Required: `"BANK_TRANSFER"` |
223
+ | (none) | `reference` | Required: payment reference string |
224
+ | `date` / `paymentDate` | `valueDate` | NOT `paymentDate`, NOT `date`. Must be `YYYY-MM-DD` |
225
+ | (flat object) | `{ payments: [...] }` | Must be wrapped in array |
226
+
227
+ **Cross-currency payments**: `paymentAmount` is the bank account currency amount (actual cash moved), `transactionAmount` is the invoice/bill currency amount (applied to balance). Verified via live FX testing: USD invoice ($1000) paid from SGD bank at 1.35 rate → `paymentAmount: 1350` (SGD), `transactionAmount: 1000` (USD).
228
+ **Bill payments**: Standalone `POST /bills/{id}/payments` was broken (nil pointer dereference) — fixed in backend PR #112. Embed-in-creation pattern is still a valid alternative.
229
+ **Invoice payments**: Standalone `POST /invoices/{id}/payments` works fine.
230
+ **TransactionFeeCollected**: NOT supported on bill payments (model field missing). Only invoice payments support collected fees.
231
+
232
+ ---
233
+
234
+ ## Tags
235
+
236
+ | What You'd Guess | Actual API Field | Notes |
237
+ |------------------|-------------------|-------|
238
+ | `name` | `tagName` | **Alias `name` now accepted on POST; GET returns both `tagName` and `name`.** |
239
+
240
+ ---
241
+
242
+ ## Credit Note Applications
243
+
244
+ | What You'd Guess | Actual API Field | Notes |
245
+ |------------------|-------------------|-------|
246
+ | `{ creditNoteResourceId, amount }` | `{ credits: [{ creditNoteResourceId, amountApplied }] }` | Must wrap in `credits` array |
247
+ | `amount` | `amountApplied` | NOT `amount` |
248
+
249
+ ---
250
+
251
+ ## Custom Fields
252
+
253
+ | What You'd Guess | Actual API Field | Notes |
254
+ |------------------|-------------------|-------|
255
+ | `name` (in GET response) | `customFieldName` | GET returns both `customFieldName` and `name` alias. |
256
+ | `name` (in POST body) | `name` | POST accepts `name`. |
257
+ | `showOnPdf` | `printOnDocuments` | Required boolean |
258
+ | `appliesTo` | DO NOT SEND | Causes "Invalid request body" |
259
+ | `type` values | `"TEXT"`, `"DATE"`, `"DROPDOWN"` | UPPERCASE strings |
260
+
261
+ ---
262
+
263
+ ## Bank Records
264
+
265
+ | What You'd Guess | Actual API Field | Notes |
266
+ |------------------|-------------------|-------|
267
+ | `date` | `transactionDate` | ISO date string |
268
+ | `direction` | `type` | `"CREDIT"` or `"DEBIT"` (uppercase) |
269
+ | `memo` | `description` | Free text |
270
+ | (negative amount) | `amount` (positive) + `type` | Always positive, direction via type |
271
+
272
+ **Creating bank records**: Use multipart `POST /api/v1/magic/importBankStatementFromAttachment` — the only endpoint for creating bank records. No JSON POST endpoint exists.
273
+
274
+ ---
275
+
276
+ ## Schedulers
277
+
278
+ | What You'd Guess | Actual API Field | Notes |
279
+ |------------------|-------------------|-------|
280
+ | `frequency` | `repeat` | Creation field. `"WEEKLY"`, `"MONTHLY"`, `"QUARTERLY"`, `"YEARLY"`. NOT `frequency` or `interval` |
281
+ | `interval` (response) | `interval` | Response field. Shows the recurrence after creation. Different name from creation! |
282
+ | (flat payload) | `{ invoice: {...} }` or `{ bill: {...} }` | Document wrapped in type key |
283
+ | `saveAsDraft: true` | `saveAsDraft: false` | MUST be false — true causes INVALID_SALE_STATUS / INVALID_PURCHASE_STATUS |
284
+
285
+ ---
286
+
287
+ ## Currencies
288
+
289
+ | What You'd Guess | Actual API Field | Notes |
290
+ |------------------|-------------------|-------|
291
+ | `{ currencyCode: "USD" }` | `{ currencies: ["USD"] }` | Enable endpoint — array of ISO codes |
292
+ | `/organization/currencies/:code/rates` | `/organization-currencies/:code/rates` | **Hyphenated** path for rates (NOT nested) |
293
+ | `exchangeRate` (rate POST body) | `rate` | Just `rate`, not `exchangeRate` |
294
+ | `effectiveDate` / `valueDate` / `date` | `rateApplicableFrom` | Rate start date, `YYYY-MM-DD` only |
295
+ | `expiryDate` | `rateApplicableTo` | Optional rate end date |
296
+ | `rate` (GET response) | `rateFunctionalToSource` | Base→source rate in GET response |
297
+ | `inverseRate` | `rateSourceToFunctional` | Source→base rate in GET response |
298
+
299
+ > **Rate direction cheat-sheet**: POST `rate` = GET `rateFunctionalToSource` = "1 base → X foreign". If your data is "1 foreign → X base", **invert before POSTing**.
300
+
301
+ ---
302
+
303
+ ## Inventory Items
304
+
305
+ | What You'd Guess | Actual API Field | Notes |
306
+ |------------------|-------------------|-------|
307
+ | `itemUnit` / `unitName` | `unit` | String, e.g., `"pcs"`, `"box"`. REQUIRED |
308
+ | `costingMethod: "FIXED_COST"` | `costingMethod: "FIXED"` | Only `"FIXED"` or `"WAC"` |
309
+ | `purchaseAccountResourceId` (any type) | `purchaseAccountResourceId` (Inventory type!) | MUST be Inventory-type CoA account |
310
+ | `DELETE /inventory-items/:id` | `DELETE /items/:id` | Delete via items endpoint, not inventory-items |
311
+
312
+ ---
313
+
314
+ ## Cash Transfer Journals
315
+
316
+ | What You'd Guess | Actual API Field | Notes |
317
+ |------------------|-------------------|-------|
318
+ | `fromAccountResourceId` | `cashOut.accountResourceId` | Sub-object, NOT flat |
319
+ | `toAccountResourceId` | `cashIn.accountResourceId` | Sub-object, NOT flat |
320
+ | `amount` (flat) | `cashOut.amount` / `cashIn.amount` | Amount in each sub-object |
321
+
322
+ ---
323
+
324
+ ## Credit Note Refunds
325
+
326
+ | What You'd Guess | Actual API Field | Notes |
327
+ |------------------|-------------------|-------|
328
+ | `payments` wrapper | `refunds` wrapper | NOT `payments` |
329
+ | `paymentAmount` | `refundAmount` | NOT `paymentAmount` |
330
+ | `paymentMethod` | `refundMethod` | NOT `paymentMethod` |
331
+
332
+ ---
333
+
334
+ ## Bookmarks
335
+
336
+ | What You'd Guess | Actual API Field | Notes |
337
+ |------------------|-------------------|-------|
338
+ | `{ name, url }` | `{ items: [{ name, value, categoryCode, datatypeCode }] }` | Array wrapper with 4 fields per item |
339
+ | `url` | `value` | General-purpose value field |
340
+ | `category` | `categoryCode` | Enum: `GENERAL_INFORMATION`, etc. |
341
+ | `type` | `datatypeCode` | Enum: `LINK`, `TEXT`, `NUMBER`, `BOOLEAN`, `DATE` |
342
+
343
+ ---
344
+
345
+ ## Scheduled Journals
346
+
347
+ | What You'd Guess | Actual API Field | Notes |
348
+ |------------------|-------------------|-------|
349
+ | `journal: { journalEntries: [...] }` | `schedulerEntries: [...]` (flat) | NOT nested like invoices/bills |
350
+ | `journalEntries` | `schedulerEntries` | Different name than regular journals |
351
+ | (nested) `reference` / `valueDate` | (top-level) `reference` / `valueDate` | Flat alongside `repeat`/`startDate`/`endDate` |
352
+
353
+ ---
354
+
355
+ ## Reports (All Types)
356
+
357
+ | Report | Required Fields | Notes |
358
+ |--------|----------------|-------|
359
+ | Trial balance | `startDate`, `endDate` | |
360
+ | Balance sheet | `primarySnapshotDate` | Single date |
361
+ | P&L | `primarySnapshotDate`, `secondarySnapshotDate` | |
362
+ | General ledger | `startDate`, `endDate`, `groupBy: "ACCOUNT"` | |
363
+ | Cashflow | `primaryStartDate`, `primaryEndDate` | Different from other date pairs |
364
+ | Cash balance | `reportDate` | Single date, unique field name |
365
+ | AR/AP report | `endDate` | Single date |
366
+ | AR/AP summary | `startDate`, `endDate` | |
367
+ | Bank balance summary | `primarySnapshotDate` | Same as balance sheet |
368
+ | Equity movement | `primarySnapshotStartDate`, `primarySnapshotEndDate` | Yet another pair |
369
+
370
+ ## Data Exports
371
+
372
+ | Export | Required Fields | Notes |
373
+ |--------|----------------|-------|
374
+ | Trial balance | `startDate`, `endDate` | Same as generate-reports |
375
+ | P&L | `startDate`, `endDate` | DIFFERENT from generate-reports (no snapshot dates) |
376
+ | General ledger | `startDate`, `endDate`, `groupBy: "ACCOUNT"` | Same as generate-reports |
377
+ | AR/AP report | `endDate` | Same as generate-reports |
378
+
379
+ ---
380
+
381
+ ## Pagination
382
+
383
+ | What You'd Guess | Actual API Field | Notes |
384
+ |------------------|-------------------|-------|
385
+ | `page` | NOT SUPPORTED | Silently ignored — use `limit`/`offset` |
386
+ | `size` | NOT SUPPORTED | Silently ignored — use `limit`/`offset` |
387
+ | `pageSize` | NOT SUPPORTED | Use `limit` |
388
+ | `per_page` | NOT SUPPORTED | Use `limit` |
389
+ | `page_number` | NOT SUPPORTED | Use `offset` (item-based, not page-based) |
390
+ | (default page size) | `limit` (default: 100) | Query param for GET, JSON body for POST /search |
391
+ | (skip N items) | `offset` (default: 0) | Query param for GET, JSON body for POST /search |
392
+
393
+ **GET list endpoints**: `?limit=100&offset=0` (query params)
394
+ **POST /search endpoints**: `{ "limit": 100, "offset": 0 }` (JSON body)
395
+ **Min/max**: limit 1–1000, offset 0–65536
396
+ **Response**: `{ totalPages, totalElements, data: [...] }` — consistent across all endpoints
397
+
398
+ ---
399
+
400
+ ## Response Shape Quirks
401
+
402
+ | Endpoint | Response Shape | What You'd Expect |
403
+ |----------|---------------|-------------------|
404
+ | `GET /organization` | `{ data: [...] }` (list!) | `{ data: {...} }` (single) |
405
+ | `GET /organization/currencies` | `{ data: { data: [...] } }` | `{ data: [...] }` |
406
+ | `POST /chart-of-accounts/bulk-upsert` | `{ data: { resourceIds: [...] } }` | Individual results |
407
+ | `POST /organization/currencies` | `{ data: { resourceIds: [...] } }` | Confirmation object |
408
+ | `GET /invoices/{id}` line items | `organizationAccountResourceId` | `accountResourceId` (POST uses `accountResourceId`) |
409
+
410
+ ---
411
+
412
+ ## Recommended Serialization Patterns
413
+
414
+ Battle-tested patterns from production Jaz API clients:
415
+
416
+ | Pattern | Detail |
417
+ |---------|--------|
418
+ | Serialization | `model_dump(mode="json", by_alias=True, exclude_unset=True, exclude_none=True)` |
419
+ | Alias generator | `alias_generator=to_camel` (snake_case to camelCase) |
420
+ | Date type | Python `date` type serializes to `YYYY-MM-DD` strings |
421
+ | Bill payments | Always embedded in bill creation body, never standalone |
422
+ | Bank records | Multipart import via `importBankStatementFromAttachment` — the only endpoint |
423
+ | Scheduled bills | Wrapped as `{ repeat, startDate, endDate, bill: {...} }`. Field is `repeat` (NOT `frequency`/`interval`) |
424
+ | FX currency | MUST use `currency` OBJECT: `{ sourceCurrency: "USD", exchangeRate: 1.35 }`. String `currencyCode` is silently ignored. |
425
+
426
+ ---
427
+
428
+ *Last updated: 2026-02-14 — Date format matrix: Added request vs response date format asymmetry (YYYY-MM-DD in, epoch ms out). Complete middleware alias table from Go source code. DateExpression vs DateTimeExpression field classification.*