@firela/api-types 0.0.0-canary.2fbeefe9 → 0.0.0-canary.2fd4afbd

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.
@@ -11,7 +11,7 @@ export const $CreateAccountDto = {
11
11
  openDate: {
12
12
  format: 'date-time',
13
13
  type: 'string',
14
- description: 'Account open date',
14
+ description: 'Account open date (server defaults to today)',
15
15
  example: '2024-01-01'
16
16
  },
17
17
  currencies: {
@@ -51,9 +51,18 @@ export const $CreateAccountDto = {
51
51
  description: 'Icon identifier (overrides template)',
52
52
  example: 'bank-custom'
53
53
  },
54
- openMeta: {
54
+ displayName: {
55
+ type: 'string',
56
+ description:
57
+ 'User-set display name override (omit/null = keep the derived name)',
58
+ nullable: true,
59
+ maxLength: 50,
60
+ example: 'Salary card'
61
+ },
62
+ openDirectiveMeta: {
55
63
  type: 'object',
56
- description: 'Additional metadata',
64
+ description:
65
+ 'Open directive metadata (NOT an opening-balance amount — use the opening-balance endpoint)',
57
66
  example: {
58
67
  branch: 'Downtown',
59
68
  accountNumber: '1234'
@@ -65,7 +74,7 @@ export const $CreateAccountDto = {
65
74
  example: 'c98e5d4a-2f71-4a5a-bb3c-92c9f231d5e2'
66
75
  }
67
76
  },
68
- required: ['path', 'openDate']
77
+ required: ['path']
69
78
  } as const;
70
79
 
71
80
  export const $AccountResponseDto = {
@@ -87,6 +96,49 @@ export const $AccountResponseDto = {
87
96
  enum: ['Assets', 'Liabilities', 'Income', 'Expenses', 'Equity'],
88
97
  example: 'Assets'
89
98
  },
99
+ assetSubClass: {
100
+ type: 'string',
101
+ description:
102
+ 'Account-level asset sub-class (product type, e.g. STOCK/DEPOSIT/CREDIT_CARD/PERSONAL_LOAN). Computed from the account path via the asset-classifier (ADR-0077). Null for non-asset accounts (Income/Expenses/Equity) or unmatched paths.',
103
+ enum: [
104
+ 'DEPOSIT',
105
+ 'CASH',
106
+ 'MONEY_MARKET_FUND',
107
+ 'STOCK',
108
+ 'ETF',
109
+ 'MUTUAL_FUND',
110
+ 'EQUITY_COMPENSATION',
111
+ 'GOVERNMENT_BOND',
112
+ 'CORPORATE_BOND',
113
+ 'BOND_FUND',
114
+ 'PRIMARY_RESIDENCE',
115
+ 'INVESTMENT_PROPERTY',
116
+ 'REIT',
117
+ 'GOLD',
118
+ 'SILVER',
119
+ 'PRECIOUS_METAL',
120
+ 'PRECIOUS_METAL_FUND',
121
+ 'COMMODITY',
122
+ 'COMMODITY_FUND',
123
+ 'CRYPTOCURRENCY',
124
+ 'RETIREMENT_ACCOUNT',
125
+ 'HEALTH_ACCOUNT',
126
+ 'EDUCATION_ACCOUNT',
127
+ 'INSURANCE',
128
+ 'PRIVATE_EQUITY',
129
+ 'HEDGE_FUND',
130
+ 'COLLECTIBLES',
131
+ 'MORTGAGE',
132
+ 'STUDENT_LOAN',
133
+ 'CREDIT_CARD',
134
+ 'PERSONAL_LOAN',
135
+ 'ACCOUNTS_PAYABLE',
136
+ 'TAX_PAYABLE',
137
+ 'OTHER'
138
+ ],
139
+ nullable: true,
140
+ example: 'STOCK'
141
+ },
90
142
  status: {
91
143
  type: 'string',
92
144
  description: 'Account status',
@@ -137,7 +189,8 @@ export const $AccountResponseDto = {
137
189
  },
138
190
  displayName: {
139
191
  type: 'string',
140
- description: 'Localized display name (ADR-0114, read-time projection)',
192
+ description:
193
+ 'Display name with precedence: user-set name (#762) > ADR-0114 localized name > path leaf (read-time projection)',
141
194
  example: 'Checking'
142
195
  },
143
196
  icon: {
@@ -145,15 +198,15 @@ export const $AccountResponseDto = {
145
198
  description: 'Icon identifier',
146
199
  example: 'bank-icbc'
147
200
  },
148
- openMeta: {
201
+ openDirectiveMeta: {
149
202
  type: 'object',
150
- description: 'Account metadata',
203
+ description: 'Open directive metadata (ADR-0115 Decision 9)',
151
204
  example: {
152
205
  branch: 'Downtown'
153
206
  }
154
207
  },
155
208
  platformId: {
156
- type: 'object',
209
+ type: 'string',
157
210
  description: 'Platform ID (null if unbound)',
158
211
  example: 'c98e5d4a-2f71-4a5a-bb3c-92c9f231d5e2'
159
212
  },
@@ -233,9 +286,18 @@ export const $UpdateAccountDto = {
233
286
  description: 'Icon identifier',
234
287
  example: 'bank-custom'
235
288
  },
236
- openMeta: {
289
+ displayName: {
290
+ type: 'string',
291
+ description:
292
+ 'User-set display name override (null = clear the override and fall back to the derived name, omit = unchanged)',
293
+ nullable: true,
294
+ maxLength: 50,
295
+ example: 'Salary card'
296
+ },
297
+ openDirectiveMeta: {
237
298
  type: 'object',
238
- description: 'Additional metadata (merged with existing)',
299
+ description:
300
+ 'Open directive metadata (merged with existing; NOT an opening-balance amount)',
239
301
  example: {
240
302
  branch: 'Uptown'
241
303
  }
@@ -282,6 +344,40 @@ export const $ReopenAccountDto = {
282
344
  }
283
345
  } as const;
284
346
 
347
+ export const $CreateOpeningBalanceDto = {
348
+ type: 'object',
349
+ properties: {
350
+ amount: {
351
+ type: 'number',
352
+ description: 'Opening balance amount (non-negative)',
353
+ example: 1000
354
+ },
355
+ currency: {
356
+ type: 'string',
357
+ description: 'Currency code',
358
+ example: 'CNY'
359
+ },
360
+ date: {
361
+ format: 'date-time',
362
+ type: 'string',
363
+ description: 'Opening-balance date (defaults to now)',
364
+ example: '2024-01-01'
365
+ }
366
+ },
367
+ required: ['amount', 'currency']
368
+ } as const;
369
+
370
+ export const $OpeningBalanceResultDto = {
371
+ type: 'object',
372
+ properties: {
373
+ transactionId: {
374
+ type: 'string',
375
+ description: 'Created opening-balance transaction id.'
376
+ }
377
+ },
378
+ required: ['transactionId']
379
+ } as const;
380
+
285
381
  export const $AccountStandardResponseDto = {
286
382
  type: 'object',
287
383
  properties: {
@@ -298,16 +394,43 @@ export const $AccountStandardResponseDto = {
298
394
  },
299
395
  name: {
300
396
  type: 'string',
301
- description: 'Short localized display name',
397
+ description:
398
+ 'Short display name. Universal rows project to the request locale (Accept-Language); regional rows keep the authored native name — mixed-language by design (ADR-0131 class P vs class A).',
302
399
  example: 'Housing Fund'
303
400
  },
401
+ aliases: {
402
+ description:
403
+ 'Authored market-language alternative names delivered verbatim (not localized copy, not xlf-managed, not locale-projected). Flat string[] per ADR-0129 D1; ADR-0131 class A.',
404
+ example: ['Alipay', 'WeChat Pay'],
405
+ type: 'array',
406
+ items: {
407
+ type: 'string'
408
+ }
409
+ },
410
+ searchTerms: {
411
+ description:
412
+ 'Locale-projected search synonyms (e.g. the zh bank-card / debit-card everyday terms for the checking account). Pure-locale projection — absent when the locale has no seeded synonyms; English fallback rides the authored aliases field. Search-only vocabulary, not the NLP routing corpus (#698, ADR-0131 fourth-class adjudication).',
413
+ example: ['yinhangka', 'jiejika'],
414
+ type: 'array',
415
+ items: {
416
+ type: 'string'
417
+ }
418
+ },
419
+ currency: {
420
+ type: 'string',
421
+ description:
422
+ 'Product denomination as a 3-letter ISO 4217 code, authored market data delivered verbatim (not localized, not xlf-managed). ADR-0131 class A. Absent = single-currency not asserted — consumers fall back to their own region currency (#714).',
423
+ example: 'HKD'
424
+ },
304
425
  description: {
305
426
  type: 'string',
306
- description: 'Account description (stable semantics only)',
427
+ description:
428
+ 'Account description (stable semantics only). Mixed-language contract: universal rows project to the request locale via the accountDesc xlf axis with an en fallback (ADR-0131 class P, ADR-0132; unseeded locales falling back to English are expected); regional rows deliver the authored market language (ADR-0131 class A, verbatim, never xlf-managed).',
307
429
  example: 'ICBC checking account for daily transactions'
308
430
  },
309
431
  tags: {
310
- description: 'Account tags for categorization',
432
+ description:
433
+ 'Account tags for categorization — structured metadata delivered verbatim (not localized, not xlf-managed). ADR-0131 class A.',
311
434
  example: ['bank', 'checking', 'primary'],
312
435
  type: 'array',
313
436
  items: {
@@ -318,9 +441,47 @@ export const $AccountStandardResponseDto = {
318
441
  type: 'string',
319
442
  description: 'Icon identifier for UI display',
320
443
  example: 'bank-icbc'
444
+ },
445
+ productCategory: {
446
+ type: 'string',
447
+ description:
448
+ 'Onboarding product category (coarse grouping derived from assetSubClass)',
449
+ enum: [
450
+ 'cash',
451
+ 'investment',
452
+ 'credit_card',
453
+ 'loan',
454
+ 'payable_tax',
455
+ 'other'
456
+ ],
457
+ example: 'investment'
458
+ },
459
+ assetClass: {
460
+ type: 'string',
461
+ description:
462
+ 'Asset class (LIQUIDITY/EQUITY/.../LIABILITY), derived at read time from classification rules',
463
+ enum: [
464
+ 'LIQUIDITY',
465
+ 'EQUITY',
466
+ 'FIXED_INCOME',
467
+ 'PRECIOUS_METALS',
468
+ 'COMMODITY',
469
+ 'INSURANCE',
470
+ 'ALTERNATIVE_INVESTMENT',
471
+ 'PERSONAL_ASSETS',
472
+ 'LIABILITY',
473
+ 'REAL_ESTATE',
474
+ 'INDEX'
475
+ ]
476
+ },
477
+ assetSubClass: {
478
+ type: 'string',
479
+ description:
480
+ 'Asset sub-class (product type, derived at read time from classification rules)',
481
+ example: 'STOCK'
321
482
  }
322
483
  },
323
- required: ['path', 'type', 'description', 'tags', 'icon']
484
+ required: ['path', 'type', 'description', 'tags', 'icon', 'productCategory']
324
485
  } as const;
325
486
 
326
487
  export const $AccountStandardListResponseDto = {
@@ -381,7 +542,10 @@ export const $RegionConfigDto = {
381
542
  },
382
543
  locale: {
383
544
  type: 'string',
384
- example: 'de-DE'
545
+ example: 'de-DE',
546
+ pattern: '^[a-z]{2,8}-[A-Z]{2}$',
547
+ description:
548
+ "Region-qualified BCP-47 tag whose region subtag equals the region's own ISO 3166-1 code (e.g., ja-JP, zh-CN, zh-HK)"
385
549
  }
386
550
  },
387
551
  required: ['currency', 'dateFormat', 'locale']
@@ -394,6 +558,12 @@ export const $RegionInfoDto = {
394
558
  type: 'string',
395
559
  example: 'de'
396
560
  },
561
+ open: {
562
+ type: 'boolean',
563
+ example: true,
564
+ description:
565
+ 'Whether the region is open (has a ready regional account template). Not-yet-open regions still return identity metadata and degrade to the universal-only catalog.'
566
+ },
397
567
  displayName: {
398
568
  type: 'string',
399
569
  example: 'Germany'
@@ -412,7 +582,7 @@ export const $RegionInfoDto = {
412
582
  $ref: '#/components/schemas/RegionConfigDto'
413
583
  }
414
584
  },
415
- required: ['code', 'displayName', 'chain', 'config']
585
+ required: ['code', 'open', 'displayName', 'chain', 'config']
416
586
  } as const;
417
587
 
418
588
  export const $RegionsMetadataResponseDto = {
@@ -659,7 +829,7 @@ export const $PostingResponseDto = {
659
829
  units: {
660
830
  type: 'string',
661
831
  description:
662
- 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned.',
832
+ 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned. Carries the raw Beancount sign (credit-normal accounts such as Income post negative — the accounting truth, ADR-0126); renderers must not infer economic semantics from this sign.',
663
833
  example: '100.50'
664
834
  },
665
835
  currency: {
@@ -1025,7 +1195,7 @@ export const $PostingDetailDto = {
1025
1195
  units: {
1026
1196
  type: 'string',
1027
1197
  description:
1028
- 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned.',
1198
+ 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned. Carries the raw Beancount sign (credit-normal accounts such as Income post negative — the accounting truth, ADR-0126); renderers must not infer economic semantics from this sign.',
1029
1199
  example: '100.50'
1030
1200
  },
1031
1201
  currency: {
@@ -1209,6 +1379,147 @@ export const $TransactionDetailDto = {
1209
1379
  ]
1210
1380
  } as const;
1211
1381
 
1382
+ export const $TransactionListItemDto = {
1383
+ type: 'object',
1384
+ properties: {
1385
+ id: {
1386
+ type: 'string',
1387
+ description: 'Transaction ID',
1388
+ example: 'clh1234567890abcdef'
1389
+ },
1390
+ date: {
1391
+ type: 'string',
1392
+ description: 'Transaction date',
1393
+ example: '2024-11-28'
1394
+ },
1395
+ flag: {
1396
+ type: 'string',
1397
+ description: 'Transaction flag',
1398
+ enum: [
1399
+ 'CLEARED',
1400
+ 'PENDING',
1401
+ 'PADDING',
1402
+ 'SUMMARIZE',
1403
+ 'TRANSFER',
1404
+ 'CONVERSIONS'
1405
+ ],
1406
+ example: 'CLEARED'
1407
+ },
1408
+ customFlag: {
1409
+ type: 'string',
1410
+ description: 'Custom flag (if not using standard flags)',
1411
+ example: 'R'
1412
+ },
1413
+ payee: {
1414
+ type: 'string',
1415
+ description: 'Payee name',
1416
+ example: 'Whole Foods Market'
1417
+ },
1418
+ narration: {
1419
+ type: 'string',
1420
+ description: 'Transaction narration',
1421
+ example: 'Grocery shopping'
1422
+ },
1423
+ tags: {
1424
+ description: 'Transaction tags',
1425
+ example: ['groceries'],
1426
+ type: 'array',
1427
+ items: {
1428
+ type: 'string'
1429
+ }
1430
+ },
1431
+ links: {
1432
+ description: 'Transaction links',
1433
+ example: ['invoice-2024-001'],
1434
+ type: 'array',
1435
+ items: {
1436
+ type: 'string'
1437
+ }
1438
+ },
1439
+ meta: {
1440
+ type: 'object',
1441
+ description: 'Transaction metadata'
1442
+ },
1443
+ status: {
1444
+ type: 'string',
1445
+ description: 'Transaction status',
1446
+ enum: ['ACTIVE', 'VOIDED', 'SUPERSEDED'],
1447
+ example: 'ACTIVE'
1448
+ },
1449
+ sourceType: {
1450
+ type: 'string',
1451
+ description:
1452
+ 'Source type (free-form string from transaction metadata, e.g. import, api)'
1453
+ },
1454
+ sourcePlatform: {
1455
+ type: 'string',
1456
+ description: 'Source platform (e.g., alipay, wechat)',
1457
+ example: 'alipay'
1458
+ },
1459
+ postings: {
1460
+ description: 'Transaction postings',
1461
+ type: 'array',
1462
+ items: {
1463
+ $ref: '#/components/schemas/PostingDetailDto'
1464
+ }
1465
+ },
1466
+ createdAt: {
1467
+ type: 'string',
1468
+ description: 'Created at timestamp',
1469
+ example: '2024-11-28T10:30:00.000Z'
1470
+ },
1471
+ voidedAt: {
1472
+ type: 'string',
1473
+ description: 'Voided at timestamp (if voided)',
1474
+ example: '2024-11-29T15:00:00.000Z'
1475
+ },
1476
+ voidedBy: {
1477
+ type: 'string',
1478
+ description: 'User ID who voided this transaction',
1479
+ example: 'clh1234567890abcdef'
1480
+ },
1481
+ correctionReason: {
1482
+ type: 'string',
1483
+ description: 'Correction reason (if voided or superseded)',
1484
+ example: 'Duplicate entry'
1485
+ },
1486
+ supersededBy: {
1487
+ type: 'string',
1488
+ description:
1489
+ 'ID of the transaction that supersedes this one (set when status=SUPERSEDED)',
1490
+ example: 'clh1234567890abcdef'
1491
+ },
1492
+ originalTxn: {
1493
+ type: 'string',
1494
+ description:
1495
+ 'ID of the transaction this one corrected/replaced (back-link on the replacement)',
1496
+ example: 'clh1234567890abcdef'
1497
+ },
1498
+ viewpointAmount: {
1499
+ type: 'string',
1500
+ description:
1501
+ 'Row amount under the request viewpoint (ADR-0126). Category viewpoint (category + flow): per-leg sign-normalized sum over the category account set (Income-root legs negated, Expenses-root identity) — positive under normal booking but NOT clamped (explicit negative expense legs and net-flip refund months stay negative). No viewpoint (plain list / search, no accountId): wallet money-flow net = raw-sign sum over cost-less Assets/Liabilities legs (income positive, expenses negative, transfers net ~0); color cue is the wallet sign (net < 0 = wealth-decreasing). Status-orthogonal: audit views match too (ADR-0128 amount-as-matching-key). Omitted under the account viewpoint (incl. dual) and for rows with no wallet leg.',
1502
+ example: '10000.00'
1503
+ },
1504
+ viewpointCurrency: {
1505
+ type: 'string',
1506
+ description:
1507
+ 'Currency of viewpointAmount. A row spanning multiple currencies takes the largest-magnitude currency group (known simplification, ADR-0126).',
1508
+ example: 'CNY'
1509
+ }
1510
+ },
1511
+ required: [
1512
+ 'id',
1513
+ 'date',
1514
+ 'narration',
1515
+ 'tags',
1516
+ 'links',
1517
+ 'status',
1518
+ 'postings',
1519
+ 'createdAt'
1520
+ ]
1521
+ } as const;
1522
+
1212
1523
  export const $BalanceByCurrencyDto = {
1213
1524
  type: 'object',
1214
1525
  properties: {
@@ -1254,7 +1565,7 @@ export const $TransactionListSummaryDto = {
1254
1565
  totalAmount: {
1255
1566
  type: 'string',
1256
1567
  description:
1257
- 'Partial converted total in base currency (rated currencies only, raw Beancount sign). When warnings is non-empty this excludes currencies missing an FX rate; may be "0.00" if ALL non-base currencies lack a rate. Converted at the dateTo (or current) available rate.',
1568
+ 'Partial converted total in base currency (rated currencies only). Sign by viewpoint (ADR-0126): account viewpoint keeps the raw Beancount sign (income negative); category viewpoint is per-leg sign-normalized (Income legs negated, Expenses legs identity — positive under normal booking, not clamped). When warnings is non-empty this excludes currencies missing an FX rate; may be "0.00" if ALL non-base currencies lack a rate. Converted at the dateTo (or current) available rate.',
1258
1569
  example: '-6000.00'
1259
1570
  },
1260
1571
  currency: {
@@ -1280,6 +1591,26 @@ export const $TransactionListSummaryDto = {
1280
1591
  required: ['totalAmount', 'currency', 'balanceByCurrency']
1281
1592
  } as const;
1282
1593
 
1594
+ export const $TransactionListViewpointDto = {
1595
+ type: 'object',
1596
+ properties: {
1597
+ type: {
1598
+ type: 'string',
1599
+ description:
1600
+ 'Viewpoint type (only category drill-down carries a viewpoint today)',
1601
+ enum: ['category'],
1602
+ example: 'category'
1603
+ },
1604
+ flow: {
1605
+ type: 'string',
1606
+ description: 'Flow root the category account set is restricted to',
1607
+ enum: ['income', 'expense'],
1608
+ example: 'expense'
1609
+ }
1610
+ },
1611
+ required: ['type', 'flow']
1612
+ } as const;
1613
+
1283
1614
  export const $TransactionListResponseDto = {
1284
1615
  type: 'object',
1285
1616
  properties: {
@@ -1287,7 +1618,7 @@ export const $TransactionListResponseDto = {
1287
1618
  description: 'List of transactions',
1288
1619
  type: 'array',
1289
1620
  items: {
1290
- $ref: '#/components/schemas/TransactionDetailDto'
1621
+ $ref: '#/components/schemas/TransactionListItemDto'
1291
1622
  }
1292
1623
  },
1293
1624
  total: {
@@ -1313,6 +1644,15 @@ export const $TransactionListResponseDto = {
1313
1644
  $ref: '#/components/schemas/TransactionListSummaryDto'
1314
1645
  }
1315
1646
  ]
1647
+ },
1648
+ viewpoint: {
1649
+ description:
1650
+ 'Viewpoint metadata (ADR-0126). Present only for a single category filter (category + flow, no accountId); dual-perspective requests are viewpoint-less (raw signs, no viewpointAmount).',
1651
+ allOf: [
1652
+ {
1653
+ $ref: '#/components/schemas/TransactionListViewpointDto'
1654
+ }
1655
+ ]
1316
1656
  }
1317
1657
  },
1318
1658
  required: ['data', 'total', 'limit', 'offset']
@@ -1664,13 +2004,17 @@ export const $ReviewStatsDto = {
1664
2004
  type: 'object',
1665
2005
  description: 'Count by type'
1666
2006
  },
2007
+ resolved: {
2008
+ type: 'number',
2009
+ description: 'Current count of reviews in RESOLVED status'
2010
+ },
1667
2011
  oldestPending: {
1668
2012
  format: 'date-time',
1669
2013
  type: 'string',
1670
2014
  description: 'Oldest pending review date'
1671
2015
  }
1672
2016
  },
1673
- required: ['total', 'byType']
2017
+ required: ['total', 'byType', 'resolved']
1674
2018
  } as const;
1675
2019
 
1676
2020
  export const $DecisionOptionDto = {
@@ -1975,6 +2319,44 @@ export const $BatchResolveDto = {
1975
2319
  required: ['reviewIds', 'action']
1976
2320
  } as const;
1977
2321
 
2322
+ export const $BatchResolveItemDto = {
2323
+ type: 'object',
2324
+ properties: {
2325
+ reviewId: {
2326
+ type: 'string',
2327
+ description: 'Review item ID'
2328
+ },
2329
+ success: {
2330
+ type: 'boolean',
2331
+ description: 'Whether this item was resolved successfully'
2332
+ },
2333
+ resolutionId: {
2334
+ type: 'string',
2335
+ description:
2336
+ 'Resolution ID for undo. Present only on successful items (failed items stay PENDING).'
2337
+ },
2338
+ messageKey: {
2339
+ type: 'string',
2340
+ description:
2341
+ 'i18n message key for the per-item failure reason (e.g., review.payee.error.no_suggestion), mirroring the single-item resolve response. Present only on resolver rejections, not on unexpected errors.'
2342
+ },
2343
+ messageParams: {
2344
+ type: 'object',
2345
+ description:
2346
+ 'Parameters for message interpolation (e.g., { name: "PayeeName" })',
2347
+ additionalProperties: {
2348
+ type: 'string'
2349
+ }
2350
+ },
2351
+ error: {
2352
+ type: 'string',
2353
+ description:
2354
+ 'Diagnostic string: the messageKey on the resolver-rejection path; an i18n key mapped from the exception type on the unexpected-error path (#903, raw exception detail stays in server logs).'
2355
+ }
2356
+ },
2357
+ required: ['reviewId', 'success']
2358
+ } as const;
2359
+
1978
2360
  export const $BatchResolveResultDto = {
1979
2361
  type: 'object',
1980
2362
  properties: {
@@ -1990,7 +2372,7 @@ export const $BatchResolveResultDto = {
1990
2372
  description: 'Details for each item',
1991
2373
  type: 'array',
1992
2374
  items: {
1993
- type: 'string'
2375
+ $ref: '#/components/schemas/BatchResolveItemDto'
1994
2376
  }
1995
2377
  }
1996
2378
  },
@@ -2223,10 +2605,10 @@ export const $UpdatePayeeDto = {
2223
2605
  meta: {
2224
2606
  type: 'object',
2225
2607
  description:
2226
- 'Metadata for extended information (location, notes, contact info, etc.). Will merge with existing metadata.',
2608
+ 'Metadata for extended information (location, notes, contact info, etc.)',
2227
2609
  example: {
2228
2610
  location: 'Zhongguancun',
2229
- note: 'Updated note',
2611
+ note: 'Near subway station',
2230
2612
  favorite: true
2231
2613
  }
2232
2614
  },
@@ -2787,170 +3169,661 @@ export const $UpdateCommodityDto = {
2787
3169
  }
2788
3170
  } as const;
2789
3171
 
2790
- export const $CreateBeanPriceDto = {
3172
+ export const $CurrencyBalanceDto = {
2791
3173
  type: 'object',
2792
3174
  properties: {
2793
3175
  currency: {
2794
3176
  type: 'string',
2795
- description: 'Currency being priced (e.g., USD, AAPL, BTC)',
2796
- example: 'USD'
2797
- },
2798
- quoteCurrency: {
2799
- type: 'string',
2800
- description: 'Quote currency (pricing currency, e.g., CNY, EUR)',
3177
+ description: 'ISO 4217 currency code',
2801
3178
  example: 'CNY'
2802
3179
  },
2803
- amount: {
2804
- type: 'number',
2805
- description:
2806
- 'Price amount (MUST be >= 0 per Beancount spec, supports up to 15 decimal places). Zero allowed for conversion entries, negative strictly prohibited.',
2807
- example: 175.5,
2808
- minimum: 0
2809
- },
2810
- date: {
3180
+ balance: {
2811
3181
  type: 'string',
2812
- description: 'Price date (ISO 8601 format)',
2813
- example: '2024-11-05'
2814
- },
2815
- metadata: {
2816
- type: 'object',
2817
- description:
2818
- 'Metadata (validated by Zod schema, max field lengths enforced)',
2819
- example: {
2820
- source: 'MANUAL',
2821
- note: 'Bank valuation report',
2822
- confidence: 0.95
2823
- }
3182
+ description: 'Balance amount',
3183
+ example: '500000.00'
2824
3184
  }
2825
3185
  },
2826
- required: ['currency', 'quoteCurrency', 'amount', 'date']
3186
+ required: ['currency', 'balance']
2827
3187
  } as const;
2828
3188
 
2829
- export const $PriceResponseDto = {
3189
+ export const $TimeSeriesPointDto = {
2830
3190
  type: 'object',
2831
3191
  properties: {
2832
- id: {
3192
+ date: {
2833
3193
  type: 'string',
2834
- description: 'Unique identifier',
2835
- example: 'uuid-123-456'
3194
+ description: 'Date in YYYY-MM-DD format',
3195
+ example: '2024-06-15'
2836
3196
  },
2837
- userId: {
3197
+ value: {
2838
3198
  type: 'string',
2839
- description: 'User ID (owner of the price)',
2840
- example: 'user-123'
3199
+ description: 'Value at this date (in base currency)',
3200
+ example: '500000.00'
2841
3201
  },
2842
- currency: {
3202
+ change: {
2843
3203
  type: 'string',
2844
- description: 'Currency being priced (e.g., USD, AAPL, BTC)',
2845
- example: 'BTC'
3204
+ description: 'Change from previous point',
3205
+ example: '5000.00'
2846
3206
  },
2847
- quoteCurrency: {
3207
+ assets: {
2848
3208
  type: 'string',
2849
- description: 'Quote currency (pricing currency, e.g., USD, CNY)',
2850
- example: 'USD'
2851
- },
2852
- amount: {
2853
- type: 'number',
2854
- description:
2855
- 'Price amount (corresponds to Beancount Amount.number). Supports up to 15 decimal places.',
2856
- example: 50000
3209
+ description: 'Total assets at this date (in base currency)',
3210
+ example: '494338.00'
2857
3211
  },
2858
- date: {
3212
+ liabilities: {
2859
3213
  type: 'string',
2860
- description:
2861
- 'Price date (ISO 8601 format). Represents the date this price was valid.',
2862
- example: '2024-01-01',
2863
- format: 'date'
3214
+ description: 'Total liabilities at this date (in base currency)',
3215
+ example: '310098.00'
2864
3216
  },
2865
- meta: {
2866
- type: 'object',
2867
- description:
2868
- 'Metadata (corresponds to Beancount meta field). Contains source, confidence, note, etc.',
2869
- example: {
2870
- source: 'MANUAL',
2871
- note: 'User-defined price',
2872
- confidence: 1
3217
+ byCurrency: {
3218
+ description: 'Multi-currency breakdown for this point',
3219
+ type: 'array',
3220
+ items: {
3221
+ $ref: '#/components/schemas/CurrencyBalanceDto'
2873
3222
  }
3223
+ }
3224
+ },
3225
+ required: ['date', 'value']
3226
+ } as const;
3227
+
3228
+ export const $TrendSummaryDto = {
3229
+ type: 'object',
3230
+ properties: {
3231
+ startValue: {
3232
+ type: 'string',
3233
+ description: 'Value at start of period',
3234
+ example: '450000.00'
2874
3235
  },
2875
- createdAt: {
2876
- format: 'date-time',
3236
+ endValue: {
2877
3237
  type: 'string',
2878
- description: 'Creation timestamp',
2879
- example: '2024-11-03T10:00:00Z'
3238
+ description: 'Value at end of period',
3239
+ example: '500000.00'
2880
3240
  },
2881
- updatedAt: {
2882
- format: 'date-time',
3241
+ totalChange: {
2883
3242
  type: 'string',
2884
- description: 'Last update timestamp',
2885
- example: '2024-11-03T10:00:00Z'
3243
+ description: 'Total change over period',
3244
+ example: '50000.00'
3245
+ },
3246
+ totalChangePercentage: {
3247
+ type: 'string',
3248
+ description: 'Total change percentage',
3249
+ example: '+11.11%'
2886
3250
  }
2887
3251
  },
2888
- required: [
2889
- 'id',
2890
- 'userId',
2891
- 'currency',
2892
- 'quoteCurrency',
2893
- 'amount',
2894
- 'date',
2895
- 'meta',
2896
- 'createdAt',
2897
- 'updatedAt'
2898
- ]
3252
+ required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
2899
3253
  } as const;
2900
3254
 
2901
- export const $PriceListResponseDto = {
3255
+ export const $MultiCurrencyPointDto = {
2902
3256
  type: 'object',
2903
3257
  properties: {
2904
- items: {
2905
- description: 'List of prices',
3258
+ date: {
3259
+ type: 'string',
3260
+ description: 'Date in YYYY-MM-DD format',
3261
+ example: '2024-06-15'
3262
+ },
3263
+ byCurrency: {
3264
+ description: 'Balances by currency',
2906
3265
  type: 'array',
2907
3266
  items: {
2908
- $ref: '#/components/schemas/PriceResponseDto'
3267
+ $ref: '#/components/schemas/CurrencyBalanceDto'
2909
3268
  }
2910
- },
2911
- total: {
2912
- type: 'number',
2913
- description: 'Total number of prices',
2914
- example: 42
2915
3269
  }
2916
3270
  },
2917
- required: ['items', 'total']
3271
+ required: ['date', 'byCurrency']
2918
3272
  } as const;
2919
3273
 
2920
- export const $UpdateBeanPriceDto = {
3274
+ export const $PortfolioTrendsResponseDto = {
2921
3275
  type: 'object',
2922
3276
  properties: {
2923
- currency: {
2924
- type: 'string',
2925
- description: 'Currency being priced'
3277
+ series: {
3278
+ description: 'Time series data points',
3279
+ type: 'array',
3280
+ items: {
3281
+ $ref: '#/components/schemas/TimeSeriesPointDto'
3282
+ }
2926
3283
  },
2927
- quoteCurrency: {
3284
+ summary: {
3285
+ description: 'Period summary',
3286
+ allOf: [
3287
+ {
3288
+ $ref: '#/components/schemas/TrendSummaryDto'
3289
+ }
3290
+ ]
3291
+ },
3292
+ period: {
2928
3293
  type: 'string',
2929
- description: 'Quote currency (pricing currency)'
3294
+ description: 'Period requested',
3295
+ example: '6m'
2930
3296
  },
2931
- amount: {
2932
- type: 'number',
2933
- description: 'Price amount (MUST be >= 0 per Beancount spec)',
2934
- minimum: 0
3297
+ granularity: {
3298
+ type: 'string',
3299
+ description: 'Data granularity',
3300
+ example: 'month'
2935
3301
  },
2936
- date: {
3302
+ currency: {
2937
3303
  type: 'string',
2938
- description: 'Price date (ISO 8601 format)'
3304
+ description: 'Base currency for converted values',
3305
+ example: 'CNY'
2939
3306
  },
2940
- metadata: {
2941
- type: 'object',
2942
- description: 'Metadata'
3307
+ byCurrency: {
3308
+ description:
3309
+ 'Multi-currency time series (each point has currency breakdown)',
3310
+ type: 'array',
3311
+ items: {
3312
+ $ref: '#/components/schemas/MultiCurrencyPointDto'
3313
+ }
3314
+ },
3315
+ warnings: {
3316
+ description: 'Exchange rate warnings',
3317
+ type: 'array',
3318
+ items: {
3319
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
3320
+ }
2943
3321
  }
2944
- }
3322
+ },
3323
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
2945
3324
  } as const;
2946
3325
 
2947
- export const $CreateRecurringRuleDto = {
3326
+ export const $CashFlowPointDto = {
2948
3327
  type: 'object',
2949
3328
  properties: {
2950
- name: {
3329
+ month: {
2951
3330
  type: 'string',
2952
- description: 'Rule name (unique per user)',
2953
- maxLength: 100
3331
+ description: 'Month key (YYYY-MM)',
3332
+ example: '2024-03'
3333
+ },
3334
+ income: {
3335
+ type: 'string',
3336
+ description: 'Income in base currency (absolute, converted)',
3337
+ example: '10000.00'
3338
+ },
3339
+ expense: {
3340
+ type: 'string',
3341
+ description: 'Expense in base currency (absolute, converted)',
3342
+ example: '5000.00'
3343
+ },
3344
+ netSavings: {
3345
+ type: 'string',
3346
+ description: 'netSavings = income − expense (savings positive)',
3347
+ example: '5000.00'
3348
+ }
3349
+ },
3350
+ required: ['month', 'income', 'expense', 'netSavings']
3351
+ } as const;
3352
+
3353
+ export const $CashFlowTrendSummaryDto = {
3354
+ type: 'object',
3355
+ properties: {
3356
+ totalIncome: {
3357
+ type: 'string',
3358
+ description: 'Total income across the period',
3359
+ example: '60000.00'
3360
+ },
3361
+ totalExpense: {
3362
+ type: 'string',
3363
+ description: 'Total expense across the period',
3364
+ example: '30000.00'
3365
+ },
3366
+ totalNetSavings: {
3367
+ type: 'string',
3368
+ description: 'income − expense across the period',
3369
+ example: '30000.00'
3370
+ },
3371
+ averageMonthlyNetSavings: {
3372
+ type: 'string',
3373
+ description:
3374
+ 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
3375
+ example: '5000.00'
3376
+ }
3377
+ },
3378
+ required: [
3379
+ 'totalIncome',
3380
+ 'totalExpense',
3381
+ 'totalNetSavings',
3382
+ 'averageMonthlyNetSavings'
3383
+ ]
3384
+ } as const;
3385
+
3386
+ export const $CashFlowTrendsResponseDto = {
3387
+ type: 'object',
3388
+ properties: {
3389
+ series: {
3390
+ description:
3391
+ 'Monthly cash-flow series (fixed N-month window, zero-filled)',
3392
+ type: 'array',
3393
+ items: {
3394
+ $ref: '#/components/schemas/CashFlowPointDto'
3395
+ }
3396
+ },
3397
+ summary: {
3398
+ description: 'Period totals',
3399
+ allOf: [
3400
+ {
3401
+ $ref: '#/components/schemas/CashFlowTrendSummaryDto'
3402
+ }
3403
+ ]
3404
+ },
3405
+ period: {
3406
+ type: 'string',
3407
+ description: 'Period requested',
3408
+ example: '6m'
3409
+ },
3410
+ granularity: {
3411
+ type: 'string',
3412
+ description: 'Data granularity (v1 returns month buckets)',
3413
+ example: 'month'
3414
+ },
3415
+ currency: {
3416
+ type: 'string',
3417
+ description: 'Base currency for converted values',
3418
+ example: 'CNY'
3419
+ },
3420
+ warnings: {
3421
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
3422
+ type: 'array',
3423
+ items: {
3424
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
3425
+ }
3426
+ }
3427
+ },
3428
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
3429
+ } as const;
3430
+
3431
+ export const $GenerateSnapshotBody = {
3432
+ type: 'object',
3433
+ properties: {}
3434
+ } as const;
3435
+
3436
+ export const $GenerateSnapshotResponse = {
3437
+ type: 'object',
3438
+ properties: {}
3439
+ } as const;
3440
+
3441
+ export const $BackfillSnapshotsBody = {
3442
+ type: 'object',
3443
+ properties: {}
3444
+ } as const;
3445
+
3446
+ export const $BackfillSnapshotsResponse = {
3447
+ type: 'object',
3448
+ properties: {}
3449
+ } as const;
3450
+
3451
+ export const $CreateBeanPriceDto = {
3452
+ type: 'object',
3453
+ properties: {
3454
+ currency: {
3455
+ type: 'string',
3456
+ description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3457
+ example: 'USD'
3458
+ },
3459
+ quoteCurrency: {
3460
+ type: 'string',
3461
+ description: 'Quote currency (pricing currency, e.g., CNY, EUR)',
3462
+ example: 'CNY'
3463
+ },
3464
+ amount: {
3465
+ type: 'number',
3466
+ description:
3467
+ 'Price amount (MUST be >= 0 per Beancount spec, supports up to 15 decimal places). Zero allowed for conversion entries, negative strictly prohibited.',
3468
+ example: 175.5,
3469
+ minimum: 0
3470
+ },
3471
+ date: {
3472
+ type: 'string',
3473
+ description: 'Price date (ISO 8601 format)',
3474
+ example: '2024-11-05'
3475
+ },
3476
+ metadata: {
3477
+ type: 'object',
3478
+ description:
3479
+ 'Metadata (validated by Zod schema, max field lengths enforced)',
3480
+ example: {
3481
+ source: 'MANUAL',
3482
+ note: 'Bank valuation report',
3483
+ confidence: 0.95
3484
+ }
3485
+ }
3486
+ },
3487
+ required: ['currency', 'quoteCurrency', 'amount', 'date']
3488
+ } as const;
3489
+
3490
+ export const $PriceResponseDto = {
3491
+ type: 'object',
3492
+ properties: {
3493
+ id: {
3494
+ type: 'string',
3495
+ description: 'Unique identifier',
3496
+ example: 'uuid-123-456'
3497
+ },
3498
+ userId: {
3499
+ type: 'string',
3500
+ description: 'User ID (owner of the price)',
3501
+ example: 'user-123'
3502
+ },
3503
+ currency: {
3504
+ type: 'string',
3505
+ description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3506
+ example: 'BTC'
3507
+ },
3508
+ quoteCurrency: {
3509
+ type: 'string',
3510
+ description: 'Quote currency (pricing currency, e.g., USD, CNY)',
3511
+ example: 'USD'
3512
+ },
3513
+ amount: {
3514
+ type: 'number',
3515
+ description:
3516
+ 'Price amount (corresponds to Beancount Amount.number). Supports up to 15 decimal places.',
3517
+ example: 50000
3518
+ },
3519
+ date: {
3520
+ type: 'string',
3521
+ description:
3522
+ 'Price date (ISO 8601 format). Represents the date this price was valid.',
3523
+ example: '2024-01-01',
3524
+ format: 'date'
3525
+ },
3526
+ meta: {
3527
+ type: 'object',
3528
+ description:
3529
+ 'Metadata (corresponds to Beancount meta field). Contains source, confidence, note, etc.',
3530
+ example: {
3531
+ source: 'MANUAL',
3532
+ note: 'User-defined price',
3533
+ confidence: 1
3534
+ }
3535
+ },
3536
+ createdAt: {
3537
+ format: 'date-time',
3538
+ type: 'string',
3539
+ description: 'Creation timestamp',
3540
+ example: '2024-11-03T10:00:00Z'
3541
+ },
3542
+ updatedAt: {
3543
+ format: 'date-time',
3544
+ type: 'string',
3545
+ description: 'Last update timestamp',
3546
+ example: '2024-11-03T10:00:00Z'
3547
+ }
3548
+ },
3549
+ required: [
3550
+ 'id',
3551
+ 'userId',
3552
+ 'currency',
3553
+ 'quoteCurrency',
3554
+ 'amount',
3555
+ 'date',
3556
+ 'meta',
3557
+ 'createdAt',
3558
+ 'updatedAt'
3559
+ ]
3560
+ } as const;
3561
+
3562
+ export const $PriceListResponseDto = {
3563
+ type: 'object',
3564
+ properties: {
3565
+ items: {
3566
+ description: 'List of prices',
3567
+ type: 'array',
3568
+ items: {
3569
+ $ref: '#/components/schemas/PriceResponseDto'
3570
+ }
3571
+ },
3572
+ total: {
3573
+ type: 'number',
3574
+ description: 'Total number of prices',
3575
+ example: 42
3576
+ }
3577
+ },
3578
+ required: ['items', 'total']
3579
+ } as const;
3580
+
3581
+ export const $UpdateBeanPriceDto = {
3582
+ type: 'object',
3583
+ properties: {
3584
+ currency: {
3585
+ type: 'string',
3586
+ description: 'Currency being priced'
3587
+ },
3588
+ quoteCurrency: {
3589
+ type: 'string',
3590
+ description: 'Quote currency (pricing currency)'
3591
+ },
3592
+ amount: {
3593
+ type: 'number',
3594
+ description: 'Price amount (MUST be >= 0 per Beancount spec)',
3595
+ minimum: 0
3596
+ },
3597
+ date: {
3598
+ type: 'string',
3599
+ description: 'Price date (ISO 8601 format)'
3600
+ },
3601
+ metadata: {
3602
+ type: 'object',
3603
+ description: 'Metadata'
3604
+ }
3605
+ }
3606
+ } as const;
3607
+
3608
+ export const $DeleteOwnUserDto = {
3609
+ type: 'object',
3610
+ properties: {
3611
+ accessToken: {
3612
+ type: 'string',
3613
+ description: 'Access token for user verification',
3614
+ example: 'abc123xyz'
3615
+ }
3616
+ },
3617
+ required: ['accessToken']
3618
+ } as const;
3619
+
3620
+ export const $UserSettingsResponseDto = {
3621
+ type: 'object',
3622
+ properties: {
3623
+ baseCurrency: {
3624
+ type: 'string',
3625
+ description:
3626
+ 'Stored base currency choice (ISO 4217) for net-worth/report aggregation. null = user never chose; aggregates fall back to the region default at display time (#713).',
3627
+ example: 'USD',
3628
+ nullable: true
3629
+ }
3630
+ },
3631
+ required: ['baseCurrency']
3632
+ } as const;
3633
+
3634
+ export const $UserResponseDto = {
3635
+ type: 'object',
3636
+ properties: {
3637
+ id: {
3638
+ type: 'string',
3639
+ description: 'User ID'
3640
+ },
3641
+ role: {
3642
+ type: 'string',
3643
+ description: 'Assigned user role'
3644
+ },
3645
+ permissions: {
3646
+ description: 'Permission strings',
3647
+ type: 'array',
3648
+ items: {
3649
+ type: 'string'
3650
+ }
3651
+ },
3652
+ settings: {
3653
+ description: 'User settings',
3654
+ allOf: [
3655
+ {
3656
+ $ref: '#/components/schemas/UserSettingsResponseDto'
3657
+ }
3658
+ ]
3659
+ }
3660
+ },
3661
+ required: ['id', 'role', 'permissions', 'settings']
3662
+ } as const;
3663
+
3664
+ export const $SignupDto = {
3665
+ type: 'object',
3666
+ properties: {
3667
+ turnstileToken: {
3668
+ type: 'string',
3669
+ description:
3670
+ 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
3671
+ example: '0.abc123def456...'
3672
+ }
3673
+ }
3674
+ } as const;
3675
+
3676
+ export const $SignupResponseDto = {
3677
+ type: 'object',
3678
+ properties: {
3679
+ authToken: {
3680
+ type: 'string',
3681
+ description: 'JWT auth token',
3682
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
3683
+ },
3684
+ accessToken: {
3685
+ type: 'string',
3686
+ description: 'Auto-generated access token'
3687
+ },
3688
+ role: {
3689
+ type: 'string',
3690
+ description: 'Assigned user role',
3691
+ enum: ['USER', 'ADMIN', 'DEMO', 'INACTIVE', 'PAID', 'OPS']
3692
+ }
3693
+ },
3694
+ required: ['authToken', 'accessToken', 'role']
3695
+ } as const;
3696
+
3697
+ export const $UpdateUserSettingDto = {
3698
+ type: 'object',
3699
+ properties: {
3700
+ secId: {
3701
+ type: 'number',
3702
+ description: 'Security ID'
3703
+ },
3704
+ annualInterestRate: {
3705
+ type: 'number',
3706
+ description: 'Annual interest rate',
3707
+ example: 0.05
3708
+ },
3709
+ currency: {
3710
+ type: 'string',
3711
+ description: 'Currency code',
3712
+ example: 'USD'
3713
+ },
3714
+ baseCurrency: {
3715
+ type: 'string',
3716
+ description: 'Base currency code',
3717
+ example: 'USD'
3718
+ },
3719
+ benchmark: {
3720
+ type: 'string',
3721
+ description: 'Benchmark symbol',
3722
+ example: 'SPY'
3723
+ },
3724
+ colorScheme: {
3725
+ type: 'string',
3726
+ description: 'Color scheme',
3727
+ enum: ['DARK', 'LIGHT']
3728
+ },
3729
+ dateRange: {
3730
+ type: 'string',
3731
+ description: 'Date range filter',
3732
+ example: '1y'
3733
+ },
3734
+ emergencyFund: {
3735
+ type: 'number',
3736
+ description: 'Emergency fund amount',
3737
+ example: 10000
3738
+ },
3739
+ 'filters.accounts': {
3740
+ description: 'Account filter IDs',
3741
+ type: 'array',
3742
+ items: {
3743
+ type: 'string'
3744
+ }
3745
+ },
3746
+ 'filters.assetClasses': {
3747
+ description: 'Asset class filters',
3748
+ type: 'array',
3749
+ items: {
3750
+ type: 'string'
3751
+ }
3752
+ },
3753
+ 'filters.dataSource': {
3754
+ type: 'string',
3755
+ description: 'Data source filter'
3756
+ },
3757
+ 'filters.symbol': {
3758
+ type: 'string',
3759
+ description: 'Symbol filter'
3760
+ },
3761
+ 'filters.tags': {
3762
+ description: 'Tag filters',
3763
+ type: 'array',
3764
+ items: {
3765
+ type: 'string'
3766
+ }
3767
+ },
3768
+ isExperimentalFeatures: {
3769
+ type: 'boolean',
3770
+ description: 'Enable experimental features'
3771
+ },
3772
+ isRestrictedView: {
3773
+ type: 'boolean',
3774
+ description: 'Enable restricted view mode'
3775
+ },
3776
+ language: {
3777
+ type: 'string',
3778
+ description: 'Language code',
3779
+ example: 'en'
3780
+ },
3781
+ locale: {
3782
+ type: 'string',
3783
+ description: 'Locale code',
3784
+ example: 'en-US'
3785
+ },
3786
+ projectedTotalAmount: {
3787
+ type: 'number',
3788
+ description: 'Projected total amount',
3789
+ example: 1000000
3790
+ },
3791
+ retirementDate: {
3792
+ type: 'string',
3793
+ description: 'Retirement date in ISO 8601 format',
3794
+ example: '2050-01-01'
3795
+ },
3796
+ savingsRate: {
3797
+ type: 'number',
3798
+ description: 'Savings rate percentage',
3799
+ example: 0.2
3800
+ },
3801
+ viewMode: {
3802
+ type: 'string',
3803
+ description: 'View mode',
3804
+ enum: ['DEFAULT', 'ZEN']
3805
+ }
3806
+ }
3807
+ } as const;
3808
+
3809
+ export const $UpdatePropertyDto = {
3810
+ type: 'object',
3811
+ properties: {
3812
+ value: {
3813
+ type: 'string',
3814
+ description: 'Property value'
3815
+ }
3816
+ },
3817
+ required: ['value']
3818
+ } as const;
3819
+
3820
+ export const $CreateRecurringRuleDto = {
3821
+ type: 'object',
3822
+ properties: {
3823
+ name: {
3824
+ type: 'string',
3825
+ description: 'Rule name (unique per user)',
3826
+ maxLength: 100
2954
3827
  },
2955
3828
  icon: {
2956
3829
  type: 'string',
@@ -2989,7 +3862,6 @@ export const $CreateRecurringRuleDto = {
2989
3862
  currency: {
2990
3863
  type: 'string',
2991
3864
  description: 'Currency code',
2992
- default: 'CNY',
2993
3865
  maxLength: 10
2994
3866
  },
2995
3867
  matchPayeePattern: {
@@ -3037,7 +3909,6 @@ export const $CreateRecurringRuleDto = {
3037
3909
  'name',
3038
3910
  'frequency',
3039
3911
  'expectedAmount',
3040
- 'currency',
3041
3912
  'matchAmountTolerance',
3042
3913
  'autoCreate'
3043
3914
  ]
@@ -3059,7 +3930,7 @@ export const $RecurringRuleResponseDto = {
3059
3930
  description: 'Rule name'
3060
3931
  },
3061
3932
  icon: {
3062
- type: 'object',
3933
+ type: 'string',
3063
3934
  description: 'Icon emoji'
3064
3935
  },
3065
3936
  frequency: {
@@ -3071,11 +3942,11 @@ export const $RecurringRuleResponseDto = {
3071
3942
  description: 'Expected amount'
3072
3943
  },
3073
3944
  expectedDay: {
3074
- type: 'object',
3945
+ type: 'number',
3075
3946
  description: 'Expected day of month'
3076
3947
  },
3077
3948
  customIntervalDays: {
3078
- type: 'object',
3949
+ type: 'number',
3079
3950
  description: 'Custom interval in days'
3080
3951
  },
3081
3952
  currency: {
@@ -3083,7 +3954,7 @@ export const $RecurringRuleResponseDto = {
3083
3954
  description: 'Currency code'
3084
3955
  },
3085
3956
  matchPayeePattern: {
3086
- type: 'object',
3957
+ type: 'string',
3087
3958
  description: 'Payee matching pattern'
3088
3959
  },
3089
3960
  matchAmountTolerance: {
@@ -3091,15 +3962,15 @@ export const $RecurringRuleResponseDto = {
3091
3962
  description: 'Amount tolerance percentage'
3092
3963
  },
3093
3964
  defaultExpenseAccount: {
3094
- type: 'object',
3965
+ type: 'string',
3095
3966
  description: 'Default expense account'
3096
3967
  },
3097
3968
  defaultPaymentAccount: {
3098
- type: 'object',
3969
+ type: 'string',
3099
3970
  description: 'Default payment account'
3100
3971
  },
3101
3972
  defaultPayee: {
3102
- type: 'object',
3973
+ type: 'string',
3103
3974
  description: 'Default payee'
3104
3975
  },
3105
3976
  isActive: {
@@ -3111,7 +3982,7 @@ export const $RecurringRuleResponseDto = {
3111
3982
  description: 'Rule start date (YYYY-MM-DD)'
3112
3983
  },
3113
3984
  endDate: {
3114
- type: 'object',
3985
+ type: 'string',
3115
3986
  description: 'Rule end date (YYYY-MM-DD)'
3116
3987
  },
3117
3988
  autoCreate: {
@@ -3119,7 +3990,7 @@ export const $RecurringRuleResponseDto = {
3119
3990
  description: 'Auto-create transaction on expected date'
3120
3991
  },
3121
3992
  lastOccurrence: {
3122
- type: 'object',
3993
+ type: 'string',
3123
3994
  description: 'Last matched occurrence date (YYYY-MM-DD)'
3124
3995
  },
3125
3996
  totalCount: {
@@ -3201,7 +4072,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3201
4072
  description: 'Rule name'
3202
4073
  },
3203
4074
  icon: {
3204
- type: 'object',
4075
+ type: 'string',
3205
4076
  description: 'Icon emoji'
3206
4077
  },
3207
4078
  frequency: {
@@ -3213,11 +4084,11 @@ export const $RecurringRuleWithStatsResponseDto = {
3213
4084
  description: 'Expected amount'
3214
4085
  },
3215
4086
  expectedDay: {
3216
- type: 'object',
4087
+ type: 'number',
3217
4088
  description: 'Expected day of month'
3218
4089
  },
3219
4090
  customIntervalDays: {
3220
- type: 'object',
4091
+ type: 'number',
3221
4092
  description: 'Custom interval in days'
3222
4093
  },
3223
4094
  currency: {
@@ -3225,7 +4096,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3225
4096
  description: 'Currency code'
3226
4097
  },
3227
4098
  matchPayeePattern: {
3228
- type: 'object',
4099
+ type: 'string',
3229
4100
  description: 'Payee matching pattern'
3230
4101
  },
3231
4102
  matchAmountTolerance: {
@@ -3233,15 +4104,15 @@ export const $RecurringRuleWithStatsResponseDto = {
3233
4104
  description: 'Amount tolerance percentage'
3234
4105
  },
3235
4106
  defaultExpenseAccount: {
3236
- type: 'object',
4107
+ type: 'string',
3237
4108
  description: 'Default expense account'
3238
4109
  },
3239
4110
  defaultPaymentAccount: {
3240
- type: 'object',
4111
+ type: 'string',
3241
4112
  description: 'Default payment account'
3242
4113
  },
3243
4114
  defaultPayee: {
3244
- type: 'object',
4115
+ type: 'string',
3245
4116
  description: 'Default payee'
3246
4117
  },
3247
4118
  isActive: {
@@ -3253,7 +4124,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3253
4124
  description: 'Rule start date (YYYY-MM-DD)'
3254
4125
  },
3255
4126
  endDate: {
3256
- type: 'object',
4127
+ type: 'string',
3257
4128
  description: 'Rule end date (YYYY-MM-DD)'
3258
4129
  },
3259
4130
  autoCreate: {
@@ -3261,7 +4132,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3261
4132
  description: 'Auto-create transaction on expected date'
3262
4133
  },
3263
4134
  lastOccurrence: {
3264
- type: 'object',
4135
+ type: 'string',
3265
4136
  description: 'Last matched occurrence date (YYYY-MM-DD)'
3266
4137
  },
3267
4138
  totalCount: {
@@ -3287,7 +4158,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3287
4158
  description: 'Number of overdue expected transactions'
3288
4159
  },
3289
4160
  nextExpectedDate: {
3290
- type: 'object',
4161
+ type: 'string',
3291
4162
  description: 'Next expected date (YYYY-MM-DD)'
3292
4163
  },
3293
4164
  totalAmount: {
@@ -3303,11 +4174,11 @@ export const $RecurringRuleWithStatsResponseDto = {
3303
4174
  description: 'Number of matched transactions'
3304
4175
  },
3305
4176
  firstDate: {
3306
- type: 'object',
4177
+ type: 'string',
3307
4178
  description: 'First matched transaction date (YYYY-MM-DD)'
3308
4179
  },
3309
4180
  lastDate: {
3310
- type: 'object',
4181
+ type: 'string',
3311
4182
  description: 'Last matched transaction date (YYYY-MM-DD)'
3312
4183
  },
3313
4184
  variance: {
@@ -3348,7 +4219,7 @@ export const $UpdateRecurringRuleDto = {
3348
4219
  properties: {
3349
4220
  name: {
3350
4221
  type: 'string',
3351
- description: 'Rule name',
4222
+ description: 'Rule name (unique per user)',
3352
4223
  maxLength: 100
3353
4224
  },
3354
4225
  icon: {
@@ -3371,7 +4242,7 @@ export const $UpdateRecurringRuleDto = {
3371
4242
  },
3372
4243
  expectedAmount: {
3373
4244
  type: 'number',
3374
- description: 'Expected amount',
4245
+ description: 'Expected amount (positive number)',
3375
4246
  minimum: 0
3376
4247
  },
3377
4248
  expectedDay: {
@@ -3380,11 +4251,6 @@ export const $UpdateRecurringRuleDto = {
3380
4251
  minimum: 1,
3381
4252
  maximum: 31
3382
4253
  },
3383
- customIntervalDays: {
3384
- type: 'number',
3385
- description: 'Custom interval in days',
3386
- minimum: 1
3387
- },
3388
4254
  currency: {
3389
4255
  type: 'string',
3390
4256
  description: 'Currency code',
@@ -3392,41 +4258,48 @@ export const $UpdateRecurringRuleDto = {
3392
4258
  },
3393
4259
  matchPayeePattern: {
3394
4260
  type: 'string',
3395
- description: 'Payee matching pattern',
4261
+ description: 'Payee matching pattern (supports wildcards)',
3396
4262
  maxLength: 200
3397
4263
  },
3398
4264
  matchAmountTolerance: {
3399
4265
  type: 'number',
3400
4266
  description: 'Amount tolerance percentage (0-1)',
4267
+ default: 0.075,
3401
4268
  minimum: 0,
3402
4269
  maximum: 1
3403
4270
  },
3404
4271
  defaultExpenseAccount: {
3405
4272
  type: 'string',
3406
- description: 'Default expense account',
4273
+ description: 'Default expense account for auto-create',
3407
4274
  maxLength: 200
3408
4275
  },
3409
4276
  defaultPaymentAccount: {
3410
4277
  type: 'string',
3411
- description: 'Default payment account',
4278
+ description: 'Default payment account for auto-create',
3412
4279
  maxLength: 200
3413
4280
  },
3414
4281
  defaultPayee: {
3415
4282
  type: 'string',
3416
- description: 'Default payee',
4283
+ description: 'Default payee for auto-create',
3417
4284
  maxLength: 200
3418
4285
  },
3419
4286
  autoCreate: {
3420
4287
  type: 'boolean',
3421
- description: 'Auto-create transaction'
3422
- },
3423
- isActive: {
3424
- type: 'boolean',
3425
- description: 'Rule active status'
4288
+ description: 'Auto-create transaction when expected date arrives',
4289
+ default: false
3426
4290
  },
3427
4291
  endDate: {
3428
4292
  type: 'string',
3429
4293
  description: 'Rule end date (ISO format)'
4294
+ },
4295
+ customIntervalDays: {
4296
+ type: 'number',
4297
+ description: 'Custom interval in days',
4298
+ minimum: 1
4299
+ },
4300
+ isActive: {
4301
+ type: 'boolean',
4302
+ description: 'Rule active status'
3430
4303
  }
3431
4304
  }
3432
4305
  } as const;
@@ -3439,7 +4312,7 @@ export const $ExpectedTransactionRuleDto = {
3439
4312
  description: 'Rule name'
3440
4313
  },
3441
4314
  icon: {
3442
- type: 'object',
4315
+ type: 'string',
3443
4316
  description: 'Rule icon'
3444
4317
  },
3445
4318
  frequency: {
@@ -3482,15 +4355,15 @@ export const $ExpectedTransactionResponseDto = {
3482
4355
  description: 'Status (PENDING, COMPLETED, SKIPPED)'
3483
4356
  },
3484
4357
  matchedTransactionId: {
3485
- type: 'object',
4358
+ type: 'string',
3486
4359
  description: 'Matched transaction ID'
3487
4360
  },
3488
4361
  matchedAt: {
3489
- type: 'object',
4362
+ type: 'string',
3490
4363
  description: 'Match timestamp (ISO 8601)'
3491
4364
  },
3492
4365
  matchConfidence: {
3493
- type: 'object',
4366
+ type: 'number',
3494
4367
  description: 'Match confidence score (0-1)'
3495
4368
  },
3496
4369
  isOverdue: {
@@ -4274,7 +5147,8 @@ export const $UpdateTransactionRuleDto = {
4274
5147
  },
4275
5148
  matchLogic: {
4276
5149
  type: 'string',
4277
- enum: ['OR', 'AND']
5150
+ enum: ['OR', 'AND'],
5151
+ default: 'OR'
4278
5152
  },
4279
5153
  amountMin: {
4280
5154
  type: 'number',
@@ -4288,13 +5162,10 @@ export const $UpdateTransactionRuleDto = {
4288
5162
  },
4289
5163
  priority: {
4290
5164
  type: 'number',
5165
+ default: 50,
4291
5166
  minimum: 0,
4292
5167
  maximum: 1000
4293
5168
  },
4294
- enabled: {
4295
- type: 'boolean',
4296
- description: 'Enable or disable the rule'
4297
- },
4298
5169
  additionalTags: {
4299
5170
  items: {
4300
5171
  type: 'array'
@@ -4304,6 +5175,10 @@ export const $UpdateTransactionRuleDto = {
4304
5175
  },
4305
5176
  additionalMetadata: {
4306
5177
  type: 'object'
5178
+ },
5179
+ enabled: {
5180
+ type: 'boolean',
5181
+ description: 'Enable or disable the rule'
4307
5182
  }
4308
5183
  }
4309
5184
  } as const;
@@ -4364,151 +5239,81 @@ export const $TestRuleResponseDto = {
4364
5239
  required: ['ruleId', 'matches', 'confidence', 'matchDetails']
4365
5240
  } as const;
4366
5241
 
4367
- export const $DeleteOwnUserDto = {
4368
- type: 'object',
4369
- properties: {
4370
- accessToken: {
4371
- type: 'string',
4372
- description: 'Access token for user verification',
4373
- example: 'abc123xyz'
4374
- }
4375
- },
4376
- required: ['accessToken']
4377
- } as const;
4378
-
4379
- export const $SignupDto = {
4380
- type: 'object',
4381
- properties: {
4382
- turnstileToken: {
4383
- type: 'string',
4384
- description:
4385
- 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
4386
- example: '0.abc123def456...'
4387
- }
4388
- }
4389
- } as const;
4390
-
4391
- export const $UpdateUserSettingDto = {
5242
+ export const $CategoryCatalogEntryDto = {
4392
5243
  type: 'object',
4393
5244
  properties: {
4394
- secId: {
4395
- type: 'number',
4396
- description: 'Security ID'
4397
- },
4398
- annualInterestRate: {
4399
- type: 'number',
4400
- description: 'Annual interest rate',
4401
- example: 0.05
4402
- },
4403
- currency: {
4404
- type: 'string',
4405
- description: 'Currency code',
4406
- example: 'USD'
4407
- },
4408
- baseCurrency: {
4409
- type: 'string',
4410
- description: 'Base currency code',
4411
- example: 'USD'
4412
- },
4413
- benchmark: {
5245
+ slug: {
4414
5246
  type: 'string',
4415
- description: 'Benchmark symbol',
4416
- example: 'SPY'
5247
+ description: 'Category slug (single source-of-truth)',
5248
+ example: 'food'
4417
5249
  },
4418
- colorScheme: {
5250
+ scenario: {
4419
5251
  type: 'string',
4420
- description: 'Color scheme',
4421
- enum: ['DARK', 'LIGHT']
5252
+ description: 'Display scenario group (maps to frontend picker _scenario)',
5253
+ enum: [
5254
+ 'expense',
5255
+ 'income',
5256
+ 'investment',
5257
+ 'banking',
5258
+ 'transfer',
5259
+ 'payment'
5260
+ ],
5261
+ example: 'expense'
4422
5262
  },
4423
- dateRange: {
5263
+ icon: {
4424
5264
  type: 'string',
4425
- description: 'Date range filter',
4426
- example: '1y'
4427
- },
4428
- emergencyFund: {
4429
- type: 'number',
4430
- description: 'Emergency fund amount',
4431
- example: 10000
5265
+ description: 'Lucide icon name',
5266
+ example: 'utensils'
4432
5267
  },
4433
- 'filters.accounts': {
4434
- description: 'Account filter IDs',
5268
+ regions: {
5269
+ description: "Applicable regions ('*' = all, 'cn' = CN-only)",
5270
+ example: ['*'],
4435
5271
  type: 'array',
4436
5272
  items: {
4437
5273
  type: 'string'
4438
5274
  }
4439
5275
  },
4440
- 'filters.assetClasses': {
4441
- description: 'Asset class filters',
5276
+ categoryAccounts: {
5277
+ description:
5278
+ "Beancount account paths (categoryAccount) of the region-enabled system rules whose categoryKeywords include this slug (#816). System rules only (public endpoint — user rules excluded); one-to-many by design (e.g. 'utilities' → Electricity/Water/Internet/Gas), sorted, [] when no rule maps the slug.",
5279
+ example: [
5280
+ 'Expenses:Utilities:Electricity',
5281
+ 'Expenses:Utilities:Gas',
5282
+ 'Expenses:Utilities:Internet',
5283
+ 'Expenses:Utilities:Water'
5284
+ ],
4442
5285
  type: 'array',
4443
5286
  items: {
4444
5287
  type: 'string'
4445
5288
  }
4446
- },
4447
- 'filters.dataSource': {
4448
- type: 'string',
4449
- description: 'Data source filter'
4450
- },
4451
- 'filters.symbol': {
4452
- type: 'string',
4453
- description: 'Symbol filter'
4454
- },
4455
- 'filters.tags': {
4456
- description: 'Tag filters',
5289
+ }
5290
+ },
5291
+ required: ['slug', 'scenario', 'icon', 'regions', 'categoryAccounts']
5292
+ } as const;
5293
+
5294
+ export const $CategoryCatalogListResponseDto = {
5295
+ type: 'object',
5296
+ properties: {
5297
+ items: {
5298
+ description: 'Category entries (region-scoped, query-filtered)',
4457
5299
  type: 'array',
4458
5300
  items: {
4459
- type: 'string'
5301
+ $ref: '#/components/schemas/CategoryCatalogEntryDto'
4460
5302
  }
4461
5303
  },
4462
- isExperimentalFeatures: {
4463
- type: 'boolean',
4464
- description: 'Enable experimental features'
4465
- },
4466
- isRestrictedView: {
4467
- type: 'boolean',
4468
- description: 'Enable restricted view mode'
4469
- },
4470
- language: {
4471
- type: 'string',
4472
- description: 'Language code',
4473
- example: 'en'
4474
- },
4475
- locale: {
4476
- type: 'string',
4477
- description: 'Locale code',
4478
- example: 'en-US'
4479
- },
4480
- projectedTotalAmount: {
4481
- type: 'number',
4482
- description: 'Projected total amount',
4483
- example: 1000000
4484
- },
4485
- retirementDate: {
4486
- type: 'string',
4487
- description: 'Retirement date in ISO 8601 format',
4488
- example: '2050-01-01'
4489
- },
4490
- savingsRate: {
5304
+ total: {
4491
5305
  type: 'number',
4492
- description: 'Savings rate percentage',
4493
- example: 0.2
5306
+ description:
5307
+ 'Total category entries for the region (before query filtering)',
5308
+ example: 30
4494
5309
  },
4495
- viewMode: {
4496
- type: 'string',
4497
- description: 'View mode',
4498
- enum: ['DEFAULT', 'ZEN']
4499
- }
4500
- }
4501
- } as const;
4502
-
4503
- export const $UpdatePropertyDto = {
4504
- type: 'object',
4505
- properties: {
4506
- value: {
5310
+ region: {
4507
5311
  type: 'string',
4508
- description: 'Property value'
5312
+ description: 'Region code',
5313
+ example: 'cn'
4509
5314
  }
4510
5315
  },
4511
- required: ['value']
5316
+ required: ['items', 'total', 'region']
4512
5317
  } as const;
4513
5318
 
4514
5319
  export const $CreateBeanEventDto = {
@@ -4674,6 +5479,14 @@ export const $OnboardingAccountDto = {
4674
5479
  description:
4675
5480
  'Platform ID to bind the account to (references Platform.id); omit for unbound',
4676
5481
  example: 'c98e5d4a-2f71-4a5a-bb3c-92c9f231d5e2'
5482
+ },
5483
+ displayName: {
5484
+ type: 'string',
5485
+ description:
5486
+ 'User-set display name override (omit/null = keep the derived name)',
5487
+ nullable: true,
5488
+ maxLength: 50,
5489
+ example: 'Salary card'
4677
5490
  }
4678
5491
  },
4679
5492
  required: ['path', 'currency']
@@ -5253,7 +6066,8 @@ export const $UpdateMapperDefaultsDto = {
5253
6066
  type: 'string',
5254
6067
  description: 'Source account for transactions (Beancount format)',
5255
6068
  example: 'Assets:CN:Alipay:Balance',
5256
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
6069
+ pattern:
6070
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5257
6071
  },
5258
6072
  currency: {
5259
6073
  type: 'string',
@@ -5267,13 +6081,15 @@ export const $UpdateMapperDefaultsDto = {
5267
6081
  type: 'string',
5268
6082
  description: 'Default expense account (optional)',
5269
6083
  example: 'Expenses:Unknown',
5270
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
6084
+ pattern:
6085
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5271
6086
  },
5272
6087
  incomeAccount: {
5273
6088
  type: 'string',
5274
6089
  description: 'Default income account (optional)',
5275
6090
  example: 'Income:Unknown',
5276
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
6091
+ pattern:
6092
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5277
6093
  },
5278
6094
  methodAccountMapping: {
5279
6095
  type: 'object',
@@ -5330,12 +6146,14 @@ export const $ProviderSyncConfigDto = {
5330
6146
  },
5331
6147
  defaultExpenseAccount: {
5332
6148
  type: 'string',
5333
- description: 'Default expense account for the second posting',
6149
+ description:
6150
+ 'Default expense account for the second posting. Omit when no real default exists; the pipeline routes to Review via the Uncategorized sentinel (#618).',
5334
6151
  example: 'Expenses:Unknown'
5335
6152
  },
5336
6153
  defaultIncomeAccount: {
5337
6154
  type: 'string',
5338
- description: 'Default income account for the second posting',
6155
+ description:
6156
+ 'Default income account for the second posting. Omit when no real default exists; the pipeline routes to Review via the Uncategorized sentinel (#618).',
5339
6157
  example: 'Income:Unknown'
5340
6158
  },
5341
6159
  filterPending: {
@@ -5350,12 +6168,7 @@ export const $ProviderSyncConfigDto = {
5350
6168
  example: 'acc_gocardless_001'
5351
6169
  }
5352
6170
  },
5353
- required: [
5354
- 'sourceAccount',
5355
- 'defaultCurrency',
5356
- 'defaultExpenseAccount',
5357
- 'defaultIncomeAccount'
5358
- ]
6171
+ required: ['sourceAccount', 'defaultCurrency']
5359
6172
  } as const;
5360
6173
 
5361
6174
  export const $ProviderSyncDto = {
@@ -5544,25 +6357,109 @@ export const $ExternalAccountLinkListResponseDto = {
5544
6357
  $ref: '#/components/schemas/ExternalAccountLinkResponseDto'
5545
6358
  }
5546
6359
  },
5547
- total: {
5548
- type: 'number'
6360
+ total: {
6361
+ type: 'number'
6362
+ },
6363
+ provider: {
6364
+ type: 'string',
6365
+ description: 'Filter by provider (query param)'
6366
+ }
6367
+ },
6368
+ required: ['items', 'total']
6369
+ } as const;
6370
+
6371
+ export const $ParserTelemetryReportDto = {
6372
+ type: 'object',
6373
+ properties: {}
6374
+ } as const;
6375
+
6376
+ export const $UncoveredFormatMissDto = {
6377
+ type: 'object',
6378
+ properties: {}
6379
+ } as const;
6380
+
6381
+ export const $ClientParsedDataDto = {
6382
+ type: 'object',
6383
+ properties: {
6384
+ amount: {
6385
+ type: 'number',
6386
+ description: 'Transaction amount',
6387
+ example: 35
6388
+ },
6389
+ currency: {
6390
+ type: 'string',
6391
+ description: 'Currency code',
6392
+ example: 'CNY'
6393
+ },
6394
+ date: {
6395
+ type: 'string',
6396
+ description: 'Transaction date (ISO 8601)',
6397
+ example: '2026-08-15'
6398
+ },
6399
+ payee: {
6400
+ type: 'string',
6401
+ description: 'Payee/merchant name',
6402
+ example: 'Starbucks'
6403
+ },
6404
+ narration: {
6405
+ type: 'string',
6406
+ description: 'Transaction narration'
6407
+ },
6408
+ category: {
6409
+ type: 'string',
6410
+ description:
6411
+ 'Category in canonical form (catalog slug or Stage-2 rule keyword token, ADR-0116) — echo back verbatim from parsedData.category. Foreign forms (locale display names, account paths) are rejected with nlp.category.invalid.',
6412
+ example: 'food'
6413
+ },
6414
+ incomeType: {
6415
+ type: 'string',
6416
+ description: 'Income type',
6417
+ example: 'Salary'
6418
+ },
6419
+ incomeSource: {
6420
+ type: 'string',
6421
+ description: 'Income source',
6422
+ example: 'Anthropic Inc.'
6423
+ },
6424
+ symbol: {
6425
+ type: 'string',
6426
+ description: 'Security symbol code (e.g., 600519, AAPL)',
6427
+ example: 'AAPL'
6428
+ },
6429
+ quantity: {
6430
+ type: 'number',
6431
+ description: 'Quantity of shares/units',
6432
+ example: 100
6433
+ },
6434
+ price: {
6435
+ type: 'number',
6436
+ description: 'Unit price per share/unit',
6437
+ example: 1900
6438
+ },
6439
+ investmentAction: {
6440
+ type: 'string',
6441
+ description: 'Investment action',
6442
+ enum: ['buy', 'sell'],
6443
+ example: 'buy'
6444
+ },
6445
+ paymentSource: {
6446
+ type: 'string',
6447
+ description: 'Payment source: asset (default) or liability (credit card)',
6448
+ enum: ['asset', 'liability'],
6449
+ example: 'asset'
5549
6450
  },
5550
- provider: {
6451
+ liabilityHint: {
5551
6452
  type: 'string',
5552
- description: 'Filter by provider (query param)'
6453
+ description: 'Liability account hint (CreditCard/Huabei/Baitiao)',
6454
+ example: 'CreditCard'
6455
+ },
6456
+ warning: {
6457
+ type: 'string',
6458
+ description:
6459
+ 'Display-only warning from the prior response; accepted but ignored.',
6460
+ example: 'Cross-currency settlement applies.'
5553
6461
  }
5554
- },
5555
- required: ['items', 'total']
5556
- } as const;
5557
-
5558
- export const $ParserTelemetryReportDto = {
5559
- type: 'object',
5560
- properties: {}
5561
- } as const;
5562
-
5563
- export const $UncoveredFormatMissDto = {
5564
- type: 'object',
5565
- properties: {}
6462
+ }
5566
6463
  } as const;
5567
6464
 
5568
6465
  export const $ProcessNlpDto = {
@@ -5570,10 +6467,17 @@ export const $ProcessNlpDto = {
5570
6467
  properties: {
5571
6468
  message: {
5572
6469
  type: 'string',
5573
- description: 'Natural language text describing a transaction (Chinese)',
5574
- example: 'yesterday Starbucks spent 35 yuan',
6470
+ description:
6471
+ 'Natural language text describing a transaction. Optional when `confirm` is true (structured confirm); otherwise required.',
6472
+ example: 'Starbucks 35',
5575
6473
  maxLength: 500
5576
6474
  },
6475
+ confirm: {
6476
+ type: 'boolean',
6477
+ description:
6478
+ 'Structured confirm signal — bypasses NL confirm-word matching when true. Send parsedData field edits alongside. The NL word-list path is the fallback.',
6479
+ example: true
6480
+ },
5577
6481
  sessionId: {
5578
6482
  type: 'string',
5579
6483
  description:
@@ -5581,17 +6485,51 @@ export const $ProcessNlpDto = {
5581
6485
  example: 'session_abc123'
5582
6486
  },
5583
6487
  parsedData: {
5584
- type: 'object',
5585
6488
  description:
5586
6489
  'Parsed data from previous NLP response for session recovery. Send back the parsedData received in confirm_payee/confirm responses.',
5587
6490
  example: {
5588
6491
  amount: 35,
5589
6492
  currency: 'CNY',
5590
6493
  payee: 'Starbucks'
5591
- }
6494
+ },
6495
+ allOf: [
6496
+ {
6497
+ $ref: '#/components/schemas/ClientParsedDataDto'
6498
+ }
6499
+ ]
6500
+ },
6501
+ selectedRuleId: {
6502
+ type: 'string',
6503
+ description:
6504
+ 'confirm_rule echo-back: rule id selected from the prior confirm_rule response (matchedRule.id or alternatives[i].ruleId). Applied directly when the session is confirming_rule — no NL re-parse.',
6505
+ example: 'rule_abc123'
6506
+ },
6507
+ selectedAccount: {
6508
+ type: 'string',
6509
+ description:
6510
+ 'confirm_account echo-back: account path selected from the prior confirm_account response (suggestedAccount, similarAccounts[i].path, or a typed path). Applied directly when the session is confirming_account — no NL re-parse.',
6511
+ example: 'Expenses:Food:Coffee'
6512
+ },
6513
+ viewpointAccount: {
6514
+ type: 'string',
6515
+ description:
6516
+ 'Viewpoint account hint: the beancount path the user drilled into (e.g. from an account drill-down). Tie-break only — never overrides accounts resolved from the text. Must be an owned, OPEN Assets:/Liabilities: account; unresolvable hints are silently ignored.',
6517
+ example: 'Assets:CN:Bank:ICBC'
6518
+ },
6519
+ viewpointCategory: {
6520
+ type: 'string',
6521
+ description:
6522
+ "Viewpoint category hint: the ADR-0075 Group segment the user drilled into (e.g. 'Food'). Resolved to a concrete OPEN account in that group; tie-break only — never overrides a category resolved from the text.",
6523
+ example: 'Food'
6524
+ },
6525
+ viewpointFlow: {
6526
+ type: 'string',
6527
+ description:
6528
+ "Companion flow root for viewpointCategory ('income' | 'expense'), mirroring the ADR-0126 list-endpoint invariant. Derived from the session's routed intent (multi-turn) when absent; a first-turn flow-less category hint is dropped — send the flow explicitly.",
6529
+ enum: ['income', 'expense'],
6530
+ example: 'expense'
5592
6531
  }
5593
- },
5594
- required: ['message']
6532
+ }
5595
6533
  } as const;
5596
6534
 
5597
6535
  export const $NlpTransactionInfoDto = {
@@ -5657,7 +6595,9 @@ export const $NlpParsedDataDto = {
5657
6595
  },
5658
6596
  category: {
5659
6597
  type: 'string',
5660
- description: 'Category'
6598
+ description:
6599
+ 'Category in canonical form: a CATEGORY_CATALOG slug (GET /{region}/bean/categories) or a Stage-2 rule categoryKeywords token (ADR-0116 D2). Never a locale display name or a beancount account path. Echo back verbatim on confirm.',
6600
+ example: 'food'
5661
6601
  },
5662
6602
  incomeType: {
5663
6603
  type: 'string',
@@ -5903,6 +6843,24 @@ export const $NlpRuleConfirmationDataDto = {
5903
6843
  ]
5904
6844
  } as const;
5905
6845
 
6846
+ export const $NlpAccountCandidateDto = {
6847
+ type: 'object',
6848
+ properties: {
6849
+ path: {
6850
+ type: 'string',
6851
+ description: 'Canonical beancount account path (echo back on selection)',
6852
+ example: 'Expenses:Food:Dining'
6853
+ },
6854
+ name: {
6855
+ type: 'string',
6856
+ description:
6857
+ 'Localized display name (ADR-0114 read-time projection, user locale)',
6858
+ example: '餐饮'
6859
+ }
6860
+ },
6861
+ required: ['path', 'name']
6862
+ } as const;
6863
+
5906
6864
  export const $NlpAccountConfirmationDataDto = {
5907
6865
  type: 'object',
5908
6866
  properties: {
@@ -5913,14 +6871,16 @@ export const $NlpAccountConfirmationDataDto = {
5913
6871
  },
5914
6872
  suggestedAccount: {
5915
6873
  type: 'string',
5916
- description: 'Suggested replacement account',
6874
+ description:
6875
+ 'Suggested replacement account (omitted when no clear candidate)',
5917
6876
  example: 'Expenses:Food:Drinks'
5918
6877
  },
5919
6878
  similarAccounts: {
5920
- description: 'Similar accounts for user selection',
6879
+ description:
6880
+ 'Similar accounts for user selection (path + localized name, #680)',
5921
6881
  type: 'array',
5922
6882
  items: {
5923
- type: 'string'
6883
+ $ref: '#/components/schemas/NlpAccountCandidateDto'
5924
6884
  }
5925
6885
  },
5926
6886
  errorMessage: {
@@ -5935,7 +6895,6 @@ export const $NlpAccountConfirmationDataDto = {
5935
6895
  },
5936
6896
  required: [
5937
6897
  'invalidAccount',
5938
- 'suggestedAccount',
5939
6898
  'similarAccounts',
5940
6899
  'errorMessage',
5941
6900
  'transactionContext'
@@ -6108,7 +7067,8 @@ export const $NlpSuggestedAccountDto = {
6108
7067
  },
6109
7068
  confidence: {
6110
7069
  type: 'number',
6111
- description: 'Confidence score for this suggestion (0-1)',
7070
+ description:
7071
+ 'Confidence score for this suggestion (0-1). Present = predicted (confirm/confirm_rule/confirm_account); omitted = actual persisted account (created). (#586)',
6112
7072
  example: 0.9
6113
7073
  }
6114
7074
  },
@@ -6144,23 +7104,31 @@ export const $NlpDefaultAccountsDto = {
6144
7104
  properties: {
6145
7105
  asset: {
6146
7106
  type: 'string',
6147
- description: 'Default asset account',
6148
- example: 'Assets:Checking'
7107
+ description:
7108
+ 'Default OPEN asset account (MRU when multiple), or null when none/ambiguous',
7109
+ example: 'Assets:Checking',
7110
+ nullable: true
6149
7111
  },
6150
7112
  expense: {
6151
7113
  type: 'string',
6152
- description: 'Default expense account',
6153
- example: 'Expenses:Uncategorized'
7114
+ description:
7115
+ 'Default OPEN expense account (MRU when multiple), or null when none/ambiguous',
7116
+ example: 'Expenses:Food:Coffee',
7117
+ nullable: true
6154
7118
  },
6155
7119
  income: {
6156
7120
  type: 'string',
6157
- description: 'Default income account',
6158
- example: 'Income:Uncategorized'
7121
+ description:
7122
+ 'Default OPEN income account (MRU when multiple), or null when none/ambiguous',
7123
+ example: 'Income:Salary',
7124
+ nullable: true
6159
7125
  },
6160
7126
  liability: {
6161
7127
  type: 'string',
6162
- description: 'Default liability account',
6163
- example: 'Liabilities:CreditCard'
7128
+ description:
7129
+ 'Default OPEN liability account (MRU when multiple), or null when none/ambiguous',
7130
+ example: 'Liabilities:CreditCard',
7131
+ nullable: true
6164
7132
  }
6165
7133
  },
6166
7134
  required: ['asset', 'expense', 'income', 'liability']
@@ -6185,7 +7153,8 @@ export const $NlpResponseDto = {
6185
7153
  'confirm_rule',
6186
7154
  'confirm_account',
6187
7155
  'confirm_payee',
6188
- 'cancel'
7156
+ 'cancel',
7157
+ 'aborted'
6189
7158
  ]
6190
7159
  },
6191
7160
  intent: {
@@ -6199,7 +7168,7 @@ export const $NlpResponseDto = {
6199
7168
  type: 'string',
6200
7169
  description:
6201
7170
  'Asset sub-type (only present when intent is "asset"). Determines which asset-related form to render.',
6202
- enum: ['transfer', 'banking', 'investment'],
7171
+ enum: ['transfer', 'banking', 'investment', 'lend', 'lend_collect'],
6203
7172
  example: 'investment'
6204
7173
  },
6205
7174
  liabilitySubType: {
@@ -6280,91 +7249,336 @@ export const $NlpResponseDto = {
6280
7249
  }
6281
7250
  ]
6282
7251
  },
6283
- duplicateData: {
7252
+ duplicateData: {
7253
+ description:
7254
+ 'Duplicate detection data (when action is "confirm_duplicate"). Contains information about potential duplicate transaction for user confirmation.',
7255
+ allOf: [
7256
+ {
7257
+ $ref: '#/components/schemas/NlpDuplicateConfirmationDataDto'
7258
+ }
7259
+ ]
7260
+ },
7261
+ ruleData: {
7262
+ description:
7263
+ 'Rule match data (when action is "confirm_rule"). Contains information about medium-confidence rule match for user confirmation.',
7264
+ allOf: [
7265
+ {
7266
+ $ref: '#/components/schemas/NlpRuleConfirmationDataDto'
7267
+ }
7268
+ ]
7269
+ },
7270
+ accountData: {
7271
+ description:
7272
+ 'Account validation data (when action is "confirm_account"). Contains information about invalid account for user correction.',
7273
+ allOf: [
7274
+ {
7275
+ $ref: '#/components/schemas/NlpAccountConfirmationDataDto'
7276
+ }
7277
+ ]
7278
+ },
7279
+ payeeData: {
7280
+ description:
7281
+ 'Payee confirmation data (when action is "confirm_payee"). Contains information about medium/low confidence payee match for user confirmation.',
7282
+ allOf: [
7283
+ {
7284
+ $ref: '#/components/schemas/NlpPayeeConfirmationDataDto'
7285
+ }
7286
+ ]
7287
+ },
7288
+ confidence: {
7289
+ type: 'number',
7290
+ description: 'Overall confidence score (0-1)',
7291
+ example: 0.85
7292
+ },
7293
+ confidenceThreshold: {
7294
+ type: 'number',
7295
+ description:
7296
+ 'Confidence threshold for automatic creation (default: 0.75). When confidence < threshold, action will be "confirm" requiring user verification.',
7297
+ example: 0.75
7298
+ },
7299
+ recurringMatch: {
7300
+ description:
7301
+ 'Recurring transaction match info (when action is "created"). Contains match details when transaction matches a pending expected transaction.',
7302
+ allOf: [
7303
+ {
7304
+ $ref: '#/components/schemas/RecurringMatchInfoDto'
7305
+ }
7306
+ ]
7307
+ },
7308
+ recurringSuggestion: {
7309
+ description:
7310
+ 'Recurring rule creation suggestion (when action is "created"). Contains suggestion to create a recurring rule based on detected patterns. Only present when no existing rule matched and similar historical transactions were found.',
7311
+ allOf: [
7312
+ {
7313
+ $ref: '#/components/schemas/RecurringSuggestionDto'
7314
+ }
7315
+ ]
7316
+ },
7317
+ suggestedAccounts: {
7318
+ description:
7319
+ 'Suggested accounts for this transaction (#586). confirm/confirm_rule/confirm_account: predicted (source/destination carry confidence); created: actual persisted accounts (confidence omitted). confirm_account destination is the suggested replacement, never the invalid account.',
7320
+ allOf: [
7321
+ {
7322
+ $ref: '#/components/schemas/NlpSuggestedAccountsDto'
7323
+ }
7324
+ ]
7325
+ },
7326
+ defaultAccounts: {
7327
+ description:
7328
+ 'Default fallback accounts for the user/region (#586). v1 returns universal constants; per-user personalization is planned.',
7329
+ allOf: [
7330
+ {
7331
+ $ref: '#/components/schemas/NlpDefaultAccountsDto'
7332
+ }
7333
+ ]
7334
+ }
7335
+ },
7336
+ required: ['status', 'action']
7337
+ } as const;
7338
+
7339
+ export const $PlatformListItemDto = {
7340
+ type: 'object',
7341
+ properties: {
7342
+ id: {
7343
+ type: 'string',
7344
+ description: 'Global platform ID'
7345
+ },
7346
+ name: {
7347
+ type: 'string',
7348
+ description: 'Platform name'
7349
+ },
7350
+ url: {
7351
+ type: 'string',
7352
+ description: 'Platform URL'
7353
+ },
7354
+ type: {
7355
+ type: 'string',
7356
+ description: 'Platform type',
7357
+ enum: [
7358
+ 'BANK',
7359
+ 'BROKERAGE',
7360
+ 'CRYPTO_EXCHANGE',
7361
+ 'PAYMENT',
7362
+ 'INVESTMENT',
7363
+ 'INSURANCE',
7364
+ 'OTHER'
7365
+ ]
7366
+ },
7367
+ canonical: {
7368
+ type: 'string',
7369
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7370
+ },
7371
+ suggestedSegment: {
7372
+ type: 'string',
7373
+ description:
7374
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
7375
+ },
7376
+ logoUrl: {
7377
+ type: 'string',
7378
+ description: 'Logo URL',
7379
+ nullable: true
7380
+ },
7381
+ countryCode: {
7382
+ type: 'string',
7383
+ description: 'ISO 3166-1 alpha-2 (UPPERCASE); null = global platform',
7384
+ example: 'CN',
7385
+ nullable: true
7386
+ },
7387
+ category: {
7388
+ type: 'string',
7389
+ description:
7390
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank). null = no region-aware suggestion; fall back to type.',
7391
+ nullable: true,
7392
+ example: 'DigitalWallet'
7393
+ },
7394
+ isBound: {
7395
+ type: 'boolean',
7396
+ description: 'Whether user has accounts using this platform'
7397
+ }
7398
+ },
7399
+ required: [
7400
+ 'id',
7401
+ 'name',
7402
+ 'url',
7403
+ 'type',
7404
+ 'canonical',
7405
+ 'suggestedSegment',
7406
+ 'logoUrl',
7407
+ 'countryCode',
7408
+ 'category',
7409
+ 'isBound'
7410
+ ]
7411
+ } as const;
7412
+
7413
+ export const $PlatformMatchResultDto = {
7414
+ type: 'object',
7415
+ properties: {
7416
+ id: {
7417
+ type: 'string',
7418
+ description: 'Global platform ID'
7419
+ },
7420
+ name: {
7421
+ type: 'string',
7422
+ description: 'Platform name (e.g., "ICBC")'
7423
+ },
7424
+ canonical: {
7425
+ type: 'string',
7426
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7427
+ },
7428
+ type: {
7429
+ type: 'string',
7430
+ description: 'Platform type',
7431
+ enum: [
7432
+ 'BANK',
7433
+ 'BROKERAGE',
7434
+ 'CRYPTO_EXCHANGE',
7435
+ 'PAYMENT',
7436
+ 'INVESTMENT',
7437
+ 'INSURANCE',
7438
+ 'OTHER'
7439
+ ]
7440
+ },
7441
+ suggestedSegment: {
7442
+ type: 'string',
6284
7443
  description:
6285
- 'Duplicate detection data (when action is "confirm_duplicate"). Contains information about potential duplicate transaction for user confirmation.',
6286
- allOf: [
6287
- {
6288
- $ref: '#/components/schemas/NlpDuplicateConfirmationDataDto'
6289
- }
6290
- ]
7444
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
6291
7445
  },
6292
- ruleData: {
6293
- description:
6294
- 'Rule match data (when action is "confirm_rule"). Contains information about medium-confidence rule match for user confirmation.',
6295
- allOf: [
6296
- {
6297
- $ref: '#/components/schemas/NlpRuleConfirmationDataDto'
6298
- }
6299
- ]
7446
+ logoUrl: {
7447
+ type: 'string',
7448
+ description: 'Logo URL',
7449
+ nullable: true
6300
7450
  },
6301
- accountData: {
7451
+ countryCode: {
7452
+ type: 'string',
7453
+ description: 'ISO 3166-1 alpha-2 (UPPERCASE); null = global platform',
7454
+ example: 'CN',
7455
+ nullable: true
7456
+ },
7457
+ category: {
7458
+ type: 'string',
6302
7459
  description:
6303
- 'Account validation data (when action is "confirm_account"). Contains information about invalid account for user correction.',
6304
- allOf: [
6305
- {
6306
- $ref: '#/components/schemas/NlpAccountConfirmationDataDto'
6307
- }
6308
- ]
7460
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank). null = no region-aware suggestion; fall back to type.',
7461
+ nullable: true,
7462
+ example: 'DigitalWallet'
6309
7463
  },
6310
- payeeData: {
7464
+ matchType: {
7465
+ type: 'string',
7466
+ description: "How this row matched: 'exact' > 'prefix' > 'substring'",
7467
+ enum: ['exact', 'prefix', 'substring']
7468
+ }
7469
+ },
7470
+ required: [
7471
+ 'id',
7472
+ 'name',
7473
+ 'canonical',
7474
+ 'type',
7475
+ 'suggestedSegment',
7476
+ 'logoUrl',
7477
+ 'countryCode',
7478
+ 'category',
7479
+ 'matchType'
7480
+ ]
7481
+ } as const;
7482
+
7483
+ export const $PlatformMatchResponseDto = {
7484
+ type: 'object',
7485
+ properties: {
7486
+ platforms: {
7487
+ description: 'Ranked matches, best tier first (at most 10 rows)',
7488
+ type: 'array',
7489
+ items: {
7490
+ $ref: '#/components/schemas/PlatformMatchResultDto'
7491
+ }
7492
+ },
7493
+ matchType: {
7494
+ type: 'string',
6311
7495
  description:
6312
- 'Payee confirmation data (when action is "confirm_payee"). Contains information about medium/low confidence payee match for user confirmation.',
6313
- allOf: [
6314
- {
6315
- $ref: '#/components/schemas/NlpPayeeConfirmationDataDto'
6316
- }
6317
- ]
7496
+ "Overall match quality — top row's tier, or 'none' when no hits",
7497
+ enum: ['none', 'exact', 'prefix', 'substring']
6318
7498
  },
6319
- confidence: {
7499
+ total: {
6320
7500
  type: 'number',
6321
- description: 'Overall confidence score (0-1)',
6322
- example: 0.85
7501
+ description: 'Total matches before LIMIT (truncation transparency)'
6323
7502
  },
6324
- confidenceThreshold: {
6325
- type: 'number',
6326
- description:
6327
- 'Confidence threshold for automatic creation (default: 0.75). When confidence < threshold, action will be "confirm" requiring user verification.',
6328
- example: 0.75
7503
+ hasMore: {
7504
+ type: 'boolean',
7505
+ description: 'true when total > platforms.length (more matches exist)'
7506
+ }
7507
+ },
7508
+ required: ['platforms', 'matchType', 'total', 'hasMore']
7509
+ } as const;
7510
+
7511
+ export const $PlatformStandardsPlatformDto = {
7512
+ type: 'object',
7513
+ properties: {
7514
+ id: {
7515
+ type: 'string',
7516
+ description: 'Global platform ID'
6329
7517
  },
6330
- recurringMatch: {
7518
+ name: {
7519
+ type: 'string',
7520
+ description: 'Platform name (e.g., "ICBC")'
7521
+ },
7522
+ canonical: {
7523
+ type: 'string',
7524
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7525
+ },
7526
+ suggestedSegment: {
7527
+ type: 'string',
6331
7528
  description:
6332
- 'Recurring transaction match info (when action is "created"). Contains match details when transaction matches a pending expected transaction.',
6333
- allOf: [
6334
- {
6335
- $ref: '#/components/schemas/RecurringMatchInfoDto'
6336
- }
7529
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
7530
+ },
7531
+ type: {
7532
+ type: 'string',
7533
+ description: 'Platform type',
7534
+ enum: [
7535
+ 'BANK',
7536
+ 'BROKERAGE',
7537
+ 'CRYPTO_EXCHANGE',
7538
+ 'PAYMENT',
7539
+ 'INVESTMENT',
7540
+ 'INSURANCE',
7541
+ 'OTHER'
6337
7542
  ]
6338
7543
  },
6339
- recurringSuggestion: {
7544
+ category: {
7545
+ type: 'string',
6340
7546
  description:
6341
- 'Recurring rule creation suggestion (when action is "created"). Contains suggestion to create a recurring rule based on detected patterns. Only present when no existing rule matched and similar historical transactions were found.',
7547
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank) resolved against the final region. null = no region-aware suggestion; fall back to type.',
7548
+ nullable: true,
7549
+ example: 'Bank'
7550
+ }
7551
+ },
7552
+ required: ['id', 'name', 'canonical', 'suggestedSegment', 'type', 'category']
7553
+ } as const;
7554
+
7555
+ export const $PlatformStandardsResponseDto = {
7556
+ type: 'object',
7557
+ properties: {
7558
+ platform: {
7559
+ description: 'The selected platform (institution lock source)',
6342
7560
  allOf: [
6343
7561
  {
6344
- $ref: '#/components/schemas/RecurringSuggestionDto'
7562
+ $ref: '#/components/schemas/PlatformStandardsPlatformDto'
6345
7563
  }
6346
7564
  ]
6347
7565
  },
6348
- suggestedAccounts: {
7566
+ region: {
7567
+ type: 'string',
6349
7568
  description:
6350
- 'Suggested accounts for this transaction. Contains recommended source and destination accounts based on the detected intent and rules.',
6351
- allOf: [
6352
- {
6353
- $ref: '#/components/schemas/NlpSuggestedAccountsDto'
6354
- }
6355
- ]
7569
+ "Resolved template region (ISO 3166-1 alpha-2, UPPERCASE): the platform's own countryCode when set, else the region query param. For regions without a regional template file the template list falls back to the universal-only catalog while region still echoes the code.",
7570
+ example: 'CN'
6356
7571
  },
6357
- defaultAccounts: {
7572
+ templates: {
6358
7573
  description:
6359
- 'Default accounts for the user/region. These are fallback accounts used when no specific suggestion is available.',
6360
- allOf: [
6361
- {
6362
- $ref: '#/components/schemas/NlpDefaultAccountsDto'
6363
- }
6364
- ]
7574
+ 'Candidate account-standard templates of the resolved region (groupable by productCategory client-side)',
7575
+ type: 'array',
7576
+ items: {
7577
+ $ref: '#/components/schemas/AccountStandardResponseDto'
7578
+ }
6365
7579
  }
6366
7580
  },
6367
- required: ['status', 'action']
7581
+ required: ['platform', 'region', 'templates']
6368
7582
  } as const;
6369
7583
 
6370
7584
  export const $CreatePlatformDto = {
@@ -6468,7 +7682,8 @@ export const $UpdatePlatformDto = {
6468
7682
  },
6469
7683
  isActive: {
6470
7684
  type: 'boolean',
6471
- description: 'Whether the platform is active'
7685
+ description: 'Whether the platform is active',
7686
+ default: true
6472
7687
  }
6473
7688
  }
6474
7689
  } as const;
@@ -6631,7 +7846,8 @@ export const $AccountItemDto = {
6631
7846
  },
6632
7847
  displayName: {
6633
7848
  type: 'string',
6634
- description: 'Display name (last part of account path)',
7849
+ description:
7850
+ 'Display name: user-set name if provided (#762), else the ADR-0114 chain — request-locale catalog name, en pivot, then the last part of the account path (#771)',
6635
7851
  example: 'Savings'
6636
7852
  },
6637
7853
  balance: {
@@ -6667,7 +7883,8 @@ export const $PlatformGroupDto = {
6667
7883
  example: 'CMB Bank'
6668
7884
  },
6669
7885
  accounts: {
6670
- description: 'Accounts within this platform',
7886
+ description:
7887
+ 'Accounts within this platform (Assets and Liabilities rows, #696)',
6671
7888
  type: 'array',
6672
7889
  items: {
6673
7890
  $ref: '#/components/schemas/AccountItemDto'
@@ -6675,7 +7892,8 @@ export const $PlatformGroupDto = {
6675
7892
  },
6676
7893
  totalBalance: {
6677
7894
  type: 'string',
6678
- description: 'FX-converted total balance in base currency',
7895
+ description:
7896
+ 'FX-converted total balance in base currency (nets Assets + Liabilities rows; can be negative)',
6679
7897
  example: '100000.00'
6680
7898
  },
6681
7899
  balanceByCurrency: {
@@ -6694,7 +7912,7 @@ export const $PlatformGroupDto = {
6694
7912
  sharePct: {
6695
7913
  type: 'number',
6696
7914
  description:
6697
- 'Share of the grand converted total (0-100); 0 when grand total is 0',
7915
+ 'Share of the converted asset-side grand total (0-100); liability balances are excluded from the basis; 0 when grand total is 0 (#696)',
6698
7916
  example: 42.5
6699
7917
  }
6700
7918
  },
@@ -6742,7 +7960,8 @@ export const $AccountsSummaryDto = {
6742
7960
  properties: {
6743
7961
  totalAccounts: {
6744
7962
  type: 'number',
6745
- description: 'Total number of accounts'
7963
+ description:
7964
+ 'Total number of accounts (balance sheet: Assets + Liabilities, #696)'
6746
7965
  },
6747
7966
  totalPlatforms: {
6748
7967
  type: 'number',
@@ -6800,7 +8019,8 @@ export const $AccountItemWithAssetClassDto = {
6800
8019
  },
6801
8020
  displayName: {
6802
8021
  type: 'string',
6803
- description: 'Display name (last part of account path)',
8022
+ description:
8023
+ 'Display name: user-set name if provided (#762), else the ADR-0114 chain — request-locale catalog name, en pivot, then the last part of the account path (#771)',
6804
8024
  example: 'Savings'
6805
8025
  },
6806
8026
  balance: {
@@ -7286,7 +8506,7 @@ export const $MonetaryDto = {
7286
8506
  example: 'USD'
7287
8507
  },
7288
8508
  baseCcyEquivalent: {
7289
- type: 'object',
8509
+ type: 'string',
7290
8510
  description: 'Converted to user base currency (Decimal string)',
7291
8511
  example: '21600',
7292
8512
  nullable: true
@@ -7362,13 +8582,13 @@ export const $HoldingPnlRowDto = {
7362
8582
  example: 'Assets:US:Broker:AAPL'
7363
8583
  },
7364
8584
  accountCcy: {
7365
- type: 'object',
8585
+ type: 'string',
7366
8586
  description: 'Account settlement currency (ISO 4217), from cost currency',
7367
8587
  nullable: true,
7368
8588
  example: 'USD'
7369
8589
  },
7370
8590
  brokerType: {
7371
- type: 'object',
8591
+ type: 'string',
7372
8592
  description: 'Broker type derived from Platform.type',
7373
8593
  nullable: true,
7374
8594
  example: 'broker'
@@ -7389,7 +8609,7 @@ export const $HoldingPnlRowDto = {
7389
8609
  example: 'EQUITY'
7390
8610
  },
7391
8611
  assetSubClass: {
7392
- type: 'object',
8612
+ type: 'string',
7393
8613
  nullable: true,
7394
8614
  example: 'STOCK'
7395
8615
  },
@@ -7436,14 +8656,14 @@ export const $HoldingPnlRowDto = {
7436
8656
  ]
7437
8657
  },
7438
8658
  unrealizedPnlBase: {
7439
- type: 'object',
8659
+ type: 'string',
7440
8660
  description:
7441
8661
  'Unrealized P&L in base currency (Decimal string); null when any FX/price missing',
7442
8662
  nullable: true,
7443
8663
  example: '6000'
7444
8664
  },
7445
8665
  unrealizedPnlPct: {
7446
- type: 'object',
8666
+ type: 'string',
7447
8667
  description: 'Unrealized P&L % (Decimal string)',
7448
8668
  nullable: true,
7449
8669
  example: '25'
@@ -7467,7 +8687,7 @@ export const $HoldingPnlRowDto = {
7467
8687
  ]
7468
8688
  },
7469
8689
  pctOfInvestedAssets: {
7470
- type: 'object',
8690
+ type: 'string',
7471
8691
  description:
7472
8692
  'Share of invested assets % (Decimal string); only for invested chartTokens',
7473
8693
  nullable: true,
@@ -7512,15 +8732,15 @@ export const $HoldingPnlWarningDto = {
7512
8732
  ]
7513
8733
  },
7514
8734
  symbol: {
7515
- type: 'object',
8735
+ type: 'string',
7516
8736
  nullable: true
7517
8737
  },
7518
8738
  accountId: {
7519
- type: 'object',
8739
+ type: 'string',
7520
8740
  nullable: true
7521
8741
  },
7522
8742
  currency: {
7523
- type: 'object',
8743
+ type: 'string',
7524
8744
  nullable: true
7525
8745
  }
7526
8746
  },
@@ -7561,292 +8781,378 @@ export const $HoldingPnlResponseDto = {
7561
8781
  required: ['asOfDate', 'baseCurrency', 'method', 'rows', 'warnings']
7562
8782
  } as const;
7563
8783
 
7564
- export const $CurrencyBalanceDto = {
8784
+ export const $AnonymousLoginDto = {
7565
8785
  type: 'object',
7566
8786
  properties: {
7567
- currency: {
8787
+ accessToken: {
7568
8788
  type: 'string',
7569
- description: 'ISO 4217 currency code',
7570
- example: 'CNY'
7571
- },
7572
- balance: {
8789
+ description: 'Access token for anonymous login'
8790
+ }
8791
+ },
8792
+ required: ['accessToken']
8793
+ } as const;
8794
+
8795
+ export const $AnonymousLoginResponseDto = {
8796
+ type: 'object',
8797
+ properties: {
8798
+ authToken: {
7573
8799
  type: 'string',
7574
- description: 'Balance amount',
7575
- example: '500000.00'
8800
+ description: 'JWT auth token',
8801
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
7576
8802
  }
7577
8803
  },
7578
- required: ['currency', 'balance']
8804
+ required: ['authToken']
7579
8805
  } as const;
7580
8806
 
7581
- export const $TimeSeriesPointDto = {
8807
+ export const $ParserContributionMetaDto = {
7582
8808
  type: 'object',
7583
8809
  properties: {
7584
- date: {
8810
+ institution: {
7585
8811
  type: 'string',
7586
- description: 'Date in YYYY-MM-DD format',
7587
- example: '2024-06-15'
8812
+ description: 'Institution slug (lowercase kebab-case)',
8813
+ pattern: '^[a-z0-9]+(-[a-z0-9]+)*$',
8814
+ example: 'icbc'
7588
8815
  },
7589
- value: {
8816
+ region: {
7590
8817
  type: 'string',
7591
- description: 'Value at this date (in base currency)',
7592
- example: '500000.00'
8818
+ enum: [
8819
+ 'cn',
8820
+ 'us',
8821
+ 'de',
8822
+ 'fr',
8823
+ 'gb',
8824
+ 'hk',
8825
+ 'jp',
8826
+ 'sg',
8827
+ 'au',
8828
+ 'ca',
8829
+ 'other'
8830
+ ]
7593
8831
  },
7594
- change: {
7595
- type: 'object',
7596
- description: 'Change from previous point',
7597
- example: '5000.00'
8832
+ accountType: {
8833
+ type: 'string',
8834
+ enum: ['checking', 'savings', 'credit', 'debit', 'investment']
7598
8835
  },
7599
- assets: {
8836
+ format: {
7600
8837
  type: 'string',
7601
- description: 'Total assets at this date (in base currency)',
7602
- example: '494338.00'
8838
+ enum: ['csv', 'xlsx', 'pdf', 'ofx', 'qif']
7603
8839
  },
7604
- liabilities: {
8840
+ institutionDisplayName: {
7605
8841
  type: 'string',
7606
- description: 'Total liabilities at this date (in base currency)',
7607
- example: '310098.00'
8842
+ example: '中国工商银行'
7608
8843
  },
7609
- byCurrency: {
7610
- description: 'Multi-currency breakdown for this point',
8844
+ encoding: {
8845
+ type: 'string',
8846
+ example: 'utf-8'
8847
+ },
8848
+ delimiter: {
8849
+ type: 'string',
8850
+ description: 'CSV delimiter character: ",", ";", "\\t" or "|"'
8851
+ },
8852
+ headerRows: {
8853
+ type: 'number',
8854
+ default: 1,
8855
+ description: 'Header row count; the client omits the field when it is 1'
8856
+ },
8857
+ notes: {
8858
+ type: 'string',
8859
+ maxLength: 2000
8860
+ }
8861
+ },
8862
+ required: ['institution', 'region', 'accountType', 'format']
8863
+ } as const;
8864
+
8865
+ export const $ParserContributionSamplesDto = {
8866
+ type: 'object',
8867
+ properties: {
8868
+ rows: {
8869
+ description:
8870
+ 'Client-sanitized sample rows (key = column name, value = cell)',
7611
8871
  type: 'array',
7612
8872
  items: {
7613
- $ref: '#/components/schemas/CurrencyBalanceDto'
8873
+ type: 'object'
7614
8874
  }
8875
+ },
8876
+ rawHeaders: {
8877
+ type: 'array',
8878
+ items: {
8879
+ type: 'string'
8880
+ }
8881
+ }
8882
+ },
8883
+ required: ['rows']
8884
+ } as const;
8885
+
8886
+ export const $FieldHintDto = {
8887
+ type: 'object',
8888
+ properties: {
8889
+ columnName: {
8890
+ type: 'string',
8891
+ example: '交易日期'
8892
+ },
8893
+ format: {
8894
+ type: 'string',
8895
+ description: 'Date format, e.g. yyyy-MM-dd HH:mm',
8896
+ example: 'yyyy-MM-dd'
8897
+ },
8898
+ signConvention: {
8899
+ type: 'string',
8900
+ enum: ['negative-expense', 'positive-expense', 'separate-columns']
8901
+ },
8902
+ creditColumn: {
8903
+ type: 'string'
8904
+ },
8905
+ debitColumn: {
8906
+ type: 'string'
8907
+ }
8908
+ },
8909
+ required: ['columnName']
8910
+ } as const;
8911
+
8912
+ export const $ParserContributionFieldHintsDto = {
8913
+ type: 'object',
8914
+ properties: {
8915
+ date: {
8916
+ $ref: '#/components/schemas/FieldHintDto'
8917
+ },
8918
+ amount: {
8919
+ $ref: '#/components/schemas/FieldHintDto'
8920
+ },
8921
+ description: {
8922
+ $ref: '#/components/schemas/FieldHintDto'
8923
+ },
8924
+ balance: {
8925
+ $ref: '#/components/schemas/FieldHintDto'
8926
+ },
8927
+ payee: {
8928
+ $ref: '#/components/schemas/FieldHintDto'
8929
+ },
8930
+ reference: {
8931
+ $ref: '#/components/schemas/FieldHintDto'
8932
+ },
8933
+ category: {
8934
+ $ref: '#/components/schemas/FieldHintDto'
7615
8935
  }
7616
8936
  },
7617
- required: ['date', 'value']
8937
+ required: ['date', 'amount']
7618
8938
  } as const;
7619
8939
 
7620
- export const $TrendSummaryDto = {
8940
+ export const $ExpectedTransactionDto = {
7621
8941
  type: 'object',
7622
8942
  properties: {
7623
- startValue: {
8943
+ date: {
7624
8944
  type: 'string',
7625
- description: 'Value at start of period',
7626
- example: '450000.00'
8945
+ example: '2026-08-01'
7627
8946
  },
7628
- endValue: {
7629
- type: 'string',
7630
- description: 'Value at end of period',
7631
- example: '500000.00'
8947
+ amount: {
8948
+ type: 'number',
8949
+ example: -45.5
7632
8950
  },
7633
- totalChange: {
8951
+ description: {
7634
8952
  type: 'string',
7635
- description: 'Total change over period',
7636
- example: '50000.00'
8953
+ example: '星巴克-***店'
7637
8954
  },
7638
- totalChangePercentage: {
7639
- type: 'string',
7640
- description: 'Total change percentage',
7641
- example: '+11.11%'
8955
+ payee: {
8956
+ type: 'string'
8957
+ },
8958
+ category: {
8959
+ type: 'string'
7642
8960
  }
7643
8961
  },
7644
- required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
8962
+ required: ['date', 'amount', 'description']
7645
8963
  } as const;
7646
8964
 
7647
- export const $MultiCurrencyPointDto = {
8965
+ export const $ParserContributionExamplesDto = {
7648
8966
  type: 'object',
7649
8967
  properties: {
7650
- date: {
7651
- type: 'string',
7652
- description: 'Date in YYYY-MM-DD format',
7653
- example: '2024-06-15'
7654
- },
7655
- byCurrency: {
7656
- description: 'Balances by currency',
8968
+ expectedTransactions: {
7657
8969
  type: 'array',
7658
8970
  items: {
7659
- $ref: '#/components/schemas/CurrencyBalanceDto'
8971
+ $ref: '#/components/schemas/ExpectedTransactionDto'
7660
8972
  }
7661
8973
  }
7662
8974
  },
7663
- required: ['date', 'byCurrency']
8975
+ required: ['expectedTransactions']
7664
8976
  } as const;
7665
8977
 
7666
- export const $PortfolioTrendsResponseDto = {
8978
+ export const $ParserContributionRequestDto = {
7667
8979
  type: 'object',
7668
8980
  properties: {
7669
- series: {
7670
- description: 'Time series data points',
7671
- type: 'array',
7672
- items: {
7673
- $ref: '#/components/schemas/TimeSeriesPointDto'
7674
- }
8981
+ meta: {
8982
+ $ref: '#/components/schemas/ParserContributionMetaDto'
7675
8983
  },
7676
- summary: {
7677
- description: 'Period summary',
8984
+ samples: {
8985
+ $ref: '#/components/schemas/ParserContributionSamplesDto'
8986
+ },
8987
+ fieldHints: {
8988
+ $ref: '#/components/schemas/ParserContributionFieldHintsDto'
8989
+ },
8990
+ examples: {
8991
+ description: 'Omitted entirely by the client when empty',
7678
8992
  allOf: [
7679
8993
  {
7680
- $ref: '#/components/schemas/TrendSummaryDto'
8994
+ $ref: '#/components/schemas/ParserContributionExamplesDto'
7681
8995
  }
7682
8996
  ]
7683
- },
7684
- period: {
7685
- type: 'string',
7686
- description: 'Period requested',
7687
- example: '6m'
7688
- },
7689
- granularity: {
7690
- type: 'string',
7691
- description: 'Data granularity',
7692
- example: 'month'
7693
- },
7694
- currency: {
8997
+ }
8998
+ },
8999
+ required: ['meta', 'samples', 'fieldHints']
9000
+ } as const;
9001
+
9002
+ export const $ParserContributionRelayResponseDto = {
9003
+ type: 'object',
9004
+ properties: {
9005
+ issueUrl: {
7695
9006
  type: 'string',
7696
- description: 'Base currency for converted values',
7697
- example: 'CNY'
7698
- },
7699
- byCurrency: {
7700
- description:
7701
- 'Multi-currency time series (each point has currency breakdown)',
7702
- type: 'array',
7703
- items: {
7704
- $ref: '#/components/schemas/MultiCurrencyPointDto'
7705
- }
9007
+ example: 'https://github.com/fire-zu/firela-vlt/issues/42'
7706
9008
  },
7707
- warnings: {
7708
- description: 'Exchange rate warnings',
7709
- type: 'array',
7710
- items: {
7711
- $ref: '#/components/schemas/ExchangeRateWarningDto'
7712
- }
9009
+ issueNumber: {
9010
+ type: 'number',
9011
+ example: 42
7713
9012
  }
7714
9013
  },
7715
- required: ['series', 'summary', 'period', 'granularity', 'currency']
9014
+ required: ['issueUrl', 'issueNumber']
7716
9015
  } as const;
7717
9016
 
7718
- export const $CashFlowPointDto = {
9017
+ export const $SymbolSearchResultDto = {
7719
9018
  type: 'object',
7720
9019
  properties: {
7721
- month: {
9020
+ symbol: {
7722
9021
  type: 'string',
7723
- description: 'Month key (YYYY-MM)',
7724
- example: '2024-03'
9022
+ example: 'AAPL'
7725
9023
  },
7726
- income: {
9024
+ name: {
7727
9025
  type: 'string',
7728
- description: 'Income in base currency (absolute, converted)',
7729
- example: '10000.00'
9026
+ example: 'Apple Inc.',
9027
+ nullable: true
7730
9028
  },
7731
- expense: {
9029
+ exchange: {
7732
9030
  type: 'string',
7733
- description: 'Expense in base currency (absolute, converted)',
7734
- example: '5000.00'
9031
+ example: 'US',
9032
+ nullable: true
7735
9033
  },
7736
- netSavings: {
9034
+ assetType: {
7737
9035
  type: 'string',
7738
- description: 'netSavings = income − expense (savings positive)',
7739
- example: '5000.00'
9036
+ description: 'OpenBB asset_type (e.g. stock, etf)',
9037
+ example: 'stock',
9038
+ nullable: true
9039
+ },
9040
+ assetClass: {
9041
+ type: 'string',
9042
+ description: 'IGN asset class (region.types.ts ASSET_CLASSES)',
9043
+ example: 'EQUITY',
9044
+ nullable: true
9045
+ },
9046
+ assetSubClass: {
9047
+ type: 'string',
9048
+ description: 'IGN asset sub-class (region.types.ts ASSET_SUB_CLASSES)',
9049
+ example: 'STOCK',
9050
+ nullable: true
9051
+ },
9052
+ currency: {
9053
+ type: 'string',
9054
+ description: 'Trading currency (extra_data or inferred from exchange)',
9055
+ example: 'USD',
9056
+ nullable: true
7740
9057
  }
7741
9058
  },
7742
- required: ['month', 'income', 'expense', 'netSavings']
9059
+ required: ['symbol']
7743
9060
  } as const;
7744
9061
 
7745
- export const $CashFlowTrendSummaryDto = {
9062
+ export const $SymbolQuoteDto = {
7746
9063
  type: 'object',
7747
9064
  properties: {
7748
- totalIncome: {
9065
+ symbol: {
7749
9066
  type: 'string',
7750
- description: 'Total income across the period',
7751
- example: '60000.00'
9067
+ example: 'AAPL'
7752
9068
  },
7753
- totalExpense: {
9069
+ name: {
7754
9070
  type: 'string',
7755
- description: 'Total expense across the period',
7756
- example: '30000.00'
9071
+ example: 'Apple Inc.',
9072
+ nullable: true
7757
9073
  },
7758
- totalNetSavings: {
9074
+ exchange: {
7759
9075
  type: 'string',
7760
- description: 'income − expense across the period',
7761
- example: '30000.00'
9076
+ example: 'US',
9077
+ nullable: true
7762
9078
  },
7763
- averageMonthlyNetSavings: {
9079
+ assetType: {
7764
9080
  type: 'string',
9081
+ description: 'OpenBB asset_type',
9082
+ example: 'stock',
9083
+ nullable: true
9084
+ },
9085
+ assetClass: {
9086
+ type: 'string',
9087
+ description: 'IGN asset class',
9088
+ example: 'EQUITY',
9089
+ nullable: true
9090
+ },
9091
+ assetSubClass: {
9092
+ type: 'string',
9093
+ description: 'IGN asset sub-class',
9094
+ example: 'STOCK',
9095
+ nullable: true
9096
+ },
9097
+ currency: {
9098
+ type: 'string',
9099
+ description: 'Trading currency (extra_data or inferred from exchange)',
9100
+ example: 'USD',
9101
+ nullable: true
9102
+ },
9103
+ price: {
9104
+ type: 'string',
9105
+ description: 'Latest price (Decimal string)',
9106
+ example: '189.84',
9107
+ nullable: true
9108
+ },
9109
+ priceDate: {
9110
+ type: 'string',
9111
+ description: 'Date the price was observed (ISO yyyy-MM-dd)',
9112
+ example: '2026-08-05',
9113
+ nullable: true
9114
+ },
9115
+ changePercent: {
9116
+ type: 'number',
7765
9117
  description:
7766
- 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
7767
- example: '5000.00'
7768
- }
7769
- },
7770
- required: [
7771
- 'totalIncome',
7772
- 'totalExpense',
7773
- 'totalNetSavings',
7774
- 'averageMonthlyNetSavings'
7775
- ]
7776
- } as const;
7777
-
7778
- export const $CashFlowTrendsResponseDto = {
7779
- type: 'object',
7780
- properties: {
7781
- series: {
7782
- description:
7783
- 'Monthly cash-flow series (fixed N-month window, zero-filled)',
7784
- type: 'array',
7785
- items: {
7786
- $ref: '#/components/schemas/CashFlowPointDto'
7787
- }
9118
+ 'Change vs previous close, in percentage points (1.7 == 1.7%). openbb stores change_percent as a normalized decimal; this exposes percentage points for frontend convenience.',
9119
+ example: 1.7,
9120
+ nullable: true
7788
9121
  },
7789
- summary: {
7790
- description: 'Period totals',
7791
- allOf: [
7792
- {
7793
- $ref: '#/components/schemas/CashFlowTrendSummaryDto'
7794
- }
7795
- ]
9122
+ prevClose: {
9123
+ type: 'string',
9124
+ description: 'Previous close (Decimal string)',
9125
+ nullable: true
7796
9126
  },
7797
- period: {
9127
+ open: {
7798
9128
  type: 'string',
7799
- description: 'Period requested',
7800
- example: '6m'
9129
+ description: 'Day open (Decimal string)',
9130
+ nullable: true
7801
9131
  },
7802
- granularity: {
9132
+ high: {
7803
9133
  type: 'string',
7804
- description: 'Data granularity (v1 returns month buckets)',
7805
- example: 'month'
9134
+ description: 'Day high (Decimal string)',
9135
+ nullable: true
7806
9136
  },
7807
- currency: {
9137
+ low: {
7808
9138
  type: 'string',
7809
- description: 'Base currency for converted values',
7810
- example: 'CNY'
9139
+ description: 'Day low (Decimal string)',
9140
+ nullable: true
7811
9141
  },
7812
- warnings: {
7813
- description: 'Exchange rate warnings (e.g. missing rate for a currency)',
7814
- type: 'array',
7815
- items: {
7816
- $ref: '#/components/schemas/ExchangeRateWarningDto'
7817
- }
7818
- }
7819
- },
7820
- required: ['series', 'summary', 'period', 'granularity', 'currency']
7821
- } as const;
7822
-
7823
- export const $GenerateSnapshotBody = {
7824
- type: 'object',
7825
- properties: {}
7826
- } as const;
7827
-
7828
- export const $GenerateSnapshotResponse = {
7829
- type: 'object',
7830
- properties: {}
7831
- } as const;
7832
-
7833
- export const $BackfillSnapshotsBody = {
7834
- type: 'object',
7835
- properties: {}
7836
- } as const;
7837
-
7838
- export const $BackfillSnapshotsResponse = {
7839
- type: 'object',
7840
- properties: {}
7841
- } as const;
7842
-
7843
- export const $AnonymousLoginDto = {
7844
- type: 'object',
7845
- properties: {
7846
- accessToken: {
9142
+ volume: {
7847
9143
  type: 'string',
7848
- description: 'Access token for anonymous login'
9144
+ description: 'Day volume (Decimal string)',
9145
+ nullable: true
9146
+ },
9147
+ yearHigh: {
9148
+ type: 'string',
9149
+ description: '52-week high (Decimal string)',
9150
+ nullable: true
9151
+ },
9152
+ yearLow: {
9153
+ type: 'string',
9154
+ description: '52-week low (Decimal string)',
9155
+ nullable: true
7849
9156
  }
7850
- },
7851
- required: ['accessToken']
9157
+ }
7852
9158
  } as const;