jaz-clio 4.58.4 → 4.58.6

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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-api
3
- version: 4.58.4
3
+ version: 4.58.6
4
4
  description: >-
5
5
  Use this skill whenever you call, debug, or review code that touches the Jaz
6
6
  REST API. Covers field names, response shapes, 117 production gotchas, error
@@ -413,7 +413,7 @@ Bills, invoices, and credit notes share identical mandatory field specs. Adding
413
413
 
414
414
  132. **Manual-journal recon: caller provides ONLY the offset side(s)** — `reconcile_manual_journal` AUTO-ADDS the bank-side leg from the bank statement entry. If the caller sends both debit AND credit legs covering the bank side, the API doubles-up after auto-add → 422 "sum of debit and credit amounts are not equal in a journal". Send only the offset journal entries (the non-bank side); the API balances them against the bank entry.
415
415
 
416
- 133. **`reconcile_invoice_receipt` and `reconcile_bill_receipt` require statement-imported BSE** — the `bankStatementEntryResourceId` MUST come from a `bank import` (CSV/OFX/XLSX upload, BT type = `BANK_STATEMENT_ENTRY`). Entries from `bank add-records` produce BT type `BANK_RECORD` and are rejected with cryptic 422 "Invalid business transaction type". To bridge: import a CSV first OR file an API issue to widen acceptance.
416
+ 133. **`reconcile_invoice_receipt` and `reconcile_bill_receipt` gate on `paymentDirection`, not BSE entry type** — error code `INVALID_BUSINESS_TRANSACTION_TYPE_ERROR` ("Invalid business transaction type", 422) is misleadingly named. The actual gate is the BSE's `paymentDirection`. **`invoice_receipt` requires `PAYIN`** (AR money in positive amount in `bank add-records`, producing `credit_amount > 0`). **`bill_receipt` requires `PAYOUT`** (AP — money out — NEGATIVE amount, producing `debit_amount > 0`). `bank add-records` produces both directions based on amount sign. Statement-imported BSEs (`bank import`) also work direction is set from the CSV. No need for the async magic-OCR `bank import` path; sync `bank add-records` with the correct sign is sufficient.
417
417
 
418
418
  134. **Bulk-upsert FLAT vs NESTED variants** — for invoices and bills, there are TWO bulk-upsert endpoints. **FLAT** (`bulk_upsert_invoices` / `bulk_upsert_bills`) — one line per row, set at row level via `itemDescription` + `totalAmount` + `invoiceAccountResourceId` (or `billAccountResourceId`). **NESTED** (`bulk_upsert_invoice_line_items` / `bulk_upsert_bill_line_items`) — multi-line per row via nested `lineItems[]`, each with `itemDescription` + `quantity` + `unitPrice` + `accountResourceId`. Use FLAT when one line per transaction is fine (CSV import, simple bills); use NESTED when each transaction needs multiple lines. Sending `lineItems[]` to the FLAT endpoint silently ignores them and creates a $0 invoice.
419
419
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-cli
3
- version: 4.58.4
3
+ version: 4.58.6
4
4
  description: >-
5
5
  Use this skill when running Clio CLI commands, building shell scripts with
6
6
  Clio, debugging auth issues, understanding --json output, paginating results,
@@ -41,4 +41,4 @@
41
41
 
42
42
  18. **Reconciliation `lineItems[]` use `name` + `organizationAccountResourceId`.** The `reconciliations invoice-receipt` and `reconciliations bill-receipt` payloads use a DIFFERENT line-item field naming than `bulk-upsert-line-items`. Recon-create uses `name` (description) + `organizationAccountResourceId` (revenue/expense account). Bulk uses `itemDescription` + `accountResourceId`. Don't copy-paste line-items between the two.
43
43
 
44
- 19. **`reconciliations invoice-receipt` / `bill-receipt` require statement-imported BSE.** The bank statement entry must come from `clio bank import` (CSV/OFX/XLSX upload produces `BANK_STATEMENT_ENTRY` type). Entries from `clio bank add-records` produce `BANK_RECORD` type and get rejected with cryptic 422 "Invalid business transaction type". For programmatic seeding use `bank import` with a tiny CSV.
44
+ 19. **`reconciliations invoice-receipt` / `bill-receipt` gate on `paymentDirection`, not BSE type.** The 422 error code "Invalid business transaction type" is misleadingly namedthe actual API check is on the BSE's `paymentDirection`. **`invoice-receipt` requires `PAYIN`** (positive amount via `clio bank add-records` `credit_amount > 0`). **`bill-receipt` requires `PAYOUT`** (NEGATIVE amount `debit_amount > 0`). Statement-imported BSEs (`clio bank import`) also work — direction is set from the CSV. For programmatic seeding, `clio bank add-records` with the correct sign is sync, fast, and reliable; no need for the async magic-OCR `bank import` path.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-conversion
3
- version: 4.58.4
3
+ version: 4.58.6
4
4
  description: >-
5
5
  Use this skill when migrating accounting data into Jaz — importing from Xero,
6
6
  QuickBooks, Sage, MYOB, or Excel exports. Covers the full conversion pipeline:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-jobs
3
- version: 4.58.4
3
+ version: 4.58.6
4
4
  description: >-
5
5
  Use this skill for recurring accounting workflows — month/quarter/year-end
6
6
  close, bank reconciliation, GST/VAT filing, payment runs, credit control,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-recipes
3
- version: 4.58.4
3
+ version: 4.58.6
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
package/cli.mjs CHANGED
@@ -838,7 +838,7 @@ Line item attributes by type:
838
838
  - Scheduler (sale/purchase/subscription, Pattern C): name, description, sku, unit, unitPrice, quantity, discount, taxProfileResourceId, organizationAccountResourceId, classifierConfig, itemResourceId, withholdingTax (purchase only). Uses arrayIndex (zero-based).
839
839
  - Journal/cash-entry: organizationAccountResourceId, amount, description, taxProfileResourceId, classifierConfig
840
840
  - Journal-schedule (Pattern D): amount, description, organizationAccountResourceId, taxProfileResourceId, classifierConfig, itemResourceId, unit, quantity, pricePerUnit. Uses lineItemResourceId (UUID).
841
- Response: { updated: string[], failed: [{ resourceId, error, errorCode }] }. On partial failure (HTTP 207), check failed.length.`,params:{entity:{type:"string",enum:[...Ku],description:"Transaction type"},lineItemResourceIds:{type:"array",items:{type:"string"},description:"Line item resourceIds to update (ARAP + accounting entities)"},attributes:{type:"object",description:"Fields to update on all specified line items"},schedulerUpdates:{type:"array",items:{type:"object"},description:"Per-scheduler updates: [{ schedulerResourceId, lineItemUpdates: [{ arrayIndex, ...fields }] }]. EXCEPTION: journal-schedules use lineItemResourceId (UUID) instead of arrayIndex."}},required:["entity"],group:"quick_fix",readOnly:!1,searchHint:"bulk update line item accounts tax profiles",execute:async(e,t)=>{let r=t.entity,n=["sale-schedules","purchase-schedules","subscription-schedules","journal-schedules"].includes(r),o={};if(n){if(!t.schedulerUpdates)throw new Error("schedulerUpdates is required for scheduler entities (sale-schedules, purchase-schedules, subscription-schedules, journal-schedules)");o.schedulerUpdates=t.schedulerUpdates}else{if(!t.lineItemResourceIds)throw new Error("lineItemResourceIds is required for non-scheduler entities");o.lineItemResourceIds=t.lineItemResourceIds,o.attributes=t.attributes??{}}return _m(e.client,r,o)}},yt("list_nano_classifiers","List nano classifiers (tracking categories). Paginated. Nano classifiers tag line items with structured categories.","nano_classifiers",(e,t,r)=>zS(e,{limit:r,offset:t}),"list nano classifiers tracking categories types"),Gn("get_nano_classifier","Get a nano classifier by resourceId. Returns type and all classes.","nano_classifiers",(e,t)=>YS(e,t),"get nano classifier tracking category details"),Nt({name:"search_nano_classifiers",description:"Search nano classifiers (tracking categories) by type name.",group:"nano_classifiers",fields:Wp,defaults:Zp,fetcher:JS,searchHint:"find nano classifiers tracking categories by type"}),{name:"create_nano_classifier",description:"Create a nano classifier (tracking category). Provide a type name and list of class names. printable defaults to true (NOTE: printable: false is currently rejected by a server bug \u2014 always use true).",params:{type:{type:"string",description:'Classifier type name (e.g., "Department", "Project")'},classes:{type:"array",items:{type:"string"},description:'Class names: ["Sales", "Marketing", "Engineering"]'},printable:{type:"boolean",description:"Show on printed documents (default: true). NOTE: false is rejected by a server bug."}},required:["type","classes"],group:"nano_classifiers",readOnly:!1,searchHint:"create new nano classifier tracking category",execute:async(e,t)=>Im(e.client,{type:t.type,classes:t.classes,printable:t.printable??!0})},{name:"update_nano_classifier",description:"Update a nano classifier \u2014 change type name, modify classes, or toggle printable.",params:{resourceId:{type:"string",description:"Nano classifier resourceId"},type:{type:"string",description:"New type name"},classes:{type:"array",items:{type:"string"},description:'Updated class names: ["Sales", "Marketing"]'},printable:{type:"boolean",description:"Show on printed documents"}},required:["resourceId"],group:"nano_classifiers",readOnly:!1,searchHint:"update nano classifier classes and settings",execute:async(e,t)=>{let r={};return t.type&&(r.type=t.type),t.classes&&(r.classes=t.classes),t.printable!==void 0&&(r.printable=t.printable),Cm(e.client,t.resourceId,r)}},fn("delete_nano_classifier","Delete a nano classifier.","nano_classifiers",(e,t)=>GS(e,t),"permanently delete a nano classifier type"),{name:"list_invoice_payments",description:"List all payments recorded against an invoice. Returns payment records with amounts, dates, and methods.",params:{resourceId:{type:"string",description:"Invoice resourceId"}},required:["resourceId"],group:"payments",readOnly:!0,searchHint:"list payment records on an invoice",isConcurrencySafe:!0,maxResultSizeChars:5e4,execute:async(e,t)=>sb(e.client,t.resourceId)},{name:"list_invoice_credits",description:"List all credit notes applied to an invoice.",params:{resourceId:{type:"string",description:"Invoice resourceId"}},required:["resourceId"],group:"payments",readOnly:!0,searchHint:"list credit applications on an invoice",isConcurrencySafe:!0,maxResultSizeChars:5e4,execute:async(e,t)=>ab(e.client,t.resourceId)},{name:"reverse_invoice_credit",description:"Reverse (unapply) a credit note from an invoice. The credit note becomes UNAPPLIED again.",params:{resourceId:{type:"string",description:"Invoice resourceId"},creditResourceId:{type:"string",description:"Credit application resourceId to reverse"}},required:["resourceId","creditResourceId"],group:"payments",readOnly:!1,searchHint:"reverse a credit note application on invoice",isDestructive:!0,execute:async(e,t)=>(await cb(e.client,t.resourceId,t.creditResourceId),{reversed:!0,invoiceId:t.resourceId,creditId:t.creditResourceId})},{name:"list_bill_payments",description:"List all payments recorded against a bill. Returns payment records with amounts, dates, and methods.",params:{resourceId:{type:"string",description:"Bill resourceId"}},required:["resourceId"],group:"payments",readOnly:!0,searchHint:"list payment records on a bill",isConcurrencySafe:!0,maxResultSizeChars:5e4,execute:async(e,t)=>ry(e.client,t.resourceId)},{name:"list_bill_credits",description:"List all credit notes applied to a bill.",params:{resourceId:{type:"string",description:"Bill resourceId"}},required:["resourceId"],group:"payments",readOnly:!0,searchHint:"list credit applications on a bill",isConcurrencySafe:!0,maxResultSizeChars:5e4,execute:async(e,t)=>ny(e.client,t.resourceId)},{name:"reverse_bill_credit",description:"Reverse (unapply) a supplier credit note from a bill. The credit note becomes UNAPPLIED again.",params:{resourceId:{type:"string",description:"Bill resourceId"},creditResourceId:{type:"string",description:"Credit application resourceId to reverse"}},required:["resourceId","creditResourceId"],group:"payments",readOnly:!1,searchHint:"reverse a credit note application on bill",isDestructive:!0,execute:async(e,t)=>(await oy(e.client,t.resourceId,t.creditResourceId),{reversed:!0,billId:t.resourceId,creditId:t.creditResourceId})},Gn("get_scheduled_invoice","Get a scheduled (recurring) invoice by resourceId.","schedulers",(e,t)=>T0(e,t),"get scheduled recurring invoice details"),{name:"update_scheduled_invoice",description:"Update a scheduled invoice \u2014 change schedule settings and/or the invoice template.",params:{resourceId:{type:"string",description:"Scheduled invoice resourceId"},repeat:{type:"string",description:"Recurrence: WEEKLY, MONTHLY, QUARTERLY, YEARLY"},startDate:{type:"string",description:"First occurrence date (YYYY-MM-DD)"},endDate:{type:"string",description:"Last occurrence date (YYYY-MM-DD)"},status:{type:"string",description:"Status: ACTIVE or PAUSED"},invoice:{type:"object",description:"Invoice template: { reference, valueDate, dueDate, contactResourceId, lineItems, currency, tag, saveAsDraft }"}},required:["resourceId"],group:"schedulers",readOnly:!1,searchHint:"update recurring scheduled invoice settings",execute:async(e,t)=>{let r={};return t.repeat&&(r.repeat=t.repeat),t.startDate&&(r.startDate=t.startDate),t.endDate&&(r.endDate=t.endDate),t.status&&(r.status=t.status),t.invoice&&(r.invoice=t.invoice),$0(e.client,t.resourceId,r)}},fn("delete_scheduled_invoice","Delete a scheduled (recurring) invoice.","schedulers",(e,t)=>O0(e,t),"delete a recurring scheduled invoice"),Gn("get_scheduled_bill","Get a scheduled (recurring) bill by resourceId.","schedulers",(e,t)=>N0(e,t),"get scheduled recurring bill details"),{name:"update_scheduled_bill",description:"Update a scheduled bill \u2014 change schedule settings and/or the bill template.",params:{resourceId:{type:"string",description:"Scheduled bill resourceId"},repeat:{type:"string",description:"Recurrence: WEEKLY, MONTHLY, QUARTERLY, YEARLY"},startDate:{type:"string",description:"First occurrence date (YYYY-MM-DD)"},endDate:{type:"string",description:"Last occurrence date (YYYY-MM-DD)"},status:{type:"string",description:"Status: ACTIVE or PAUSED"},bill:{type:"object",description:"Bill template: { reference, valueDate, dueDate, contactResourceId, lineItems, currency, tag, saveAsDraft }"}},required:["resourceId"],group:"schedulers",readOnly:!1,searchHint:"update recurring scheduled bill settings",execute:async(e,t)=>{let r={};return t.repeat&&(r.repeat=t.repeat),t.startDate&&(r.startDate=t.startDate),t.endDate&&(r.endDate=t.endDate),t.status&&(r.status=t.status),t.bill&&(r.bill=t.bill),R0(e.client,t.resourceId,r)}},fn("delete_scheduled_bill","Delete a scheduled (recurring) bill.","schedulers",(e,t)=>k0(e,t),"delete a recurring scheduled bill"),Gn("get_scheduled_journal","Get a scheduled (recurring) journal by resourceId.","schedulers",(e,t)=>F0(e,t),"get scheduled recurring journal details"),{name:"update_scheduled_journal",description:"Update a scheduled journal \u2014 change schedule settings and/or the journal template.",params:{resourceId:{type:"string",description:"Scheduled journal resourceId"},repeat:{type:"string",description:"Recurrence: WEEKLY, MONTHLY, QUARTERLY, YEARLY"},startDate:{type:"string",description:"First occurrence date (YYYY-MM-DD)"},endDate:{type:"string",description:"Last occurrence date (YYYY-MM-DD)"},status:{type:"string",description:"Status: ACTIVE or PAUSED"},valueDate:{type:"string",description:"Journal date (YYYY-MM-DD)"},schedulerEntries:{type:"array",items:{type:"object"},description:"Journal entries: [{ accountResourceId, type: CREDIT|DEBIT, amount, ... }]"},reference:{type:"string",description:"Journal reference"},notes:{type:"string",description:"Journal notes"}},required:["resourceId"],group:"schedulers",readOnly:!1,searchHint:"update recurring scheduled journal settings",execute:async(e,t)=>{let r={};return t.repeat&&(r.repeat=t.repeat),t.startDate&&(r.startDate=t.startDate),t.endDate&&(r.endDate=t.endDate),t.status&&(r.status=t.status),t.valueDate&&(r.valueDate=t.valueDate),t.schedulerEntries&&(r.schedulerEntries=t.schedulerEntries),t.reference&&(r.reference=t.reference),t.notes&&(r.notes=t.notes),P0(e.client,t.resourceId,r)}},fn("delete_scheduled_journal","Delete a scheduled (recurring) journal.","schedulers",(e,t)=>L0(e,t),"delete a recurring scheduled journal"),Gn("get_payment","Get a specific payment record by resourceId. Returns payment amount, method, date, and reference.","payments",(e,t)=>Ob(e,t),"get payment record details by id"),{name:"update_payment",description:"Update a payment record \u2014 correct amount, reference, date, method, or account.",params:{resourceId:{type:"string",description:"Payment resourceId (from invoice/bill paymentRecords)"},paymentAmount:{type:"number",description:"Corrected payment amount (bank currency)"},reference:{type:"string",description:"Payment reference"},valueDate:{type:"string",description:"Payment date (YYYY-MM-DD)"},paymentMethod:wm,accountResourceId:{type:"string",description:"Bank/cash account resourceId"},transactionFee:{type:"number",description:"Transaction fee amount"}},required:["resourceId"],group:"payments",readOnly:!1,searchHint:"update payment amount reference date method",execute:async(e,t)=>{let r={};return t.paymentAmount!==void 0&&(r.paymentAmount=t.paymentAmount),t.reference&&(r.reference=t.reference),t.valueDate&&(r.valueDate=t.valueDate),t.paymentMethod&&(r.paymentMethod=t.paymentMethod),t.accountResourceId&&(r.accountResourceId=t.accountResourceId),t.transactionFee!==void 0&&(r.transactionFee=t.transactionFee),Nb(e.client,t.resourceId,r)}},fn("delete_payment","Delete (void) a payment record. The associated invoice/bill balance is restored.","payments",(e,t)=>Rb(e,t),"delete void a payment record restore balance"),{name:"get_export_columns",description:"List all exportable columns for an entity type, including their paths and data types. Use paths from this response to build custom column sets for export_records or preview_export_records.",params:{entityType:L$},required:["entityType"],group:"export_records",readOnly:!0,isConcurrencySafe:!0,searchHint:"list export columns fields for entity type",execute:async(e,t)=>WS(e.client,t.entityType)},{name:"preview_export_records",description:"Preview an export before generating the file. Returns totalRecords, up to 10 sample rows, resolved column definitions, and a human-readable filterDescription. Use this to confirm scope before calling export_records. Pass either query OR filter, never both.",params:{entityType:L$,query:cJ,filter:uJ,columns:lJ,sort:dJ},required:["entityType"],group:"export_records",readOnly:!0,isConcurrencySafe:!0,searchHint:"preview export records count sample rows filter",execute:async(e,t)=>HS(e.client,{entityType:t.entityType,outputFormat:"XLSX",query:t.query,filter:t.filter,columns:t.columns,sort:t.sort})},{name:"export_records",description:"Generate a filtered XLSX export for an entity type. Returns a pre-signed download URL (expires in ~5 minutes \u2014 download immediately), file name, and total record count. Pass either query OR filter, never both. Use preview_export_records first to confirm scope.",params:{entityType:L$,query:cJ,filter:uJ,columns:lJ,sort:dJ},required:["entityType"],group:"export_records",readOnly:!0,isConcurrencySafe:!0,searchHint:"export records download xlsx file url",execute:async(e,t)=>VS(e.client,{entityType:t.entityType,outputFormat:"XLSX",query:t.query,filter:t.filter,columns:t.columns,sort:t.sort})},Nt({name:"search_background_jobs",description:"Search and poll background jobs. ANY operation that returns a jobId (bulk_upsert_contacts, bulk_upsert_items, bank statement import, magic file processing, etc.) can be tracked here. Filter by resourceId (the jobId value) to poll a specific job. Poll until status is SUCCESS, FAILED, or PARTIAL_SUCCESS. Use processedCount/failedCount/totalRecords for progress. IMPORTANT: filter by resourceId field, NOT jobId \u2014 they differ.",group:"background_jobs",fields:Op,defaults:Np,fetcher:Am,searchHint:"poll background job status by jobId type status"}),{name:"bulk_upsert_contacts",description:"Create or update contacts in bulk (max 500 per call). Provide resourceId per contact to update (partial \u2014 only changed fields needed). Omit resourceId to create new contacts. Returns a jobId \u2014 this is async. Poll search_background_jobs with filter {resourceId:{eq:jobId}} until status is SUCCESS, FAILED, or PARTIAL_SUCCESS. NOTE: unlike bulk_upsert_items (sync), contacts bulk-upsert is async.",params:{contacts:{type:"array",description:"Array of contacts to create or update (max 500)",items:{type:"object",properties:{resourceId:{type:"string",description:"Contact resourceId (omit for create, provide UUID for update)"},billingName:{type:"string",description:"Billing name (required for create)"},name:{type:"string",description:"Display name (defaults to billingName)"},emails:{type:"array",items:{type:"string"},description:"Email addresses"},customer:{type:"boolean",description:"Mark as customer"},supplier:{type:"boolean",description:"Mark as supplier"},taxId:{type:"string",description:"Tax ID / GST registration number"},taxIdType:{type:"string",description:"Tax ID type (e.g., GST, VAT)"},registrationNumber:{type:"string",description:"Business registration number"},currencyCode:{type:"string",description:"Default currency code (e.g., SGD)"},status:{type:"string",enum:["ACTIVE","INACTIVE"],description:"Contact status"},paymentTerms:{type:"number",description:"Payment terms in days (e.g., 30 for Net 30)"},notes:{type:"string",description:"Internal notes"},billingAddress:{type:"object",description:"Billing address",properties:{address:{type:"string"},city:{type:"string"},state:{type:"string"},postalCode:{type:"string"},country:{type:"string"}}},shippingAddress:{type:"object",description:"Shipping address",properties:{address:{type:"string"},city:{type:"string"},state:{type:"string"},postalCode:{type:"string"},country:{type:"string"}}}}}}},required:["contacts"],group:"contacts",readOnly:!1,searchHint:"bulk create update contacts upsert",execute:async(e,t)=>(Gr(t.contacts,"contacts"),uy(e.client,t.contacts))},{name:"bulk_upsert_invoices",description:"Create or update invoices in bulk (max 500 per call). FLAT shape: ONE line per invoice via `itemDescription` + `totalAmount` + `invoiceAccountResourceId` at row level. For multi-line invoices use `bulk_upsert_invoice_line_items` instead \u2014 that variant takes nested `lineItems[]`. Natural key: `invoiceReference` (rows sharing one within a batch are MERGED \u2014 last wins). Provide resourceId per invoice to update via UUID; or omit and rely on invoiceReference for upsert. Async \u2014 returns a jobId. Poll search_background_jobs with filter {resourceId:{eq:jobId}} until SUCCESS / FAILED / PARTIAL_SUCCESS; on PARTIAL_SUCCESS read data[0].errorDetails on the same response for per-row failures. Dates are ISO 8601 (YYYY-MM-DD) only \u2014 the dateFormat field was removed.",params:{invoices:{type:"array",description:"Array of invoices to create or update (max 500). Each row needs at least: invoiceReference, contactResourceId, valueDate, totalAmount, invoiceAccountResourceId.",items:{type:"object",properties:{rowIndex:{type:"string",description:"Optional caller-supplied row index for error reporting"},resourceId:{type:"string",description:"Invoice resourceId (UUID) \u2014 provide to update by ID"},invoiceReference:{type:"string",description:"Natural key (e.g., INV-2025-001) \u2014 required"},contactResourceId:{type:"string",description:"Customer contact UUID \u2014 required"},valueDate:{type:"string",description:"Invoice date YYYY-MM-DD \u2014 required"},dueDate:{type:"string",description:"Due date YYYY-MM-DD"},totalAmount:{type:"number",description:"Total amount (BigDecimal)"},currencyCode:{type:"string",description:"Currency (e.g., SGD)"},invoiceAccountResourceId:{type:"string",description:"Revenue account UUID"},itemDescription:{type:"string",description:"Single-line item description"},internalNotes:{type:"string",description:"Internal notes"},tags:{type:"array",items:{type:"string"},description:"Tag resourceIds"}}}}},required:["invoices"],group:"invoices",readOnly:!1,searchHint:"bulk create update invoices upsert import migrate",execute:async(e,t)=>{Gr(t.invoices,"invoices");let r=t.invoices;return to(r,["valueDate","dueDate"]),ub(e.client,r)}},{name:"bulk_upsert_invoice_line_items",description:"Create or update invoices with nested line items in bulk (max 500 invoices per call). Each row carries lineItems[] under its parent invoice (scoped by invoiceReference). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 only.",params:{invoices:{type:"array",description:"Array of invoices with line items (max 500). Each invoice row has lineItems[].",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string",description:"Invoice resourceId \u2014 provide to update by ID"},invoiceReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Customer UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},dueDate:{type:"string",description:"YYYY-MM-DD"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},lineItems:{type:"array",description:"Line items belonging to this invoice",items:{type:"object",properties:{itemDescription:{type:"string",description:"Line description \u2014 required"},quantity:{type:"number"},unit:{type:"string",description:"Unit of measure (pcs, kg, etc.)"},unitPrice:{type:"number"},accountResourceId:{type:"string",description:"Revenue account UUID"},taxProfileResourceId:{type:"string"}}}}}}}},required:["invoices"],group:"invoices",readOnly:!1,searchHint:"bulk invoices line items multi-line upsert import",execute:async(e,t)=>{Gr(t.invoices,"invoices");let r=t.invoices;return to(r,["valueDate","dueDate"]),lb(e.client,r)}},{name:"bulk_upsert_bills",description:"Create or update bills in bulk (max 500 per call). FLAT shape: ONE line per bill via `itemDescription` + `totalAmount` + `billAccountResourceId` at row level. For multi-line bills use `bulk_upsert_bill_line_items` instead \u2014 that variant takes nested `lineItems[]`. Natural key: `billReference` (rows sharing one within a batch are MERGED \u2014 last wins). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 only \u2014 dateFormat field was removed.",params:{bills:{type:"array",description:"Array of bills to create or update (max 500). Each row needs at least: billReference, contactResourceId, valueDate, totalAmount, billAccountResourceId.",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},billReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Supplier UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},dueDate:{type:"string"},totalAmount:{type:"number"},currencyCode:{type:"string"},billAccountResourceId:{type:"string",description:"Expense account UUID"},itemDescription:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}}}}}},required:["bills"],group:"bills",readOnly:!1,searchHint:"bulk create update bills upsert import migrate",execute:async(e,t)=>{Gr(t.bills,"bills");let r=t.bills;return to(r,["valueDate","dueDate"]),iy(e.client,r)}},{name:"bulk_upsert_bill_line_items",description:"Create or update bills with nested line items in bulk (max 500 bills per call). Each row carries lineItems[] under its parent bill (scoped by billReference). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures.",params:{bills:{type:"array",description:"Array of bills with line items (max 500). Each bill row has lineItems[].",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},billReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Supplier UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},dueDate:{type:"string"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},lineItems:{type:"array",items:{type:"object",properties:{itemDescription:{type:"string",description:"Required"},quantity:{type:"number"},unit:{type:"string"},unitPrice:{type:"number"},accountResourceId:{type:"string",description:"Expense account UUID"},taxProfileResourceId:{type:"string"}}}}}}}},required:["bills"],group:"bills",readOnly:!1,searchHint:"bulk bills line items multi-line upsert import",execute:async(e,t)=>{Gr(t.bills,"bills");let r=t.bills;return to(r,["valueDate","dueDate"]),sy(e.client,r)}},{name:"bulk_upsert_customer_credit_notes",description:"Create or update customer credit notes in bulk (max 500 per call). Natural key: creditNoteReference. Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 only.",params:{customerCreditNotes:{type:"array",description:"Array of customer credit notes (max 500).",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},creditNoteReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Customer UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},lineItems:{type:"array",items:{type:"object",properties:{itemDescription:{type:"string",description:"Required"},quantity:{type:"number"},unitPrice:{type:"number"},accountResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}}}}}},required:["customerCreditNotes"],group:"customer_credit_notes",readOnly:!1,searchHint:"bulk customer credit notes refund upsert import",execute:async(e,t)=>{Gr(t.customerCreditNotes,"customerCreditNotes",500,"customer credit notes");let r=t.customerCreditNotes;return to(r,["valueDate"]),n0(e.client,r)}},{name:"bulk_upsert_supplier_credit_notes",description:"Create or update supplier credit notes in bulk (max 500 per call). Natural key: creditNoteReference. Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 only.",params:{supplierCreditNotes:{type:"array",description:"Array of supplier credit notes (max 500).",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},creditNoteReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Supplier UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},lineItems:{type:"array",items:{type:"object",properties:{itemDescription:{type:"string",description:"Required"},quantity:{type:"number"},unitPrice:{type:"number"},accountResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}}}}}},required:["supplierCreditNotes"],group:"supplier_credit_notes",readOnly:!1,searchHint:"bulk supplier credit notes refund upsert import",execute:async(e,t)=>{Gr(t.supplierCreditNotes,"supplierCreditNotes",500,"supplier credit notes");let r=t.supplierCreditNotes;return to(r,["valueDate"]),c0(e.client,r)}},{name:"bulk_upsert_journals",description:"Create or update manual journals in bulk (max 500 per call). NATURAL KEY: `journalReference` (NOT `reference` \u2014 every other bulk-upsert uses entityReference, this one is asymmetric). LEGS field: `journalEntries[]` (NOT `entries[]` \u2014 different from `clio journals create` which uses entries). Each leg has `accountResourceId` + `debitAmount` + `creditAmount` (debit + credit must balance per row). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 (YYYY-MM-DD) only \u2014 dateFormat field was removed.",params:{journals:{type:"array",description:"Array of journals to create or update (max 500). Each row has entries[] (debit/credit legs).",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},journalReference:{type:"string",description:"Natural key \u2014 required (NOTE: field is `journalReference`, not `reference`)"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},journalEntries:{type:"array",description:"Journal legs (debit + credit amounts must balance) \u2014 field is `journalEntries`, NOT `entries`",items:{type:"object",properties:{accountResourceId:{type:"string",description:"Required"},description:{type:"string"},debitAmount:{type:"number"},creditAmount:{type:"number"},contactResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}}}}}},required:["journals"],group:"journals",readOnly:!1,searchHint:"bulk manual journals upsert import migration",execute:async(e,t)=>{Gr(t.journals,"journals");let r=t.journals;return to(r,["valueDate"]),yb(e.client,r)}},{name:"bulk_upsert_fixed_assets",description:'\u26A0\uFE0F DATE FIELD MISMATCH: bulk-upsert REQUEST uses `valueDate` (not `purchaseDate`); the GET response uses `purchaseDate`. Sending `purchaseDate` returns a cryptic 400 "Invalid request body" with no field detail. Create or update fixed assets in bulk (max 500 per call). Natural key: `reference`. Each row REQUIRED: `reference`, `registrationType` (NEW | TRANSFER). Recommended: `typeCode`, `typeName`, `category` (TANGIBLE | INTANGIBLE), `cost` (or synonym `purchaseAmount`), `valueDate`, `depreciationStartDate`, `effectiveLife` (or synonym `usefulLifeMonths`), `depreciationMethod`, `purchaseAssetAccountResourceId`, `depreciationExpenseAccountResourceId`, `accumulatedDepreciationAccountResourceId`. Account fields must be valid UUIDv4. Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 (YYYY-MM-DD) only.',params:{fixedAssets:{type:"array",description:"Array of fixed assets to create or update (max 500).",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},reference:{type:"string",description:"Natural key \u2014 required"},registrationType:{type:"string",enum:["NEW","TRANSFER"],description:"NEW = newly acquired, TRANSFER = inherited from prior system \u2014 required"},typeCode:{type:"string",description:"Asset class code (e.g., FURNITURE_AND_FIXTURE)"},typeName:{type:"string",description:'Human label for the typeCode (e.g., "Furniture and Fixtures")'},category:{type:"string",description:"TANGIBLE | INTANGIBLE"},name:{type:"string",description:"Asset name"},valueDate:{type:"string",description:"Acquisition date YYYY-MM-DD (NOTE: bulk uses `valueDate`, the GET response uses `purchaseDate` \u2014 different fields)"},cost:{type:"number",description:"Cost basis (alias for purchaseAmount on the bulk endpoint)"},purchaseAmount:{type:"number",description:"Cost basis (synonym of `cost`)"},currencyCode:{type:"string"},depreciationStartDate:{type:"number",description:'Epoch milliseconds (NOT YYYY-MM-DD \u2014 inconsistent with valueDate which IS YYYY-MM-DD on this same endpoint). Sending YYYY-MM-DD returns generic 400 "Invalid request body" with no detail. Omit to default to valueDate.'},effectiveLife:{type:"number",description:"Useful life in months (alias for usefulLifeMonths)"},usefulLifeMonths:{type:"number",description:"Useful life in months (synonym of effectiveLife)"},depreciationMethod:{type:"string",description:"e.g., STRAIGHT_LINE, DOUBLE_DECLINING_BALANCE"},purchaseAssetAccountResourceId:{type:"string",description:"Asset (PPE) account UUID \u2014 must be valid UUIDv4"},depreciationExpenseAccountResourceId:{type:"string",description:"Depreciation expense account UUID \u2014 must be valid UUIDv4"},accumulatedDepreciationAccountResourceId:{type:"string",description:"Accumulated depreciation account UUID"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}}}}}},required:["fixedAssets"],group:"fixed_assets",readOnly:!1,searchHint:"bulk fixed assets ppe register upsert import migrate",execute:async(e,t)=>{Gr(t.fixedAssets,"fixedAssets",500,"fixed assets");let r=t.fixedAssets;return to(r,["valueDate"]),vS(e.client,r)}},{name:"quick_reconcile",description:"Bulk-reconcile bank statement entries against a list of journals (max 500). Reconciliation mode is hardcoded to QUICK_RECON. Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails. Caller provides bankAccountResourceId + journalsForReconciliation[] (each row: bankStatementEntryResourceId, journalReference, journalAccountResourceId).",params:{bankAccountResourceId:{type:"string",description:"Bank account UUID (the entries belong to this account)"},journalsForReconciliation:{type:"array",description:"Per-row reconciliation instructions (max 500).",items:{type:"object",properties:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},journalReference:{type:"string",description:"Journal reference text \u2014 required"},journalAccountResourceId:{type:"string",description:"Offsetting account UUID (revenue for cash-in, expense for cash-out) \u2014 required"},contactResourceId:{type:"string",description:"Contact UUID"},capsuleResourceId:{type:"string",description:"Capsule UUID"},taxProfileResourceId:{type:"string",description:"Tax profile UUID"},internalNotes:{type:"string"},journalEntryDescription:{type:"string"},tags:{type:"array",items:{type:"string"}},rowIndex:{type:"string",description:"Optional caller-supplied index for error correlation"}}}}},required:["bankAccountResourceId","journalsForReconciliation"],group:"reconciliations",readOnly:!1,searchHint:"bulk reconcile bank statement journals match",execute:async(e,t)=>(Gr(t.journalsForReconciliation,"journalsForReconciliation",500,"journals"),QS(e.client,t))},{name:"apply_bank_rule",description:"Apply a pre-configured bank rule (action shortcut) to a batch of bank statement entries (max 500). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId. The rule executes its configured action (e.g. RECONCILE_WITH_DIRECT_CASH_ENTRY) on each entry.",params:{actionShortcutResourceId:{type:"string",description:"Bank rule UUID \u2014 required"},businessTransactionResourceIds:{type:"array",description:"Bank statement entry UUIDs to apply the rule to (max 500). Note: the field is named businessTransactionResourceIds for legacy reasons but accepts bank entry IDs.",items:{type:"string"}}},required:["actionShortcutResourceId","businessTransactionResourceIds"],group:"reconciliations",readOnly:!1,searchHint:"bank rule apply action shortcut bulk reconcile",execute:async(e,t)=>(Gr(t.businessTransactionResourceIds,"businessTransactionResourceIds",500,"entries"),eE(e.client,t))},{name:"reconcile_direct_cash_entry",description:"Reconcile a bank statement entry with a single cash-in / cash-out line. Direction (cash-in vs cash-out) is INFERRED from the bank entry sign. Sync \u2014 returns the reconciled entry status. NOT idempotent: calling twice on the same bankStatementEntryResourceId creates duplicate journals. Confirm reconciled-state via view_auto_reconciliation before retrying.",params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID (used to look up the entry) \u2014 required"},reference:{type:"string",description:"Reference for the cash entry \u2014 required"},accountResourceId:{type:"string",description:"Offsetting account UUID (revenue for cash-in, expense for cash-out) \u2014 required"},amount:{type:"number",description:"Amount in source currency. Defaults to bank entry amount if omitted."},description:{type:"string"},contactResourceId:{type:"string"},taxProfileResourceId:{type:"string"},internalNotes:{type:"string"},bankAccountJournalEntryDescription:{type:"string",description:"Description for the bank-side journal entry"},tags:{type:"array",items:{type:"string"}},taxVatApplicable:{type:"boolean"},taxInclusion:{type:"boolean"},capsuleResourceId:{type:"string"}},required:["bankStatementEntryResourceId","bankAccountResourceId","reference","accountResourceId"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry direct cash in out single line",execute:async(e,t)=>tE(e.client,t)},{name:"reconcile_cash_journal",description:"Reconcile a bank statement entry with a multi-line cashflow journal (multiple cash splits, max 200 lines). Sync \u2014 returns the reconciled entry status. NOT idempotent \u2014 confirm reconciled-state before retrying.",params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},reference:{type:"string",description:"Journal reference \u2014 required"},journalEntries:{type:"array",description:"Cash journal lines (max 200). Each row is one debit OR credit against an account.",items:{type:"object",properties:{accountResourceId:{type:"string",description:"Account UUID \u2014 required"},amount:{type:"number",description:"Amount in source currency \u2014 required (>0)"},description:{type:"string"},taxProfileResourceId:{type:"string"}}}},contactResourceId:{type:"string"},bankAccountJournalEntryDescription:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},taxVatApplicable:{type:"boolean"},taxInclusion:{type:"boolean"},capsuleResourceId:{type:"string"}},required:["bankStatementEntryResourceId","bankAccountResourceId","reference","journalEntries"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry multi line cash journal splits",execute:async(e,t)=>(Gr(t.journalEntries,"journalEntries",200,"entries"),rE(e.client,t))},{name:"reconcile_manual_journal",description:'\u26A0\uFE0F CALLER PROVIDES ONLY THE OFFSET LEG(S) \u2014 backend AUTO-ADDS the bank-side leg from the statement entry. Sending both debit AND credit legs \u2192 422 "sum of debit and credit amounts are not equal" (your sides duplicate after the auto-add). Reconcile a bank statement entry with a double-entry manual journal. Sync \u2014 returns the reconciled entry status. valueDate prefills from bank entry if omitted. NOT idempotent.',params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},status:{type:"string",enum:["DRAFT","ACTIVE"],description:"Journal status \u2014 required"},journalEntries:{type:"array",description:"Offset-side journal entries only (max 200). The bank-side leg is auto-added by the API.",items:{type:"object",properties:{accountResourceId:{type:"string",description:"Account UUID \u2014 required"},type:{type:"string",enum:["DEBIT","CREDIT"]},amount:{type:"number",description:"Amount \u2014 required"},description:{type:"string"},contactResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}},reference:{type:"string"},valueDate:{type:"string",description:"YYYY-MM-DD. Defaults to bank entry value date."},contactResourceId:{type:"string"},internalNotes:{type:"string"},bankAccountJournalEntryDescription:{type:"string"},taxVatApplicable:{type:"boolean"},taxInclusion:{type:"boolean"},tags:{type:"array",items:{type:"string"}},capsuleResourceId:{type:"string"}},required:["bankStatementEntryResourceId","bankAccountResourceId","status","journalEntries"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry manual journal double entry",execute:async(e,t)=>(Gr(t.journalEntries,"journalEntries",200,"entries"),nE(e.client,t))},{name:"reconcile_cash_transfer",description:"Reconcile a bank statement entry with an inter-account transfer. Sync \u2014 returns the reconciled entry status. amount is required only when the counterparty account is in a non-functional currency. NOT idempotent.",params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},accountResourceId:{type:"string",description:"Counterparty cash account UUID \u2014 required"},reference:{type:"string",description:"Transfer reference \u2014 required"},amount:{type:"number",description:"Amount in source currency. Required only for cross-currency transfers."},contactResourceId:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},capsuleResourceId:{type:"string"}},required:["bankStatementEntryResourceId","bankAccountResourceId","accountResourceId","reference"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry transfer between accounts",execute:async(e,t)=>oE(e.client,t)},{name:"reconcile_invoice_receipt",description:'\u26A0\uFE0F BSE must be from `bank import` (statement-imported, type=BANK_STATEMENT_ENTRY). Entries from `bank add-records` (type=BANK_RECORD) are rejected with cryptic 422 "Invalid business transaction type". Create an invoice and auto-reconcile it to a bank statement entry (AR). Sync \u2014 returns the reconciled entry status. valueDate / dueDate / payment amount prefill from the bank entry if omitted. NOT idempotent.',params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},invoiceDetails:{type:"object",description:"The invoice to create. Required.",properties:{reference:{type:"string",description:"Invoice reference \u2014 required"},contactResourceId:{type:"string",description:"Customer UUID"},valueDate:{type:"string",description:"YYYY-MM-DD. Defaults to bank entry value date."},dueDate:{type:"string",description:"YYYY-MM-DD. Defaults to value date."},taxInclusion:{type:"boolean"},isTaxVATApplicable:{type:"boolean"},lineItems:{type:"array",description:"Invoice line items (max 500) \u2014 required",items:{type:"object",properties:{name:{type:"string",description:"Line description \u2014 required"},quantity:{type:"number"},unit:{type:"string"},unitPrice:{type:"number"},organizationAccountResourceId:{type:"string",description:"Revenue account UUID"},itemResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}},recordedPayment:{type:"object",description:"Optional. The matching payment record \u2014 auto-built from the bank entry if omitted.",properties:{reference:{type:"string"},valueDate:{type:"string",description:"YYYY-MM-DD. Defaults to bank entry value date."},organizationAccountResourceId:{type:"string"},paymentAmount:{type:"number"},transactionAmount:{type:"number"},paymentMethod:{type:"string",description:"Defaults to BANK_TRANSFER"}}},capsuleResourceId:{type:"string"}}}},required:["bankStatementEntryResourceId","bankAccountResourceId","invoiceDetails"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry invoice receipt AR sale",execute:async(e,t)=>(k$(t.invoiceDetails,"invoiceDetails"),iE(e.client,t))},{name:"reconcile_bill_receipt",description:'\u26A0\uFE0F BSE must be from `bank import` (statement-imported, type=BANK_STATEMENT_ENTRY). Entries from `bank add-records` (type=BANK_RECORD) are rejected with cryptic 422 "Invalid business transaction type". Create a bill and auto-reconcile it to a bank statement entry (AP). Sync \u2014 returns the reconciled entry status. valueDate / dueDate / payment amount prefill from the bank entry if omitted. NOT idempotent.',params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},billDetails:{type:"object",description:"The bill to create. Required.",properties:{reference:{type:"string",description:"Bill reference \u2014 required"},contactResourceId:{type:"string",description:"Supplier UUID"},valueDate:{type:"string",description:"YYYY-MM-DD. Defaults to bank entry value date."},dueDate:{type:"string",description:"YYYY-MM-DD. Defaults to value date."},taxInclusion:{type:"boolean"},isTaxVATApplicable:{type:"boolean"},lineItems:{type:"array",description:"Bill line items (max 500) \u2014 required",items:{type:"object",properties:{name:{type:"string",description:"Line description \u2014 required"},quantity:{type:"number"},unit:{type:"string"},unitPrice:{type:"number"},organizationAccountResourceId:{type:"string",description:"Expense account UUID"},itemResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}},recordedPayment:{type:"object",description:"Optional. The matching payment record \u2014 auto-built from the bank entry if omitted.",properties:{reference:{type:"string"},valueDate:{type:"string",description:"YYYY-MM-DD"},organizationAccountResourceId:{type:"string"},paymentAmount:{type:"number"},transactionAmount:{type:"number"},paymentMethod:{type:"string",description:"Defaults to BANK_TRANSFER"}}},capsuleResourceId:{type:"string"}}}},required:["bankStatementEntryResourceId","bankAccountResourceId","billDetails"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry bill receipt AP purchase",execute:async(e,t)=>(k$(t.billDetails,"billDetails"),sE(e.client,t))},{name:"validate_drafts",description:"BULK validate \u2014 process up to 500 draft business transactions in ONE call, mixing any combination of invoices, bills, customer credit notes, and supplier credit notes (no per-type tools needed). SYNC: returns per-item errors and display data inline; no state change. Use this before convert_drafts_to_active to surface eligibility issues client-side. btType enum: SALE = invoice, PURCHASE = bill, SALE_CREDIT_NOTE = customer CN, PURCHASE_CREDIT_NOTE = supplier CN. Journals are NOT in this enum.",params:{items:{type:"array",description:"Draft business transaction references (max 500). Mix any btType freely.",items:{type:"object",properties:{btResourceId:{type:"string",description:"Draft BT resource ID (UUID) \u2014 required"},btType:{type:"string",enum:["SALE","PURCHASE","SALE_CREDIT_NOTE","PURCHASE_CREDIT_NOTE"],description:"Required"}}}}},required:["items"],group:"drafts",readOnly:!0,isConcurrencySafe:!0,searchHint:"validate drafts eligibility check before convert promote",execute:async(e,t)=>(Xu(t.items),ZS(e.client,t.items))},{name:"convert_drafts_to_active",description:"BULK promote \u2014 finalize up to 500 draft business transactions to ACTIVE in ONE call, mixing any combination of invoices, bills, and credit notes (no per-type tools needed). ASYNC: returns a jobId \u2014 poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. NOT idempotent: a second call on already-promoted drafts returns 422. Filter the draft list by status: DRAFT before submitting. Pair with validate_drafts for a pre-flight check on large batches.",params:{items:{type:"array",description:"Draft BT references (max 500). Mix any btType.",items:{type:"object",properties:{btResourceId:{type:"string",description:"Draft BT resource ID (UUID) \u2014 required"},btType:{type:"string",enum:["SALE","PURCHASE","SALE_CREDIT_NOTE","PURCHASE_CREDIT_NOTE"],description:"Required"}}}}},required:["items"],group:"drafts",readOnly:!1,searchHint:"convert drafts to active promote finalize bulk",execute:async(e,t)=>(Xu(t.items),KS(e.client,t.items))},{name:"submit_drafts_for_approval",description:"BULK submit \u2014 route up to 500 draft business transactions into the approval workflow in ONE call, mixing any combination of invoices, bills, and credit notes. ASYNC: returns a jobId \u2014 poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. NOT idempotent on drafts that already have an in-flight approval request.",params:{items:{type:"array",description:"Draft BT references (max 500). Mix any btType.",items:{type:"object",properties:{btResourceId:{type:"string",description:"Draft BT resource ID (UUID) \u2014 required"},btType:{type:"string",enum:["SALE","PURCHASE","SALE_CREDIT_NOTE","PURCHASE_CREDIT_NOTE"],description:"Required"}}}}},required:["items"],group:"drafts",readOnly:!1,searchHint:"submit drafts for approval workflow review bulk",execute:async(e,t)=>(Xu(t.items),XS(e.client,t.items))}];var aE=null;function Ove(){if(!aE){aE=new Map;for(let e of el)aE.set(e.name,e)}return aE}function cE(e){return Ove().get(e)}function M$(){return el}function tl(e){return M$().filter(t=>t.group===e)}Zi();function Nve(e){switch(e){case 401:return"Invalid or missing API key. Run `clio auth add` or set JAZ_API_KEY.";case 403:return"Insufficient permissions for this operation.";case 404:return"Resource not found \u2014 check the resourceId. Use a search/list tool to look it up.";case 409:return"Conflict \u2014 resource may have been modified. Re-fetch and retry.";case 422:return"Validation error \u2014 check field values against the tool description.";case 429:return"Rate limited \u2014 wait a moment and retry.";default:return""}}function hJ(e){if(e instanceof Wi){let r=Nve(e.status);return{error:e.message,status:e.status,endpoint:e.endpoint,...r?{hint:r}:{}}}return{error:e instanceof Error?e.message:String(e)}}function gJ(e,t){if(e.readOnly)return{valid:!0,errors:[]};let r=[];for(let n of e.required){let o=t[n];if(o==null){r.push(`Missing required field: ${n}`);continue}typeof o=="string"&&o.trim()===""&&r.push(`Required field "${n}" is empty`)}for(let[n,o]of Object.entries(t)){if(o==null)continue;let i=e.params[n];if(!i)continue;let s=Rve(n,o,i);s&&r.push(s),i.enum&&typeof o=="string"&&(i.enum.includes(o)||r.push(`Field "${n}" value "${o}" not in allowed values: ${i.enum.join(", ")}`))}return{valid:r.length===0,errors:r}}function Rve(e,t,r){switch(r.type){case"string":if(typeof t!="string")return`Field "${e}" expected string, got ${typeof t}`;break;case"number":if(typeof t!="number"||!Number.isFinite(t))return`Field "${e}" expected finite number, got ${typeof t=="number"?"non-finite":typeof t}`;break;case"boolean":if(typeof t!="boolean")return`Field "${e}" expected boolean, got ${typeof t}`;break;case"array":if(!Array.isArray(t))return`Field "${e}" expected array, got ${typeof t}`;break;case"object":if(typeof t!="object"||Array.isArray(t))return`Field "${e}" expected object, got ${Array.isArray(t)?"array":typeof t}`;break}return null}var rl=[{name:"invoices",description:"Sales invoices (INV/SI). Create, search, get, update, delete, pay, finalize, apply credits, download PDF. Also: receivables, AR, billing, overdue invoices.",groups:["invoices"]},{name:"customer_credit_notes",description:"Customer credit notes (CN). Create, search, update, delete, finalize, refund, download PDF. Also: sales returns, customer CN.",groups:["customer_credit_notes"]},{name:"bills",description:"Purchase bills (PO/PI). Create, search, get, update, delete, pay, finalize, apply credits. Also: payables, AP, vendor invoices, supplier bills.",groups:["bills"]},{name:"supplier_credit_notes",description:"Supplier credit notes. Create, search, update, delete, finalize, refund. Also: purchase returns, debit notes, supplier CN.",groups:["supplier_credit_notes"]},{name:"journals",description:"Journal entries (JE). Create, search, update, delete manual journals. Also: adjusting entries, accruals, reclassifications, corrections.",groups:["journals"]},{name:"cash_entries",description:"Cash-in receipts and cash-out disbursements for external cash movements. WHEN TO USE: money received from customers/external \u2192 cash-in. Money paid to suppliers/external \u2192 cash-out. For internal account-to-account transfers, use cash_transfers namespace.",groups:["cash_entries"]},{name:"cash_transfers",description:"Cash transfers between your own bank/cash accounts and cashflow transaction search. WHEN TO USE: moving funds between own accounts (main bank \u2192 petty cash, USD \u2192 SGD). For external receipts/payments, use cash_entries namespace.",groups:["cash_transfers"]},{name:"bank_accounts",description:"Bank accounts, bank statement imports (CSV/OFX), bank records search, auto-reconciliation. For unreconciled queries: ALWAYS search bank records with status UNRECONCILED after listing accounts. Also: bank feeds, bank balance.",groups:["bank"]},{name:"bank_rules",description:"Bank reconciliation rules (action shortcuts). Create, search, update, delete bank rules. Configure auto-matching rules for bank records.",groups:["bank_rules"]},{name:"reconciliations",description:"Apply a reconciliation decision to a bank statement entry \u2014 write side. Distinct from bank_accounts/bank_rules (which configure auto-reconciliation) and view_auto_reconciliation (which queries suggestions). Eight endpoints: quick_reconcile + apply_bank_rule (async, bulk), and direct_cash_entry / cash_journal / manual_journal / cash_transfer / invoice_receipt / bill_receipt (sync, per-entry). Most fields prefill from the bank entry when omitted.",groups:["reconciliations"]},{name:"financial_reports",description:"Core financial statements: trial balance (TB), balance sheet (BS/B/S), profit & loss (PnL/P&L/income statement), cash flow, general ledger (GL), cash balance/position, equity movement, VAT/GST ledger. Also: how profitable, what is the balance.",groups:["financial_reports"]},{name:"operational_reports",description:"Aging and operational reports: aged receivables (AR aging), aged payables (AP aging), AR report, bank balance summary, bank reconciliation reports, fixed asset (FA) summary, FA reconciliation. Data exports (CSV/Excel). Also: overdue analysis, how much owed.",groups:["operational_reports","exports"]},{name:"contacts",description:"Contacts (customers/suppliers/vendors), contact groups. Create, search, get, update, delete contacts. Bulk upsert contacts (async \u2014 returns jobId, poll background_jobs). List/create contact groups.",groups:["contacts","contact_groups"]},{name:"items_and_inventory",description:"Products, services, inventory items. Create, search, get, update, delete items. Check inventory balance. Also: SKU, catalog, stock.",groups:["items","inventory"]},{name:"tags_and_custom_fields",description:"Tags for categorizing transactions. Custom fields for adding metadata (text, date, dropdown). Create, search, delete tags and custom fields.",groups:["tags","custom_fields"]},{name:"nano_classifiers",description:"Nano classifiers (tracking categories/dimensions). List, search, create, update, delete classifiers and their classes. Used for line-item tagging and dimensional reporting. Also: tracking categories, cost centers, departments, projects.",groups:["nano_classifiers"]},{name:"chart_of_accounts",description:"Chart of accounts (COA/GL accounts). Create, search, update accounts. Bookmarks (favorites/shortcuts). Also: ledger codes, account types.",groups:["accounts","bookmarks"]},{name:"currencies",description:"Currencies, exchange rates (FX/forex). List/add org currencies. Set, update, import currency rates. Also: multi-currency, FX rates.",groups:["currencies"]},{name:"tax_profiles",description:"Tax profiles (GST/VAT/sales tax), withholding tax codes (WHT/ATC). Search, create, update tax profiles. List WHT codes.",groups:["tax_profiles"]},{name:"capsules_and_recipes",description:"Capsules (transaction groupings/capsule types). Financial recipes: amortization, depreciation, deferred revenue, IFRS 16 leases, hire purchase, fixed deposits, FX revaluation, loan schedules, ECL/expected credit loss, IAS 37 provisions, asset disposal. Plan and execute recipes. Keywords: calculate, provision, schedule, expected credit loss, revaluation.",groups:["capsules","recipes"]},{name:"scheduled_transactions",description:"Scheduled/recurring invoices, bills, journals. Create scheduled invoices/bills/journals, search scheduled transactions. Also: recurring, auto-generate.",groups:["schedulers"]},{name:"subscriptions",description:"Subscriptions (recurring billing/payment plans). Create, update, cancel, search subscriptions. Also: recurring charges, subscription schedules.",groups:["subscriptions"]},{name:"organization",description:"Organization info (name, currency, country, fiscal year). User management: invite, update, remove, search org users. Bulk invite.",groups:["organization","org_users"]},{name:"document_ai",description:"File attachments, AI document extraction (magic/OCR). Upload/list attachments. Create transactions from PDFs/images (invoice scanning, bill extraction). Track extraction workflows.",groups:["attachments","magic"]},{name:"fixed_assets",description:"Fixed assets (PP&E/property, plant, equipment). Search, create, update, discard, sell, transfer, undo disposal. Also: depreciation, asset register.",groups:["fixed_assets"]},{name:"payments_and_search",description:"Payment records: get, update, delete individual payments. List payments/credits on invoices and bills. Reverse credit applications. Cashflow transaction search. Universal cross-entity search. Also: void payment, payment history, credit note applications.",groups:["payments","cashflow","search"]},{name:"quick_fix",description:"Quick Fix: bulk-update multiple transactions or line items in one call. Change dates, contacts, tags, accounts, tax profiles, custom fields across many invoices/bills/journals/credit-notes/cash-entries/schedulers at once. Also: batch update, mass edit.",groups:["quick_fix"]},{name:"export_records",description:"Export records to XLSX. List available columns, preview export scope (row count + sample), generate export file with pre-signed download URL. Supports any entity type: invoices, bills, contacts, items, journals, bank records, cashflow, fixed assets, etc. Pass query (structured search syntax) or filter (JSON), never both.",groups:["export_records"]},{name:"background_jobs",description:"Background job tracking. Poll any async operation by jobId (contacts bulk-upsert, items bulk-upsert, bank import, magic file processing, etc.). Filter by resourceId field to look up a specific job. Poll until status is SUCCESS, FAILED, or PARTIAL_SUCCESS.",groups:["background_jobs"]},{name:"drafts",description:"Draft business transactions \u2014 both local payload validation (invoices, bills, journals, credit notes) AND BULK-FRIENDLY server-side lifecycle: validate_drafts (sync eligibility check), convert_drafts_to_active (async promote to ACTIVE), submit_drafts_for_approval (async route to approval). The lifecycle tools are GENERIC and BULK \u2014 one call accepts up to 500 items mixing any combination of {btResourceId, btType: SALE|PURCHASE|SALE_CREDIT_NOTE|PURCHASE_CREDIT_NOTE}. No need for per-entity tools when promoting/submitting drafts at scale. NOT idempotent on already-promoted drafts.",groups:["drafts"]},{name:"close_procedures",description:"Period-end close checklists: month-end, quarter-end, year-end close. Bank reconciliation job. GST/VAT filing job. Audit preparation. Returns structured blueprints.",groups:["close_jobs"]},{name:"operational_jobs",description:"Operational job checklists: payment runs, credit control/collections, supplier reconciliation, fixed asset review, document collection, statutory filing. Returns structured blueprints.",groups:["operational_jobs"]}];function yJ(e,t=5){let r=e.trim().toLowerCase();if(!r)return[];let n=r.split(/[\s_-]+/).filter(i=>i.length>=2);return n.length===0?[]:rl.map(i=>{let s=0,a=i.name.toLowerCase(),c=i.description.toLowerCase();(a===r||a===r.replace(/\s+/g,"_"))&&(s+=5),a.includes(r)&&(s+=3),c.includes(r)&&(s+=1);for(let u of n)a.includes(u)&&(s+=2),c.includes(u)&&(s+=1);return{ns:i,score:s}}).filter(i=>i.score>0).sort((i,s)=>s.score-i.score).slice(0,t).map(i=>i.ns)}function uE(e){let t={type:e.type};if(e.description&&(t.description=e.description),e.enum&&(t.enum=e.enum),e.type==="array"&&e.items&&(t.items=uE(e.items)),e.type==="object"&&e.properties){let r={};for(let[n,o]of Object.entries(e.properties))r[n]=uE(o);t.properties=r,e.required?.length&&(t.required=e.required)}return t}function Za(e,t){let r={};for(let[n,o]of Object.entries(e))r[n]=uE(o);return{type:"object",properties:r,...t.length>0?{required:t}:{}}}function DJ(e){return{name:e.name,description:e.description,input_schema:Za(e.params,e.required),...e.searchHint?{searchHint:e.searchHint}:{}}}function kve(e){if(typeof e!="string")return e.isDestructive??!1;let t=e;return t.startsWith("delete_")||t.startsWith("pay_")||t.startsWith("finalize_")||t.includes("refund")||t==="remove_org_user"}function bJ(e){if(!e.trim())return{namespaces:rl.map(o=>{let i=o.groups.flatMap(s=>tl(s));return{name:o.name,description:o.description,toolCount:i.length,tools:i.map(s=>s.name)}}),hint:"Call describe_tools with specific tool names to get full schemas before executing."};let t=yJ(e,5);if(t.length===0)return{matches:[],hint:`No tools match "${e}". Try broader terms or call search_tools with empty query to see all namespaces.`};let n=e.toLowerCase().split(/\s+/).filter(Boolean);return{matches:t.map(o=>{let s=o.groups.flatMap(a=>tl(a)).map(a=>{let c=`${a.name} ${a.searchHint??""} ${a.description.split(`
841
+ Response: { updated: string[], failed: [{ resourceId, error, errorCode }] }. On partial failure (HTTP 207), check failed.length.`,params:{entity:{type:"string",enum:[...Ku],description:"Transaction type"},lineItemResourceIds:{type:"array",items:{type:"string"},description:"Line item resourceIds to update (ARAP + accounting entities)"},attributes:{type:"object",description:"Fields to update on all specified line items"},schedulerUpdates:{type:"array",items:{type:"object"},description:"Per-scheduler updates: [{ schedulerResourceId, lineItemUpdates: [{ arrayIndex, ...fields }] }]. EXCEPTION: journal-schedules use lineItemResourceId (UUID) instead of arrayIndex."}},required:["entity"],group:"quick_fix",readOnly:!1,searchHint:"bulk update line item accounts tax profiles",execute:async(e,t)=>{let r=t.entity,n=["sale-schedules","purchase-schedules","subscription-schedules","journal-schedules"].includes(r),o={};if(n){if(!t.schedulerUpdates)throw new Error("schedulerUpdates is required for scheduler entities (sale-schedules, purchase-schedules, subscription-schedules, journal-schedules)");o.schedulerUpdates=t.schedulerUpdates}else{if(!t.lineItemResourceIds)throw new Error("lineItemResourceIds is required for non-scheduler entities");o.lineItemResourceIds=t.lineItemResourceIds,o.attributes=t.attributes??{}}return _m(e.client,r,o)}},yt("list_nano_classifiers","List nano classifiers (tracking categories). Paginated. Nano classifiers tag line items with structured categories.","nano_classifiers",(e,t,r)=>zS(e,{limit:r,offset:t}),"list nano classifiers tracking categories types"),Gn("get_nano_classifier","Get a nano classifier by resourceId. Returns type and all classes.","nano_classifiers",(e,t)=>YS(e,t),"get nano classifier tracking category details"),Nt({name:"search_nano_classifiers",description:"Search nano classifiers (tracking categories) by type name.",group:"nano_classifiers",fields:Wp,defaults:Zp,fetcher:JS,searchHint:"find nano classifiers tracking categories by type"}),{name:"create_nano_classifier",description:"Create a nano classifier (tracking category). Provide a type name and list of class names. printable defaults to true (NOTE: printable: false is currently rejected by a server bug \u2014 always use true).",params:{type:{type:"string",description:'Classifier type name (e.g., "Department", "Project")'},classes:{type:"array",items:{type:"string"},description:'Class names: ["Sales", "Marketing", "Engineering"]'},printable:{type:"boolean",description:"Show on printed documents (default: true). NOTE: false is rejected by a server bug."}},required:["type","classes"],group:"nano_classifiers",readOnly:!1,searchHint:"create new nano classifier tracking category",execute:async(e,t)=>Im(e.client,{type:t.type,classes:t.classes,printable:t.printable??!0})},{name:"update_nano_classifier",description:"Update a nano classifier \u2014 change type name, modify classes, or toggle printable.",params:{resourceId:{type:"string",description:"Nano classifier resourceId"},type:{type:"string",description:"New type name"},classes:{type:"array",items:{type:"string"},description:'Updated class names: ["Sales", "Marketing"]'},printable:{type:"boolean",description:"Show on printed documents"}},required:["resourceId"],group:"nano_classifiers",readOnly:!1,searchHint:"update nano classifier classes and settings",execute:async(e,t)=>{let r={};return t.type&&(r.type=t.type),t.classes&&(r.classes=t.classes),t.printable!==void 0&&(r.printable=t.printable),Cm(e.client,t.resourceId,r)}},fn("delete_nano_classifier","Delete a nano classifier.","nano_classifiers",(e,t)=>GS(e,t),"permanently delete a nano classifier type"),{name:"list_invoice_payments",description:"List all payments recorded against an invoice. Returns payment records with amounts, dates, and methods.",params:{resourceId:{type:"string",description:"Invoice resourceId"}},required:["resourceId"],group:"payments",readOnly:!0,searchHint:"list payment records on an invoice",isConcurrencySafe:!0,maxResultSizeChars:5e4,execute:async(e,t)=>sb(e.client,t.resourceId)},{name:"list_invoice_credits",description:"List all credit notes applied to an invoice.",params:{resourceId:{type:"string",description:"Invoice resourceId"}},required:["resourceId"],group:"payments",readOnly:!0,searchHint:"list credit applications on an invoice",isConcurrencySafe:!0,maxResultSizeChars:5e4,execute:async(e,t)=>ab(e.client,t.resourceId)},{name:"reverse_invoice_credit",description:"Reverse (unapply) a credit note from an invoice. The credit note becomes UNAPPLIED again.",params:{resourceId:{type:"string",description:"Invoice resourceId"},creditResourceId:{type:"string",description:"Credit application resourceId to reverse"}},required:["resourceId","creditResourceId"],group:"payments",readOnly:!1,searchHint:"reverse a credit note application on invoice",isDestructive:!0,execute:async(e,t)=>(await cb(e.client,t.resourceId,t.creditResourceId),{reversed:!0,invoiceId:t.resourceId,creditId:t.creditResourceId})},{name:"list_bill_payments",description:"List all payments recorded against a bill. Returns payment records with amounts, dates, and methods.",params:{resourceId:{type:"string",description:"Bill resourceId"}},required:["resourceId"],group:"payments",readOnly:!0,searchHint:"list payment records on a bill",isConcurrencySafe:!0,maxResultSizeChars:5e4,execute:async(e,t)=>ry(e.client,t.resourceId)},{name:"list_bill_credits",description:"List all credit notes applied to a bill.",params:{resourceId:{type:"string",description:"Bill resourceId"}},required:["resourceId"],group:"payments",readOnly:!0,searchHint:"list credit applications on a bill",isConcurrencySafe:!0,maxResultSizeChars:5e4,execute:async(e,t)=>ny(e.client,t.resourceId)},{name:"reverse_bill_credit",description:"Reverse (unapply) a supplier credit note from a bill. The credit note becomes UNAPPLIED again.",params:{resourceId:{type:"string",description:"Bill resourceId"},creditResourceId:{type:"string",description:"Credit application resourceId to reverse"}},required:["resourceId","creditResourceId"],group:"payments",readOnly:!1,searchHint:"reverse a credit note application on bill",isDestructive:!0,execute:async(e,t)=>(await oy(e.client,t.resourceId,t.creditResourceId),{reversed:!0,billId:t.resourceId,creditId:t.creditResourceId})},Gn("get_scheduled_invoice","Get a scheduled (recurring) invoice by resourceId.","schedulers",(e,t)=>T0(e,t),"get scheduled recurring invoice details"),{name:"update_scheduled_invoice",description:"Update a scheduled invoice \u2014 change schedule settings and/or the invoice template.",params:{resourceId:{type:"string",description:"Scheduled invoice resourceId"},repeat:{type:"string",description:"Recurrence: WEEKLY, MONTHLY, QUARTERLY, YEARLY"},startDate:{type:"string",description:"First occurrence date (YYYY-MM-DD)"},endDate:{type:"string",description:"Last occurrence date (YYYY-MM-DD)"},status:{type:"string",description:"Status: ACTIVE or PAUSED"},invoice:{type:"object",description:"Invoice template: { reference, valueDate, dueDate, contactResourceId, lineItems, currency, tag, saveAsDraft }"}},required:["resourceId"],group:"schedulers",readOnly:!1,searchHint:"update recurring scheduled invoice settings",execute:async(e,t)=>{let r={};return t.repeat&&(r.repeat=t.repeat),t.startDate&&(r.startDate=t.startDate),t.endDate&&(r.endDate=t.endDate),t.status&&(r.status=t.status),t.invoice&&(r.invoice=t.invoice),$0(e.client,t.resourceId,r)}},fn("delete_scheduled_invoice","Delete a scheduled (recurring) invoice.","schedulers",(e,t)=>O0(e,t),"delete a recurring scheduled invoice"),Gn("get_scheduled_bill","Get a scheduled (recurring) bill by resourceId.","schedulers",(e,t)=>N0(e,t),"get scheduled recurring bill details"),{name:"update_scheduled_bill",description:"Update a scheduled bill \u2014 change schedule settings and/or the bill template.",params:{resourceId:{type:"string",description:"Scheduled bill resourceId"},repeat:{type:"string",description:"Recurrence: WEEKLY, MONTHLY, QUARTERLY, YEARLY"},startDate:{type:"string",description:"First occurrence date (YYYY-MM-DD)"},endDate:{type:"string",description:"Last occurrence date (YYYY-MM-DD)"},status:{type:"string",description:"Status: ACTIVE or PAUSED"},bill:{type:"object",description:"Bill template: { reference, valueDate, dueDate, contactResourceId, lineItems, currency, tag, saveAsDraft }"}},required:["resourceId"],group:"schedulers",readOnly:!1,searchHint:"update recurring scheduled bill settings",execute:async(e,t)=>{let r={};return t.repeat&&(r.repeat=t.repeat),t.startDate&&(r.startDate=t.startDate),t.endDate&&(r.endDate=t.endDate),t.status&&(r.status=t.status),t.bill&&(r.bill=t.bill),R0(e.client,t.resourceId,r)}},fn("delete_scheduled_bill","Delete a scheduled (recurring) bill.","schedulers",(e,t)=>k0(e,t),"delete a recurring scheduled bill"),Gn("get_scheduled_journal","Get a scheduled (recurring) journal by resourceId.","schedulers",(e,t)=>F0(e,t),"get scheduled recurring journal details"),{name:"update_scheduled_journal",description:"Update a scheduled journal \u2014 change schedule settings and/or the journal template.",params:{resourceId:{type:"string",description:"Scheduled journal resourceId"},repeat:{type:"string",description:"Recurrence: WEEKLY, MONTHLY, QUARTERLY, YEARLY"},startDate:{type:"string",description:"First occurrence date (YYYY-MM-DD)"},endDate:{type:"string",description:"Last occurrence date (YYYY-MM-DD)"},status:{type:"string",description:"Status: ACTIVE or PAUSED"},valueDate:{type:"string",description:"Journal date (YYYY-MM-DD)"},schedulerEntries:{type:"array",items:{type:"object"},description:"Journal entries: [{ accountResourceId, type: CREDIT|DEBIT, amount, ... }]"},reference:{type:"string",description:"Journal reference"},notes:{type:"string",description:"Journal notes"}},required:["resourceId"],group:"schedulers",readOnly:!1,searchHint:"update recurring scheduled journal settings",execute:async(e,t)=>{let r={};return t.repeat&&(r.repeat=t.repeat),t.startDate&&(r.startDate=t.startDate),t.endDate&&(r.endDate=t.endDate),t.status&&(r.status=t.status),t.valueDate&&(r.valueDate=t.valueDate),t.schedulerEntries&&(r.schedulerEntries=t.schedulerEntries),t.reference&&(r.reference=t.reference),t.notes&&(r.notes=t.notes),P0(e.client,t.resourceId,r)}},fn("delete_scheduled_journal","Delete a scheduled (recurring) journal.","schedulers",(e,t)=>L0(e,t),"delete a recurring scheduled journal"),Gn("get_payment","Get a specific payment record by resourceId. Returns payment amount, method, date, and reference.","payments",(e,t)=>Ob(e,t),"get payment record details by id"),{name:"update_payment",description:"Update a payment record \u2014 correct amount, reference, date, method, or account.",params:{resourceId:{type:"string",description:"Payment resourceId (from invoice/bill paymentRecords)"},paymentAmount:{type:"number",description:"Corrected payment amount (bank currency)"},reference:{type:"string",description:"Payment reference"},valueDate:{type:"string",description:"Payment date (YYYY-MM-DD)"},paymentMethod:wm,accountResourceId:{type:"string",description:"Bank/cash account resourceId"},transactionFee:{type:"number",description:"Transaction fee amount"}},required:["resourceId"],group:"payments",readOnly:!1,searchHint:"update payment amount reference date method",execute:async(e,t)=>{let r={};return t.paymentAmount!==void 0&&(r.paymentAmount=t.paymentAmount),t.reference&&(r.reference=t.reference),t.valueDate&&(r.valueDate=t.valueDate),t.paymentMethod&&(r.paymentMethod=t.paymentMethod),t.accountResourceId&&(r.accountResourceId=t.accountResourceId),t.transactionFee!==void 0&&(r.transactionFee=t.transactionFee),Nb(e.client,t.resourceId,r)}},fn("delete_payment","Delete (void) a payment record. The associated invoice/bill balance is restored.","payments",(e,t)=>Rb(e,t),"delete void a payment record restore balance"),{name:"get_export_columns",description:"List all exportable columns for an entity type, including their paths and data types. Use paths from this response to build custom column sets for export_records or preview_export_records.",params:{entityType:L$},required:["entityType"],group:"export_records",readOnly:!0,isConcurrencySafe:!0,searchHint:"list export columns fields for entity type",execute:async(e,t)=>WS(e.client,t.entityType)},{name:"preview_export_records",description:"Preview an export before generating the file. Returns totalRecords, up to 10 sample rows, resolved column definitions, and a human-readable filterDescription. Use this to confirm scope before calling export_records. Pass either query OR filter, never both.",params:{entityType:L$,query:cJ,filter:uJ,columns:lJ,sort:dJ},required:["entityType"],group:"export_records",readOnly:!0,isConcurrencySafe:!0,searchHint:"preview export records count sample rows filter",execute:async(e,t)=>HS(e.client,{entityType:t.entityType,outputFormat:"XLSX",query:t.query,filter:t.filter,columns:t.columns,sort:t.sort})},{name:"export_records",description:"Generate a filtered XLSX export for an entity type. Returns a pre-signed download URL (expires in ~5 minutes \u2014 download immediately), file name, and total record count. Pass either query OR filter, never both. Use preview_export_records first to confirm scope.",params:{entityType:L$,query:cJ,filter:uJ,columns:lJ,sort:dJ},required:["entityType"],group:"export_records",readOnly:!0,isConcurrencySafe:!0,searchHint:"export records download xlsx file url",execute:async(e,t)=>VS(e.client,{entityType:t.entityType,outputFormat:"XLSX",query:t.query,filter:t.filter,columns:t.columns,sort:t.sort})},Nt({name:"search_background_jobs",description:"Search and poll background jobs. ANY operation that returns a jobId (bulk_upsert_contacts, bulk_upsert_items, bank statement import, magic file processing, etc.) can be tracked here. Filter by resourceId (the jobId value) to poll a specific job. Poll until status is SUCCESS, FAILED, or PARTIAL_SUCCESS. Use processedCount/failedCount/totalRecords for progress. IMPORTANT: filter by resourceId field, NOT jobId \u2014 they differ.",group:"background_jobs",fields:Op,defaults:Np,fetcher:Am,searchHint:"poll background job status by jobId type status"}),{name:"bulk_upsert_contacts",description:"Create or update contacts in bulk (max 500 per call). Provide resourceId per contact to update (partial \u2014 only changed fields needed). Omit resourceId to create new contacts. Returns a jobId \u2014 this is async. Poll search_background_jobs with filter {resourceId:{eq:jobId}} until status is SUCCESS, FAILED, or PARTIAL_SUCCESS. NOTE: unlike bulk_upsert_items (sync), contacts bulk-upsert is async.",params:{contacts:{type:"array",description:"Array of contacts to create or update (max 500)",items:{type:"object",properties:{resourceId:{type:"string",description:"Contact resourceId (omit for create, provide UUID for update)"},billingName:{type:"string",description:"Billing name (required for create)"},name:{type:"string",description:"Display name (defaults to billingName)"},emails:{type:"array",items:{type:"string"},description:"Email addresses"},customer:{type:"boolean",description:"Mark as customer"},supplier:{type:"boolean",description:"Mark as supplier"},taxId:{type:"string",description:"Tax ID / GST registration number"},taxIdType:{type:"string",description:"Tax ID type (e.g., GST, VAT)"},registrationNumber:{type:"string",description:"Business registration number"},currencyCode:{type:"string",description:"Default currency code (e.g., SGD)"},status:{type:"string",enum:["ACTIVE","INACTIVE"],description:"Contact status"},paymentTerms:{type:"number",description:"Payment terms in days (e.g., 30 for Net 30)"},notes:{type:"string",description:"Internal notes"},billingAddress:{type:"object",description:"Billing address",properties:{address:{type:"string"},city:{type:"string"},state:{type:"string"},postalCode:{type:"string"},country:{type:"string"}}},shippingAddress:{type:"object",description:"Shipping address",properties:{address:{type:"string"},city:{type:"string"},state:{type:"string"},postalCode:{type:"string"},country:{type:"string"}}}}}}},required:["contacts"],group:"contacts",readOnly:!1,searchHint:"bulk create update contacts upsert",execute:async(e,t)=>(Gr(t.contacts,"contacts"),uy(e.client,t.contacts))},{name:"bulk_upsert_invoices",description:"Create or update invoices in bulk (max 500 per call). FLAT shape: ONE line per invoice via `itemDescription` + `totalAmount` + `invoiceAccountResourceId` at row level. For multi-line invoices use `bulk_upsert_invoice_line_items` instead \u2014 that variant takes nested `lineItems[]`. Natural key: `invoiceReference` (rows sharing one within a batch are MERGED \u2014 last wins). Provide resourceId per invoice to update via UUID; or omit and rely on invoiceReference for upsert. Async \u2014 returns a jobId. Poll search_background_jobs with filter {resourceId:{eq:jobId}} until SUCCESS / FAILED / PARTIAL_SUCCESS; on PARTIAL_SUCCESS read data[0].errorDetails on the same response for per-row failures. Dates are ISO 8601 (YYYY-MM-DD) only \u2014 the dateFormat field was removed.",params:{invoices:{type:"array",description:"Array of invoices to create or update (max 500). Each row needs at least: invoiceReference, contactResourceId, valueDate, totalAmount, invoiceAccountResourceId.",items:{type:"object",properties:{rowIndex:{type:"string",description:"Optional caller-supplied row index for error reporting"},resourceId:{type:"string",description:"Invoice resourceId (UUID) \u2014 provide to update by ID"},invoiceReference:{type:"string",description:"Natural key (e.g., INV-2025-001) \u2014 required"},contactResourceId:{type:"string",description:"Customer contact UUID \u2014 required"},valueDate:{type:"string",description:"Invoice date YYYY-MM-DD \u2014 required"},dueDate:{type:"string",description:"Due date YYYY-MM-DD"},totalAmount:{type:"number",description:"Total amount (BigDecimal)"},currencyCode:{type:"string",description:"Currency (e.g., SGD)"},invoiceAccountResourceId:{type:"string",description:"Revenue account UUID"},itemDescription:{type:"string",description:"Single-line item description"},internalNotes:{type:"string",description:"Internal notes"},tags:{type:"array",items:{type:"string"},description:"Tag resourceIds"}}}}},required:["invoices"],group:"invoices",readOnly:!1,searchHint:"bulk create update invoices upsert import migrate",execute:async(e,t)=>{Gr(t.invoices,"invoices");let r=t.invoices;return to(r,["valueDate","dueDate"]),ub(e.client,r)}},{name:"bulk_upsert_invoice_line_items",description:"Create or update invoices with nested line items in bulk (max 500 invoices per call). Each row carries lineItems[] under its parent invoice (scoped by invoiceReference). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 only.",params:{invoices:{type:"array",description:"Array of invoices with line items (max 500). Each invoice row has lineItems[].",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string",description:"Invoice resourceId \u2014 provide to update by ID"},invoiceReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Customer UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},dueDate:{type:"string",description:"YYYY-MM-DD"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},lineItems:{type:"array",description:"Line items belonging to this invoice",items:{type:"object",properties:{itemDescription:{type:"string",description:"Line description \u2014 required"},quantity:{type:"number"},unit:{type:"string",description:"Unit of measure (pcs, kg, etc.)"},unitPrice:{type:"number"},accountResourceId:{type:"string",description:"Revenue account UUID"},taxProfileResourceId:{type:"string"}}}}}}}},required:["invoices"],group:"invoices",readOnly:!1,searchHint:"bulk invoices line items multi-line upsert import",execute:async(e,t)=>{Gr(t.invoices,"invoices");let r=t.invoices;return to(r,["valueDate","dueDate"]),lb(e.client,r)}},{name:"bulk_upsert_bills",description:"Create or update bills in bulk (max 500 per call). FLAT shape: ONE line per bill via `itemDescription` + `totalAmount` + `billAccountResourceId` at row level. For multi-line bills use `bulk_upsert_bill_line_items` instead \u2014 that variant takes nested `lineItems[]`. Natural key: `billReference` (rows sharing one within a batch are MERGED \u2014 last wins). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 only \u2014 dateFormat field was removed.",params:{bills:{type:"array",description:"Array of bills to create or update (max 500). Each row needs at least: billReference, contactResourceId, valueDate, totalAmount, billAccountResourceId.",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},billReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Supplier UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},dueDate:{type:"string"},totalAmount:{type:"number"},currencyCode:{type:"string"},billAccountResourceId:{type:"string",description:"Expense account UUID"},itemDescription:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}}}}}},required:["bills"],group:"bills",readOnly:!1,searchHint:"bulk create update bills upsert import migrate",execute:async(e,t)=>{Gr(t.bills,"bills");let r=t.bills;return to(r,["valueDate","dueDate"]),iy(e.client,r)}},{name:"bulk_upsert_bill_line_items",description:"Create or update bills with nested line items in bulk (max 500 bills per call). Each row carries lineItems[] under its parent bill (scoped by billReference). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures.",params:{bills:{type:"array",description:"Array of bills with line items (max 500). Each bill row has lineItems[].",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},billReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Supplier UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},dueDate:{type:"string"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},lineItems:{type:"array",items:{type:"object",properties:{itemDescription:{type:"string",description:"Required"},quantity:{type:"number"},unit:{type:"string"},unitPrice:{type:"number"},accountResourceId:{type:"string",description:"Expense account UUID"},taxProfileResourceId:{type:"string"}}}}}}}},required:["bills"],group:"bills",readOnly:!1,searchHint:"bulk bills line items multi-line upsert import",execute:async(e,t)=>{Gr(t.bills,"bills");let r=t.bills;return to(r,["valueDate","dueDate"]),sy(e.client,r)}},{name:"bulk_upsert_customer_credit_notes",description:"Create or update customer credit notes in bulk (max 500 per call). Natural key: creditNoteReference. Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 only.",params:{customerCreditNotes:{type:"array",description:"Array of customer credit notes (max 500).",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},creditNoteReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Customer UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},lineItems:{type:"array",items:{type:"object",properties:{itemDescription:{type:"string",description:"Required"},quantity:{type:"number"},unitPrice:{type:"number"},accountResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}}}}}},required:["customerCreditNotes"],group:"customer_credit_notes",readOnly:!1,searchHint:"bulk customer credit notes refund upsert import",execute:async(e,t)=>{Gr(t.customerCreditNotes,"customerCreditNotes",500,"customer credit notes");let r=t.customerCreditNotes;return to(r,["valueDate"]),n0(e.client,r)}},{name:"bulk_upsert_supplier_credit_notes",description:"Create or update supplier credit notes in bulk (max 500 per call). Natural key: creditNoteReference. Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 only.",params:{supplierCreditNotes:{type:"array",description:"Array of supplier credit notes (max 500).",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},creditNoteReference:{type:"string",description:"Natural key \u2014 required"},contactResourceId:{type:"string",description:"Supplier UUID \u2014 required"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},lineItems:{type:"array",items:{type:"object",properties:{itemDescription:{type:"string",description:"Required"},quantity:{type:"number"},unitPrice:{type:"number"},accountResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}}}}}},required:["supplierCreditNotes"],group:"supplier_credit_notes",readOnly:!1,searchHint:"bulk supplier credit notes refund upsert import",execute:async(e,t)=>{Gr(t.supplierCreditNotes,"supplierCreditNotes",500,"supplier credit notes");let r=t.supplierCreditNotes;return to(r,["valueDate"]),c0(e.client,r)}},{name:"bulk_upsert_journals",description:"Create or update manual journals in bulk (max 500 per call). NATURAL KEY: `journalReference` (NOT `reference` \u2014 every other bulk-upsert uses entityReference, this one is asymmetric). LEGS field: `journalEntries[]` (NOT `entries[]` \u2014 different from `clio journals create` which uses entries). Each leg has `accountResourceId` + `debitAmount` + `creditAmount` (debit + credit must balance per row). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 (YYYY-MM-DD) only \u2014 dateFormat field was removed.",params:{journals:{type:"array",description:"Array of journals to create or update (max 500). Each row has entries[] (debit/credit legs).",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},journalReference:{type:"string",description:"Natural key \u2014 required (NOTE: field is `journalReference`, not `reference`)"},valueDate:{type:"string",description:"YYYY-MM-DD \u2014 required"},currencyCode:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},journalEntries:{type:"array",description:"Journal legs (debit + credit amounts must balance) \u2014 field is `journalEntries`, NOT `entries`",items:{type:"object",properties:{accountResourceId:{type:"string",description:"Required"},description:{type:"string"},debitAmount:{type:"number"},creditAmount:{type:"number"},contactResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}}}}}},required:["journals"],group:"journals",readOnly:!1,searchHint:"bulk manual journals upsert import migration",execute:async(e,t)=>{Gr(t.journals,"journals");let r=t.journals;return to(r,["valueDate"]),yb(e.client,r)}},{name:"bulk_upsert_fixed_assets",description:'\u26A0\uFE0F DATE FIELD MISMATCH: bulk-upsert REQUEST uses `valueDate` (not `purchaseDate`); the GET response uses `purchaseDate`. Sending `purchaseDate` returns a cryptic 400 "Invalid request body" with no field detail. Create or update fixed assets in bulk (max 500 per call). Natural key: `reference`. Each row REQUIRED: `reference`, `registrationType` (NEW | TRANSFER). Recommended: `typeCode`, `typeName`, `category` (TANGIBLE | INTANGIBLE), `cost` (or synonym `purchaseAmount`), `valueDate`, `depreciationStartDate`, `effectiveLife` (or synonym `usefulLifeMonths`), `depreciationMethod`, `purchaseAssetAccountResourceId`, `depreciationExpenseAccountResourceId`, `accumulatedDepreciationAccountResourceId`. Account fields must be valid UUIDv4. Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. Dates are ISO 8601 (YYYY-MM-DD) only.',params:{fixedAssets:{type:"array",description:"Array of fixed assets to create or update (max 500).",items:{type:"object",properties:{rowIndex:{type:"string"},resourceId:{type:"string"},reference:{type:"string",description:"Natural key \u2014 required"},registrationType:{type:"string",enum:["NEW","TRANSFER"],description:"NEW = newly acquired, TRANSFER = inherited from prior system \u2014 required"},typeCode:{type:"string",description:"Asset class code (e.g., FURNITURE_AND_FIXTURE)"},typeName:{type:"string",description:'Human label for the typeCode (e.g., "Furniture and Fixtures")'},category:{type:"string",description:"TANGIBLE | INTANGIBLE"},name:{type:"string",description:"Asset name"},valueDate:{type:"string",description:"Acquisition date YYYY-MM-DD (NOTE: bulk uses `valueDate`, the GET response uses `purchaseDate` \u2014 different fields)"},cost:{type:"number",description:"Cost basis (alias for purchaseAmount on the bulk endpoint)"},purchaseAmount:{type:"number",description:"Cost basis (synonym of `cost`)"},currencyCode:{type:"string"},depreciationStartDate:{type:"number",description:'Epoch milliseconds (NOT YYYY-MM-DD \u2014 inconsistent with valueDate which IS YYYY-MM-DD on this same endpoint). Sending YYYY-MM-DD returns generic 400 "Invalid request body" with no detail. Omit to default to valueDate.'},effectiveLife:{type:"number",description:"Useful life in months (alias for usefulLifeMonths)"},usefulLifeMonths:{type:"number",description:"Useful life in months (synonym of effectiveLife)"},depreciationMethod:{type:"string",description:"e.g., STRAIGHT_LINE, DOUBLE_DECLINING_BALANCE"},purchaseAssetAccountResourceId:{type:"string",description:"Asset (PPE) account UUID \u2014 must be valid UUIDv4"},depreciationExpenseAccountResourceId:{type:"string",description:"Depreciation expense account UUID \u2014 must be valid UUIDv4"},accumulatedDepreciationAccountResourceId:{type:"string",description:"Accumulated depreciation account UUID"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}}}}}},required:["fixedAssets"],group:"fixed_assets",readOnly:!1,searchHint:"bulk fixed assets ppe register upsert import migrate",execute:async(e,t)=>{Gr(t.fixedAssets,"fixedAssets",500,"fixed assets");let r=t.fixedAssets;return to(r,["valueDate"]),vS(e.client,r)}},{name:"quick_reconcile",description:"Bulk-reconcile bank statement entries against a list of journals (max 500). Reconciliation mode is hardcoded to QUICK_RECON. Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails. Caller provides bankAccountResourceId + journalsForReconciliation[] (each row: bankStatementEntryResourceId, journalReference, journalAccountResourceId).",params:{bankAccountResourceId:{type:"string",description:"Bank account UUID (the entries belong to this account)"},journalsForReconciliation:{type:"array",description:"Per-row reconciliation instructions (max 500).",items:{type:"object",properties:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},journalReference:{type:"string",description:"Journal reference text \u2014 required"},journalAccountResourceId:{type:"string",description:"Offsetting account UUID (revenue for cash-in, expense for cash-out) \u2014 required"},contactResourceId:{type:"string",description:"Contact UUID"},capsuleResourceId:{type:"string",description:"Capsule UUID"},taxProfileResourceId:{type:"string",description:"Tax profile UUID"},internalNotes:{type:"string"},journalEntryDescription:{type:"string"},tags:{type:"array",items:{type:"string"}},rowIndex:{type:"string",description:"Optional caller-supplied index for error correlation"}}}}},required:["bankAccountResourceId","journalsForReconciliation"],group:"reconciliations",readOnly:!1,searchHint:"bulk reconcile bank statement journals match",execute:async(e,t)=>(Gr(t.journalsForReconciliation,"journalsForReconciliation",500,"journals"),QS(e.client,t))},{name:"apply_bank_rule",description:"Apply a pre-configured bank rule (action shortcut) to a batch of bank statement entries (max 500). Async \u2014 returns a jobId. Poll search_background_jobs filtered by resourceId. The rule executes its configured action (e.g. RECONCILE_WITH_DIRECT_CASH_ENTRY) on each entry.",params:{actionShortcutResourceId:{type:"string",description:"Bank rule UUID \u2014 required"},businessTransactionResourceIds:{type:"array",description:"Bank statement entry UUIDs to apply the rule to (max 500). Note: the field is named businessTransactionResourceIds for legacy reasons but accepts bank entry IDs.",items:{type:"string"}}},required:["actionShortcutResourceId","businessTransactionResourceIds"],group:"reconciliations",readOnly:!1,searchHint:"bank rule apply action shortcut bulk reconcile",execute:async(e,t)=>(Gr(t.businessTransactionResourceIds,"businessTransactionResourceIds",500,"entries"),eE(e.client,t))},{name:"reconcile_direct_cash_entry",description:"Reconcile a bank statement entry with a single cash-in / cash-out line. Direction (cash-in vs cash-out) is INFERRED from the bank entry sign. Sync \u2014 returns the reconciled entry status. NOT idempotent: calling twice on the same bankStatementEntryResourceId creates duplicate journals. Confirm reconciled-state via view_auto_reconciliation before retrying.",params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID (used to look up the entry) \u2014 required"},reference:{type:"string",description:"Reference for the cash entry \u2014 required"},accountResourceId:{type:"string",description:"Offsetting account UUID (revenue for cash-in, expense for cash-out) \u2014 required"},amount:{type:"number",description:"Amount in source currency. Defaults to bank entry amount if omitted."},description:{type:"string"},contactResourceId:{type:"string"},taxProfileResourceId:{type:"string"},internalNotes:{type:"string"},bankAccountJournalEntryDescription:{type:"string",description:"Description for the bank-side journal entry"},tags:{type:"array",items:{type:"string"}},taxVatApplicable:{type:"boolean"},taxInclusion:{type:"boolean"},capsuleResourceId:{type:"string"}},required:["bankStatementEntryResourceId","bankAccountResourceId","reference","accountResourceId"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry direct cash in out single line",execute:async(e,t)=>tE(e.client,t)},{name:"reconcile_cash_journal",description:"Reconcile a bank statement entry with a multi-line cashflow journal (multiple cash splits, max 200 lines). Sync \u2014 returns the reconciled entry status. NOT idempotent \u2014 confirm reconciled-state before retrying.",params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},reference:{type:"string",description:"Journal reference \u2014 required"},journalEntries:{type:"array",description:"Cash journal lines (max 200). Each row is one debit OR credit against an account.",items:{type:"object",properties:{accountResourceId:{type:"string",description:"Account UUID \u2014 required"},amount:{type:"number",description:"Amount in source currency \u2014 required (>0)"},description:{type:"string"},taxProfileResourceId:{type:"string"}}}},contactResourceId:{type:"string"},bankAccountJournalEntryDescription:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},taxVatApplicable:{type:"boolean"},taxInclusion:{type:"boolean"},capsuleResourceId:{type:"string"}},required:["bankStatementEntryResourceId","bankAccountResourceId","reference","journalEntries"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry multi line cash journal splits",execute:async(e,t)=>(Gr(t.journalEntries,"journalEntries",200,"entries"),rE(e.client,t))},{name:"reconcile_manual_journal",description:'\u26A0\uFE0F CALLER PROVIDES ONLY THE OFFSET LEG(S) \u2014 backend AUTO-ADDS the bank-side leg from the statement entry. Sending both debit AND credit legs \u2192 422 "sum of debit and credit amounts are not equal" (your sides duplicate after the auto-add). Reconcile a bank statement entry with a double-entry manual journal. Sync \u2014 returns the reconciled entry status. valueDate prefills from bank entry if omitted. NOT idempotent.',params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},status:{type:"string",enum:["DRAFT","ACTIVE"],description:"Journal status \u2014 required"},journalEntries:{type:"array",description:"Offset-side journal entries only (max 200). The bank-side leg is auto-added by the API.",items:{type:"object",properties:{accountResourceId:{type:"string",description:"Account UUID \u2014 required"},type:{type:"string",enum:["DEBIT","CREDIT"]},amount:{type:"number",description:"Amount \u2014 required"},description:{type:"string"},contactResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}},reference:{type:"string"},valueDate:{type:"string",description:"YYYY-MM-DD. Defaults to bank entry value date."},contactResourceId:{type:"string"},internalNotes:{type:"string"},bankAccountJournalEntryDescription:{type:"string"},taxVatApplicable:{type:"boolean"},taxInclusion:{type:"boolean"},tags:{type:"array",items:{type:"string"}},capsuleResourceId:{type:"string"}},required:["bankStatementEntryResourceId","bankAccountResourceId","status","journalEntries"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry manual journal double entry",execute:async(e,t)=>(Gr(t.journalEntries,"journalEntries",200,"entries"),nE(e.client,t))},{name:"reconcile_cash_transfer",description:"Reconcile a bank statement entry with an inter-account transfer. Sync \u2014 returns the reconciled entry status. amount is required only when the counterparty account is in a non-functional currency. NOT idempotent.",params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},accountResourceId:{type:"string",description:"Counterparty cash account UUID \u2014 required"},reference:{type:"string",description:"Transfer reference \u2014 required"},amount:{type:"number",description:"Amount in source currency. Required only for cross-currency transfers."},contactResourceId:{type:"string"},internalNotes:{type:"string"},tags:{type:"array",items:{type:"string"}},capsuleResourceId:{type:"string"}},required:["bankStatementEntryResourceId","bankAccountResourceId","accountResourceId","reference"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry transfer between accounts",execute:async(e,t)=>oE(e.client,t)},{name:"reconcile_invoice_receipt",description:'\u26A0\uFE0F BSE must have `paymentDirection: PAYIN` (money in \u2014 AR). Produce via `bank add-records` with a POSITIVE amount (creates `credit_amount > 0` \u2192 PAYIN). Statement-imported BSEs from `bank import` also work. The error code "Invalid business transaction type" (422) is misleadingly named \u2014 the actual gate is direction, not entry type. Create an invoice and auto-reconcile it to a bank statement entry (AR). Sync \u2014 returns the reconciled entry status. valueDate / dueDate / payment amount prefill from the bank entry if omitted. NOT idempotent.',params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},invoiceDetails:{type:"object",description:"The invoice to create. Required.",properties:{reference:{type:"string",description:"Invoice reference \u2014 required"},contactResourceId:{type:"string",description:"Customer UUID"},valueDate:{type:"string",description:"YYYY-MM-DD. Defaults to bank entry value date."},dueDate:{type:"string",description:"YYYY-MM-DD. Defaults to value date."},taxInclusion:{type:"boolean"},isTaxVATApplicable:{type:"boolean"},lineItems:{type:"array",description:"Invoice line items (max 500) \u2014 required",items:{type:"object",properties:{name:{type:"string",description:"Line description \u2014 required"},quantity:{type:"number"},unit:{type:"string"},unitPrice:{type:"number"},organizationAccountResourceId:{type:"string",description:"Revenue account UUID"},itemResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}},recordedPayment:{type:"object",description:"Optional. The matching payment record \u2014 auto-built from the bank entry if omitted.",properties:{reference:{type:"string"},valueDate:{type:"string",description:"YYYY-MM-DD. Defaults to bank entry value date."},organizationAccountResourceId:{type:"string"},paymentAmount:{type:"number"},transactionAmount:{type:"number"},paymentMethod:{type:"string",description:"Defaults to BANK_TRANSFER"}}},capsuleResourceId:{type:"string"}}}},required:["bankStatementEntryResourceId","bankAccountResourceId","invoiceDetails"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry invoice receipt AR sale",execute:async(e,t)=>(k$(t.invoiceDetails,"invoiceDetails"),iE(e.client,t))},{name:"reconcile_bill_receipt",description:'\u26A0\uFE0F BSE must have `paymentDirection: PAYOUT` (money out \u2014 AP). Produce via `bank add-records` with a NEGATIVE amount (creates `debit_amount > 0` \u2192 PAYOUT). Statement-imported BSEs from `bank import` also work. The error code "Invalid business transaction type" (422) is misleadingly named \u2014 the actual gate is direction, not entry type. Create a bill and auto-reconcile it to a bank statement entry (AP). Sync \u2014 returns the reconciled entry status. valueDate / dueDate / payment amount prefill from the bank entry if omitted. NOT idempotent.',params:{bankStatementEntryResourceId:{type:"string",description:"Bank entry UUID \u2014 required"},bankAccountResourceId:{type:"string",description:"Bank account UUID \u2014 required"},billDetails:{type:"object",description:"The bill to create. Required.",properties:{reference:{type:"string",description:"Bill reference \u2014 required"},contactResourceId:{type:"string",description:"Supplier UUID"},valueDate:{type:"string",description:"YYYY-MM-DD. Defaults to bank entry value date."},dueDate:{type:"string",description:"YYYY-MM-DD. Defaults to value date."},taxInclusion:{type:"boolean"},isTaxVATApplicable:{type:"boolean"},lineItems:{type:"array",description:"Bill line items (max 500) \u2014 required",items:{type:"object",properties:{name:{type:"string",description:"Line description \u2014 required"},quantity:{type:"number"},unit:{type:"string"},unitPrice:{type:"number"},organizationAccountResourceId:{type:"string",description:"Expense account UUID"},itemResourceId:{type:"string"},taxProfileResourceId:{type:"string"}}}},recordedPayment:{type:"object",description:"Optional. The matching payment record \u2014 auto-built from the bank entry if omitted.",properties:{reference:{type:"string"},valueDate:{type:"string",description:"YYYY-MM-DD"},organizationAccountResourceId:{type:"string"},paymentAmount:{type:"number"},transactionAmount:{type:"number"},paymentMethod:{type:"string",description:"Defaults to BANK_TRANSFER"}}},capsuleResourceId:{type:"string"}}}},required:["bankStatementEntryResourceId","bankAccountResourceId","billDetails"],group:"reconciliations",readOnly:!1,searchHint:"reconcile bank entry bill receipt AP purchase",execute:async(e,t)=>(k$(t.billDetails,"billDetails"),sE(e.client,t))},{name:"validate_drafts",description:"BULK validate \u2014 process up to 500 draft business transactions in ONE call, mixing any combination of invoices, bills, customer credit notes, and supplier credit notes (no per-type tools needed). SYNC: returns per-item errors and display data inline; no state change. Use this before convert_drafts_to_active to surface eligibility issues client-side. btType enum: SALE = invoice, PURCHASE = bill, SALE_CREDIT_NOTE = customer CN, PURCHASE_CREDIT_NOTE = supplier CN. Journals are NOT in this enum.",params:{items:{type:"array",description:"Draft business transaction references (max 500). Mix any btType freely.",items:{type:"object",properties:{btResourceId:{type:"string",description:"Draft BT resource ID (UUID) \u2014 required"},btType:{type:"string",enum:["SALE","PURCHASE","SALE_CREDIT_NOTE","PURCHASE_CREDIT_NOTE"],description:"Required"}}}}},required:["items"],group:"drafts",readOnly:!0,isConcurrencySafe:!0,searchHint:"validate drafts eligibility check before convert promote",execute:async(e,t)=>(Xu(t.items),ZS(e.client,t.items))},{name:"convert_drafts_to_active",description:"BULK promote \u2014 finalize up to 500 draft business transactions to ACTIVE in ONE call, mixing any combination of invoices, bills, and credit notes (no per-type tools needed). ASYNC: returns a jobId \u2014 poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. NOT idempotent: a second call on already-promoted drafts returns 422. Filter the draft list by status: DRAFT before submitting. Pair with validate_drafts for a pre-flight check on large batches.",params:{items:{type:"array",description:"Draft BT references (max 500). Mix any btType.",items:{type:"object",properties:{btResourceId:{type:"string",description:"Draft BT resource ID (UUID) \u2014 required"},btType:{type:"string",enum:["SALE","PURCHASE","SALE_CREDIT_NOTE","PURCHASE_CREDIT_NOTE"],description:"Required"}}}}},required:["items"],group:"drafts",readOnly:!1,searchHint:"convert drafts to active promote finalize bulk",execute:async(e,t)=>(Xu(t.items),KS(e.client,t.items))},{name:"submit_drafts_for_approval",description:"BULK submit \u2014 route up to 500 draft business transactions into the approval workflow in ONE call, mixing any combination of invoices, bills, and credit notes. ASYNC: returns a jobId \u2014 poll search_background_jobs filtered by resourceId; on PARTIAL_SUCCESS read data[0].errorDetails for per-row failures. NOT idempotent on drafts that already have an in-flight approval request.",params:{items:{type:"array",description:"Draft BT references (max 500). Mix any btType.",items:{type:"object",properties:{btResourceId:{type:"string",description:"Draft BT resource ID (UUID) \u2014 required"},btType:{type:"string",enum:["SALE","PURCHASE","SALE_CREDIT_NOTE","PURCHASE_CREDIT_NOTE"],description:"Required"}}}}},required:["items"],group:"drafts",readOnly:!1,searchHint:"submit drafts for approval workflow review bulk",execute:async(e,t)=>(Xu(t.items),XS(e.client,t.items))}];var aE=null;function Ove(){if(!aE){aE=new Map;for(let e of el)aE.set(e.name,e)}return aE}function cE(e){return Ove().get(e)}function M$(){return el}function tl(e){return M$().filter(t=>t.group===e)}Zi();function Nve(e){switch(e){case 401:return"Invalid or missing API key. Run `clio auth add` or set JAZ_API_KEY.";case 403:return"Insufficient permissions for this operation.";case 404:return"Resource not found \u2014 check the resourceId. Use a search/list tool to look it up.";case 409:return"Conflict \u2014 resource may have been modified. Re-fetch and retry.";case 422:return"Validation error \u2014 check field values against the tool description.";case 429:return"Rate limited \u2014 wait a moment and retry.";default:return""}}function hJ(e){if(e instanceof Wi){let r=Nve(e.status);return{error:e.message,status:e.status,endpoint:e.endpoint,...r?{hint:r}:{}}}return{error:e instanceof Error?e.message:String(e)}}function gJ(e,t){if(e.readOnly)return{valid:!0,errors:[]};let r=[];for(let n of e.required){let o=t[n];if(o==null){r.push(`Missing required field: ${n}`);continue}typeof o=="string"&&o.trim()===""&&r.push(`Required field "${n}" is empty`)}for(let[n,o]of Object.entries(t)){if(o==null)continue;let i=e.params[n];if(!i)continue;let s=Rve(n,o,i);s&&r.push(s),i.enum&&typeof o=="string"&&(i.enum.includes(o)||r.push(`Field "${n}" value "${o}" not in allowed values: ${i.enum.join(", ")}`))}return{valid:r.length===0,errors:r}}function Rve(e,t,r){switch(r.type){case"string":if(typeof t!="string")return`Field "${e}" expected string, got ${typeof t}`;break;case"number":if(typeof t!="number"||!Number.isFinite(t))return`Field "${e}" expected finite number, got ${typeof t=="number"?"non-finite":typeof t}`;break;case"boolean":if(typeof t!="boolean")return`Field "${e}" expected boolean, got ${typeof t}`;break;case"array":if(!Array.isArray(t))return`Field "${e}" expected array, got ${typeof t}`;break;case"object":if(typeof t!="object"||Array.isArray(t))return`Field "${e}" expected object, got ${Array.isArray(t)?"array":typeof t}`;break}return null}var rl=[{name:"invoices",description:"Sales invoices (INV/SI). Create, search, get, update, delete, pay, finalize, apply credits, download PDF. Also: receivables, AR, billing, overdue invoices.",groups:["invoices"]},{name:"customer_credit_notes",description:"Customer credit notes (CN). Create, search, update, delete, finalize, refund, download PDF. Also: sales returns, customer CN.",groups:["customer_credit_notes"]},{name:"bills",description:"Purchase bills (PO/PI). Create, search, get, update, delete, pay, finalize, apply credits. Also: payables, AP, vendor invoices, supplier bills.",groups:["bills"]},{name:"supplier_credit_notes",description:"Supplier credit notes. Create, search, update, delete, finalize, refund. Also: purchase returns, debit notes, supplier CN.",groups:["supplier_credit_notes"]},{name:"journals",description:"Journal entries (JE). Create, search, update, delete manual journals. Also: adjusting entries, accruals, reclassifications, corrections.",groups:["journals"]},{name:"cash_entries",description:"Cash-in receipts and cash-out disbursements for external cash movements. WHEN TO USE: money received from customers/external \u2192 cash-in. Money paid to suppliers/external \u2192 cash-out. For internal account-to-account transfers, use cash_transfers namespace.",groups:["cash_entries"]},{name:"cash_transfers",description:"Cash transfers between your own bank/cash accounts and cashflow transaction search. WHEN TO USE: moving funds between own accounts (main bank \u2192 petty cash, USD \u2192 SGD). For external receipts/payments, use cash_entries namespace.",groups:["cash_transfers"]},{name:"bank_accounts",description:"Bank accounts, bank statement imports (CSV/OFX), bank records search, auto-reconciliation. For unreconciled queries: ALWAYS search bank records with status UNRECONCILED after listing accounts. Also: bank feeds, bank balance.",groups:["bank"]},{name:"bank_rules",description:"Bank reconciliation rules (action shortcuts). Create, search, update, delete bank rules. Configure auto-matching rules for bank records.",groups:["bank_rules"]},{name:"reconciliations",description:"Apply a reconciliation decision to a bank statement entry \u2014 write side. Distinct from bank_accounts/bank_rules (which configure auto-reconciliation) and view_auto_reconciliation (which queries suggestions). Eight endpoints: quick_reconcile + apply_bank_rule (async, bulk), and direct_cash_entry / cash_journal / manual_journal / cash_transfer / invoice_receipt / bill_receipt (sync, per-entry). Most fields prefill from the bank entry when omitted.",groups:["reconciliations"]},{name:"financial_reports",description:"Core financial statements: trial balance (TB), balance sheet (BS/B/S), profit & loss (PnL/P&L/income statement), cash flow, general ledger (GL), cash balance/position, equity movement, VAT/GST ledger. Also: how profitable, what is the balance.",groups:["financial_reports"]},{name:"operational_reports",description:"Aging and operational reports: aged receivables (AR aging), aged payables (AP aging), AR report, bank balance summary, bank reconciliation reports, fixed asset (FA) summary, FA reconciliation. Data exports (CSV/Excel). Also: overdue analysis, how much owed.",groups:["operational_reports","exports"]},{name:"contacts",description:"Contacts (customers/suppliers/vendors), contact groups. Create, search, get, update, delete contacts. Bulk upsert contacts (async \u2014 returns jobId, poll background_jobs). List/create contact groups.",groups:["contacts","contact_groups"]},{name:"items_and_inventory",description:"Products, services, inventory items. Create, search, get, update, delete items. Check inventory balance. Also: SKU, catalog, stock.",groups:["items","inventory"]},{name:"tags_and_custom_fields",description:"Tags for categorizing transactions. Custom fields for adding metadata (text, date, dropdown). Create, search, delete tags and custom fields.",groups:["tags","custom_fields"]},{name:"nano_classifiers",description:"Nano classifiers (tracking categories/dimensions). List, search, create, update, delete classifiers and their classes. Used for line-item tagging and dimensional reporting. Also: tracking categories, cost centers, departments, projects.",groups:["nano_classifiers"]},{name:"chart_of_accounts",description:"Chart of accounts (COA/GL accounts). Create, search, update accounts. Bookmarks (favorites/shortcuts). Also: ledger codes, account types.",groups:["accounts","bookmarks"]},{name:"currencies",description:"Currencies, exchange rates (FX/forex). List/add org currencies. Set, update, import currency rates. Also: multi-currency, FX rates.",groups:["currencies"]},{name:"tax_profiles",description:"Tax profiles (GST/VAT/sales tax), withholding tax codes (WHT/ATC). Search, create, update tax profiles. List WHT codes.",groups:["tax_profiles"]},{name:"capsules_and_recipes",description:"Capsules (transaction groupings/capsule types). Financial recipes: amortization, depreciation, deferred revenue, IFRS 16 leases, hire purchase, fixed deposits, FX revaluation, loan schedules, ECL/expected credit loss, IAS 37 provisions, asset disposal. Plan and execute recipes. Keywords: calculate, provision, schedule, expected credit loss, revaluation.",groups:["capsules","recipes"]},{name:"scheduled_transactions",description:"Scheduled/recurring invoices, bills, journals. Create scheduled invoices/bills/journals, search scheduled transactions. Also: recurring, auto-generate.",groups:["schedulers"]},{name:"subscriptions",description:"Subscriptions (recurring billing/payment plans). Create, update, cancel, search subscriptions. Also: recurring charges, subscription schedules.",groups:["subscriptions"]},{name:"organization",description:"Organization info (name, currency, country, fiscal year). User management: invite, update, remove, search org users. Bulk invite.",groups:["organization","org_users"]},{name:"document_ai",description:"File attachments, AI document extraction (magic/OCR). Upload/list attachments. Create transactions from PDFs/images (invoice scanning, bill extraction). Track extraction workflows.",groups:["attachments","magic"]},{name:"fixed_assets",description:"Fixed assets (PP&E/property, plant, equipment). Search, create, update, discard, sell, transfer, undo disposal. Also: depreciation, asset register.",groups:["fixed_assets"]},{name:"payments_and_search",description:"Payment records: get, update, delete individual payments. List payments/credits on invoices and bills. Reverse credit applications. Cashflow transaction search. Universal cross-entity search. Also: void payment, payment history, credit note applications.",groups:["payments","cashflow","search"]},{name:"quick_fix",description:"Quick Fix: bulk-update multiple transactions or line items in one call. Change dates, contacts, tags, accounts, tax profiles, custom fields across many invoices/bills/journals/credit-notes/cash-entries/schedulers at once. Also: batch update, mass edit.",groups:["quick_fix"]},{name:"export_records",description:"Export records to XLSX. List available columns, preview export scope (row count + sample), generate export file with pre-signed download URL. Supports any entity type: invoices, bills, contacts, items, journals, bank records, cashflow, fixed assets, etc. Pass query (structured search syntax) or filter (JSON), never both.",groups:["export_records"]},{name:"background_jobs",description:"Background job tracking. Poll any async operation by jobId (contacts bulk-upsert, items bulk-upsert, bank import, magic file processing, etc.). Filter by resourceId field to look up a specific job. Poll until status is SUCCESS, FAILED, or PARTIAL_SUCCESS.",groups:["background_jobs"]},{name:"drafts",description:"Draft business transactions \u2014 both local payload validation (invoices, bills, journals, credit notes) AND BULK-FRIENDLY server-side lifecycle: validate_drafts (sync eligibility check), convert_drafts_to_active (async promote to ACTIVE), submit_drafts_for_approval (async route to approval). The lifecycle tools are GENERIC and BULK \u2014 one call accepts up to 500 items mixing any combination of {btResourceId, btType: SALE|PURCHASE|SALE_CREDIT_NOTE|PURCHASE_CREDIT_NOTE}. No need for per-entity tools when promoting/submitting drafts at scale. NOT idempotent on already-promoted drafts.",groups:["drafts"]},{name:"close_procedures",description:"Period-end close checklists: month-end, quarter-end, year-end close. Bank reconciliation job. GST/VAT filing job. Audit preparation. Returns structured blueprints.",groups:["close_jobs"]},{name:"operational_jobs",description:"Operational job checklists: payment runs, credit control/collections, supplier reconciliation, fixed asset review, document collection, statutory filing. Returns structured blueprints.",groups:["operational_jobs"]}];function yJ(e,t=5){let r=e.trim().toLowerCase();if(!r)return[];let n=r.split(/[\s_-]+/).filter(i=>i.length>=2);return n.length===0?[]:rl.map(i=>{let s=0,a=i.name.toLowerCase(),c=i.description.toLowerCase();(a===r||a===r.replace(/\s+/g,"_"))&&(s+=5),a.includes(r)&&(s+=3),c.includes(r)&&(s+=1);for(let u of n)a.includes(u)&&(s+=2),c.includes(u)&&(s+=1);return{ns:i,score:s}}).filter(i=>i.score>0).sort((i,s)=>s.score-i.score).slice(0,t).map(i=>i.ns)}function uE(e){let t={type:e.type};if(e.description&&(t.description=e.description),e.enum&&(t.enum=e.enum),e.type==="array"&&e.items&&(t.items=uE(e.items)),e.type==="object"&&e.properties){let r={};for(let[n,o]of Object.entries(e.properties))r[n]=uE(o);t.properties=r,e.required?.length&&(t.required=e.required)}return t}function Za(e,t){let r={};for(let[n,o]of Object.entries(e))r[n]=uE(o);return{type:"object",properties:r,...t.length>0?{required:t}:{}}}function DJ(e){return{name:e.name,description:e.description,input_schema:Za(e.params,e.required),...e.searchHint?{searchHint:e.searchHint}:{}}}function kve(e){if(typeof e!="string")return e.isDestructive??!1;let t=e;return t.startsWith("delete_")||t.startsWith("pay_")||t.startsWith("finalize_")||t.includes("refund")||t==="remove_org_user"}function bJ(e){if(!e.trim())return{namespaces:rl.map(o=>{let i=o.groups.flatMap(s=>tl(s));return{name:o.name,description:o.description,toolCount:i.length,tools:i.map(s=>s.name)}}),hint:"Call describe_tools with specific tool names to get full schemas before executing."};let t=yJ(e,5);if(t.length===0)return{matches:[],hint:`No tools match "${e}". Try broader terms or call search_tools with empty query to see all namespaces.`};let n=e.toLowerCase().split(/\s+/).filter(Boolean);return{matches:t.map(o=>{let s=o.groups.flatMap(a=>tl(a)).map(a=>{let c=`${a.name} ${a.searchHint??""} ${a.description.split(`
842
842
  `)[0]}`.toLowerCase(),u=n.filter(l=>c.includes(l)).length;return{tool:a,score:u}}).sort((a,c)=>c.score-a.score);return{namespace:o.name,description:o.description,tools:s.map(a=>({name:a.tool.name,description:a.tool.description.split(`
843
843
  `)[0],...a.tool.searchHint?{searchHint:a.tool.searchHint}:{}}))}}),hint:"Call describe_tools with the tool names you need, then execute_tool to run them."}}var Fve={name:"search_tools",description:"Search for available Jaz accounting tools by keyword. Returns matching tool namespaces with tool names and descriptions. Call with empty query to list all namespaces. ALWAYS call this first to discover what tools are available.",inputSchema:Za({query:{type:"string",description:'Search keyword (e.g. "invoice", "bank recon", "depreciation"). Empty string lists all namespaces.'}},[])};function vJ(e){if(!Array.isArray(e)||!e.every(n=>typeof n=="string"))return{error:"Invalid `tools` parameter. Expected string[]."};if(e.length===0)return{error:"Provide at least one tool name. Use search_tools first to discover tool names."};let t=[],r=[];for(let n of e){let o=cE(n);if(!o){r.push(n);continue}t.push({...DJ(o),readOnly:o.readOnly,isDestructive:o.isDestructive??!1,isConcurrencySafe:o.isConcurrencySafe??!1,destructiveHint:!o.readOnly&&kve(o),group:o.group})}return{tools:t,...r.length>0?{notFound:r,hint:`Tools not found: ${r.join(", ")}. Use search_tools to find correct names.`}:{}}}var Pve={name:"describe_tools",description:"Get full JSON Schema (parameters, types, required fields) for specific tools. Call this after search_tools to get the exact input format before calling execute_tool.",inputSchema:Za({tools:{type:"array",items:{type:"string"},description:'Tool names to describe (e.g. ["create_invoice", "search_contacts"])'}},["tools"])},Lve={name:"execute_tool",description:"Execute a Jaz accounting tool. Call describe_tools first to get the required parameters. Pass the tool name and its arguments.",inputSchema:Za({tool:{type:"string",description:'Tool name (e.g. "create_invoice")'},arguments:{type:"object",description:"Tool arguments (see describe_tools for schema)"},org_id:{type:"string",description:"Organization ID (UUID). Required in multi-org mode (PAT or multiple API keys). Call list_organizations to get available IDs."}},["tool"])},SJ={name:"list_organizations",description:"List organizations available to the current authentication. Returns org names and resource IDs for use as org_id in execute_tool calls.",inputSchema:Za({},[])},B$=[Fve,Pve,Lve];Mc();Zi();var jve=new Set(["close_jobs","operational_jobs"]);function U$(e,t){return!!(jve.has(e)||e==="recipes"&&t==="plan_recipe")}function Mve(e,t){return new qr({mode:"pat",token:e,orgId:t})}async function EJ(e,t=5e3){let r=new Map,n=[],o=a=>Promise.race([a,new Promise(c=>setTimeout(()=>c(null),t))]),i=e.map(a=>({auth:a,client:new qr(a)})),s=i[0]?.client??null;return await Promise.all(i.map(async({auth:a,client:c})=>{try{let u=await o(Ln(c));if(u)r.set(u.resourceId,{name:u.name,resourceId:u.resourceId,currency:u.currency,client:c});else{let l=a.mode==="direct"?"api-key":a.mode;n.push(`Org lookup returned empty (${l}).`)}}catch(u){let l=a.mode==="direct"?"api-key":a.mode;n.push(`Org lookup failed (${l}): ${u instanceof Error?u.message:"unknown"}`)}})),{orgMap:r,primaryClient:s,errors:n}}function _J(e){e.command("mcp").description("Start MCP stdio server for Claude Code / Cowork").option("--api-key <key>","API key, PAT, or comma-separated keys (overrides stored/env)").action(async t=>{let r;try{r=DC(t.apiKey)}catch(b){process.stderr.write(`jaz-ai: ${b instanceof Error?b.message:b}
844
844
  `),process.exit(1)}let n=e.version()??"0.0.0",o=new Map,i=null,s=r.length>1||r[0]?.mode==="pat";if(r.length>0){let b=await EJ(r);o=b.orgMap,i=b.primaryClient;for(let S of b.errors)process.stderr.write(`warning: ${S}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaz-clio",
3
- "version": "4.58.4",
3
+ "version": "4.58.6",
4
4
  "description": "Clio: Command Line Interface Operator for Jaz AI.",
5
5
  "type": "module",
6
6
  "bin": {