AgentSkillsCN

jaz-api

Jaz/Juan REST API 的完整参考——会计平台后端。无论您是在构建、修改、调试,还是扩展任何调用该 API 的代码(包括 API 客户端、集成、数据种子、测试数据,或新增端点工作),均可使用此技能。其中囊括了通过实际生产环境测试所发现的所有字段名称、响应结构、错误、易错点,以及各种边缘案例。

SKILL.md
--- frontmatter
name: jaz-api
version: 1.4.0
description: Complete reference for the Jaz/Juan REST API — the accounting platform backend. Use this skill whenever building, modifying, debugging, or extending any code that calls the API — including API clients, integrations, data seeding, test data, or new endpoint work. Contains every field name, response shape, error, gotcha, and edge case discovered through live production testing.

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)

  1. All IDs are resourceId — never id. References use <resource>ResourceId suffix.
  2. Dates are valueDate — not issueDate, not invoiceDate, not date.
  3. Payment field is paymentAmount — not amount. Also needs transactionAmount.
  4. Payment date is valueDate — not paymentDate, not date.
  5. Payment bank account is accountResourceId — not bankAccountResourceId.
  6. Payments require 6 fields: paymentAmount, transactionAmount, accountResourceId, paymentMethod, reference, valueDate.
  7. Line item descriptions use name — not description.
  8. Item names use internalName — not name.
  9. Tag names use tagName — not name.
  10. Custom field names (in GET response) use customFieldName — not name.
  11. Invoice/bill number is reference — not referenceNumber.
  12. saveAsDraft is required on invoices, bills, credit notes, journals, cash entries.
  13. If saveAsDraft: false, every lineItem MUST have accountResourceId.
  14. Phones MUST be E.164+65XXXXXXXX (SG), +63XXXXXXXXXX (PH). No spaces.
  15. Tax profiles pre-exist — NEVER create them. Only GET and map.
  16. Bank accounts are CoA entries with accountType: "Bank Accounts". No separate endpoint.
  17. Currency rates have NO API — only enable currencies, rates via UI only.
  18. CoA bulk-upsert wrapper is accounts — not chartOfAccounts.
  19. CoA uses currency in POST — not currencyCode.
  20. Payments wrapped in { payments: [...] } — array even for single payment.
  21. Schedulers wrap document in { invoice: {...} } or { bill: {...} } — not flat. Recurrence field is repeat (NOT frequency or interval). saveAsDraft: false required (true causes INVALID_SALE_STATUS / INVALID_PURCHASE_STATUS), which means accountResourceId on every line item.
  22. Journals use journalEntries with amount + type: "DEBIT"|"CREDIT" — NOT debit/credit number fields.
  23. Journals have NO currency field at top level — sending it causes "Invalid request body".
  24. Cash entries use accountResourceId at top level for the BANK account (not bankAccountResourceId) + journalEntries array for offsets.
  25. Credit note application wraps in credits array with amountApplied — not flat { creditNoteResourceId, amount }.
  26. Custom fields: do NOT send appliesTo — causes "Invalid request body". Only send name, type, printOnDocuments.
  27. Bank record dates are transactionDate — not date.
  28. Invoice GET responses use organizationAccountResourceId for line item accounts (POST uses accountResourceId).
  29. Bill payments standalone endpoint fixedPOST /bills/{id}/payments was broken (nil pointer in the API backend) — fixed in backend PR #112. Now works. Embed-in-creation pattern is still valid as an alternative.
  30. Invoice payments standalone endpoint WORKSPOST /invoices/{id}/payments is reliable.
  31. 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).
  32. FX invoice/bill currency: use currencyCode: "USD" (string) — NOT currency: "USD" (string). An alternative object form { sourceCurrency, exchangeRate } also exists but is a different API shape.
  33. Dates are always YYYY-MM-DD strings — bill payment validation rejects ISO datetime and epoch ms. OAS may declare integer/int64 but YYYY-MM-DD strings work.
  34. 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.
  35. saveAsDraft is required for cash journalsPOST /cash-in-journals and POST /cash-out-journals require saveAsDraft field.
  36. Bill payments do NOT support TransactionFeeCollected — the bill payment model in the API backend lacks this field. Only invoice payments support collected transaction fees.
  37. Withholding tax retry pattern — Bills and supplier credit notes support withholdingTax on line items ({ code, rate, description? }). If the org doesn't support it, API returns WITHHOLDING_CODE_NOT_FOUND — strip the field and retry. Only supported on bills and supplier credit notes (NOT invoices).
  38. 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.
  39. Item creation requires itemCode, appliesToSale (boolean), appliesToPurchase (boolean). When appliesToSale: true, must also include saleItemName. When appliesToPurchase: true, must also include purchaseItemName. Missing any of these causes 422.
  40. Search sort is an object{ sort: { sortBy: ["valueDate"], order: "DESC" } }, NOT top-level sortBy/order fields. sort is required when offset is present.
  41. 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.
  42. POST /items/search does NOT exist — returns 404. Use GET /items with pagination instead.
  43. Inventory items require additional fields: unit (string, e.g., "pcs"), costingMethod ("FIXED" or "WAC"), cogsResourceId (Direct Costs account), blockInsufficientDeductions (boolean), inventoryAccountResourceId (Inventory-type CoA). The purchaseAccountResourceId MUST point to an Inventory-type CoA account (NOT Direct Costs). Delete inventory items via DELETE /items/:id (not /inventory-items/:id).
  44. Cash transfer journals use cashOut/cashIn sub-objects — NOT fromAccountResourceId/toAccountResourceId/amount. Each has { accountResourceId, amount }.
  45. Credit note refunds use refunds wrapper with refundAmount + refundMethod — NOT payments wrapper with paymentAmount/paymentMethod. Also needs transactionAmount, accountResourceId, reference, valueDate.
  46. Bookmarks use items array wrapper. Each item needs name, 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.
  47. Scheduled journals use flat structure with schedulerEntries — NOT nested journal object. Fields: reference, valueDate, saveAsDraft, schedulerEntries (same format as journalEntries), plus repeat/startDate/endDate at top level.
  48. Data exports use simpler field names than generate-reports: P&L export uses startDate/endDate (NOT primarySnapshotDate). AR/AP export uses endDate. Trial balance and general ledger exports use startDate/endDate.
  49. Known API bugs (500s): Contact groups PUT, custom fields PUT (requires appliesTo but 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:

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 date type → YYYY-MM-DD strings. Never send datetime or epoch.
  • Bill payments: Embed in bill creation body (safest). Standalone POST /bills/{id}/payments also 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 is repeat not frequency
  • FX currency (alternative): Object form currency: { sourceCurrency: "USD", exchangeRate: 1.35 } also works as an alternative to currencyCode: "USD" string