jaz-cli 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,714 @@
1
+ # Jaz API — Search Endpoint Reference
2
+
3
+ > Single source of truth for all `POST /*/search` endpoints. Every filter field,
4
+ > sort field, and operator is extracted from the API backend Go structs and validated
5
+ > against the live production API. **Do not guess — look up the exact fields here.**
6
+
7
+ ---
8
+
9
+ ## Universal Search Pattern
10
+
11
+ All search endpoints share this identical structure:
12
+
13
+ ```json
14
+ {
15
+ "filter": { "fieldName": { "operator": "value" } },
16
+ "sort": { "sortBy": ["field1"], "order": "ASC" },
17
+ "limit": 100,
18
+ "offset": 0
19
+ }
20
+ ```
21
+
22
+ | Property | Type | Required | Constraints |
23
+ |----------|------|----------|-------------|
24
+ | `filter` | object | No | Per-endpoint fields (see tables below) |
25
+ | `sort` | object | **Yes if `offset` is present** | `sortBy`: array of field names; `order`: `"ASC"` or `"DESC"` |
26
+ | `limit` | int | No | Default: 100, min: 1, max: 1000 |
27
+ | `offset` | int | No | Default: 0, min: 0, max: 65536 |
28
+
29
+ **Response shape**: `{ totalElements, totalPages, data: [...] }` — all search/list endpoints return this flat structure directly (no outer `data` wrapper).
30
+
31
+ > **Exception**: `POST /organization-report-template/search` returns a plain array (no pagination metadata, no `totalElements`/`totalPages`).
32
+
33
+ ---
34
+
35
+ ## Filter Operators
36
+
37
+ ### String Operators (`StringExpression`)
38
+
39
+ | Operator | Type | Example | Notes |
40
+ |----------|------|---------|-------|
41
+ | `eq` | string | `{ "status": { "eq": "ACTIVE" } }` | Exact match |
42
+ | `neq` | string | `{ "status": { "neq": "DRAFT" } }` | Not equal |
43
+ | `contains` | string | `{ "reference": { "contains": "INV" } }` | Substring match |
44
+ | `in` | string[] | `{ "status": { "in": ["ACTIVE", "DRAFT"] } }` | Max 100 values |
45
+ | `reg` | string[] | `{ "name": { "reg": ["^Acme.*"] } }` | Regex patterns, max 100 |
46
+ | `likeIn` | string[] | `{ "name": { "likeIn": ["Acme%"] } }` | SQL LIKE patterns, max 100 |
47
+ | `isNull` | string | `{ "reference": { "isNull": "true" } }` | Null check |
48
+
49
+ ### Numeric Operators (`BigDecimalExpression`)
50
+
51
+ | Operator | Type | Example |
52
+ |----------|------|---------|
53
+ | `eq` | number | `{ "totalAmount": { "eq": 1000 } }` |
54
+ | `gt` | number | `{ "totalAmount": { "gt": 500 } }` |
55
+ | `gte` | number | `{ "totalAmount": { "gte": 500 } }` |
56
+ | `lt` | number | `{ "totalAmount": { "lt": 10000 } }` |
57
+ | `lte` | number | `{ "totalAmount": { "lte": 10000 } }` |
58
+ | `in` | number[] | `{ "totalAmount": { "in": [100, 200, 300] } }` |
59
+
60
+ ### Integer Operators (`IntExpression`)
61
+
62
+ Same as numeric: `eq`, `gt`, `gte`, `lt`, `lte`, `in` (used by `terms` field on invoices/bills).
63
+
64
+ ### Date Operators (`DateExpression`) — format: `YYYY-MM-DD`
65
+
66
+ | Operator | Type | Example |
67
+ |----------|------|---------|
68
+ | `eq` | string | `{ "valueDate": { "eq": "2026-01-15" } }` |
69
+ | `gt` | string | `{ "valueDate": { "gt": "2026-01-01" } }` |
70
+ | `gte` | string | `{ "valueDate": { "gte": "2026-01-01" } }` |
71
+ | `lt` | string | `{ "valueDate": { "lt": "2026-12-31" } }` |
72
+ | `lte` | string | `{ "valueDate": { "lte": "2026-12-31" } }` |
73
+ | `between` | string[2] | `{ "valueDate": { "between": ["2026-01-01", "2026-03-31"] } }` |
74
+
75
+ **CRITICAL**: `between` requires EXACTLY 2 values. All date strings must be `YYYY-MM-DD`.
76
+
77
+ ### DateTime Operators (`DateTimeExpression`) — format: RFC3339
78
+
79
+ Same operators as DateExpression but accepts RFC3339 strings (e.g., `"2026-01-15T00:00:00Z"`).
80
+ Used by `createdAt` and `updatedAt` fields. Internally converted to epoch milliseconds.
81
+
82
+ ### Boolean Operators (`BooleanExpression`)
83
+
84
+ | Operator | Type | Example |
85
+ |----------|------|---------|
86
+ | `eq` | boolean | `{ "customer": { "eq": true } }` |
87
+
88
+ ### JSON Operators (`JsonExpression`)
89
+
90
+ | Operator | Type | Example |
91
+ |----------|------|---------|
92
+ | `jsonIn` | array | `{ "createdBy": { "jsonIn": [{ "key": "email", "value": "admin@co.sg" }] } }` |
93
+ | `jsonNotIn` | array | Same structure, excludes matches |
94
+
95
+ ### Logical Operators
96
+
97
+ Nest filters inside `and`, `or`, `not` objects:
98
+
99
+ ```json
100
+ {
101
+ "filter": {
102
+ "status": { "eq": "POSTED" },
103
+ "and": {
104
+ "totalAmount": { "gt": 1000 }
105
+ }
106
+ }
107
+ }
108
+ ```
109
+
110
+ Invoices, bills, and journals also support `andGroup` / `orGroup` (arrays of filter groups):
111
+
112
+ ```json
113
+ {
114
+ "filter": {
115
+ "andGroup": [
116
+ { "and": { "status": { "eq": "POSTED" } } },
117
+ { "or": { "valueDate": { "gte": "2026-01-01" } } }
118
+ ]
119
+ }
120
+ }
121
+ ```
122
+
123
+ ### Nested Filter Objects
124
+
125
+ Some fields accept nested object filters:
126
+
127
+ **`contact` (ContactNestedFilter)**: `name`, `resourceId`, `status`, `taxId`
128
+ ```json
129
+ { "filter": { "contact": { "name": { "contains": "Acme" } } } }
130
+ ```
131
+
132
+ **`account` (OrganizationAccountNestedFilter)**: `accountType`, `accountClass`, `code`, `name`, `resourceId`
133
+ ```json
134
+ { "filter": { "account": { "accountType": { "eq": "Bank Accounts" } } } }
135
+ ```
136
+
137
+ **`approvedBy` / `submittedBy` / `reconciledBy` (UserNestedFilter)**: `email`, `firstName`, `lastName`, `phoneRegistered`, `resourceId`, `status`
138
+
139
+ **`attachments` (AttachmentNestedFilter)**: `fileName`, `fileType`, `fileUrl`, `resourceId`
140
+
141
+ ---
142
+
143
+ ## Date Format Asymmetry (CRITICAL)
144
+
145
+ | Direction | Format | Fields |
146
+ |-----------|--------|--------|
147
+ | **Request** (filter dates) | `YYYY-MM-DD` strings | `valueDate`, `dueDate`, `startDate`, `endDate`, `purchaseDate`, etc. |
148
+ | **Request** (filter datetimes) | RFC3339 strings | `createdAt`, `updatedAt` |
149
+ | **Response** (ALL dates) | `int64` epoch milliseconds | `valueDate`, `createdAt`, `updatedAt`, `approvedAt`, `submittedAt`, `matchDate`, etc. |
150
+
151
+ To convert response dates: `new Date(epochMs).toISOString().slice(0, 10)` → `YYYY-MM-DD`
152
+
153
+ ---
154
+
155
+ ## Per-Endpoint Filter & Sort Fields
156
+
157
+ ### 1. POST /api/v1/invoices/search
158
+
159
+ **Filter fields** (`SaleFilter`):
160
+ | Field | Type | Notes |
161
+ |-------|------|-------|
162
+ | `resourceId` | StringExpression | |
163
+ | `contactResourceId` | StringExpression | |
164
+ | `status` | StringExpression | POSTED, DRAFT, VOIDED, etc. |
165
+ | `reference` | StringExpression | Invoice number |
166
+ | `terms` | IntExpression | Payment terms (days) |
167
+ | `contact` | ContactNestedFilter | Nested: name, resourceId, status, taxId |
168
+ | `valueDate` | DateExpression | |
169
+ | `dueDate` | DateExpression | |
170
+ | `tags` | StringExpression | |
171
+ | `currencyCode` | StringExpression | |
172
+ | `approvalStatus` | StringExpression | |
173
+ | `approvedAt` | DateExpression | |
174
+ | `approvedBy` | UserNestedFilter | |
175
+ | `submittedAt` | DateExpression | |
176
+ | `submittedBy` | UserNestedFilter | |
177
+ | `balanceAmount` | BigDecimalExpression | |
178
+ | `creditAppliedAmount` | BigDecimalExpression | |
179
+ | `paymentRecordedAmount` | BigDecimalExpression | |
180
+ | `reconciledAmount` | BigDecimalExpression | |
181
+ | `totalAmount` | BigDecimalExpression | |
182
+ | `createdAt` | DateTimeExpression | RFC3339 input |
183
+ | `createdBy` | JsonExpression | |
184
+ | `updatedAt` | DateTimeExpression | RFC3339 input |
185
+ | `updatedBy` | JsonExpression | |
186
+ | `attachments` | AttachmentNestedFilter | |
187
+
188
+ **Logical**: `and`, `or`, `andGroup`, `orGroup`
189
+
190
+ **Sort fields** (max 25): `resourceId`, `contactResourceId`, `status`, `reference`, `terms`, `contact`, `valueDate`, `dueDate`, `tags`, `currencyCode`, `createdAt`, `createdBy`, `attachments`, `balanceAmount`, `creditAppliedAmount`, `paymentRecordedAmount`, `reconciledAmount`, `totalAmount`, `approvalStatus`, `approvedAt`, `approvedBy`, `submittedAt`, `submittedBy`, `updatedAt`, `updatedBy`
191
+
192
+ ---
193
+
194
+ ### 2. POST /api/v1/bills/search
195
+
196
+ **Filter fields** (`PurchaseFilter`):
197
+ | Field | Type | Notes |
198
+ |-------|------|-------|
199
+ | `resourceId` | StringExpression | |
200
+ | `contactResourceId` | StringExpression | |
201
+ | `contact` | ContactNestedFilter | |
202
+ | `status` | StringExpression | |
203
+ | `reference` | StringExpression | |
204
+ | `valueDate` | DateExpression | |
205
+ | `dueDate` | DateExpression | |
206
+ | `terms` | IntExpression | |
207
+ | `tags` | StringExpression | |
208
+ | `currencyCode` | StringExpression | |
209
+ | `approvalStatus` | StringExpression | |
210
+ | `submittedBy` | UserNestedFilter | |
211
+ | `submittedAt` | DateExpression | |
212
+ | `approvedBy` | UserNestedFilter | |
213
+ | `approvedAt` | DateExpression | |
214
+ | `createdBy` | JsonExpression | |
215
+ | `createdAt` | DateTimeExpression | |
216
+ | `totalAmount` | BigDecimalExpression | |
217
+ | `attachments` | AttachmentNestedFilter | |
218
+ | `balanceAmount` | BigDecimalExpression | |
219
+ | `paymentRecordedAmount` | BigDecimalExpression | |
220
+ | `reconciledAmount` | BigDecimalExpression | |
221
+ | `creditAppliedAmount` | BigDecimalExpression | |
222
+ | `updatedBy` | JsonExpression | |
223
+ | `updatedAt` | DateTimeExpression | |
224
+
225
+ **Logical**: `and`, `or`, `andGroup`, `orGroup`
226
+
227
+ **Sort fields** (max 25): `resourceId`, `contactResourceId`, `contactName`, `status`, `reference`, `valueDate`, `dueDate`, `terms`, `tags`, `currencyCode`, `approvalStatus`, `submittedBy`, `submittedAt`, `approvedBy`, `approvedAt`, `createdBy`, `createdAt`, `totalAmount`, `attachments`, `balanceAmount`, `paymentRecordedAmount`, `reconciledAmount`, `creditAppliedAmount`, `updatedBy`, `updatedAt`
228
+
229
+ ---
230
+
231
+ ### 3. POST /api/v1/customer-credit-notes/search
232
+
233
+ **Filter fields** (`CustomerCreditNoteFilter`):
234
+ | Field | Type |
235
+ |-------|------|
236
+ | `resourceId` | StringExpression |
237
+ | `contactResourceId` | StringExpression |
238
+ | `status` | StringExpression |
239
+ | `reference` | StringExpression |
240
+ | `tags` | StringExpression |
241
+ | `valueDate` | DateExpression |
242
+ | `contact` | ContactNestedFilter |
243
+ | `currencyCode` | StringExpression |
244
+ | `approvalStatus` | StringExpression |
245
+ | `submittedBy` | UserNestedFilter |
246
+ | `submittedAt` | DateExpression |
247
+ | `approvedBy` | UserNestedFilter |
248
+ | `approvedAt` | DateExpression |
249
+ | `createdAt` | DateTimeExpression |
250
+ | `updatedAt` | DateTimeExpression |
251
+ | `createdBy` | JsonExpression |
252
+
253
+ **Logical**: `and`, `or`
254
+
255
+ **Sort fields** (max 15): `resourceId`, `contactResourceId`, `status`, `reference`, `tags`, `valueDate`, `contact`, `currencyCode`, `approvalStatus`, `submittedBy`, `submittedAt`, `approvedBy`, `approvedAt`, `createdAt`, `createdBy`
256
+
257
+ ---
258
+
259
+ ### 4. POST /api/v1/supplier-credit-notes/search
260
+
261
+ **Filter fields** (`SupplierCreditNoteFilter`): Same as customer-credit-notes (resourceId, contactResourceId, status, reference, tags, valueDate, contact, currencyCode, approvalStatus, submittedBy, submittedAt, approvedBy, approvedAt, createdAt, createdBy, updatedAt).
262
+
263
+ **Logical**: `and`, `or`
264
+
265
+ **Sort fields** (max 15): Same as customer-credit-notes.
266
+
267
+ ---
268
+
269
+ ### 5. POST /api/v1/journals/search
270
+
271
+ **Filter fields** (`JournalFilter`):
272
+ | Field | Type | Notes |
273
+ |-------|------|-------|
274
+ | `resourceId` | StringExpression | |
275
+ | `tags` | StringExpression | |
276
+ | `reference` | StringExpression | |
277
+ | `status` | StringExpression | |
278
+ | `contact` | ContactNestedFilter | |
279
+ | `creator` | UserNestedFilter | |
280
+ | `createdAt` | DateTimeExpression | |
281
+ | `updatedAt` | DateTimeExpression | |
282
+ | `valueDate` | DateExpression | |
283
+ | `type` | StringExpression | JOURNAL_MANUAL, JOURNAL_DIRECT_CASH_IN, etc. |
284
+ | `templateType` | StringExpression | |
285
+ | `internalNotes` | StringExpression | |
286
+
287
+ **Logical**: `and`, `or`, `andGroup`, `orGroup`
288
+
289
+ **Sort fields** (max 10): `resourceId`, `reference`, `status`, `contact`, `creator`, `createdAt`, `valueDate`, `type`, `templateType`
290
+
291
+ ---
292
+
293
+ ### 6. POST /api/v1/contacts/search
294
+
295
+ **Filter fields** (`ContactFilter`):
296
+ | Field | Type |
297
+ |-------|------|
298
+ | `resourceId` | StringExpression |
299
+ | `customer` | BooleanExpression |
300
+ | `supplier` | BooleanExpression |
301
+ | `email` | StringExpression |
302
+ | `name` | StringExpression |
303
+ | `networkId` | StringExpression |
304
+ | `notes` | StringExpression |
305
+ | `organizationId` | StringExpression |
306
+ | `registrationId` | StringExpression |
307
+ | `status` | StringExpression |
308
+ | `taxId` | StringExpression |
309
+ | `website` | StringExpression |
310
+ | `createdAt` | DateExpression |
311
+ | `updatedAt` | DateExpression |
312
+
313
+ **Logical**: `not`, `and`, `or`
314
+
315
+ **Sort fields** (max 13): `resourceId`, `customer`, `supplier`, `name`, `networkId`, `notes`, `organizationId`, `registrationId`, `status`, `taxId`, `website`, `createdAt`, `updatedAt`
316
+
317
+ ---
318
+
319
+ ### 7. POST /api/v1/items/search
320
+
321
+ **Filter fields** (`ItemFilter`):
322
+ | Field | Type |
323
+ |-------|------|
324
+ | `resourceId` | StringExpression |
325
+ | `appliesToPurchase` | BooleanExpression |
326
+ | `purchaseAccountResourceId` | StringExpression |
327
+ | `appliesToSale` | BooleanExpression |
328
+ | `saleAccountResourceId` | StringExpression |
329
+ | `status` | StringExpression |
330
+ | `itemCategory` | StringExpression |
331
+
332
+ **Sort fields** (max 10): `resourceId`, `internalName`, `itemCode`, `itemCategory`, `status`, `updatedAt`, `createdAt`
333
+
334
+ > **Note**: Filter uses `itemCategory` but sort uses `internalName` and `itemCode` — these are sort-only fields not available as filters.
335
+
336
+ ---
337
+
338
+ ### 8. POST /api/v1/tags/search
339
+
340
+ **Filter fields** (`TagFilter`):
341
+ | Field | Type |
342
+ |-------|------|
343
+ | `resourceId` | StringExpression |
344
+ | `organizationResourceId` | StringExpression |
345
+ | `status` | StringExpression |
346
+ | `tagName` | StringExpression |
347
+
348
+ **Logical**: `not`, `and`, `or`
349
+
350
+ **Sort fields** (max 13): `resourceId`, `organizationResourceId`, `tagName`, `status`
351
+
352
+ ---
353
+
354
+ ### 9. POST /api/v1/chart-of-accounts/search
355
+
356
+ **Filter fields** (`AccountFilter`):
357
+ | Field | Type |
358
+ |-------|------|
359
+ | `accountClass` | StringExpression |
360
+ | `accountType` | StringExpression |
361
+ | `appliesTo` | StringExpression |
362
+ | `code` | StringExpression |
363
+ | `controlFlag` | BooleanExpression |
364
+ | `name` | StringExpression |
365
+ | `currencyCode` | StringExpression |
366
+ | `resourceId` | StringExpression |
367
+ | `sgaName` | StringExpression |
368
+ | `status` | StringExpression |
369
+ | `createdAt` | DateExpression |
370
+ | `updatedAt` | DateExpression |
371
+
372
+ **Logical**: `and`, `or`
373
+
374
+ **Sort fields** (max 10): `accountClass`, `accountType`, `appliesTo`, `code`, `controlFlag`, `currencyCode`, `name`, `resourceId`, `sgaName`, `status`
375
+
376
+ ---
377
+
378
+ ### 10. POST /api/v1/cashflow-transactions/search
379
+
380
+ **Filter fields** (`TransactionsFilter`):
381
+ | Field | Type | Notes |
382
+ |-------|------|-------|
383
+ | `resourceId` | StringExpression | |
384
+ | `contact` | ContactNestedFilter | |
385
+ | `businessTransactionReference` | StringExpression | |
386
+ | `direction` | StringExpression | `PAYIN` or `PAYOUT` |
387
+ | `businessTransactionStatus` | StringExpression | |
388
+ | `account` | OrganizationAccountNestedFilter | Nested: accountType, accountClass, code, name, resourceId |
389
+ | `organizationAccountResourceId` | StringExpression | |
390
+ | `bankStatementEntryResourceId` | StringExpression | |
391
+ | `businessTransactionType` | StringExpression | SALE, PURCHASE, JOURNAL_MANUAL, etc. |
392
+ | `valueDate` | DateExpression | |
393
+ | `matchDate` | DateExpression | |
394
+ | `balanceAmount` | BigDecimalExpression | |
395
+ | `totalAmount` | BigDecimalExpression | |
396
+
397
+ **Logical**: `and`, `or`
398
+
399
+ **Sort fields** (max 13): `resourceId`, `contact`, `businessTransactionReference`, `direction`, `businessTransactionStatus`, `account`, `organizationAccountResourceId`, `bankStatementEntryResourceId`, `businessTransactionType`, `valueDate`, `matchDate`, `balanceAmount`, `totalAmount`
400
+
401
+ **Response shape**: `{ totalElements, totalPages, data: [...] }` (flat, same as all other search endpoints).
402
+
403
+ ---
404
+
405
+ ### 11. POST /api/v1/bank-records/:accountResourceId/search
406
+
407
+ **Path parameter**: `accountResourceId` (UUID of a bank-type CoA account — required)
408
+
409
+ **Filter fields** (`BankStatementEntryFilter`):
410
+ | Field | Type | Notes |
411
+ |-------|------|-------|
412
+ | `resourceId` | StringExpression | |
413
+ | `description` | StringExpression | |
414
+ | `extAccountNumber` | StringExpression | |
415
+ | `extContactName` | StringExpression | |
416
+ | `extReference` | StringExpression | |
417
+ | `netAmount` | BigDecimalExpression | |
418
+ | `status` | StringExpression | `RECONCILED`, `UNRECONCILED`, `ARCHIVED`, `POSSIBLE_DUPLICATE` |
419
+ | `valueDate` | DateExpression | |
420
+ | `reconciledBy` | UserNestedFilter | |
421
+
422
+ **Logical**: `and`, `or`
423
+
424
+ **Sort fields** (max 9): `description`, `extAccountNumber`, `extContactName`, `extReference`, `netAmount`, `reconciledBy`, `resourceId`, `status`, `valueDate`
425
+
426
+ ---
427
+
428
+ ### 12. POST /api/v1/tax-profiles/search
429
+
430
+ **Filter fields** (`TaxProfileFilter`):
431
+ | Field | Type |
432
+ |-------|------|
433
+ | `resourceId` | StringExpression |
434
+ | `appliesToPurchase` | BooleanExpression |
435
+ | `appliesToPurchaseCreditNote` | BooleanExpression |
436
+ | `appliesToSale` | BooleanExpression |
437
+ | `appliesToSaleCreditNote` | BooleanExpression |
438
+ | `organizationResourceId` | StringExpression |
439
+ | `description` | StringExpression |
440
+ | `name` | StringExpression |
441
+ | `status` | StringExpression |
442
+ | `taxTypeCode` | StringExpression |
443
+ | `taxTypeName` | StringExpression |
444
+ | `isDefault` | BooleanExpression |
445
+ | `isShipping` | BooleanExpression |
446
+ | `vatValue` | BigDecimalExpression |
447
+ | `withholdingValue` | BigDecimalExpression |
448
+
449
+ **Logical**: `not`, `and`, `or`
450
+
451
+ **Sort fields** (max 15): `resourceId`, `organizationResourceId`, `name`, `description`, `status`, `taxTypeCode`, `taxTypeName`, `isDefault`, `isShipping`, `vatValue`, `withholdingValue`, `appliesToPurchase`, `appliesToPurchaseCreditNote`, `appliesToSale`, `appliesToSaleCreditNote`
452
+
453
+ ---
454
+
455
+ ### 13. POST /api/v1/custom-fields/search
456
+
457
+ **Filter fields** (`CustomFieldFilter`):
458
+ | Field | Type |
459
+ |-------|------|
460
+ | `resourceId` | StringExpression |
461
+ | `organizationResourceId` | StringExpression |
462
+ | `status` | StringExpression |
463
+ | `applyToPurchase` | StringExpression |
464
+ | `applyToPurchaseCreditNote` | StringExpression |
465
+ | `applyToSales` | StringExpression |
466
+ | `applyToSaleCreditNote` | StringExpression |
467
+ | `appliesToFixedAssets` | StringExpression |
468
+ | `appliesToItems` | StringExpression |
469
+ | `applyToCreditNote` | StringExpression |
470
+ | `applyToPayment` | StringExpression |
471
+ | `datatypeCode` | StringExpression |
472
+ | `customFieldName` | StringExpression |
473
+
474
+ **Logical**: `not`, `and`, `or`
475
+
476
+ **Sort fields** (max 13): `resourceId`, `organizationResourceId`, `customFieldName`, `datatypeCode`, `status`, `appliesToPurchase`, `appliesToPurchaseCreditNote`, `appliesToSale`, `appliesToSaleCreditNote`, `appliesToFixedAssets`, `appliesToItems`, `applyToCreditNote`, `applyToPayment`
477
+
478
+ ---
479
+
480
+ ### 14. POST /api/v1/contact-groups/search
481
+
482
+ **Filter fields** (`ContactGroupFilter`):
483
+ | Field | Type |
484
+ |-------|------|
485
+ | `resourceId` | StringExpression |
486
+ | `name` | StringExpression |
487
+
488
+ **Logical**: `and`, `or`
489
+
490
+ **Sort fields** (max 13): `resourceId`, `name`
491
+
492
+ ---
493
+
494
+ ### 15. POST /api/v1/capsules/search
495
+
496
+ **Filter fields** (`CapsuleFilter`):
497
+ | Field | Type |
498
+ |-------|------|
499
+ | `resourceId` | StringExpression |
500
+ | `description` | StringExpression |
501
+ | `endDate` | DateExpression |
502
+ | `startDate` | DateExpression |
503
+ | `status` | StringExpression |
504
+ | `title` | StringExpression |
505
+
506
+ **Logical**: `and`, `or`
507
+
508
+ **Sort fields** (max 10): `resourceId`, `title`, `status`, `description`, `attributes`, `endDate`, `startDate`, `organizationResourceId`, `totalSchedulers`, `totalTransactions`
509
+
510
+ > **Note**: Capsules uses `title` (not `name`) for the display name field.
511
+
512
+ ---
513
+
514
+ ### 16. POST /api/v1/capsuleTypes/search
515
+
516
+ **Filter fields** (`CapsuleTypesFilter`):
517
+ | Field | Type |
518
+ |-------|------|
519
+ | `resourceId` | StringExpression |
520
+ | `description` | StringExpression |
521
+ | `displayName` | StringExpression |
522
+ | `name` | StringExpression |
523
+ | `status` | StringExpression |
524
+ | `controlFlag` | BooleanExpression |
525
+ | `isLocked` | BooleanExpression |
526
+
527
+ **Logical**: `and`, `or`
528
+
529
+ **Sort fields** (max 10): `resourceId`, `title`, `status`, `description`, `displayName`, `name`
530
+
531
+ ---
532
+
533
+ ### 17. POST /api/v1/fixed-assets/search
534
+
535
+ **Filter fields** (`FixedAssetsFilter`):
536
+ | Field | Type |
537
+ |-------|------|
538
+ | `resourceId` | StringExpression |
539
+ | `name` | StringExpression |
540
+ | `reference` | StringExpression |
541
+ | `category` | StringExpression |
542
+ | `currencyCode` | StringExpression |
543
+ | `depreciationEndDate` | DateExpression |
544
+ | `depreciationStartDate` | DateExpression |
545
+ | `depreciationMethod` | StringExpression |
546
+ | `disposalType` | StringExpression |
547
+ | `typeName` | StringExpression |
548
+ | `typeCode` | StringExpression |
549
+ | `tags` | StringExpression |
550
+ | `status` | StringExpression |
551
+ | `registrationType` | StringExpression |
552
+ | `purchaseBusinessTransactionType` | StringExpression |
553
+ | `purchaseDate` | DateExpression |
554
+ | `disposalValueDate` | DateExpression |
555
+ | `purchaseAmount` | BigDecimalExpression |
556
+ | `netBookAtDisposalAmount` | BigDecimalExpression |
557
+ | `bookValueAmount` | BigDecimalExpression |
558
+ | `assetDisposalGainLossAmount` | BigDecimalExpression |
559
+
560
+ **Logical**: `and`, `or`
561
+
562
+ **Sort fields** (max 13): `resourceId`, `name`, `purchaseDate`, `disposalValueDate`, `purchaseAmount`, `bookValueAmount`, `netBookAtDisposalAmount`, `assetDisposalGainLossAmount`, `typeName`, `typeCode`, `category`
563
+
564
+ ---
565
+
566
+ ### 18. POST /api/v1/fixed-assets-types/search
567
+
568
+ **Filter fields** (`FixedAssetsTypesFilter`):
569
+ | Field | Type |
570
+ |-------|------|
571
+ | `categoryCode` | StringExpression |
572
+ | `typeName` | StringExpression |
573
+ | `typeCode` | StringExpression |
574
+ | `resourceId` | StringExpression |
575
+
576
+ **Logical**: `and`, `or`
577
+
578
+ **Sort fields**: `resourceId`, `typeName`, `typeCode`, `categoryCode`
579
+
580
+ ---
581
+
582
+ ### 19. POST /api/v1/scheduled-transaction/search
583
+
584
+ **Filter fields** (`TransactionScheduleFilter`):
585
+ | Field | Type | Notes |
586
+ |-------|------|-------|
587
+ | `resourceId` | StringExpression | |
588
+ | `businessTransactionReference` | StringExpression | |
589
+ | `businessTransactionResourceId` | StringExpression | |
590
+ | `businessTransactionType` | StringExpression | |
591
+ | `schedulerType` | StringExpression | |
592
+ | `contactResourceId` | StringExpression | |
593
+ | `contact` | ContactNestedFilter | |
594
+ | `status` | StringExpression | |
595
+ | `currencyCode` | StringExpression | |
596
+ | `startDate` | DateExpression | |
597
+ | `endDate` | DateExpression | |
598
+ | `subscriptionStatus` | StringExpression | |
599
+ | `interval` | StringExpression | WEEKLY, MONTHLY, QUARTERLY, YEARLY |
600
+ | `lastScheduleDate` | DateExpression | |
601
+ | `nextScheduleDate` | DateExpression | |
602
+ | `paymentRecordedAmount` | BigDecimalExpression | |
603
+ | `totalAmount` | BigDecimalExpression | |
604
+ | `referenceGenerationMode` | StringExpression | |
605
+ | `proratedStartDate` | DateExpression | |
606
+
607
+ **Logical**: `and`, `or`
608
+
609
+ **Sort fields** (max 25): `resourceId`, `businessTransactionReference`, `businessTransactionResourceId`, `businessTransactionType`, `schedulerType`, `contactResourceId`, `status`, `currencyCode`, `startDate`, `endDate`, `subscriptionStatus`, `interval`, `lastScheduleDate`, `nextScheduleDate`, `paymentRecordedAmount`, `totalAmount`, `referenceGenerationMode`, `proratedStartDate`
610
+
611
+ ---
612
+
613
+ ### 20. POST /api/v1/nano-classifiers/search
614
+
615
+ **Filter fields** (`NanoClassifiersFilter`):
616
+ | Field | Type |
617
+ |-------|------|
618
+ | `resourceId` | StringExpression |
619
+ | `type` | StringExpression |
620
+ | `classes` | ClassifierClassFilter (nested: `className`, `resourceId`) |
621
+
622
+ **Logical**: `not`, `and`, `or`
623
+
624
+ **Sort fields**: `resourceId`, `type`
625
+
626
+ ---
627
+
628
+ ### 21. POST /api/v1/organization-users/search
629
+
630
+ See `organization-users.go`. Standard pattern with limit/offset/filter/sort.
631
+
632
+ ---
633
+
634
+ ### 22. POST /api/v1/bank-rules/search
635
+
636
+ See `bankRule.go`. Standard pattern with limit/offset/filter/sort.
637
+
638
+ ---
639
+
640
+ ### 23. POST /api/v1/purchase-items/search
641
+
642
+ **Filter fields** (`PurchaseItemFilter`): `currencyCode`, `name`, `purchaseResourceId`, `resourceId`, `reference` (plain strings — NOT expression objects. Operators like `contains`, `in` are not supported on this endpoint).
643
+
644
+ **Sort fields** (max 13): `resourceId`, `name`, `reference`, `currencyCode`, `status`, `valueDate`, `totalItemAmount`, `description`
645
+
646
+ ---
647
+
648
+ ## Quick Lookup: Common Search Patterns
649
+
650
+ ### Find all invoices for a contact
651
+ ```json
652
+ POST /api/v1/invoices/search
653
+ {
654
+ "filter": { "contactResourceId": { "eq": "uuid-here" } },
655
+ "sort": { "sortBy": ["valueDate"], "order": "DESC" },
656
+ "limit": 100
657
+ }
658
+ ```
659
+
660
+ ### Find unpaid invoices in a date range
661
+ ```json
662
+ POST /api/v1/invoices/search
663
+ {
664
+ "filter": {
665
+ "status": { "eq": "POSTED" },
666
+ "balanceAmount": { "gt": 0 },
667
+ "valueDate": { "between": ["2026-01-01", "2026-06-30"] }
668
+ },
669
+ "sort": { "sortBy": ["valueDate"], "order": "ASC" }
670
+ }
671
+ ```
672
+
673
+ ### Find bank accounts (via CoA search)
674
+ ```json
675
+ POST /api/v1/chart-of-accounts/search
676
+ {
677
+ "filter": { "accountType": { "eq": "Bank Accounts" } },
678
+ "sort": { "sortBy": ["name"], "order": "ASC" }
679
+ }
680
+ ```
681
+
682
+ ### Find unreconciled bank records
683
+ ```json
684
+ POST /api/v1/bank-records/:accountResourceId/search
685
+ {
686
+ "filter": { "status": { "eq": "UNRECONCILED" } },
687
+ "sort": { "sortBy": ["valueDate"], "order": "DESC" }
688
+ }
689
+ ```
690
+
691
+ ### Find contacts by name pattern
692
+ ```json
693
+ POST /api/v1/contacts/search
694
+ {
695
+ "filter": { "name": { "contains": "Sterling" } },
696
+ "sort": { "sortBy": ["name"], "order": "ASC" }
697
+ }
698
+ ```
699
+
700
+ ### Find all cashflow transactions for a bank account
701
+ ```json
702
+ POST /api/v1/cashflow-transactions/search
703
+ {
704
+ "filter": {
705
+ "organizationAccountResourceId": { "eq": "bank-uuid" },
706
+ "valueDate": { "gte": "2026-01-01" }
707
+ },
708
+ "sort": { "sortBy": ["valueDate"], "order": "DESC" }
709
+ }
710
+ ```
711
+
712
+ ---
713
+
714
+ *Source of truth: Go structs in the API backend (`models/*.go`). All filter/sort fields extracted from Go struct validation tags and verified against live production API. Last updated: 2026-02-14 — All search/list responses standardized to flat shape. Capsules/capsuleTypes sort now array. Purchase-items sort fields corrected. Tax-profiles max fixed. Catalogs search returns paginated response.*