Jaz API Skill
You are working with the Jaz/Juan REST API — the backend for Jaz (Singapore) and Juan (Philippines) accounting platforms.
When to Use This Skill
- •Writing or modifying any code that calls the Jaz API
- •Building API clients, integrations, or data pipelines
- •Debugging API errors (422, 400, 404, 500)
- •Adding support for new Jaz API endpoints
- •Reviewing code that constructs Jaz API request payloads
Quick Reference
Base URL: https://api.getjaz.com
Auth: x-jk-api-key: <key> header on every request — key has jk- prefix (e.g., jk-a1b2c3...). NOT Authorization: Bearer or x-api-key.
Content-Type: application/json for all POST/PUT/PATCH
All paths are prefixed: /api/v1/ (e.g., https://api.getjaz.com/api/v1/invoices)
Critical Rules (Memorize These)
- •All IDs are
resourceId— neverid. References use<resource>ResourceIdsuffix. - •Dates are
valueDate— notissueDate, notinvoiceDate, notdate. - •Payment field is
paymentAmount— notamount. Also needstransactionAmount. - •Payment date is
valueDate— notpaymentDate, notdate. - •Payment bank account is
accountResourceId— notbankAccountResourceId. - •Payments require 6 fields:
paymentAmount,transactionAmount,accountResourceId,paymentMethod,reference,valueDate. - •Line item descriptions use
name— notdescription. - •Item names use
internalName— notname. - •Tag names use
tagName— notname. - •Custom field names (in GET response) use
customFieldName— notname. - •Invoice/bill number is
reference— notreferenceNumber. - •
saveAsDraftis required on invoices, bills, credit notes, journals, cash entries. - •If
saveAsDraft: false, every lineItem MUST haveaccountResourceId. - •Phones MUST be E.164 —
+65XXXXXXXX(SG),+63XXXXXXXXXX(PH). No spaces. - •Tax profiles pre-exist — NEVER create them. Only GET and map.
- •Bank accounts are CoA entries with
accountType: "Bank Accounts". No separate endpoint. - •Currency rates have NO API — only enable currencies, rates via UI only.
- •CoA bulk-upsert wrapper is
accounts— notchartOfAccounts. - •CoA uses
currencyin POST — notcurrencyCode. - •Payments wrapped in
{ payments: [...] }— array even for single payment. - •Schedulers wrap document in
{ invoice: {...} }or{ bill: {...} }— not flat. Recurrence field isrepeat(NOTfrequencyorinterval).saveAsDraft: falserequired (true causes INVALID_SALE_STATUS / INVALID_PURCHASE_STATUS), which meansaccountResourceIdon every line item. - •Journals use
journalEntrieswithamount+type: "DEBIT"|"CREDIT"— NOTdebit/creditnumber fields. - •Journals have NO
currencyfield at top level — sending it causes "Invalid request body". - •Cash entries use
accountResourceIdat top level for the BANK account (notbankAccountResourceId) +journalEntriesarray for offsets. - •Credit note application wraps in
creditsarray withamountApplied— not flat{ creditNoteResourceId, amount }. - •Custom fields: do NOT send
appliesTo— causes "Invalid request body". Only sendname,type,printOnDocuments. - •Bank record dates are
transactionDate— notdate. - •Invoice GET responses use
organizationAccountResourceIdfor line item accounts (POST usesaccountResourceId). - •Bill payments standalone endpoint fixed —
POST /bills/{id}/paymentswas broken (nil pointer in the API backend) — fixed in backend PR #112. Now works. Embed-in-creation pattern is still valid as an alternative. - •Invoice payments standalone endpoint WORKS —
POST /invoices/{id}/paymentsis reliable. - •Bank records: use multipart import only — There is NO JSON POST endpoint for creating bank records. Use
POST /api/v1/magic/importBankStatementFromAttachment(multipart form upload with CSV/OFX file). - •FX invoice/bill currency: use
currencyCode: "USD"(string) — NOTcurrency: "USD"(string). An alternative object form{ sourceCurrency, exchangeRate }also exists but is a different API shape. - •Dates are always
YYYY-MM-DDstrings — bill payment validation rejects ISO datetime and epoch ms. OAS may declareinteger/int64butYYYY-MM-DDstrings work. - •CoA code mapping: match by NAME, not code — pre-existing accounts may have different codes than templates (e.g., "Cost of Goods Sold" = code 310 in the API, code 5000 in template). Resource IDs are the universal identifier.
- •
saveAsDraftis required for cash journals —POST /cash-in-journalsandPOST /cash-out-journalsrequiresaveAsDraftfield. - •Bill payments do NOT support
TransactionFeeCollected— the bill payment model in the API backend lacks this field. Only invoice payments support collected transaction fees. - •Withholding tax retry pattern — Bills and supplier credit notes support
withholdingTaxon line items ({ code, rate, description? }). If the org doesn't support it, API returnsWITHHOLDING_CODE_NOT_FOUND— strip the field and retry. Only supported on bills and supplier credit notes (NOT invoices). - •Bank records batching — When using multipart CSV import, keep CSV files under ~500 rows. Amount must always be positive; use Debit/Credit columns for direction.
- •Item creation requires
itemCode,appliesToSale(boolean),appliesToPurchase(boolean). WhenappliesToSale: true, must also includesaleItemName. WhenappliesToPurchase: true, must also includepurchaseItemName. Missing any of these causes 422. - •Search sort is an object —
{ sort: { sortBy: ["valueDate"], order: "DESC" } }, NOT top-levelsortBy/orderfields.sortis required whenoffsetis present. - •Report field names differ by type: Trial balance =
startDate/endDate. Balance sheet =primarySnapshotDate. P&L =primarySnapshotDate+secondarySnapshotDate. General ledger =groupBy: "ACCOUNT"+startDate/endDate. Cashflow =primaryStartDate/primaryEndDate. Cash balance =reportDate. AR/AP report =endDate. AR/AP summary =startDate+endDate. Bank balance summary =primarySnapshotDate. Equity movement =primarySnapshotStartDate/primarySnapshotEndDate. - •
POST /items/searchdoes NOT exist — returns 404. UseGET /itemswith pagination instead. - •Inventory items require additional fields:
unit(string, e.g.,"pcs"),costingMethod("FIXED"or"WAC"),cogsResourceId(Direct Costs account),blockInsufficientDeductions(boolean),inventoryAccountResourceId(Inventory-type CoA). ThepurchaseAccountResourceIdMUST point to an Inventory-type CoA account (NOT Direct Costs). Delete inventory items viaDELETE /items/:id(not/inventory-items/:id). - •Cash transfer journals use
cashOut/cashInsub-objects — NOTfromAccountResourceId/toAccountResourceId/amount. Each has{ accountResourceId, amount }. - •Credit note refunds use
refundswrapper withrefundAmount+refundMethod— NOTpaymentswrapper withpaymentAmount/paymentMethod. Also needstransactionAmount,accountResourceId,reference,valueDate. - •Bookmarks use
itemsarray wrapper. Each item needsname,value,categoryCode(e.g.,"GENERAL_INFORMATION"),datatypeCode(e.g.,"LINK"). Valid categoryCode:AUDIT_AND_ASSURANCE,BANKING_AND_FINANCE,BUDGETS_AND_CONTROLS,EMPLOYEES_AND_PAYROLL,EXTERNAL_DOCUMENTS,GENERAL_INFORMATION,OWNERS_AND_DIRECTORS,TAXATION_AND_COMPLIANCE,WORKFLOWS_AND_PROCESSES. Valid datatypeCode:TEXT,NUMBER,BOOLEAN,DATE,LINK. - •Scheduled journals use flat structure with
schedulerEntries— NOT nestedjournalobject. Fields:reference,valueDate,saveAsDraft,schedulerEntries(same format asjournalEntries), plusrepeat/startDate/endDateat top level. - •Data exports use simpler field names than generate-reports: P&L export uses
startDate/endDate(NOTprimarySnapshotDate). AR/AP export usesendDate. Trial balance and general ledger exports usestartDate/endDate. - •Known API bugs (500s): Contact groups PUT, custom fields PUT (requires
appliesTobut 500s with correct payload), fixed assets POST, capsules POST — all return 500. Use create + delete as workaround.
Supporting Files
For detailed reference, read these files in this skill directory:
- •references/endpoints.md — Full API endpoint reference with request/response examples for every endpoint
- •references/errors.md — Complete error catalog: every error we've encountered, what caused it, and the fix
- •references/field-map.md — Complete field name mapping (what you'd guess vs actual API name)
- •references/dependencies.md — Resource creation dependencies and required order
- •references/full-api-surface.md — Complete endpoint catalog, auth types, search filter syntax, enums, and limits
Recommended Client Patterns
Battle-tested patterns from production Jaz API clients:
- •Serialization (Python):
model_dump(mode="json", by_alias=True, exclude_unset=True, exclude_none=True) - •Field names: All request bodies use camelCase (snake_case in code → camelCase in JSON)
- •Date serialization: Python
datetype →YYYY-MM-DDstrings. Never send datetime or epoch. - •Bill payments: Embed in bill creation body (safest). Standalone
POST /bills/{id}/paymentsalso works (fixed in backend PR #112). - •Bank records: Use multipart
POST /magic/importBankStatementFromAttachment— the only endpoint for creating bank records. - •Scheduled bills: Wrap as
{ status, startDate, endDate, repeat, bill: {...} }— note: field isrepeatnotfrequency - •FX currency (alternative): Object form
currency: { sourceCurrency: "USD", exchangeRate: 1.35 }also works as an alternative tocurrencyCode: "USD"string