@firela/api-types 0.0.0-canary.614ff760 → 0.0.0-canary.6a42fd0e

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.
@@ -466,6 +466,66 @@ export const $RegionsMetadataResponseDto = {
466
466
  required: ['regions']
467
467
  } as const;
468
468
 
469
+ export const $CostSpecDto = {
470
+ type: 'object',
471
+ properties: {
472
+ mode: {
473
+ type: 'string',
474
+ enum: ['per-unit', 'total', 'date', 'label', 'auto'],
475
+ description: 'Cost specification mode (mirrors engine CostSpec)'
476
+ },
477
+ numberPerUnit: {
478
+ type: 'string',
479
+ description: 'Per-unit cost (required when mode is "per-unit")',
480
+ example: '240'
481
+ },
482
+ totalNumber: {
483
+ type: 'string',
484
+ description: 'Total cost for all units (required when mode is "total")',
485
+ example: '12000'
486
+ },
487
+ currency: {
488
+ type: 'string',
489
+ description: 'Cost currency (required in all modes)',
490
+ example: 'USD'
491
+ },
492
+ date: {
493
+ type: 'string',
494
+ description:
495
+ 'Lot acquisition date, ISO 8601 (required when mode is "date")',
496
+ example: '2024-01-15'
497
+ },
498
+ label: {
499
+ type: 'string',
500
+ description:
501
+ 'Lot label (required when mode is "label"; optional tag in buy modes)'
502
+ },
503
+ merge: {
504
+ type: 'boolean',
505
+ description: 'Merge lots for AVERAGE booking (mode: auto)'
506
+ }
507
+ },
508
+ required: ['mode', 'currency']
509
+ } as const;
510
+
511
+ export const $AmountDto = {
512
+ type: 'object',
513
+ properties: {
514
+ number: {
515
+ type: 'string',
516
+ description:
517
+ 'Amount as decimal string (max 15 integer + 15 decimal digits)',
518
+ example: '170.50'
519
+ },
520
+ currency: {
521
+ type: 'string',
522
+ description: 'Currency/commodity code',
523
+ example: 'USD'
524
+ }
525
+ },
526
+ required: ['number', 'currency']
527
+ } as const;
528
+
469
529
  export const $CreatePostingDto = {
470
530
  type: 'object',
471
531
  properties: {
@@ -495,6 +555,33 @@ export const $CreatePostingDto = {
495
555
  example: {
496
556
  'tax-lot': 'Q1-2024'
497
557
  }
558
+ },
559
+ cost: {
560
+ description:
561
+ 'Cost basis (Beancount `{...}`). Maps to engine costSpec. Required for commodity holdings so they carry a monetary weight that can balance.',
562
+ example: {
563
+ mode: 'per-unit',
564
+ numberPerUnit: '240',
565
+ currency: 'USD'
566
+ },
567
+ allOf: [
568
+ {
569
+ $ref: '#/components/schemas/CostSpecDto'
570
+ }
571
+ ]
572
+ },
573
+ price: {
574
+ description:
575
+ 'Price annotation (Beancount `@...`). Maps to engine price. Used for valuation; cost takes priority for balance weight.',
576
+ example: {
577
+ number: '170',
578
+ currency: 'USD'
579
+ },
580
+ allOf: [
581
+ {
582
+ $ref: '#/components/schemas/AmountDto'
583
+ }
584
+ ]
498
585
  }
499
586
  },
500
587
  required: ['account']
@@ -573,6 +660,32 @@ export const $CreateTransactionDto = {
573
660
  required: ['date', 'narration', 'postings']
574
661
  } as const;
575
662
 
663
+ export const $CostDetailDto = {
664
+ type: 'object',
665
+ properties: {
666
+ number: {
667
+ type: 'string',
668
+ description: 'Per-unit cost basis (mirrors engine Cost.number)',
669
+ example: '240'
670
+ },
671
+ currency: {
672
+ type: 'string',
673
+ description: 'Cost currency',
674
+ example: 'USD'
675
+ },
676
+ date: {
677
+ type: 'string',
678
+ description: 'Lot acquisition date (ISO yyyy-mm-dd)',
679
+ example: '2024-01-15'
680
+ },
681
+ label: {
682
+ type: 'string',
683
+ description: 'Lot label',
684
+ example: 'lot-2024-01'
685
+ }
686
+ }
687
+ } as const;
688
+
576
689
  export const $PostingResponseDto = {
577
690
  type: 'object',
578
691
  properties: {
@@ -591,6 +704,15 @@ export const $PostingResponseDto = {
591
704
  type: 'string',
592
705
  description: 'Currency',
593
706
  example: 'USD'
707
+ },
708
+ cost: {
709
+ description:
710
+ 'Booking-resolved cost (mirrors engine Cost). Undefined when the posting has no cost basis.',
711
+ allOf: [
712
+ {
713
+ $ref: '#/components/schemas/CostDetailDto'
714
+ }
715
+ ]
594
716
  }
595
717
  },
596
718
  required: ['account']
@@ -933,9 +1055,9 @@ export const $PostingDetailDto = {
933
1055
  description: 'Account ID',
934
1056
  example: 'clh1234567890abcdef'
935
1057
  },
936
- accountName: {
1058
+ account: {
937
1059
  type: 'string',
938
- description: 'Account name',
1060
+ description: 'Fully-qualified Beancount account path',
939
1061
  example: 'Assets:Bank:Checking'
940
1062
  },
941
1063
  units: {
@@ -964,6 +1086,15 @@ export const $PostingDetailDto = {
964
1086
  description: 'Cost date',
965
1087
  example: '2024-01-15'
966
1088
  },
1089
+ cost: {
1090
+ description:
1091
+ 'Booking-resolved cost (mirrors engine Cost). Undefined when the posting has no cost basis.',
1092
+ allOf: [
1093
+ {
1094
+ $ref: '#/components/schemas/CostDetailDto'
1095
+ }
1096
+ ]
1097
+ },
967
1098
  priceAmount: {
968
1099
  type: 'string',
969
1100
  description: 'Price amount',
@@ -984,7 +1115,7 @@ export const $PostingDetailDto = {
984
1115
  description: 'Posting metadata'
985
1116
  }
986
1117
  },
987
- required: ['id', 'accountId', 'accountName']
1118
+ required: ['id', 'accountId', 'account']
988
1119
  } as const;
989
1120
 
990
1121
  export const $TransactionDetailDto = {
@@ -1116,6 +1247,77 @@ export const $TransactionDetailDto = {
1116
1247
  ]
1117
1248
  } as const;
1118
1249
 
1250
+ export const $BalanceByCurrencyDto = {
1251
+ type: 'object',
1252
+ properties: {
1253
+ currency: {
1254
+ type: 'string',
1255
+ description: 'ISO 4217 currency code',
1256
+ example: 'CNY'
1257
+ },
1258
+ balance: {
1259
+ type: 'string',
1260
+ description: 'Balance amount',
1261
+ example: '50000.00'
1262
+ }
1263
+ },
1264
+ required: ['currency', 'balance']
1265
+ } as const;
1266
+
1267
+ export const $ExchangeRateWarningDto = {
1268
+ type: 'object',
1269
+ properties: {
1270
+ type: {
1271
+ type: 'string',
1272
+ description: 'Warning type',
1273
+ example: 'MISSING_EXCHANGE_RATE'
1274
+ },
1275
+ currency: {
1276
+ type: 'string',
1277
+ description: 'Currency without exchange rate',
1278
+ example: 'EUR'
1279
+ },
1280
+ totalAmount: {
1281
+ type: 'string',
1282
+ description: 'Total amount affected',
1283
+ example: '1000.00'
1284
+ }
1285
+ },
1286
+ required: ['type', 'currency', 'totalAmount']
1287
+ } as const;
1288
+
1289
+ export const $TransactionListSummaryDto = {
1290
+ type: 'object',
1291
+ properties: {
1292
+ totalAmount: {
1293
+ type: 'string',
1294
+ description:
1295
+ '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.',
1296
+ example: '-6000.00'
1297
+ },
1298
+ currency: {
1299
+ type: 'string',
1300
+ description: 'Base currency (ISO 4217)',
1301
+ example: 'CNY'
1302
+ },
1303
+ balanceByCurrency: {
1304
+ description: 'Raw (unconverted) balance per currency',
1305
+ type: 'array',
1306
+ items: {
1307
+ $ref: '#/components/schemas/BalanceByCurrencyDto'
1308
+ }
1309
+ },
1310
+ warnings: {
1311
+ description: 'Currencies missing an FX rate (omitted when empty)',
1312
+ type: 'array',
1313
+ items: {
1314
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
1315
+ }
1316
+ }
1317
+ },
1318
+ required: ['totalAmount', 'currency', 'balanceByCurrency']
1319
+ } as const;
1320
+
1119
1321
  export const $TransactionListResponseDto = {
1120
1322
  type: 'object',
1121
1323
  properties: {
@@ -1140,6 +1342,15 @@ export const $TransactionListResponseDto = {
1140
1342
  type: 'number',
1141
1343
  description: 'Number of items skipped',
1142
1344
  example: 0
1345
+ },
1346
+ summary: {
1347
+ description:
1348
+ 'Amount summary for the full filtered set (#514). Present only when the request has a single account OR category viewpoint; omitted for search-only / plain-list / dual-perspective requests.',
1349
+ allOf: [
1350
+ {
1351
+ $ref: '#/components/schemas/TransactionListSummaryDto'
1352
+ }
1353
+ ]
1143
1354
  }
1144
1355
  },
1145
1356
  required: ['data', 'total', 'limit', 'offset']
@@ -1724,7 +1935,8 @@ export const $ResolveResultDto = {
1724
1935
  },
1725
1936
  resolutionId: {
1726
1937
  type: 'string',
1727
- description: 'Resolution ID for undo'
1938
+ description:
1939
+ 'Resolution ID for undo. Absent when the resolver rejected the decision (review stayed PENDING).'
1728
1940
  },
1729
1941
  canUndo: {
1730
1942
  type: 'boolean',
@@ -1742,7 +1954,7 @@ export const $ResolveResultDto = {
1742
1954
  example: 'rule_01HXK5V8N2M3P4Q5R6S7T8U9V0'
1743
1955
  }
1744
1956
  },
1745
- required: ['success', 'resolutionId', 'canUndo', 'undoDeadline']
1957
+ required: ['success']
1746
1958
  } as const;
1747
1959
 
1748
1960
  export const $UndoResultDto = {
@@ -2613,84 +2825,241 @@ export const $UpdateCommodityDto = {
2613
2825
  }
2614
2826
  } as const;
2615
2827
 
2616
- export const $CreateRecurringRuleDto = {
2828
+ export const $CreateBeanPriceDto = {
2617
2829
  type: 'object',
2618
2830
  properties: {
2619
- name: {
2620
- type: 'string',
2621
- description: 'Rule name (unique per user)',
2622
- maxLength: 100
2623
- },
2624
- icon: {
2831
+ currency: {
2625
2832
  type: 'string',
2626
- description: 'Icon emoji',
2627
- maxLength: 10
2833
+ description: 'Currency being priced (e.g., USD, AAPL, BTC)',
2834
+ example: 'USD'
2628
2835
  },
2629
- frequency: {
2836
+ quoteCurrency: {
2630
2837
  type: 'string',
2631
- description: 'Recurring frequency',
2632
- enum: [
2633
- 'WEEKLY',
2634
- 'BIWEEKLY',
2635
- 'MONTHLY',
2636
- 'BIMONTHLY',
2637
- 'QUARTERLY',
2638
- 'YEARLY',
2639
- 'CUSTOM'
2640
- ]
2838
+ description: 'Quote currency (pricing currency, e.g., CNY, EUR)',
2839
+ example: 'CNY'
2641
2840
  },
2642
- expectedAmount: {
2841
+ amount: {
2643
2842
  type: 'number',
2644
- description: 'Expected amount (positive number)',
2843
+ description:
2844
+ 'Price amount (MUST be >= 0 per Beancount spec, supports up to 15 decimal places). Zero allowed for conversion entries, negative strictly prohibited.',
2845
+ example: 175.5,
2645
2846
  minimum: 0
2646
2847
  },
2647
- expectedDay: {
2648
- type: 'number',
2649
- description: 'Expected day of month (1-31)',
2650
- minimum: 1,
2651
- maximum: 31
2848
+ date: {
2849
+ type: 'string',
2850
+ description: 'Price date (ISO 8601 format)',
2851
+ example: '2024-11-05'
2652
2852
  },
2653
- customIntervalDays: {
2654
- type: 'number',
2655
- description: 'Custom interval in days (required for CUSTOM frequency)',
2656
- minimum: 1
2853
+ metadata: {
2854
+ type: 'object',
2855
+ description:
2856
+ 'Metadata (validated by Zod schema, max field lengths enforced)',
2857
+ example: {
2858
+ source: 'MANUAL',
2859
+ note: 'Bank valuation report',
2860
+ confidence: 0.95
2861
+ }
2862
+ }
2863
+ },
2864
+ required: ['currency', 'quoteCurrency', 'amount', 'date']
2865
+ } as const;
2866
+
2867
+ export const $PriceResponseDto = {
2868
+ type: 'object',
2869
+ properties: {
2870
+ id: {
2871
+ type: 'string',
2872
+ description: 'Unique identifier',
2873
+ example: 'uuid-123-456'
2874
+ },
2875
+ userId: {
2876
+ type: 'string',
2877
+ description: 'User ID (owner of the price)',
2878
+ example: 'user-123'
2657
2879
  },
2658
2880
  currency: {
2659
2881
  type: 'string',
2660
- description: 'Currency code',
2661
- default: 'CNY',
2662
- maxLength: 10
2882
+ description: 'Currency being priced (e.g., USD, AAPL, BTC)',
2883
+ example: 'BTC'
2663
2884
  },
2664
- matchPayeePattern: {
2885
+ quoteCurrency: {
2665
2886
  type: 'string',
2666
- description: 'Payee matching pattern (supports wildcards)',
2667
- maxLength: 200
2887
+ description: 'Quote currency (pricing currency, e.g., USD, CNY)',
2888
+ example: 'USD'
2668
2889
  },
2669
- matchAmountTolerance: {
2890
+ amount: {
2670
2891
  type: 'number',
2671
- description: 'Amount tolerance percentage (0-1)',
2672
- default: 0.075,
2673
- minimum: 0,
2674
- maximum: 1
2892
+ description:
2893
+ 'Price amount (corresponds to Beancount Amount.number). Supports up to 15 decimal places.',
2894
+ example: 50000
2675
2895
  },
2676
- defaultExpenseAccount: {
2896
+ date: {
2677
2897
  type: 'string',
2678
- description: 'Default expense account for auto-create',
2679
- maxLength: 200
2898
+ description:
2899
+ 'Price date (ISO 8601 format). Represents the date this price was valid.',
2900
+ example: '2024-01-01',
2901
+ format: 'date'
2680
2902
  },
2681
- defaultPaymentAccount: {
2682
- type: 'string',
2683
- description: 'Default payment account for auto-create',
2684
- maxLength: 200
2903
+ meta: {
2904
+ type: 'object',
2905
+ description:
2906
+ 'Metadata (corresponds to Beancount meta field). Contains source, confidence, note, etc.',
2907
+ example: {
2908
+ source: 'MANUAL',
2909
+ note: 'User-defined price',
2910
+ confidence: 1
2911
+ }
2685
2912
  },
2686
- defaultPayee: {
2913
+ createdAt: {
2914
+ format: 'date-time',
2687
2915
  type: 'string',
2688
- description: 'Default payee for auto-create',
2689
- maxLength: 200
2916
+ description: 'Creation timestamp',
2917
+ example: '2024-11-03T10:00:00Z'
2690
2918
  },
2691
- autoCreate: {
2692
- type: 'boolean',
2693
- description: 'Auto-create transaction when expected date arrives',
2919
+ updatedAt: {
2920
+ format: 'date-time',
2921
+ type: 'string',
2922
+ description: 'Last update timestamp',
2923
+ example: '2024-11-03T10:00:00Z'
2924
+ }
2925
+ },
2926
+ required: [
2927
+ 'id',
2928
+ 'userId',
2929
+ 'currency',
2930
+ 'quoteCurrency',
2931
+ 'amount',
2932
+ 'date',
2933
+ 'meta',
2934
+ 'createdAt',
2935
+ 'updatedAt'
2936
+ ]
2937
+ } as const;
2938
+
2939
+ export const $PriceListResponseDto = {
2940
+ type: 'object',
2941
+ properties: {
2942
+ items: {
2943
+ description: 'List of prices',
2944
+ type: 'array',
2945
+ items: {
2946
+ $ref: '#/components/schemas/PriceResponseDto'
2947
+ }
2948
+ },
2949
+ total: {
2950
+ type: 'number',
2951
+ description: 'Total number of prices',
2952
+ example: 42
2953
+ }
2954
+ },
2955
+ required: ['items', 'total']
2956
+ } as const;
2957
+
2958
+ export const $UpdateBeanPriceDto = {
2959
+ type: 'object',
2960
+ properties: {
2961
+ currency: {
2962
+ type: 'string',
2963
+ description: 'Currency being priced'
2964
+ },
2965
+ quoteCurrency: {
2966
+ type: 'string',
2967
+ description: 'Quote currency (pricing currency)'
2968
+ },
2969
+ amount: {
2970
+ type: 'number',
2971
+ description: 'Price amount (MUST be >= 0 per Beancount spec)',
2972
+ minimum: 0
2973
+ },
2974
+ date: {
2975
+ type: 'string',
2976
+ description: 'Price date (ISO 8601 format)'
2977
+ },
2978
+ metadata: {
2979
+ type: 'object',
2980
+ description: 'Metadata'
2981
+ }
2982
+ }
2983
+ } as const;
2984
+
2985
+ export const $CreateRecurringRuleDto = {
2986
+ type: 'object',
2987
+ properties: {
2988
+ name: {
2989
+ type: 'string',
2990
+ description: 'Rule name (unique per user)',
2991
+ maxLength: 100
2992
+ },
2993
+ icon: {
2994
+ type: 'string',
2995
+ description: 'Icon emoji',
2996
+ maxLength: 10
2997
+ },
2998
+ frequency: {
2999
+ type: 'string',
3000
+ description: 'Recurring frequency',
3001
+ enum: [
3002
+ 'WEEKLY',
3003
+ 'BIWEEKLY',
3004
+ 'MONTHLY',
3005
+ 'BIMONTHLY',
3006
+ 'QUARTERLY',
3007
+ 'YEARLY',
3008
+ 'CUSTOM'
3009
+ ]
3010
+ },
3011
+ expectedAmount: {
3012
+ type: 'number',
3013
+ description: 'Expected amount (positive number)',
3014
+ minimum: 0
3015
+ },
3016
+ expectedDay: {
3017
+ type: 'number',
3018
+ description: 'Expected day of month (1-31)',
3019
+ minimum: 1,
3020
+ maximum: 31
3021
+ },
3022
+ customIntervalDays: {
3023
+ type: 'number',
3024
+ description: 'Custom interval in days (required for CUSTOM frequency)',
3025
+ minimum: 1
3026
+ },
3027
+ currency: {
3028
+ type: 'string',
3029
+ description: 'Currency code',
3030
+ default: 'CNY',
3031
+ maxLength: 10
3032
+ },
3033
+ matchPayeePattern: {
3034
+ type: 'string',
3035
+ description: 'Payee matching pattern (supports wildcards)',
3036
+ maxLength: 200
3037
+ },
3038
+ matchAmountTolerance: {
3039
+ type: 'number',
3040
+ description: 'Amount tolerance percentage (0-1)',
3041
+ default: 0.075,
3042
+ minimum: 0,
3043
+ maximum: 1
3044
+ },
3045
+ defaultExpenseAccount: {
3046
+ type: 'string',
3047
+ description: 'Default expense account for auto-create',
3048
+ maxLength: 200
3049
+ },
3050
+ defaultPaymentAccount: {
3051
+ type: 'string',
3052
+ description: 'Default payment account for auto-create',
3053
+ maxLength: 200
3054
+ },
3055
+ defaultPayee: {
3056
+ type: 'string',
3057
+ description: 'Default payee for auto-create',
3058
+ maxLength: 200
3059
+ },
3060
+ autoCreate: {
3061
+ type: 'boolean',
3062
+ description: 'Auto-create transaction when expected date arrives',
2694
3063
  default: false
2695
3064
  },
2696
3065
  startDate: {
@@ -4180,107 +4549,447 @@ export const $UpdatePropertyDto = {
4180
4549
  required: ['value']
4181
4550
  } as const;
4182
4551
 
4183
- export const $FileImportDto = {
4552
+ export const $CreateBeanEventDto = {
4184
4553
  type: 'object',
4185
4554
  properties: {
4186
- file: {
4555
+ date: {
4187
4556
  type: 'string',
4188
- format: 'binary',
4189
- description: 'Bill file to import (CSV, PDF, OFX, etc.)',
4190
- example: 'alipay.csv'
4191
- }
4192
- },
4193
- required: ['file']
4194
- } as const;
4195
-
4196
- export const $ImportErrorDto = {
4197
- type: 'object',
4198
- properties: {
4199
- index: {
4200
- type: 'number',
4201
- description: 'Index of failed transaction in the file',
4202
- example: 5
4557
+ description: 'Life event date (ISO 8601)',
4558
+ example: '2024-03-15'
4203
4559
  },
4204
- error: {
4560
+ type: {
4205
4561
  type: 'string',
4206
- description: 'Error message',
4207
- example: 'Transaction does not balance: -100 USD != 0'
4562
+ description:
4563
+ 'Life event type (e.g., "employer", "location", "marital-status") — user-defined, no enum constraint at engine layer',
4564
+ example: 'employer'
4565
+ },
4566
+ description: {
4567
+ type: 'string',
4568
+ description:
4569
+ 'Life event description. Empty string is a VALID value (distinct from absence).',
4570
+ example: 'Acme Corp'
4571
+ },
4572
+ meta: {
4573
+ type: 'object',
4574
+ description:
4575
+ 'Product-side metadata (lives in BeanEvent.meta JSON, never in engine Event fields)',
4576
+ example: {
4577
+ note: 'Promotion'
4578
+ }
4208
4579
  }
4209
4580
  },
4210
- required: ['index', 'error']
4581
+ required: ['date', 'type', 'description']
4211
4582
  } as const;
4212
4583
 
4213
- export const $ReviewItemPreviewDto = {
4584
+ export const $EventResponseDto = {
4214
4585
  type: 'object',
4215
4586
  properties: {
4216
- index: {
4217
- type: 'number',
4218
- description: 'Index in the import batch (for tracking)',
4219
- example: 0
4220
- },
4221
- date: {
4587
+ id: {
4222
4588
  type: 'string',
4223
- description: 'Transaction date (ISO format)',
4224
- example: '2026-03-05'
4225
- },
4226
- amount: {
4227
- type: 'number',
4228
- description: 'Transaction amount (absolute value)',
4229
- example: 99
4589
+ description: 'Unique identifier',
4590
+ example: 'uuid-123-456'
4230
4591
  },
4231
- currency: {
4592
+ userId: {
4232
4593
  type: 'string',
4233
- description: 'Currency code',
4234
- example: 'CNY'
4594
+ description: 'User ID (owner of the life event)',
4595
+ example: 'user-123'
4235
4596
  },
4236
- narration: {
4597
+ date: {
4237
4598
  type: 'string',
4238
- description: 'Transaction narration/description',
4239
- example: 'Restaurant expense'
4599
+ description: 'Life event date (ISO 8601 format)',
4600
+ example: '2024-03-15',
4601
+ format: 'date'
4240
4602
  },
4241
- payee: {
4603
+ type: {
4242
4604
  type: 'string',
4243
- description: 'Payee name',
4244
- example: 'Restaurant ABC'
4605
+ description:
4606
+ 'Life event type (user-defined, e.g., "employer", "location")',
4607
+ example: 'employer'
4245
4608
  },
4246
- category: {
4609
+ description: {
4247
4610
  type: 'string',
4248
- description: 'Inferred category from rule matching',
4249
- example: 'food'
4611
+ description:
4612
+ 'Life event description. May be an empty string (a valid value distinct from absence).',
4613
+ example: 'Acme Corp'
4250
4614
  },
4251
- confidence: {
4252
- type: 'number',
4253
- description: 'Confidence score for the match (0-1)',
4254
- example: 0.85
4615
+ meta: {
4616
+ type: 'object',
4617
+ description: 'Product-side metadata (free-form JSON)',
4618
+ example: {
4619
+ note: 'Promotion'
4620
+ }
4255
4621
  },
4256
- branchType: {
4622
+ createdAt: {
4623
+ format: 'date-time',
4257
4624
  type: 'string',
4258
- description: 'Type of branch requiring review',
4259
- enum: [
4260
- 'DUPLICATE',
4261
- 'PAYEE_MATCH',
4262
- 'RULE_MATCH',
4263
- 'ACCOUNT_VALIDATION',
4264
- 'PIPELINE_ERROR'
4265
- ],
4266
- example: 'RULE_MATCH'
4625
+ description: 'Creation timestamp',
4626
+ example: '2024-03-15T10:00:00Z'
4267
4627
  },
4268
- reasons: {
4269
- description: 'Human-readable reasons for requiring review',
4270
- example: ['Moderate confidence rule match', 'Multiple rules matched'],
4628
+ updatedAt: {
4629
+ format: 'date-time',
4630
+ type: 'string',
4631
+ description:
4632
+ 'Last update timestamp. Also emitted as the ETag response header for If-Match optimistic concurrency.',
4633
+ example: '2024-03-15T10:00:00Z'
4634
+ }
4635
+ },
4636
+ required: [
4637
+ 'id',
4638
+ 'userId',
4639
+ 'date',
4640
+ 'type',
4641
+ 'description',
4642
+ 'meta',
4643
+ 'createdAt',
4644
+ 'updatedAt'
4645
+ ]
4646
+ } as const;
4647
+
4648
+ export const $EventListResponseDto = {
4649
+ type: 'object',
4650
+ properties: {
4651
+ items: {
4652
+ description: 'List of life events',
4271
4653
  type: 'array',
4272
4654
  items: {
4273
- type: 'string'
4655
+ $ref: '#/components/schemas/EventResponseDto'
4274
4656
  }
4657
+ },
4658
+ total: {
4659
+ type: 'number',
4660
+ description: 'Total number of life events matching the query',
4661
+ example: 42
4275
4662
  }
4276
4663
  },
4277
- required: ['index', 'date', 'narration']
4664
+ required: ['items', 'total']
4278
4665
  } as const;
4279
4666
 
4280
- export const $ImportResultDto = {
4667
+ export const $UpdateBeanEventDto = {
4281
4668
  type: 'object',
4282
4669
  properties: {
4283
- imported: {
4670
+ date: {
4671
+ type: 'string',
4672
+ description: 'Life event date (ISO 8601)'
4673
+ },
4674
+ type: {
4675
+ type: 'string',
4676
+ description: 'Life event type (user-defined)'
4677
+ },
4678
+ description: {
4679
+ type: 'string',
4680
+ description:
4681
+ 'Life event description. Empty string is a VALID value (distinct from absence).'
4682
+ },
4683
+ meta: {
4684
+ type: 'object',
4685
+ description: 'Product-side metadata (free-form JSON)'
4686
+ }
4687
+ }
4688
+ } as const;
4689
+
4690
+ export const $ActualBalanceDto = {
4691
+ type: 'object',
4692
+ properties: {
4693
+ amount: {
4694
+ type: 'string',
4695
+ description:
4696
+ 'Actual balance amount as a decimal string (preserves precision for tolerance inference).',
4697
+ example: '1234.56'
4698
+ },
4699
+ ccy: {
4700
+ type: 'string',
4701
+ description: 'Currency code (ISO 4217 or commodity ticker).',
4702
+ example: 'CNY'
4703
+ }
4704
+ },
4705
+ required: ['amount', 'ccy']
4706
+ } as const;
4707
+
4708
+ export const $ComputeReconciliationDto = {
4709
+ type: 'object',
4710
+ properties: {
4711
+ accountId: {
4712
+ type: 'string',
4713
+ description: 'BeanAccount id to reconcile.'
4714
+ },
4715
+ asOfDate: {
4716
+ type: 'string',
4717
+ description: 'Assertion date (ISO 8601, e.g. "2026-07-24").',
4718
+ example: '2026-07-24'
4719
+ },
4720
+ actualBalance: {
4721
+ description: 'Actual balance from the external statement.',
4722
+ allOf: [
4723
+ {
4724
+ $ref: '#/components/schemas/ActualBalanceDto'
4725
+ }
4726
+ ]
4727
+ }
4728
+ },
4729
+ required: ['accountId', 'asOfDate', 'actualBalance']
4730
+ } as const;
4731
+
4732
+ export const $ReconciliationComputeResultDto = {
4733
+ type: 'object',
4734
+ properties: {
4735
+ accountId: {
4736
+ type: 'string'
4737
+ },
4738
+ asOfDate: {
4739
+ type: 'string'
4740
+ },
4741
+ bookBalance: {
4742
+ type: 'string',
4743
+ description: 'System-computed book balance (decimal string).'
4744
+ },
4745
+ actualBalance: {
4746
+ type: 'string',
4747
+ description: 'User-entered actual balance (decimal string).'
4748
+ },
4749
+ currency: {
4750
+ type: 'string'
4751
+ },
4752
+ diff: {
4753
+ type: 'string',
4754
+ description: 'Diff = book − actual (decimal string).'
4755
+ },
4756
+ tolerance: {
4757
+ type: 'string',
4758
+ description: 'Applied tolerance (decimal string).'
4759
+ },
4760
+ withinTolerance: {
4761
+ type: 'boolean',
4762
+ description: 'true when |diff| ≤ tolerance.'
4763
+ },
4764
+ suggestedAction: {
4765
+ type: 'string',
4766
+ enum: ['assert', 'pad'],
4767
+ description:
4768
+ 'Suggested next action: assert when within tolerance, pad otherwise.'
4769
+ }
4770
+ },
4771
+ required: [
4772
+ 'accountId',
4773
+ 'asOfDate',
4774
+ 'bookBalance',
4775
+ 'actualBalance',
4776
+ 'currency',
4777
+ 'diff',
4778
+ 'tolerance',
4779
+ 'withinTolerance',
4780
+ 'suggestedAction'
4781
+ ]
4782
+ } as const;
4783
+
4784
+ export const $AssertReconciliationDto = {
4785
+ type: 'object',
4786
+ properties: {
4787
+ accountId: {
4788
+ type: 'string',
4789
+ description: 'BeanAccount id to reconcile.'
4790
+ },
4791
+ asOfDate: {
4792
+ type: 'string',
4793
+ description: 'Assertion date (ISO 8601, e.g. "2026-07-24").',
4794
+ example: '2026-07-24'
4795
+ },
4796
+ actualBalance: {
4797
+ description: 'Actual balance from the external statement.',
4798
+ allOf: [
4799
+ {
4800
+ $ref: '#/components/schemas/ActualBalanceDto'
4801
+ }
4802
+ ]
4803
+ },
4804
+ tolerance: {
4805
+ type: 'string',
4806
+ description:
4807
+ 'Optional explicit tolerance override. Omit to infer from amount precision (Beancount default).',
4808
+ example: '0.01'
4809
+ }
4810
+ },
4811
+ required: ['accountId', 'asOfDate', 'actualBalance']
4812
+ } as const;
4813
+
4814
+ export const $ReconciliationRecordDto = {
4815
+ type: 'object',
4816
+ properties: {
4817
+ id: {
4818
+ type: 'string'
4819
+ },
4820
+ accountId: {
4821
+ type: 'string'
4822
+ },
4823
+ date: {
4824
+ type: 'string'
4825
+ },
4826
+ amount: {
4827
+ type: 'string',
4828
+ description: 'Asserted (actual) amount.'
4829
+ },
4830
+ currency: {
4831
+ type: 'string'
4832
+ },
4833
+ tolerance: {
4834
+ type: 'string'
4835
+ },
4836
+ diffAmount: {
4837
+ type: 'string',
4838
+ description: 'book − actual.'
4839
+ },
4840
+ diffCurrency: {
4841
+ type: 'string'
4842
+ },
4843
+ createdAt: {
4844
+ type: 'string'
4845
+ }
4846
+ },
4847
+ required: ['id', 'accountId', 'date', 'amount', 'currency', 'createdAt']
4848
+ } as const;
4849
+
4850
+ export const $PadReconciliationDto = {
4851
+ type: 'object',
4852
+ properties: {
4853
+ accountId: {
4854
+ type: 'string',
4855
+ description: 'BeanAccount id to reconcile.'
4856
+ },
4857
+ asOfDate: {
4858
+ type: 'string',
4859
+ description: 'Assertion date (ISO 8601, e.g. "2026-07-24").',
4860
+ example: '2026-07-24'
4861
+ },
4862
+ actualBalance: {
4863
+ description: 'Actual balance from the external statement.',
4864
+ allOf: [
4865
+ {
4866
+ $ref: '#/components/schemas/ActualBalanceDto'
4867
+ }
4868
+ ]
4869
+ },
4870
+ sourceAccount: {
4871
+ type: 'string',
4872
+ description:
4873
+ 'Pad source account. Defaults to Equity:Opening-Balances (official Beancount convention).',
4874
+ example: 'Equity:Opening-Balances',
4875
+ default: 'Equity:Opening-Balances'
4876
+ }
4877
+ },
4878
+ required: ['accountId', 'asOfDate', 'actualBalance']
4879
+ } as const;
4880
+
4881
+ export const $PadResultDto = {
4882
+ type: 'object',
4883
+ properties: {
4884
+ transactionId: {
4885
+ type: 'string',
4886
+ description: 'Created pad adjusting transaction id.'
4887
+ }
4888
+ },
4889
+ required: ['transactionId']
4890
+ } as const;
4891
+
4892
+ export const $FileImportDto = {
4893
+ type: 'object',
4894
+ properties: {
4895
+ file: {
4896
+ type: 'string',
4897
+ format: 'binary',
4898
+ description: 'Bill file to import (CSV, PDF, OFX, etc.)',
4899
+ example: 'alipay.csv'
4900
+ }
4901
+ },
4902
+ required: ['file']
4903
+ } as const;
4904
+
4905
+ export const $ImportErrorDto = {
4906
+ type: 'object',
4907
+ properties: {
4908
+ index: {
4909
+ type: 'number',
4910
+ description: 'Index of failed transaction in the file',
4911
+ example: 5
4912
+ },
4913
+ error: {
4914
+ type: 'string',
4915
+ description: 'Error message',
4916
+ example: 'Transaction does not balance: -100 USD != 0'
4917
+ }
4918
+ },
4919
+ required: ['index', 'error']
4920
+ } as const;
4921
+
4922
+ export const $ReviewItemPreviewDto = {
4923
+ type: 'object',
4924
+ properties: {
4925
+ index: {
4926
+ type: 'number',
4927
+ description: 'Index in the import batch (for tracking)',
4928
+ example: 0
4929
+ },
4930
+ date: {
4931
+ type: 'string',
4932
+ description: 'Transaction date (ISO format)',
4933
+ example: '2026-03-05'
4934
+ },
4935
+ amount: {
4936
+ type: 'number',
4937
+ description: 'Transaction amount (absolute value)',
4938
+ example: 99
4939
+ },
4940
+ currency: {
4941
+ type: 'string',
4942
+ description: 'Currency code',
4943
+ example: 'CNY'
4944
+ },
4945
+ narration: {
4946
+ type: 'string',
4947
+ description: 'Transaction narration/description',
4948
+ example: 'Restaurant expense'
4949
+ },
4950
+ payee: {
4951
+ type: 'string',
4952
+ description: 'Payee name',
4953
+ example: 'Restaurant ABC'
4954
+ },
4955
+ category: {
4956
+ type: 'string',
4957
+ description: 'Inferred category from rule matching',
4958
+ example: 'food'
4959
+ },
4960
+ confidence: {
4961
+ type: 'number',
4962
+ description: 'Confidence score for the match (0-1)',
4963
+ example: 0.85
4964
+ },
4965
+ branchType: {
4966
+ type: 'string',
4967
+ description: 'Type of branch requiring review',
4968
+ enum: [
4969
+ 'DUPLICATE',
4970
+ 'PAYEE_MATCH',
4971
+ 'RULE_MATCH',
4972
+ 'ACCOUNT_VALIDATION',
4973
+ 'PIPELINE_ERROR'
4974
+ ],
4975
+ example: 'RULE_MATCH'
4976
+ },
4977
+ reasons: {
4978
+ description: 'Human-readable reasons for requiring review',
4979
+ example: ['Moderate confidence rule match', 'Multiple rules matched'],
4980
+ type: 'array',
4981
+ items: {
4982
+ type: 'string'
4983
+ }
4984
+ }
4985
+ },
4986
+ required: ['index', 'date', 'narration']
4987
+ } as const;
4988
+
4989
+ export const $ImportResultDto = {
4990
+ type: 'object',
4991
+ properties: {
4992
+ imported: {
4284
4993
  type: 'number',
4285
4994
  description: 'Number of successfully imported transactions',
4286
4995
  example: 45
@@ -4852,6 +5561,11 @@ export const $ParserTelemetryReportDto = {
4852
5561
  properties: {}
4853
5562
  } as const;
4854
5563
 
5564
+ export const $UncoveredFormatMissDto = {
5565
+ type: 'object',
5566
+ properties: {}
5567
+ } as const;
5568
+
4855
5569
  export const $ProcessNlpDto = {
4856
5570
  type: 'object',
4857
5571
  properties: {
@@ -5654,24 +6368,7 @@ export const $NlpResponseDto = {
5654
6368
  required: ['status', 'action']
5655
6369
  } as const;
5656
6370
 
5657
- export const $BalanceByCurrencyDto = {
5658
- type: 'object',
5659
- properties: {
5660
- currency: {
5661
- type: 'string',
5662
- description: 'ISO 4217 currency code',
5663
- example: 'CNY'
5664
- },
5665
- balance: {
5666
- type: 'string',
5667
- description: 'Balance amount',
5668
- example: '50000.00'
5669
- }
5670
- },
5671
- required: ['currency', 'balance']
5672
- } as const;
5673
-
5674
- export const $NetWorthByCurrencyDto = {
6371
+ export const $NetWorthByCurrencyDto = {
5675
6372
  type: 'object',
5676
6373
  properties: {
5677
6374
  netWorth: {
@@ -5740,28 +6437,6 @@ export const $ConvertedNetWorthDto = {
5740
6437
  ]
5741
6438
  } as const;
5742
6439
 
5743
- export const $ExchangeRateWarningDto = {
5744
- type: 'object',
5745
- properties: {
5746
- type: {
5747
- type: 'string',
5748
- description: 'Warning type',
5749
- example: 'MISSING_EXCHANGE_RATE'
5750
- },
5751
- currency: {
5752
- type: 'string',
5753
- description: 'Currency without exchange rate',
5754
- example: 'EUR'
5755
- },
5756
- totalAmount: {
5757
- type: 'string',
5758
- description: 'Total amount affected',
5759
- example: '1000.00'
5760
- }
5761
- },
5762
- required: ['type', 'currency', 'totalAmount']
5763
- } as const;
5764
-
5765
6440
  export const $NetWorthResponseDto = {
5766
6441
  type: 'object',
5767
6442
  properties: {
@@ -5863,6 +6538,12 @@ export const $AccountItemDto = {
5863
6538
  type: 'string',
5864
6539
  description: 'Currency code',
5865
6540
  example: 'CNY'
6541
+ },
6542
+ convertedBalance: {
6543
+ type: 'string',
6544
+ description:
6545
+ 'FX-converted balance in base currency; omitted when not convertible',
6546
+ example: '50000.00'
5866
6547
  }
5867
6548
  },
5868
6549
  required: ['id', 'name', 'displayName', 'balance', 'currency']
@@ -5889,11 +6570,66 @@ export const $PlatformGroupDto = {
5889
6570
  },
5890
6571
  totalBalance: {
5891
6572
  type: 'string',
5892
- description: 'Total balance across all accounts in platform',
6573
+ description: 'FX-converted total balance in base currency',
6574
+ example: '100000.00'
6575
+ },
6576
+ balanceByCurrency: {
6577
+ description: 'Raw (unconverted) balances grouped by currency',
6578
+ type: 'array',
6579
+ items: {
6580
+ $ref: '#/components/schemas/BalanceByCurrencyDto'
6581
+ }
6582
+ },
6583
+ convertedBalance: {
6584
+ type: 'string',
6585
+ description:
6586
+ 'Converted balance in base currency (omitted when no currency is convertible)',
5893
6587
  example: '100000.00'
6588
+ },
6589
+ sharePct: {
6590
+ type: 'number',
6591
+ description:
6592
+ 'Share of the grand converted total (0-100); 0 when grand total is 0',
6593
+ example: 42.5
6594
+ }
6595
+ },
6596
+ required: [
6597
+ 'platformId',
6598
+ 'platformName',
6599
+ 'accounts',
6600
+ 'totalBalance',
6601
+ 'balanceByCurrency',
6602
+ 'sharePct'
6603
+ ]
6604
+ } as const;
6605
+
6606
+ export const $AccountExchangeRateWarningDto = {
6607
+ type: 'object',
6608
+ properties: {
6609
+ type: {
6610
+ type: 'string',
6611
+ description: 'Warning type',
6612
+ example: 'MISSING_EXCHANGE_RATE'
6613
+ },
6614
+ currency: {
6615
+ type: 'string',
6616
+ description: 'Currency without exchange rate',
6617
+ example: 'USD'
6618
+ },
6619
+ accounts: {
6620
+ description: 'Affected account paths',
6621
+ type: 'array',
6622
+ items: {
6623
+ type: 'string'
6624
+ }
6625
+ },
6626
+ totalAmount: {
6627
+ type: 'string',
6628
+ description: 'Total amount in this currency',
6629
+ example: '5000.00'
5894
6630
  }
5895
6631
  },
5896
- required: ['platformId', 'platformName', 'accounts', 'totalBalance']
6632
+ required: ['type', 'currency', 'accounts', 'totalAmount']
5897
6633
  } as const;
5898
6634
 
5899
6635
  export const $AccountsSummaryDto = {
@@ -5906,9 +6642,21 @@ export const $AccountsSummaryDto = {
5906
6642
  totalPlatforms: {
5907
6643
  type: 'number',
5908
6644
  description: 'Total number of platforms'
6645
+ },
6646
+ baseCurrency: {
6647
+ type: 'string',
6648
+ description: 'Base currency for conversion',
6649
+ example: 'CNY'
6650
+ },
6651
+ warnings: {
6652
+ description: 'Per-account exchange rate warnings',
6653
+ type: 'array',
6654
+ items: {
6655
+ $ref: '#/components/schemas/AccountExchangeRateWarningDto'
6656
+ }
5909
6657
  }
5910
6658
  },
5911
- required: ['totalAccounts', 'totalPlatforms']
6659
+ required: ['totalAccounts', 'totalPlatforms', 'baseCurrency']
5912
6660
  } as const;
5913
6661
 
5914
6662
  export const $AccountsResponseDto = {
@@ -5960,6 +6708,12 @@ export const $AccountItemWithAssetClassDto = {
5960
6708
  description: 'Currency code',
5961
6709
  example: 'CNY'
5962
6710
  },
6711
+ convertedBalance: {
6712
+ type: 'string',
6713
+ description:
6714
+ 'FX-converted balance in base currency; omitted when not convertible',
6715
+ example: '50000.00'
6716
+ },
5963
6717
  assetClass: {
5964
6718
  type: 'string',
5965
6719
  description: 'Asset class',
@@ -5979,6 +6733,12 @@ export const $AccountItemWithAssetClassDto = {
5979
6733
  type: 'string',
5980
6734
  description: 'Risk level',
5981
6735
  example: 'LOW'
6736
+ },
6737
+ source: {
6738
+ type: 'string',
6739
+ description:
6740
+ 'ADR-0105 classification provenance (holding level always; account level only on FALLBACK)',
6741
+ enum: ['USER_META', 'FIAT_CURRENCY', 'OPENBB_MAPPING', 'FALLBACK']
5982
6742
  }
5983
6743
  },
5984
6744
  required: ['id', 'name', 'displayName', 'balance', 'currency', 'assetClass']
@@ -6033,35 +6793,6 @@ export const $AssetClassGroupDto = {
6033
6793
  required: ['assetClass', 'accounts', 'balanceByCurrency']
6034
6794
  } as const;
6035
6795
 
6036
- export const $AccountExchangeRateWarningDto = {
6037
- type: 'object',
6038
- properties: {
6039
- type: {
6040
- type: 'string',
6041
- description: 'Warning type',
6042
- example: 'MISSING_EXCHANGE_RATE'
6043
- },
6044
- currency: {
6045
- type: 'string',
6046
- description: 'Currency without exchange rate',
6047
- example: 'USD'
6048
- },
6049
- accounts: {
6050
- description: 'Affected account paths',
6051
- type: 'array',
6052
- items: {
6053
- type: 'string'
6054
- }
6055
- },
6056
- totalAmount: {
6057
- type: 'string',
6058
- description: 'Total amount in this currency',
6059
- example: '5000.00'
6060
- }
6061
- },
6062
- required: ['type', 'currency', 'accounts', 'totalAmount']
6063
- } as const;
6064
-
6065
6796
  export const $AssetClassSummaryDto = {
6066
6797
  type: 'object',
6067
6798
  properties: {
@@ -6084,6 +6815,11 @@ export const $AssetClassSummaryDto = {
6084
6815
  items: {
6085
6816
  $ref: '#/components/schemas/AccountExchangeRateWarningDto'
6086
6817
  }
6818
+ },
6819
+ fallback: {
6820
+ type: 'object',
6821
+ description:
6822
+ 'ADR-0105 §4 fallback provenance stats (holding level only). valueRatio is the grey-area share of total converted value; count is the number of source=FALLBACK holdings.'
6087
6823
  }
6088
6824
  },
6089
6825
  required: ['totalAccounts', 'totalAssetClasses', 'baseCurrency']
@@ -6106,11 +6842,107 @@ export const $AssetClassAccountsResponseDto = {
6106
6842
  $ref: '#/components/schemas/AssetClassSummaryDto'
6107
6843
  }
6108
6844
  ]
6845
+ },
6846
+ uncategorized: {
6847
+ description:
6848
+ 'ADR-0105 §6 holding-level grey-area bucket (source=FALLBACK holdings peeled out of groups). Present only for groupBy=holdingAssetClass when FALLBACK holdings exist.',
6849
+ allOf: [
6850
+ {
6851
+ $ref: '#/components/schemas/AssetClassGroupDto'
6852
+ }
6853
+ ]
6109
6854
  }
6110
6855
  },
6111
6856
  required: ['groups', 'summary']
6112
6857
  } as const;
6113
6858
 
6859
+ export const $HoldingAssetClassAccountSliceDto = {
6860
+ type: 'object',
6861
+ properties: {
6862
+ accountId: {
6863
+ type: 'string',
6864
+ description: 'Account ID'
6865
+ },
6866
+ accountPath: {
6867
+ type: 'string',
6868
+ description: 'Full account path',
6869
+ example: 'Assets:US:Investments:Brokerage'
6870
+ },
6871
+ accountCurrency: {
6872
+ type: 'string',
6873
+ description:
6874
+ 'Currency of the holding with the largest converted base value; undefined when no holding is convertible',
6875
+ example: 'USD'
6876
+ },
6877
+ marketValueBase: {
6878
+ type: 'string',
6879
+ description:
6880
+ "Account's market value in base currency (Σ converted holdings; grey bucket included)",
6881
+ example: '50000.00'
6882
+ },
6883
+ shareOfTotalPct: {
6884
+ type: 'number',
6885
+ description:
6886
+ 'Share of the global total (0-100). 0 when globalTotal is zero (no NaN/Infinity).',
6887
+ example: 42.5
6888
+ },
6889
+ groups: {
6890
+ description: 'Per-account asset-class breakdown',
6891
+ type: 'array',
6892
+ items: {
6893
+ $ref: '#/components/schemas/AssetClassGroupDto'
6894
+ }
6895
+ },
6896
+ uncategorized: {
6897
+ description:
6898
+ 'Per-account grey bucket (source=FALLBACK holdings, incl. broker cash)',
6899
+ allOf: [
6900
+ {
6901
+ $ref: '#/components/schemas/AssetClassGroupDto'
6902
+ }
6903
+ ]
6904
+ },
6905
+ holdings: {
6906
+ description:
6907
+ 'Every holding row for this account (account ID in each row’s `id` field)',
6908
+ type: 'array',
6909
+ items: {
6910
+ $ref: '#/components/schemas/AccountItemWithAssetClassDto'
6911
+ }
6912
+ }
6913
+ },
6914
+ required: [
6915
+ 'accountId',
6916
+ 'accountPath',
6917
+ 'marketValueBase',
6918
+ 'shareOfTotalPct',
6919
+ 'groups',
6920
+ 'holdings'
6921
+ ]
6922
+ } as const;
6923
+
6924
+ export const $HoldingAssetClassCrossAccountResponseDto = {
6925
+ type: 'object',
6926
+ properties: {
6927
+ global: {
6928
+ description: 'Merged cross-account holding aggregation',
6929
+ allOf: [
6930
+ {
6931
+ $ref: '#/components/schemas/AssetClassAccountsResponseDto'
6932
+ }
6933
+ ]
6934
+ },
6935
+ byAccount: {
6936
+ description: 'Per-account slices',
6937
+ type: 'array',
6938
+ items: {
6939
+ $ref: '#/components/schemas/HoldingAssetClassAccountSliceDto'
6940
+ }
6941
+ }
6942
+ },
6943
+ required: ['global', 'byAccount']
6944
+ } as const;
6945
+
6114
6946
  export const $CashFlowByCurrencyDto = {
6115
6947
  type: 'object',
6116
6948
  properties: {
@@ -6240,64 +7072,458 @@ export const $CashFlowResponseDto = {
6240
7072
  ]
6241
7073
  } as const;
6242
7074
 
6243
- export const $CurrencyBalanceDto = {
7075
+ export const $CategoryGroupDto = {
6244
7076
  type: 'object',
6245
7077
  properties: {
6246
- currency: {
7078
+ category: {
6247
7079
  type: 'string',
6248
- description: 'ISO 4217 currency code',
6249
- example: 'CNY'
7080
+ description:
7081
+ 'Functional category (account-path Group segment); regional and universal account paths merge under it',
7082
+ example: 'Food'
6250
7083
  },
6251
- balance: {
7084
+ totalExpense: {
6252
7085
  type: 'string',
6253
- description: 'Balance amount',
6254
- example: '500000.00'
7086
+ description:
7087
+ 'Converted total for this category in base currency (expense amount when flow=expense, income amount when flow=income)',
7088
+ example: '1200.00'
7089
+ },
7090
+ sharePct: {
7091
+ type: 'number',
7092
+ description: 'Share of grand total (0-100); 0 when grand total is 0',
7093
+ example: 42.5
7094
+ },
7095
+ balanceByCurrency: {
7096
+ description: 'Raw (unconverted) expense per currency',
7097
+ type: 'array',
7098
+ items: {
7099
+ $ref: '#/components/schemas/BalanceByCurrencyDto'
7100
+ }
7101
+ },
7102
+ convertedBalance: {
7103
+ type: 'string',
7104
+ description:
7105
+ 'Converted total in base currency (omitted when FX missing for all currencies in this category)',
7106
+ example: '1200.00'
6255
7107
  }
6256
7108
  },
6257
- required: ['currency', 'balance']
7109
+ required: ['category', 'totalExpense', 'sharePct', 'balanceByCurrency']
6258
7110
  } as const;
6259
7111
 
6260
- export const $TimeSeriesPointDto = {
7112
+ export const $ExpensesByCategorySummaryDto = {
6261
7113
  type: 'object',
6262
7114
  properties: {
6263
- date: {
6264
- type: 'string',
6265
- description: 'Date in YYYY-MM-DD format',
6266
- example: '2024-06-15'
6267
- },
6268
- value: {
7115
+ totalExpense: {
6269
7116
  type: 'string',
6270
- description: 'Value at this date (in base currency)',
6271
- example: '500000.00'
6272
- },
6273
- change: {
6274
- type: 'object',
6275
- description: 'Change from previous point',
7117
+ description:
7118
+ 'Total across all categories, converted (convertible categories only); expense totals when flow=expense, income totals when flow=income',
6276
7119
  example: '5000.00'
6277
7120
  },
6278
- byCurrency: {
6279
- description: 'Multi-currency breakdown for this point',
6280
- type: 'array',
6281
- items: {
6282
- $ref: '#/components/schemas/CurrencyBalanceDto'
6283
- }
7121
+ categoryCount: {
7122
+ type: 'number',
7123
+ description: 'Number of categories',
7124
+ example: 8
6284
7125
  }
6285
7126
  },
6286
- required: ['date', 'value']
7127
+ required: ['totalExpense', 'categoryCount']
6287
7128
  } as const;
6288
7129
 
6289
- export const $TrendSummaryDto = {
7130
+ export const $ExpensesByCategoryResponseDto = {
6290
7131
  type: 'object',
6291
7132
  properties: {
6292
- startValue: {
7133
+ period: {
6293
7134
  type: 'string',
6294
- description: 'Value at start of period',
6295
- example: '450000.00'
7135
+ description: 'Period requested',
7136
+ example: '1m'
6296
7137
  },
6297
- endValue: {
7138
+ baseCurrency: {
6298
7139
  type: 'string',
6299
- description: 'Value at end of period',
6300
- example: '500000.00'
7140
+ description: 'Base currency for converted values',
7141
+ example: 'CNY'
7142
+ },
7143
+ groups: {
7144
+ description:
7145
+ 'Expense groups by functional category, sorted by converted total desc',
7146
+ type: 'array',
7147
+ items: {
7148
+ $ref: '#/components/schemas/CategoryGroupDto'
7149
+ }
7150
+ },
7151
+ summary: {
7152
+ description: 'Summary statistics',
7153
+ allOf: [
7154
+ {
7155
+ $ref: '#/components/schemas/ExpensesByCategorySummaryDto'
7156
+ }
7157
+ ]
7158
+ },
7159
+ warnings: {
7160
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
7161
+ type: 'array',
7162
+ items: {
7163
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
7164
+ }
7165
+ }
7166
+ },
7167
+ required: ['period', 'baseCurrency', 'groups', 'summary']
7168
+ } as const;
7169
+
7170
+ export const $MonetaryDto = {
7171
+ type: 'object',
7172
+ properties: {
7173
+ amount: {
7174
+ type: 'string',
7175
+ description: 'Amount (Decimal string)',
7176
+ example: '3000'
7177
+ },
7178
+ currency: {
7179
+ type: 'string',
7180
+ description: 'ISO 4217 currency',
7181
+ example: 'USD'
7182
+ },
7183
+ baseCcyEquivalent: {
7184
+ type: 'object',
7185
+ description: 'Converted to user base currency (Decimal string)',
7186
+ example: '21600',
7187
+ nullable: true
7188
+ }
7189
+ },
7190
+ required: ['amount', 'currency']
7191
+ } as const;
7192
+
7193
+ export const $CurrentPriceDto = {
7194
+ type: 'object',
7195
+ properties: {
7196
+ amount: {
7197
+ type: 'string',
7198
+ description: 'Price amount (Decimal string)',
7199
+ example: '250'
7200
+ },
7201
+ currency: {
7202
+ type: 'string',
7203
+ description: 'Price currency (ISO 4217)',
7204
+ example: 'USD'
7205
+ },
7206
+ date: {
7207
+ type: 'string',
7208
+ description: 'Price date (ISO 8601)',
7209
+ example: '2024-06-01'
7210
+ },
7211
+ source: {
7212
+ type: 'string',
7213
+ description: 'Price source',
7214
+ example: 'USER_OVERRIDE',
7215
+ enum: ['USER_OVERRIDE', 'OPENBB_EQUITY', 'OPENBB_CURRENCY']
7216
+ }
7217
+ },
7218
+ required: ['amount', 'currency', 'date', 'source']
7219
+ } as const;
7220
+
7221
+ export const $FxRateDto = {
7222
+ type: 'object',
7223
+ properties: {
7224
+ from: {
7225
+ type: 'string',
7226
+ example: 'USD'
7227
+ },
7228
+ to: {
7229
+ type: 'string',
7230
+ example: 'CNY'
7231
+ },
7232
+ rate: {
7233
+ type: 'string',
7234
+ description: 'FX rate (Decimal string)',
7235
+ example: '7.2'
7236
+ },
7237
+ date: {
7238
+ type: 'string',
7239
+ description: 'Rate date (ISO 8601)',
7240
+ example: '2024-01-15'
7241
+ }
7242
+ },
7243
+ required: ['from', 'to', 'rate', 'date']
7244
+ } as const;
7245
+
7246
+ export const $HoldingPnlRowDto = {
7247
+ type: 'object',
7248
+ properties: {
7249
+ accountId: {
7250
+ type: 'string',
7251
+ description: 'Account UUID',
7252
+ example: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
7253
+ },
7254
+ accountPath: {
7255
+ type: 'string',
7256
+ description: 'Full account path',
7257
+ example: 'Assets:US:Broker:AAPL'
7258
+ },
7259
+ accountCcy: {
7260
+ type: 'object',
7261
+ description: 'Account settlement currency (ISO 4217), from cost currency',
7262
+ nullable: true,
7263
+ example: 'USD'
7264
+ },
7265
+ brokerType: {
7266
+ type: 'object',
7267
+ description: 'Broker type derived from Platform.type',
7268
+ nullable: true,
7269
+ example: 'broker'
7270
+ },
7271
+ symbol: {
7272
+ type: 'string',
7273
+ description: 'Commodity symbol',
7274
+ example: 'AAPL'
7275
+ },
7276
+ chartToken: {
7277
+ type: 'string',
7278
+ description: 'Chart segment token (libs/common resolver)',
7279
+ example: 'equity',
7280
+ enum: ['equity', 'fund', 'bond', 'cash', 'other']
7281
+ },
7282
+ assetClass: {
7283
+ type: 'string',
7284
+ example: 'EQUITY'
7285
+ },
7286
+ assetSubClass: {
7287
+ type: 'object',
7288
+ nullable: true,
7289
+ example: 'STOCK'
7290
+ },
7291
+ units: {
7292
+ type: 'string',
7293
+ description: 'Net held units (Decimal string)',
7294
+ example: '12'
7295
+ },
7296
+ averageCostPerUnit: {
7297
+ description:
7298
+ 'Average cost per unit; null when cost currency conflicts or no cost',
7299
+ nullable: true,
7300
+ allOf: [
7301
+ {
7302
+ $ref: '#/components/schemas/MonetaryDto'
7303
+ }
7304
+ ]
7305
+ },
7306
+ costBasis: {
7307
+ description: 'Cost basis of held units',
7308
+ nullable: true,
7309
+ allOf: [
7310
+ {
7311
+ $ref: '#/components/schemas/MonetaryDto'
7312
+ }
7313
+ ]
7314
+ },
7315
+ marketValue: {
7316
+ description: 'Market value at asOf price',
7317
+ nullable: true,
7318
+ allOf: [
7319
+ {
7320
+ $ref: '#/components/schemas/MonetaryDto'
7321
+ }
7322
+ ]
7323
+ },
7324
+ currentPrice: {
7325
+ description: 'Price used for market value',
7326
+ nullable: true,
7327
+ allOf: [
7328
+ {
7329
+ $ref: '#/components/schemas/CurrentPriceDto'
7330
+ }
7331
+ ]
7332
+ },
7333
+ unrealizedPnlBase: {
7334
+ type: 'object',
7335
+ description:
7336
+ 'Unrealized P&L in base currency (Decimal string); null when any FX/price missing',
7337
+ nullable: true,
7338
+ example: '6000'
7339
+ },
7340
+ unrealizedPnlPct: {
7341
+ type: 'object',
7342
+ description: 'Unrealized P&L % (Decimal string)',
7343
+ nullable: true,
7344
+ example: '25'
7345
+ },
7346
+ costFxRate: {
7347
+ description: 'Historical FX rate applied to cost basis',
7348
+ nullable: true,
7349
+ allOf: [
7350
+ {
7351
+ $ref: '#/components/schemas/FxRateDto'
7352
+ }
7353
+ ]
7354
+ },
7355
+ marketFxRate: {
7356
+ description: 'FX rate applied to market value',
7357
+ nullable: true,
7358
+ allOf: [
7359
+ {
7360
+ $ref: '#/components/schemas/FxRateDto'
7361
+ }
7362
+ ]
7363
+ },
7364
+ pctOfInvestedAssets: {
7365
+ type: 'object',
7366
+ description:
7367
+ 'Share of invested assets % (Decimal string); only for invested chartTokens',
7368
+ nullable: true,
7369
+ example: '40'
7370
+ },
7371
+ realizedPnl: {
7372
+ description:
7373
+ 'Cumulative realized P&L on sold lots (asOf-date cutoff); null when the method has no applicable sells, a sell lacks a price, or any required FX rate is missing (never-mix). When a sell spans multiple currencies (cross-currency sale), amount and currency reflect the base currency; baseCcyEquivalent is always the authoritative dual-FX figure',
7374
+ nullable: true,
7375
+ allOf: [
7376
+ {
7377
+ $ref: '#/components/schemas/MonetaryDto'
7378
+ }
7379
+ ]
7380
+ }
7381
+ },
7382
+ required: [
7383
+ 'accountId',
7384
+ 'accountPath',
7385
+ 'symbol',
7386
+ 'chartToken',
7387
+ 'assetClass',
7388
+ 'units'
7389
+ ]
7390
+ } as const;
7391
+
7392
+ export const $HoldingPnlWarningDto = {
7393
+ type: 'object',
7394
+ properties: {
7395
+ type: {
7396
+ type: 'string',
7397
+ description: 'Warning type',
7398
+ example: 'MISSING_COST_FX_RATE',
7399
+ enum: [
7400
+ 'MISSING_COST_FX_RATE',
7401
+ 'MISSING_MARKET_FX_RATE',
7402
+ 'MISSING_SALE_PRICE',
7403
+ 'MISSING_REALIZED_FX_RATE',
7404
+ 'OVERSOLD_LOTS',
7405
+ 'NO_PRICE',
7406
+ 'MIXED_COST_CURRENCY'
7407
+ ]
7408
+ },
7409
+ symbol: {
7410
+ type: 'object',
7411
+ nullable: true
7412
+ },
7413
+ accountId: {
7414
+ type: 'object',
7415
+ nullable: true
7416
+ },
7417
+ currency: {
7418
+ type: 'object',
7419
+ nullable: true
7420
+ }
7421
+ },
7422
+ required: ['type']
7423
+ } as const;
7424
+
7425
+ export const $HoldingPnlResponseDto = {
7426
+ type: 'object',
7427
+ properties: {
7428
+ asOfDate: {
7429
+ type: 'string',
7430
+ example: '2026-07-08'
7431
+ },
7432
+ baseCurrency: {
7433
+ type: 'string',
7434
+ example: 'CNY'
7435
+ },
7436
+ method: {
7437
+ type: 'string',
7438
+ description:
7439
+ 'Realized-P&L lot-matching method (FIFO or average). Unrealized cost basis remains average regardless of this value (#473).',
7440
+ enum: ['average', 'FIFO'],
7441
+ example: 'average'
7442
+ },
7443
+ rows: {
7444
+ type: 'array',
7445
+ items: {
7446
+ $ref: '#/components/schemas/HoldingPnlRowDto'
7447
+ }
7448
+ },
7449
+ warnings: {
7450
+ type: 'array',
7451
+ items: {
7452
+ $ref: '#/components/schemas/HoldingPnlWarningDto'
7453
+ }
7454
+ }
7455
+ },
7456
+ required: ['asOfDate', 'baseCurrency', 'method', 'rows', 'warnings']
7457
+ } as const;
7458
+
7459
+ export const $CurrencyBalanceDto = {
7460
+ type: 'object',
7461
+ properties: {
7462
+ currency: {
7463
+ type: 'string',
7464
+ description: 'ISO 4217 currency code',
7465
+ example: 'CNY'
7466
+ },
7467
+ balance: {
7468
+ type: 'string',
7469
+ description: 'Balance amount',
7470
+ example: '500000.00'
7471
+ }
7472
+ },
7473
+ required: ['currency', 'balance']
7474
+ } as const;
7475
+
7476
+ export const $TimeSeriesPointDto = {
7477
+ type: 'object',
7478
+ properties: {
7479
+ date: {
7480
+ type: 'string',
7481
+ description: 'Date in YYYY-MM-DD format',
7482
+ example: '2024-06-15'
7483
+ },
7484
+ value: {
7485
+ type: 'string',
7486
+ description: 'Value at this date (in base currency)',
7487
+ example: '500000.00'
7488
+ },
7489
+ change: {
7490
+ type: 'object',
7491
+ description: 'Change from previous point',
7492
+ example: '5000.00'
7493
+ },
7494
+ assets: {
7495
+ type: 'string',
7496
+ description: 'Total assets at this date (in base currency)',
7497
+ example: '494338.00'
7498
+ },
7499
+ liabilities: {
7500
+ type: 'string',
7501
+ description: 'Total liabilities at this date (in base currency)',
7502
+ example: '310098.00'
7503
+ },
7504
+ byCurrency: {
7505
+ description: 'Multi-currency breakdown for this point',
7506
+ type: 'array',
7507
+ items: {
7508
+ $ref: '#/components/schemas/CurrencyBalanceDto'
7509
+ }
7510
+ }
7511
+ },
7512
+ required: ['date', 'value']
7513
+ } as const;
7514
+
7515
+ export const $TrendSummaryDto = {
7516
+ type: 'object',
7517
+ properties: {
7518
+ startValue: {
7519
+ type: 'string',
7520
+ description: 'Value at start of period',
7521
+ example: '450000.00'
7522
+ },
7523
+ endValue: {
7524
+ type: 'string',
7525
+ description: 'Value at end of period',
7526
+ example: '500000.00'
6301
7527
  },
6302
7528
  totalChange: {
6303
7529
  type: 'string',
@@ -6384,6 +7610,111 @@ export const $PortfolioTrendsResponseDto = {
6384
7610
  required: ['series', 'summary', 'period', 'granularity', 'currency']
6385
7611
  } as const;
6386
7612
 
7613
+ export const $CashFlowPointDto = {
7614
+ type: 'object',
7615
+ properties: {
7616
+ month: {
7617
+ type: 'string',
7618
+ description: 'Month key (YYYY-MM)',
7619
+ example: '2024-03'
7620
+ },
7621
+ income: {
7622
+ type: 'string',
7623
+ description: 'Income in base currency (absolute, converted)',
7624
+ example: '10000.00'
7625
+ },
7626
+ expense: {
7627
+ type: 'string',
7628
+ description: 'Expense in base currency (absolute, converted)',
7629
+ example: '5000.00'
7630
+ },
7631
+ netSavings: {
7632
+ type: 'string',
7633
+ description: 'netSavings = income − expense (savings positive)',
7634
+ example: '5000.00'
7635
+ }
7636
+ },
7637
+ required: ['month', 'income', 'expense', 'netSavings']
7638
+ } as const;
7639
+
7640
+ export const $CashFlowTrendSummaryDto = {
7641
+ type: 'object',
7642
+ properties: {
7643
+ totalIncome: {
7644
+ type: 'string',
7645
+ description: 'Total income across the period',
7646
+ example: '60000.00'
7647
+ },
7648
+ totalExpense: {
7649
+ type: 'string',
7650
+ description: 'Total expense across the period',
7651
+ example: '30000.00'
7652
+ },
7653
+ totalNetSavings: {
7654
+ type: 'string',
7655
+ description: 'income − expense across the period',
7656
+ example: '30000.00'
7657
+ },
7658
+ averageMonthlyNetSavings: {
7659
+ type: 'string',
7660
+ description:
7661
+ 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
7662
+ example: '5000.00'
7663
+ }
7664
+ },
7665
+ required: [
7666
+ 'totalIncome',
7667
+ 'totalExpense',
7668
+ 'totalNetSavings',
7669
+ 'averageMonthlyNetSavings'
7670
+ ]
7671
+ } as const;
7672
+
7673
+ export const $CashFlowTrendsResponseDto = {
7674
+ type: 'object',
7675
+ properties: {
7676
+ series: {
7677
+ description:
7678
+ 'Monthly cash-flow series (fixed N-month window, zero-filled)',
7679
+ type: 'array',
7680
+ items: {
7681
+ $ref: '#/components/schemas/CashFlowPointDto'
7682
+ }
7683
+ },
7684
+ summary: {
7685
+ description: 'Period totals',
7686
+ allOf: [
7687
+ {
7688
+ $ref: '#/components/schemas/CashFlowTrendSummaryDto'
7689
+ }
7690
+ ]
7691
+ },
7692
+ period: {
7693
+ type: 'string',
7694
+ description: 'Period requested',
7695
+ example: '6m'
7696
+ },
7697
+ granularity: {
7698
+ type: 'string',
7699
+ description: 'Data granularity (v1 returns month buckets)',
7700
+ example: 'month'
7701
+ },
7702
+ currency: {
7703
+ type: 'string',
7704
+ description: 'Base currency for converted values',
7705
+ example: 'CNY'
7706
+ },
7707
+ warnings: {
7708
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
7709
+ type: 'array',
7710
+ items: {
7711
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
7712
+ }
7713
+ }
7714
+ },
7715
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
7716
+ } as const;
7717
+
6387
7718
  export const $GenerateSnapshotBody = {
6388
7719
  type: 'object',
6389
7720
  properties: {}