@firela/api-types 0.0.0-canary.9256c41b → 0.0.0-canary.97006feb

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.
@@ -3751,517 +3751,454 @@ export const $ForecastResponseDto = {
3751
3751
  ]
3752
3752
  } as const;
3753
3753
 
3754
- export const $CreateTransactionRuleDto = {
3754
+ export const $CurrencyBalanceDto = {
3755
3755
  type: 'object',
3756
3756
  properties: {
3757
- name: {
3757
+ currency: {
3758
3758
  type: 'string',
3759
- minLength: 1,
3760
- maxLength: 100
3759
+ description: 'ISO 4217 currency code',
3760
+ example: 'CNY'
3761
3761
  },
3762
- description: {
3762
+ balance: {
3763
3763
  type: 'string',
3764
- maxLength: 500
3765
- },
3766
- narrationKeywords: {
3767
- items: {
3768
- type: 'array'
3769
- },
3770
- maxItems: 50,
3771
- type: 'array'
3772
- },
3773
- payeeKeywords: {
3774
- items: {
3775
- type: 'array'
3776
- },
3777
- maxItems: 50,
3778
- type: 'array'
3779
- },
3780
- categoryKeywords: {
3781
- items: {
3782
- type: 'array'
3783
- },
3784
- maxItems: 50,
3785
- type: 'array'
3786
- },
3787
- methodKeywords: {
3788
- items: {
3789
- type: 'array'
3790
- },
3791
- maxItems: 50,
3792
- description: 'Payment method keywords (e.g., HuaBei, YuEBao)',
3793
- type: 'array'
3794
- },
3795
- categoryAccount: {
3764
+ description: 'Balance amount',
3765
+ example: '500000.00'
3766
+ }
3767
+ },
3768
+ required: ['currency', 'balance']
3769
+ } as const;
3770
+
3771
+ export const $TimeSeriesPointDto = {
3772
+ type: 'object',
3773
+ properties: {
3774
+ date: {
3796
3775
  type: 'string',
3797
- maxLength: 200,
3798
- description:
3799
- 'Destination account for expenses/income (e.g., Expenses:Food:Coffee)'
3776
+ description: 'Date in YYYY-MM-DD format',
3777
+ example: '2024-06-15'
3800
3778
  },
3801
- matchLogic: {
3779
+ value: {
3802
3780
  type: 'string',
3803
- enum: ['OR', 'AND'],
3804
- default: 'OR'
3781
+ description: 'Value at this date (in base currency)',
3782
+ example: '500000.00'
3805
3783
  },
3806
- amountMin: {
3807
- type: 'number',
3808
- minimum: 0,
3809
- description: 'Minimum transaction amount (inclusive)'
3784
+ change: {
3785
+ type: 'object',
3786
+ description: 'Change from previous point',
3787
+ example: '5000.00'
3810
3788
  },
3811
- amountMax: {
3812
- type: 'number',
3813
- minimum: 0,
3814
- description: 'Maximum transaction amount (inclusive)'
3789
+ assets: {
3790
+ type: 'string',
3791
+ description: 'Total assets at this date (in base currency)',
3792
+ example: '494338.00'
3815
3793
  },
3816
- priority: {
3817
- type: 'number',
3818
- default: 50,
3819
- minimum: 0,
3820
- maximum: 1000
3794
+ liabilities: {
3795
+ type: 'string',
3796
+ description: 'Total liabilities at this date (in base currency)',
3797
+ example: '310098.00'
3821
3798
  },
3822
- additionalTags: {
3799
+ byCurrency: {
3800
+ description: 'Multi-currency breakdown for this point',
3801
+ type: 'array',
3823
3802
  items: {
3824
- type: 'array'
3825
- },
3826
- maxItems: 20,
3827
- type: 'array'
3828
- },
3829
- additionalMetadata: {
3830
- type: 'object'
3831
- },
3832
- upsertByPayee: {
3833
- type: 'boolean',
3834
- description:
3835
- 'If true, update existing rule with matching payeeKeywords[0] instead of creating new rule'
3803
+ $ref: '#/components/schemas/CurrencyBalanceDto'
3804
+ }
3836
3805
  }
3837
3806
  },
3838
- required: ['name', 'matchLogic', 'priority']
3807
+ required: ['date', 'value']
3839
3808
  } as const;
3840
3809
 
3841
- export const $AmountRangeDto = {
3810
+ export const $TrendSummaryDto = {
3842
3811
  type: 'object',
3843
3812
  properties: {
3844
- min: {
3845
- type: 'number',
3846
- description: 'Minimum amount'
3813
+ startValue: {
3814
+ type: 'string',
3815
+ description: 'Value at start of period',
3816
+ example: '450000.00'
3847
3817
  },
3848
- max: {
3849
- type: 'number',
3850
- description: 'Maximum amount'
3818
+ endValue: {
3819
+ type: 'string',
3820
+ description: 'Value at end of period',
3821
+ example: '500000.00'
3822
+ },
3823
+ totalChange: {
3824
+ type: 'string',
3825
+ description: 'Total change over period',
3826
+ example: '50000.00'
3827
+ },
3828
+ totalChangePercentage: {
3829
+ type: 'string',
3830
+ description: 'Total change percentage',
3831
+ example: '+11.11%'
3851
3832
  }
3852
- }
3833
+ },
3834
+ required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
3853
3835
  } as const;
3854
3836
 
3855
- export const $TransactionRuleResponseDto = {
3837
+ export const $MultiCurrencyPointDto = {
3856
3838
  type: 'object',
3857
3839
  properties: {
3858
- id: {
3859
- type: 'string',
3860
- description: 'Rule ID'
3861
- },
3862
- name: {
3863
- type: 'string',
3864
- description: 'Rule name'
3865
- },
3866
- description: {
3840
+ date: {
3867
3841
  type: 'string',
3868
- description: 'Rule description'
3869
- },
3870
- narrationKeywords: {
3871
- description: 'Keywords to match in transaction narration',
3872
- type: 'array',
3873
- items: {
3874
- type: 'string'
3875
- }
3876
- },
3877
- payeeKeywords: {
3878
- description: 'Keywords to match in payee name',
3879
- type: 'array',
3880
- items: {
3881
- type: 'string'
3882
- }
3842
+ description: 'Date in YYYY-MM-DD format',
3843
+ example: '2024-06-15'
3883
3844
  },
3884
- categoryKeywords: {
3885
- description: 'Keywords to match in category',
3845
+ byCurrency: {
3846
+ description: 'Balances by currency',
3886
3847
  type: 'array',
3887
3848
  items: {
3888
- type: 'string'
3849
+ $ref: '#/components/schemas/CurrencyBalanceDto'
3889
3850
  }
3890
- },
3891
- methodKeywords: {
3892
- description: 'Keywords to match in payment method',
3851
+ }
3852
+ },
3853
+ required: ['date', 'byCurrency']
3854
+ } as const;
3855
+
3856
+ export const $PortfolioTrendsResponseDto = {
3857
+ type: 'object',
3858
+ properties: {
3859
+ series: {
3860
+ description: 'Time series data points',
3893
3861
  type: 'array',
3894
3862
  items: {
3895
- type: 'string'
3863
+ $ref: '#/components/schemas/TimeSeriesPointDto'
3896
3864
  }
3897
3865
  },
3898
- categoryAccount: {
3899
- type: 'string',
3900
- description: 'Destination account for categorization'
3901
- },
3902
- matchLogic: {
3903
- type: 'string',
3904
- description: 'Keyword matching logic',
3905
- enum: ['OR', 'AND'],
3906
- example: 'OR'
3907
- },
3908
- amountRange: {
3909
- description: 'Amount range for matching',
3866
+ summary: {
3867
+ description: 'Period summary',
3910
3868
  allOf: [
3911
3869
  {
3912
- $ref: '#/components/schemas/AmountRangeDto'
3870
+ $ref: '#/components/schemas/TrendSummaryDto'
3913
3871
  }
3914
3872
  ]
3915
3873
  },
3916
- priority: {
3917
- type: 'number',
3918
- description: 'Rule priority (0-1000, higher = first match)',
3919
- example: 50
3920
- },
3921
- enabled: {
3922
- type: 'boolean',
3923
- description: 'Whether the rule is enabled'
3924
- },
3925
- learningSource: {
3874
+ period: {
3926
3875
  type: 'string',
3927
- description: 'Learning source: NLP, REVIEW_CENTER, or null for manual',
3928
- enum: ['NLP', 'REVIEW_CENTER'],
3929
- nullable: true,
3930
- example: 'REVIEW_CENTER'
3876
+ description: 'Period requested',
3877
+ example: '6m'
3931
3878
  },
3932
- autoApplyEnabled: {
3933
- type: 'boolean',
3934
- description: 'Whether auto-apply is enabled for this rule'
3879
+ granularity: {
3880
+ type: 'string',
3881
+ description: 'Data granularity',
3882
+ example: 'month'
3935
3883
  },
3936
- confirmationCount: {
3937
- type: 'number',
3938
- description: 'Number of confirmations for NLP-learned rules',
3939
- example: 3
3884
+ currency: {
3885
+ type: 'string',
3886
+ description: 'Base currency for converted values',
3887
+ example: 'CNY'
3940
3888
  },
3941
- additionalTags: {
3942
- description: 'Additional tags',
3889
+ byCurrency: {
3890
+ description:
3891
+ 'Multi-currency time series (each point has currency breakdown)',
3943
3892
  type: 'array',
3944
3893
  items: {
3945
- type: 'string'
3894
+ $ref: '#/components/schemas/MultiCurrencyPointDto'
3946
3895
  }
3947
3896
  },
3948
- additionalMetadata: {
3949
- type: 'object',
3950
- description: 'Additional metadata',
3951
- additionalProperties: {
3952
- type: 'string'
3897
+ warnings: {
3898
+ description: 'Exchange rate warnings',
3899
+ type: 'array',
3900
+ items: {
3901
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
3953
3902
  }
3954
- },
3955
- createdAt: {
3956
- format: 'date-time',
3957
- type: 'string',
3958
- description: 'Created timestamp'
3959
- },
3960
- updatedAt: {
3961
- format: 'date-time',
3962
- type: 'string',
3963
- description: 'Updated timestamp'
3964
3903
  }
3965
3904
  },
3966
- required: [
3967
- 'id',
3968
- 'name',
3969
- 'narrationKeywords',
3970
- 'payeeKeywords',
3971
- 'categoryKeywords',
3972
- 'methodKeywords',
3973
- 'matchLogic',
3974
- 'priority',
3975
- 'enabled',
3976
- 'autoApplyEnabled',
3977
- 'confirmationCount',
3978
- 'additionalTags',
3979
- 'createdAt',
3980
- 'updatedAt'
3981
- ]
3905
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
3982
3906
  } as const;
3983
3907
 
3984
- export const $TransactionRuleListResponseDto = {
3908
+ export const $CashFlowPointDto = {
3985
3909
  type: 'object',
3986
3910
  properties: {
3987
- data: {
3988
- type: 'array',
3989
- items: {
3990
- $ref: '#/components/schemas/TransactionRuleResponseDto'
3991
- }
3911
+ month: {
3912
+ type: 'string',
3913
+ description: 'Month key (YYYY-MM)',
3914
+ example: '2024-03'
3992
3915
  },
3993
- total: {
3994
- type: 'number',
3995
- description: 'Total count of rules'
3916
+ income: {
3917
+ type: 'string',
3918
+ description: 'Income in base currency (absolute, converted)',
3919
+ example: '10000.00'
3996
3920
  },
3997
- limit: {
3998
- type: 'number',
3999
- description: 'Results per page'
3921
+ expense: {
3922
+ type: 'string',
3923
+ description: 'Expense in base currency (absolute, converted)',
3924
+ example: '5000.00'
4000
3925
  },
4001
- offset: {
4002
- type: 'number',
4003
- description: 'Pagination offset'
3926
+ netSavings: {
3927
+ type: 'string',
3928
+ description: 'netSavings = income − expense (savings positive)',
3929
+ example: '5000.00'
4004
3930
  }
4005
3931
  },
4006
- required: ['data', 'total', 'limit', 'offset']
3932
+ required: ['month', 'income', 'expense', 'netSavings']
4007
3933
  } as const;
4008
3934
 
4009
- export const $ValidateRuleDto = {
3935
+ export const $CashFlowTrendSummaryDto = {
4010
3936
  type: 'object',
4011
3937
  properties: {
4012
- name: {
3938
+ totalIncome: {
4013
3939
  type: 'string',
4014
- minLength: 1,
4015
- maxLength: 100
3940
+ description: 'Total income across the period',
3941
+ example: '60000.00'
4016
3942
  },
4017
- description: {
3943
+ totalExpense: {
4018
3944
  type: 'string',
4019
- maxLength: 500
4020
- },
4021
- narrationKeywords: {
4022
- items: {
4023
- type: 'array'
4024
- },
4025
- maxItems: 50,
4026
- type: 'array'
3945
+ description: 'Total expense across the period',
3946
+ example: '30000.00'
4027
3947
  },
4028
- payeeKeywords: {
4029
- items: {
4030
- type: 'array'
4031
- },
4032
- maxItems: 50,
4033
- type: 'array'
3948
+ totalNetSavings: {
3949
+ type: 'string',
3950
+ description: 'income − expense across the period',
3951
+ example: '30000.00'
4034
3952
  },
4035
- categoryKeywords: {
3953
+ averageMonthlyNetSavings: {
3954
+ type: 'string',
3955
+ description:
3956
+ 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
3957
+ example: '5000.00'
3958
+ }
3959
+ },
3960
+ required: [
3961
+ 'totalIncome',
3962
+ 'totalExpense',
3963
+ 'totalNetSavings',
3964
+ 'averageMonthlyNetSavings'
3965
+ ]
3966
+ } as const;
3967
+
3968
+ export const $CashFlowTrendsResponseDto = {
3969
+ type: 'object',
3970
+ properties: {
3971
+ series: {
3972
+ description:
3973
+ 'Monthly cash-flow series (fixed N-month window, zero-filled)',
3974
+ type: 'array',
4036
3975
  items: {
4037
- type: 'array'
4038
- },
4039
- maxItems: 50,
4040
- type: 'array'
3976
+ $ref: '#/components/schemas/CashFlowPointDto'
3977
+ }
4041
3978
  },
4042
- methodKeywords: {
4043
- items: {
4044
- type: 'array'
4045
- },
4046
- maxItems: 50,
4047
- description: 'Payment method keywords (e.g., HuaBei, YuEBao)',
4048
- type: 'array'
3979
+ summary: {
3980
+ description: 'Period totals',
3981
+ allOf: [
3982
+ {
3983
+ $ref: '#/components/schemas/CashFlowTrendSummaryDto'
3984
+ }
3985
+ ]
4049
3986
  },
4050
- categoryAccount: {
3987
+ period: {
4051
3988
  type: 'string',
4052
- maxLength: 200,
4053
- description:
4054
- 'Destination account for expenses/income (e.g., Expenses:Food:Coffee)'
3989
+ description: 'Period requested',
3990
+ example: '6m'
4055
3991
  },
4056
- matchLogic: {
3992
+ granularity: {
4057
3993
  type: 'string',
4058
- enum: ['OR', 'AND'],
4059
- default: 'OR'
4060
- },
4061
- amountMin: {
4062
- type: 'number',
4063
- minimum: 0,
4064
- description: 'Minimum transaction amount (inclusive)'
4065
- },
4066
- amountMax: {
4067
- type: 'number',
4068
- minimum: 0,
4069
- description: 'Maximum transaction amount (inclusive)'
3994
+ description: 'Data granularity (v1 returns month buckets)',
3995
+ example: 'month'
4070
3996
  },
4071
- priority: {
4072
- type: 'number',
4073
- default: 50,
4074
- minimum: 0,
4075
- maximum: 1000
3997
+ currency: {
3998
+ type: 'string',
3999
+ description: 'Base currency for converted values',
4000
+ example: 'CNY'
4076
4001
  },
4077
- additionalTags: {
4002
+ warnings: {
4003
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
4004
+ type: 'array',
4078
4005
  items: {
4079
- type: 'array'
4080
- },
4081
- maxItems: 20,
4082
- type: 'array'
4083
- },
4084
- additionalMetadata: {
4085
- type: 'object'
4086
- },
4087
- upsertByPayee: {
4088
- type: 'boolean',
4089
- description:
4090
- 'If true, update existing rule with matching payeeKeywords[0] instead of creating new rule'
4006
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
4007
+ }
4091
4008
  }
4092
4009
  },
4093
- required: ['name', 'matchLogic', 'priority']
4010
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
4094
4011
  } as const;
4095
4012
 
4096
- export const $ValidateRuleResponseDto = {
4013
+ export const $GenerateSnapshotBody = {
4014
+ type: 'object',
4015
+ properties: {}
4016
+ } as const;
4017
+
4018
+ export const $GenerateSnapshotResponse = {
4019
+ type: 'object',
4020
+ properties: {}
4021
+ } as const;
4022
+
4023
+ export const $BackfillSnapshotsBody = {
4024
+ type: 'object',
4025
+ properties: {}
4026
+ } as const;
4027
+
4028
+ export const $BackfillSnapshotsResponse = {
4029
+ type: 'object',
4030
+ properties: {}
4031
+ } as const;
4032
+
4033
+ export const $DeleteOwnUserDto = {
4097
4034
  type: 'object',
4098
4035
  properties: {
4099
- valid: {
4100
- type: 'boolean',
4101
- description: 'Whether the rule configuration is valid',
4102
- example: true
4103
- },
4104
- errors: {
4105
- description: 'List of validation errors (empty if valid)',
4106
- example: [],
4107
- items: {
4108
- type: 'array'
4109
- },
4110
- type: 'array'
4111
- },
4112
- warnings: {
4113
- description: 'List of validation warnings (non-blocking issues)',
4114
- example: [
4115
- 'No account constraints specified - rule will match any account'
4116
- ],
4117
- items: {
4118
- type: 'array'
4119
- },
4120
- type: 'array'
4036
+ accessToken: {
4037
+ type: 'string',
4038
+ description: 'Access token for user verification',
4039
+ example: 'abc123xyz'
4121
4040
  }
4122
4041
  },
4123
- required: ['valid', 'errors', 'warnings']
4042
+ required: ['accessToken']
4124
4043
  } as const;
4125
4044
 
4126
- export const $BulkCreateRulesDto = {
4045
+ export const $SignupDto = {
4127
4046
  type: 'object',
4128
4047
  properties: {
4129
- rules: {
4130
- items: {
4131
- type: 'array'
4132
- },
4133
- description: 'Array of rules to import',
4134
- type: 'array'
4135
- },
4136
- conflictStrategy: {
4048
+ turnstileToken: {
4137
4049
  type: 'string',
4138
- enum: ['replace', 'skip'],
4139
- default: 'skip',
4140
4050
  description:
4141
- 'Conflict handling strategy: skip (default) ignores duplicates, replace soft-deletes existing rule'
4051
+ 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
4052
+ example: '0.abc123def456...'
4142
4053
  }
4143
- },
4144
- required: ['rules', 'conflictStrategy']
4054
+ }
4145
4055
  } as const;
4146
4056
 
4147
- export const $BulkCreateRulesResponseDto = {
4057
+ export const $SignupResponseDto = {
4148
4058
  type: 'object',
4149
4059
  properties: {
4150
- successCount: {
4151
- type: 'number',
4152
- description: 'Number of successfully created rules'
4060
+ authToken: {
4061
+ type: 'string',
4062
+ description: 'JWT auth token',
4063
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
4153
4064
  },
4154
- failureCount: {
4065
+ accessToken: {
4066
+ type: 'string',
4067
+ description: 'Auto-generated access token'
4068
+ },
4069
+ role: {
4070
+ type: 'string',
4071
+ description: 'Assigned user role',
4072
+ enum: ['USER', 'ADMIN', 'DEMO', 'INACTIVE', 'PAID', 'OPS']
4073
+ }
4074
+ },
4075
+ required: ['authToken', 'accessToken', 'role']
4076
+ } as const;
4077
+
4078
+ export const $UpdateUserSettingDto = {
4079
+ type: 'object',
4080
+ properties: {
4081
+ secId: {
4155
4082
  type: 'number',
4156
- description: 'Number of failed rules'
4083
+ description: 'Security ID'
4157
4084
  },
4158
- errors: {
4085
+ annualInterestRate: {
4086
+ type: 'number',
4087
+ description: 'Annual interest rate',
4088
+ example: 0.05
4089
+ },
4090
+ currency: {
4091
+ type: 'string',
4092
+ description: 'Currency code',
4093
+ example: 'USD'
4094
+ },
4095
+ baseCurrency: {
4096
+ type: 'string',
4097
+ description: 'Base currency code',
4098
+ example: 'USD'
4099
+ },
4100
+ benchmark: {
4101
+ type: 'string',
4102
+ description: 'Benchmark symbol',
4103
+ example: 'SPY'
4104
+ },
4105
+ colorScheme: {
4106
+ type: 'string',
4107
+ description: 'Color scheme',
4108
+ enum: ['DARK', 'LIGHT']
4109
+ },
4110
+ dateRange: {
4111
+ type: 'string',
4112
+ description: 'Date range filter',
4113
+ example: '1y'
4114
+ },
4115
+ emergencyFund: {
4116
+ type: 'number',
4117
+ description: 'Emergency fund amount',
4118
+ example: 10000
4119
+ },
4120
+ 'filters.accounts': {
4121
+ description: 'Account filter IDs',
4159
4122
  type: 'array',
4160
- description: 'Error details for failed rules',
4161
4123
  items: {
4162
- type: 'object',
4163
- properties: {
4164
- index: {
4165
- type: 'number'
4166
- },
4167
- message: {
4168
- type: 'string'
4169
- }
4170
- }
4124
+ type: 'string'
4171
4125
  }
4172
4126
  },
4173
- createdRuleIds: {
4174
- description: 'IDs of successfully created rules',
4127
+ 'filters.assetClasses': {
4128
+ description: 'Asset class filters',
4175
4129
  type: 'array',
4176
4130
  items: {
4177
4131
  type: 'string'
4178
4132
  }
4179
- }
4180
- },
4181
- required: ['successCount', 'failureCount', 'errors', 'createdRuleIds']
4182
- } as const;
4183
-
4184
- export const $ExportRulesResponseDto = {
4185
- type: 'object',
4186
- properties: {
4187
- exportedAt: {
4188
- type: 'string',
4189
- description: 'Export timestamp'
4190
4133
  },
4191
- userId: {
4134
+ 'filters.dataSource': {
4192
4135
  type: 'string',
4193
- description: 'User ID'
4136
+ description: 'Data source filter'
4194
4137
  },
4195
- ruleCount: {
4196
- type: 'number',
4197
- description: 'Number of exported rules'
4138
+ 'filters.symbol': {
4139
+ type: 'string',
4140
+ description: 'Symbol filter'
4198
4141
  },
4199
- rules: {
4142
+ 'filters.tags': {
4143
+ description: 'Tag filters',
4200
4144
  type: 'array',
4201
- description: 'Exported rules'
4202
- }
4203
- },
4204
- required: ['exportedAt', 'userId', 'ruleCount', 'rules']
4205
- } as const;
4206
-
4207
- export const $RuleStatisticsResponseDto = {
4208
- type: 'object',
4209
- properties: {
4210
- period: {
4145
+ items: {
4146
+ type: 'string'
4147
+ }
4148
+ },
4149
+ isExperimentalFeatures: {
4150
+ type: 'boolean',
4151
+ description: 'Enable experimental features'
4152
+ },
4153
+ isRestrictedView: {
4154
+ type: 'boolean',
4155
+ description: 'Enable restricted view mode'
4156
+ },
4157
+ language: {
4211
4158
  type: 'string',
4212
- description: 'Statistics time period',
4213
- enum: ['7d', '30d', '90d']
4159
+ description: 'Language code',
4160
+ example: 'en'
4214
4161
  },
4215
- totalRules: {
4216
- type: 'number',
4217
- description: 'Total number of rules'
4162
+ locale: {
4163
+ type: 'string',
4164
+ description: 'Locale code',
4165
+ example: 'en-US'
4218
4166
  },
4219
- rulesWithMatches: {
4167
+ projectedTotalAmount: {
4220
4168
  type: 'number',
4221
- description: 'Number of rules with at least one match'
4169
+ description: 'Projected total amount',
4170
+ example: 1000000
4222
4171
  },
4223
- totalMatches: {
4224
- type: 'number',
4225
- description: 'Total number of matches across all rules'
4172
+ retirementDate: {
4173
+ type: 'string',
4174
+ description: 'Retirement date in ISO 8601 format',
4175
+ example: '2050-01-01'
4226
4176
  },
4227
- averageConfidence: {
4177
+ savingsRate: {
4228
4178
  type: 'number',
4229
- description: 'Average confidence score across all matches',
4230
- example: 0.82
4179
+ description: 'Savings rate percentage',
4180
+ example: 0.2
4231
4181
  },
4232
- ruleStats: {
4233
- type: 'array',
4234
- description: 'Per-rule statistics',
4235
- items: {
4236
- type: 'object',
4237
- properties: {
4238
- ruleId: {
4239
- type: 'string'
4240
- },
4241
- ruleName: {
4242
- type: 'string'
4243
- },
4244
- matchCount: {
4245
- type: 'number'
4246
- },
4247
- averageConfidence: {
4248
- type: 'number'
4249
- }
4250
- }
4251
- }
4182
+ viewMode: {
4183
+ type: 'string',
4184
+ description: 'View mode',
4185
+ enum: ['DEFAULT', 'ZEN']
4186
+ }
4187
+ }
4188
+ } as const;
4189
+
4190
+ export const $UpdatePropertyDto = {
4191
+ type: 'object',
4192
+ properties: {
4193
+ value: {
4194
+ type: 'string',
4195
+ description: 'Property value'
4252
4196
  }
4253
4197
  },
4254
- required: [
4255
- 'period',
4256
- 'totalRules',
4257
- 'rulesWithMatches',
4258
- 'totalMatches',
4259
- 'averageConfidence',
4260
- 'ruleStats'
4261
- ]
4198
+ required: ['value']
4262
4199
  } as const;
4263
4200
 
4264
- export const $UpdateTransactionRuleDto = {
4201
+ export const $CreateTransactionRuleDto = {
4265
4202
  type: 'object',
4266
4203
  properties: {
4267
4204
  name: {
@@ -4310,7 +4247,8 @@ export const $UpdateTransactionRuleDto = {
4310
4247
  },
4311
4248
  matchLogic: {
4312
4249
  type: 'string',
4313
- enum: ['OR', 'AND']
4250
+ enum: ['OR', 'AND'],
4251
+ default: 'OR'
4314
4252
  },
4315
4253
  amountMin: {
4316
4254
  type: 'number',
@@ -4324,13 +4262,10 @@ export const $UpdateTransactionRuleDto = {
4324
4262
  },
4325
4263
  priority: {
4326
4264
  type: 'number',
4265
+ default: 50,
4327
4266
  minimum: 0,
4328
4267
  maximum: 1000
4329
4268
  },
4330
- enabled: {
4331
- type: 'boolean',
4332
- description: 'Enable or disable the rule'
4333
- },
4334
4269
  additionalTags: {
4335
4270
  items: {
4336
4271
  type: 'array'
@@ -4340,232 +4275,576 @@ export const $UpdateTransactionRuleDto = {
4340
4275
  },
4341
4276
  additionalMetadata: {
4342
4277
  type: 'object'
4278
+ },
4279
+ upsertByPayee: {
4280
+ type: 'boolean',
4281
+ description:
4282
+ 'If true, update existing rule with matching payeeKeywords[0] instead of creating new rule'
4343
4283
  }
4344
- }
4284
+ },
4285
+ required: ['name', 'matchLogic', 'priority']
4345
4286
  } as const;
4346
4287
 
4347
- export const $TestRuleDto = {
4288
+ export const $AmountRangeDto = {
4348
4289
  type: 'object',
4349
4290
  properties: {
4350
- narration: {
4351
- type: 'string',
4352
- minLength: 1,
4353
- maxLength: 500
4354
- },
4355
- payee: {
4356
- type: 'string',
4357
- maxLength: 200
4358
- },
4359
- categoryAccount: {
4360
- type: 'string',
4361
- maxLength: 200
4362
- },
4363
- amount: {
4364
- type: 'number'
4291
+ min: {
4292
+ type: 'number',
4293
+ description: 'Minimum amount'
4365
4294
  },
4366
- currency: {
4367
- type: 'string',
4368
- maxLength: 10
4295
+ max: {
4296
+ type: 'number',
4297
+ description: 'Maximum amount'
4369
4298
  }
4370
- },
4371
- required: ['narration']
4299
+ }
4372
4300
  } as const;
4373
4301
 
4374
- export const $TestRuleResponseDto = {
4302
+ export const $TransactionRuleResponseDto = {
4375
4303
  type: 'object',
4376
4304
  properties: {
4377
- ruleId: {
4305
+ id: {
4378
4306
  type: 'string',
4379
- description: 'Rule ID that was tested'
4307
+ description: 'Rule ID'
4380
4308
  },
4381
- matches: {
4382
- type: 'boolean',
4383
- description: 'Whether the rule matched the test data'
4309
+ name: {
4310
+ type: 'string',
4311
+ description: 'Rule name'
4384
4312
  },
4385
- confidence: {
4313
+ description: {
4314
+ type: 'string',
4315
+ description: 'Rule description'
4316
+ },
4317
+ narrationKeywords: {
4318
+ description: 'Keywords to match in transaction narration',
4319
+ type: 'array',
4320
+ items: {
4321
+ type: 'string'
4322
+ }
4323
+ },
4324
+ payeeKeywords: {
4325
+ description: 'Keywords to match in payee name',
4326
+ type: 'array',
4327
+ items: {
4328
+ type: 'string'
4329
+ }
4330
+ },
4331
+ categoryKeywords: {
4332
+ description: 'Keywords to match in category',
4333
+ type: 'array',
4334
+ items: {
4335
+ type: 'string'
4336
+ }
4337
+ },
4338
+ methodKeywords: {
4339
+ description: 'Keywords to match in payment method',
4340
+ type: 'array',
4341
+ items: {
4342
+ type: 'string'
4343
+ }
4344
+ },
4345
+ categoryAccount: {
4346
+ type: 'string',
4347
+ description: 'Destination account for categorization'
4348
+ },
4349
+ matchLogic: {
4350
+ type: 'string',
4351
+ description: 'Keyword matching logic',
4352
+ enum: ['OR', 'AND'],
4353
+ example: 'OR'
4354
+ },
4355
+ amountRange: {
4356
+ description: 'Amount range for matching',
4357
+ allOf: [
4358
+ {
4359
+ $ref: '#/components/schemas/AmountRangeDto'
4360
+ }
4361
+ ]
4362
+ },
4363
+ priority: {
4386
4364
  type: 'number',
4387
- description: 'Match confidence score (0-1)',
4388
- example: 0.85
4365
+ description: 'Rule priority (0-1000, higher = first match)',
4366
+ example: 50
4389
4367
  },
4390
- matchDetails: {
4368
+ enabled: {
4369
+ type: 'boolean',
4370
+ description: 'Whether the rule is enabled'
4371
+ },
4372
+ learningSource: {
4373
+ type: 'string',
4374
+ description: 'Learning source: NLP, REVIEW_CENTER, or null for manual',
4375
+ enum: ['NLP', 'REVIEW_CENTER'],
4376
+ nullable: true,
4377
+ example: 'REVIEW_CENTER'
4378
+ },
4379
+ autoApplyEnabled: {
4380
+ type: 'boolean',
4381
+ description: 'Whether auto-apply is enabled for this rule'
4382
+ },
4383
+ confirmationCount: {
4384
+ type: 'number',
4385
+ description: 'Number of confirmations for NLP-learned rules',
4386
+ example: 3
4387
+ },
4388
+ additionalTags: {
4389
+ description: 'Additional tags',
4390
+ type: 'array',
4391
+ items: {
4392
+ type: 'string'
4393
+ }
4394
+ },
4395
+ additionalMetadata: {
4391
4396
  type: 'object',
4392
- description: 'Details of which fields matched',
4393
- example: {
4394
- narration: true,
4395
- payee: false,
4396
- categoryAccount: false
4397
+ description: 'Additional metadata',
4398
+ additionalProperties: {
4399
+ type: 'string'
4397
4400
  }
4401
+ },
4402
+ createdAt: {
4403
+ format: 'date-time',
4404
+ type: 'string',
4405
+ description: 'Created timestamp'
4406
+ },
4407
+ updatedAt: {
4408
+ format: 'date-time',
4409
+ type: 'string',
4410
+ description: 'Updated timestamp'
4398
4411
  }
4399
4412
  },
4400
- required: ['ruleId', 'matches', 'confidence', 'matchDetails']
4413
+ required: [
4414
+ 'id',
4415
+ 'name',
4416
+ 'narrationKeywords',
4417
+ 'payeeKeywords',
4418
+ 'categoryKeywords',
4419
+ 'methodKeywords',
4420
+ 'matchLogic',
4421
+ 'priority',
4422
+ 'enabled',
4423
+ 'autoApplyEnabled',
4424
+ 'confirmationCount',
4425
+ 'additionalTags',
4426
+ 'createdAt',
4427
+ 'updatedAt'
4428
+ ]
4401
4429
  } as const;
4402
4430
 
4403
- export const $DeleteOwnUserDto = {
4431
+ export const $TransactionRuleListResponseDto = {
4404
4432
  type: 'object',
4405
4433
  properties: {
4406
- accessToken: {
4434
+ data: {
4435
+ type: 'array',
4436
+ items: {
4437
+ $ref: '#/components/schemas/TransactionRuleResponseDto'
4438
+ }
4439
+ },
4440
+ total: {
4441
+ type: 'number',
4442
+ description: 'Total count of rules'
4443
+ },
4444
+ limit: {
4445
+ type: 'number',
4446
+ description: 'Results per page'
4447
+ },
4448
+ offset: {
4449
+ type: 'number',
4450
+ description: 'Pagination offset'
4451
+ }
4452
+ },
4453
+ required: ['data', 'total', 'limit', 'offset']
4454
+ } as const;
4455
+
4456
+ export const $ValidateRuleDto = {
4457
+ type: 'object',
4458
+ properties: {
4459
+ name: {
4407
4460
  type: 'string',
4408
- description: 'Access token for user verification',
4409
- example: 'abc123xyz'
4461
+ minLength: 1,
4462
+ maxLength: 100
4463
+ },
4464
+ description: {
4465
+ type: 'string',
4466
+ maxLength: 500
4467
+ },
4468
+ narrationKeywords: {
4469
+ items: {
4470
+ type: 'array'
4471
+ },
4472
+ maxItems: 50,
4473
+ type: 'array'
4474
+ },
4475
+ payeeKeywords: {
4476
+ items: {
4477
+ type: 'array'
4478
+ },
4479
+ maxItems: 50,
4480
+ type: 'array'
4481
+ },
4482
+ categoryKeywords: {
4483
+ items: {
4484
+ type: 'array'
4485
+ },
4486
+ maxItems: 50,
4487
+ type: 'array'
4488
+ },
4489
+ methodKeywords: {
4490
+ items: {
4491
+ type: 'array'
4492
+ },
4493
+ maxItems: 50,
4494
+ description: 'Payment method keywords (e.g., HuaBei, YuEBao)',
4495
+ type: 'array'
4496
+ },
4497
+ categoryAccount: {
4498
+ type: 'string',
4499
+ maxLength: 200,
4500
+ description:
4501
+ 'Destination account for expenses/income (e.g., Expenses:Food:Coffee)'
4502
+ },
4503
+ matchLogic: {
4504
+ type: 'string',
4505
+ enum: ['OR', 'AND'],
4506
+ default: 'OR'
4507
+ },
4508
+ amountMin: {
4509
+ type: 'number',
4510
+ minimum: 0,
4511
+ description: 'Minimum transaction amount (inclusive)'
4512
+ },
4513
+ amountMax: {
4514
+ type: 'number',
4515
+ minimum: 0,
4516
+ description: 'Maximum transaction amount (inclusive)'
4517
+ },
4518
+ priority: {
4519
+ type: 'number',
4520
+ default: 50,
4521
+ minimum: 0,
4522
+ maximum: 1000
4523
+ },
4524
+ additionalTags: {
4525
+ items: {
4526
+ type: 'array'
4527
+ },
4528
+ maxItems: 20,
4529
+ type: 'array'
4530
+ },
4531
+ additionalMetadata: {
4532
+ type: 'object'
4533
+ },
4534
+ upsertByPayee: {
4535
+ type: 'boolean',
4536
+ description:
4537
+ 'If true, update existing rule with matching payeeKeywords[0] instead of creating new rule'
4410
4538
  }
4411
4539
  },
4412
- required: ['accessToken']
4540
+ required: ['name', 'matchLogic', 'priority']
4413
4541
  } as const;
4414
4542
 
4415
- export const $SignupDto = {
4543
+ export const $ValidateRuleResponseDto = {
4416
4544
  type: 'object',
4417
4545
  properties: {
4418
- turnstileToken: {
4546
+ valid: {
4547
+ type: 'boolean',
4548
+ description: 'Whether the rule configuration is valid',
4549
+ example: true
4550
+ },
4551
+ errors: {
4552
+ description: 'List of validation errors (empty if valid)',
4553
+ example: [],
4554
+ items: {
4555
+ type: 'array'
4556
+ },
4557
+ type: 'array'
4558
+ },
4559
+ warnings: {
4560
+ description: 'List of validation warnings (non-blocking issues)',
4561
+ example: [
4562
+ 'No account constraints specified - rule will match any account'
4563
+ ],
4564
+ items: {
4565
+ type: 'array'
4566
+ },
4567
+ type: 'array'
4568
+ }
4569
+ },
4570
+ required: ['valid', 'errors', 'warnings']
4571
+ } as const;
4572
+
4573
+ export const $BulkCreateRulesDto = {
4574
+ type: 'object',
4575
+ properties: {
4576
+ rules: {
4577
+ items: {
4578
+ type: 'array'
4579
+ },
4580
+ description: 'Array of rules to import',
4581
+ type: 'array'
4582
+ },
4583
+ conflictStrategy: {
4419
4584
  type: 'string',
4585
+ enum: ['replace', 'skip'],
4586
+ default: 'skip',
4420
4587
  description:
4421
- 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
4422
- example: '0.abc123def456...'
4588
+ 'Conflict handling strategy: skip (default) ignores duplicates, replace soft-deletes existing rule'
4589
+ }
4590
+ },
4591
+ required: ['rules', 'conflictStrategy']
4592
+ } as const;
4593
+
4594
+ export const $BulkCreateRulesResponseDto = {
4595
+ type: 'object',
4596
+ properties: {
4597
+ successCount: {
4598
+ type: 'number',
4599
+ description: 'Number of successfully created rules'
4600
+ },
4601
+ failureCount: {
4602
+ type: 'number',
4603
+ description: 'Number of failed rules'
4604
+ },
4605
+ errors: {
4606
+ type: 'array',
4607
+ description: 'Error details for failed rules',
4608
+ items: {
4609
+ type: 'object',
4610
+ properties: {
4611
+ index: {
4612
+ type: 'number'
4613
+ },
4614
+ message: {
4615
+ type: 'string'
4616
+ }
4617
+ }
4618
+ }
4619
+ },
4620
+ createdRuleIds: {
4621
+ description: 'IDs of successfully created rules',
4622
+ type: 'array',
4623
+ items: {
4624
+ type: 'string'
4625
+ }
4423
4626
  }
4424
- }
4627
+ },
4628
+ required: ['successCount', 'failureCount', 'errors', 'createdRuleIds']
4425
4629
  } as const;
4426
4630
 
4427
- export const $SignupResponseDto = {
4631
+ export const $ExportRulesResponseDto = {
4428
4632
  type: 'object',
4429
4633
  properties: {
4430
- authToken: {
4634
+ exportedAt: {
4431
4635
  type: 'string',
4432
- description: 'JWT auth token',
4433
- example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
4636
+ description: 'Export timestamp'
4434
4637
  },
4435
- accessToken: {
4638
+ userId: {
4436
4639
  type: 'string',
4437
- description: 'Auto-generated access token'
4640
+ description: 'User ID'
4438
4641
  },
4439
- role: {
4440
- type: 'string',
4441
- description: 'Assigned user role',
4442
- enum: ['USER', 'ADMIN', 'DEMO', 'INACTIVE', 'PAID', 'OPS']
4642
+ ruleCount: {
4643
+ type: 'number',
4644
+ description: 'Number of exported rules'
4645
+ },
4646
+ rules: {
4647
+ type: 'array',
4648
+ description: 'Exported rules'
4443
4649
  }
4444
4650
  },
4445
- required: ['authToken', 'accessToken', 'role']
4651
+ required: ['exportedAt', 'userId', 'ruleCount', 'rules']
4446
4652
  } as const;
4447
4653
 
4448
- export const $UpdateUserSettingDto = {
4654
+ export const $RuleStatisticsResponseDto = {
4449
4655
  type: 'object',
4450
4656
  properties: {
4451
- secId: {
4657
+ period: {
4658
+ type: 'string',
4659
+ description: 'Statistics time period',
4660
+ enum: ['7d', '30d', '90d']
4661
+ },
4662
+ totalRules: {
4452
4663
  type: 'number',
4453
- description: 'Security ID'
4664
+ description: 'Total number of rules'
4454
4665
  },
4455
- annualInterestRate: {
4666
+ rulesWithMatches: {
4456
4667
  type: 'number',
4457
- description: 'Annual interest rate',
4458
- example: 0.05
4668
+ description: 'Number of rules with at least one match'
4459
4669
  },
4460
- currency: {
4461
- type: 'string',
4462
- description: 'Currency code',
4463
- example: 'USD'
4670
+ totalMatches: {
4671
+ type: 'number',
4672
+ description: 'Total number of matches across all rules'
4464
4673
  },
4465
- baseCurrency: {
4466
- type: 'string',
4467
- description: 'Base currency code',
4468
- example: 'USD'
4674
+ averageConfidence: {
4675
+ type: 'number',
4676
+ description: 'Average confidence score across all matches',
4677
+ example: 0.82
4469
4678
  },
4470
- benchmark: {
4679
+ ruleStats: {
4680
+ type: 'array',
4681
+ description: 'Per-rule statistics',
4682
+ items: {
4683
+ type: 'object',
4684
+ properties: {
4685
+ ruleId: {
4686
+ type: 'string'
4687
+ },
4688
+ ruleName: {
4689
+ type: 'string'
4690
+ },
4691
+ matchCount: {
4692
+ type: 'number'
4693
+ },
4694
+ averageConfidence: {
4695
+ type: 'number'
4696
+ }
4697
+ }
4698
+ }
4699
+ }
4700
+ },
4701
+ required: [
4702
+ 'period',
4703
+ 'totalRules',
4704
+ 'rulesWithMatches',
4705
+ 'totalMatches',
4706
+ 'averageConfidence',
4707
+ 'ruleStats'
4708
+ ]
4709
+ } as const;
4710
+
4711
+ export const $UpdateTransactionRuleDto = {
4712
+ type: 'object',
4713
+ properties: {
4714
+ name: {
4471
4715
  type: 'string',
4472
- description: 'Benchmark symbol',
4473
- example: 'SPY'
4716
+ minLength: 1,
4717
+ maxLength: 100
4474
4718
  },
4475
- colorScheme: {
4719
+ description: {
4476
4720
  type: 'string',
4477
- description: 'Color scheme',
4478
- enum: ['DARK', 'LIGHT']
4721
+ maxLength: 500
4479
4722
  },
4480
- dateRange: {
4481
- type: 'string',
4482
- description: 'Date range filter',
4483
- example: '1y'
4723
+ narrationKeywords: {
4724
+ items: {
4725
+ type: 'array'
4726
+ },
4727
+ maxItems: 50,
4728
+ type: 'array'
4484
4729
  },
4485
- emergencyFund: {
4486
- type: 'number',
4487
- description: 'Emergency fund amount',
4488
- example: 10000
4730
+ payeeKeywords: {
4731
+ items: {
4732
+ type: 'array'
4733
+ },
4734
+ maxItems: 50,
4735
+ type: 'array'
4489
4736
  },
4490
- 'filters.accounts': {
4491
- description: 'Account filter IDs',
4492
- type: 'array',
4737
+ categoryKeywords: {
4493
4738
  items: {
4494
- type: 'string'
4495
- }
4739
+ type: 'array'
4740
+ },
4741
+ maxItems: 50,
4742
+ type: 'array'
4496
4743
  },
4497
- 'filters.assetClasses': {
4498
- description: 'Asset class filters',
4499
- type: 'array',
4744
+ methodKeywords: {
4500
4745
  items: {
4501
- type: 'string'
4502
- }
4746
+ type: 'array'
4747
+ },
4748
+ maxItems: 50,
4749
+ description: 'Payment method keywords (e.g., HuaBei, YuEBao)',
4750
+ type: 'array'
4503
4751
  },
4504
- 'filters.dataSource': {
4752
+ categoryAccount: {
4505
4753
  type: 'string',
4506
- description: 'Data source filter'
4754
+ maxLength: 200,
4755
+ description:
4756
+ 'Destination account for expenses/income (e.g., Expenses:Food:Coffee)'
4507
4757
  },
4508
- 'filters.symbol': {
4758
+ matchLogic: {
4509
4759
  type: 'string',
4510
- description: 'Symbol filter'
4760
+ enum: ['OR', 'AND']
4511
4761
  },
4512
- 'filters.tags': {
4513
- description: 'Tag filters',
4514
- type: 'array',
4515
- items: {
4516
- type: 'string'
4517
- }
4762
+ amountMin: {
4763
+ type: 'number',
4764
+ minimum: 0,
4765
+ description: 'Minimum transaction amount (inclusive)'
4518
4766
  },
4519
- isExperimentalFeatures: {
4520
- type: 'boolean',
4521
- description: 'Enable experimental features'
4767
+ amountMax: {
4768
+ type: 'number',
4769
+ minimum: 0,
4770
+ description: 'Maximum transaction amount (inclusive)'
4522
4771
  },
4523
- isRestrictedView: {
4772
+ priority: {
4773
+ type: 'number',
4774
+ minimum: 0,
4775
+ maximum: 1000
4776
+ },
4777
+ enabled: {
4524
4778
  type: 'boolean',
4525
- description: 'Enable restricted view mode'
4779
+ description: 'Enable or disable the rule'
4526
4780
  },
4527
- language: {
4528
- type: 'string',
4529
- description: 'Language code',
4530
- example: 'en'
4781
+ additionalTags: {
4782
+ items: {
4783
+ type: 'array'
4784
+ },
4785
+ maxItems: 20,
4786
+ type: 'array'
4531
4787
  },
4532
- locale: {
4788
+ additionalMetadata: {
4789
+ type: 'object'
4790
+ }
4791
+ }
4792
+ } as const;
4793
+
4794
+ export const $TestRuleDto = {
4795
+ type: 'object',
4796
+ properties: {
4797
+ narration: {
4533
4798
  type: 'string',
4534
- description: 'Locale code',
4535
- example: 'en-US'
4799
+ minLength: 1,
4800
+ maxLength: 500
4536
4801
  },
4537
- projectedTotalAmount: {
4538
- type: 'number',
4539
- description: 'Projected total amount',
4540
- example: 1000000
4802
+ payee: {
4803
+ type: 'string',
4804
+ maxLength: 200
4541
4805
  },
4542
- retirementDate: {
4806
+ categoryAccount: {
4543
4807
  type: 'string',
4544
- description: 'Retirement date in ISO 8601 format',
4545
- example: '2050-01-01'
4808
+ maxLength: 200
4546
4809
  },
4547
- savingsRate: {
4548
- type: 'number',
4549
- description: 'Savings rate percentage',
4550
- example: 0.2
4810
+ amount: {
4811
+ type: 'number'
4551
4812
  },
4552
- viewMode: {
4813
+ currency: {
4553
4814
  type: 'string',
4554
- description: 'View mode',
4555
- enum: ['DEFAULT', 'ZEN']
4815
+ maxLength: 10
4556
4816
  }
4557
- }
4817
+ },
4818
+ required: ['narration']
4558
4819
  } as const;
4559
4820
 
4560
- export const $UpdatePropertyDto = {
4821
+ export const $TestRuleResponseDto = {
4561
4822
  type: 'object',
4562
4823
  properties: {
4563
- value: {
4824
+ ruleId: {
4564
4825
  type: 'string',
4565
- description: 'Property value'
4826
+ description: 'Rule ID that was tested'
4827
+ },
4828
+ matches: {
4829
+ type: 'boolean',
4830
+ description: 'Whether the rule matched the test data'
4831
+ },
4832
+ confidence: {
4833
+ type: 'number',
4834
+ description: 'Match confidence score (0-1)',
4835
+ example: 0.85
4836
+ },
4837
+ matchDetails: {
4838
+ type: 'object',
4839
+ description: 'Details of which fields matched',
4840
+ example: {
4841
+ narration: true,
4842
+ payee: false,
4843
+ categoryAccount: false
4844
+ }
4566
4845
  }
4567
4846
  },
4568
- required: ['value']
4847
+ required: ['ruleId', 'matches', 'confidence', 'matchDetails']
4569
4848
  } as const;
4570
4849
 
4571
4850
  export const $CreateBeanEventDto = {
@@ -6242,7 +6521,8 @@ export const $NlpResponseDto = {
6242
6521
  'confirm_rule',
6243
6522
  'confirm_account',
6244
6523
  'confirm_payee',
6245
- 'cancel'
6524
+ 'cancel',
6525
+ 'aborted'
6246
6526
  ]
6247
6527
  },
6248
6528
  intent: {
@@ -7601,442 +7881,163 @@ export const $HoldingPnlRowDto = {
7601
7881
  description:
7602
7882
  'Average cost per unit; null when cost currency conflicts or no cost',
7603
7883
  nullable: true,
7604
- allOf: [
7605
- {
7606
- $ref: '#/components/schemas/MonetaryDto'
7607
- }
7608
- ]
7609
- },
7610
- costBasis: {
7611
- description: 'Cost basis of held units',
7612
- nullable: true,
7613
- allOf: [
7614
- {
7615
- $ref: '#/components/schemas/MonetaryDto'
7616
- }
7617
- ]
7618
- },
7619
- marketValue: {
7620
- description: 'Market value at asOf price',
7621
- nullable: true,
7622
- allOf: [
7623
- {
7624
- $ref: '#/components/schemas/MonetaryDto'
7625
- }
7626
- ]
7627
- },
7628
- currentPrice: {
7629
- description: 'Price used for market value',
7630
- nullable: true,
7631
- allOf: [
7632
- {
7633
- $ref: '#/components/schemas/CurrentPriceDto'
7634
- }
7635
- ]
7636
- },
7637
- unrealizedPnlBase: {
7638
- type: 'object',
7639
- description:
7640
- 'Unrealized P&L in base currency (Decimal string); null when any FX/price missing',
7641
- nullable: true,
7642
- example: '6000'
7643
- },
7644
- unrealizedPnlPct: {
7645
- type: 'object',
7646
- description: 'Unrealized P&L % (Decimal string)',
7647
- nullable: true,
7648
- example: '25'
7649
- },
7650
- costFxRate: {
7651
- description: 'Historical FX rate applied to cost basis',
7652
- nullable: true,
7653
- allOf: [
7654
- {
7655
- $ref: '#/components/schemas/FxRateDto'
7656
- }
7657
- ]
7658
- },
7659
- marketFxRate: {
7660
- description: 'FX rate applied to market value',
7661
- nullable: true,
7662
- allOf: [
7663
- {
7664
- $ref: '#/components/schemas/FxRateDto'
7665
- }
7666
- ]
7667
- },
7668
- pctOfInvestedAssets: {
7669
- type: 'object',
7670
- description:
7671
- 'Share of invested assets % (Decimal string); only for invested chartTokens',
7672
- nullable: true,
7673
- example: '40'
7674
- },
7675
- realizedPnl: {
7676
- description:
7677
- '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',
7678
- nullable: true,
7679
- allOf: [
7680
- {
7681
- $ref: '#/components/schemas/MonetaryDto'
7682
- }
7683
- ]
7684
- }
7685
- },
7686
- required: [
7687
- 'accountId',
7688
- 'accountPath',
7689
- 'symbol',
7690
- 'chartToken',
7691
- 'assetClass',
7692
- 'units'
7693
- ]
7694
- } as const;
7695
-
7696
- export const $HoldingPnlWarningDto = {
7697
- type: 'object',
7698
- properties: {
7699
- type: {
7700
- type: 'string',
7701
- description: 'Warning type',
7702
- example: 'MISSING_COST_FX_RATE',
7703
- enum: [
7704
- 'MISSING_COST_FX_RATE',
7705
- 'MISSING_MARKET_FX_RATE',
7706
- 'MISSING_SALE_PRICE',
7707
- 'MISSING_REALIZED_FX_RATE',
7708
- 'OVERSOLD_LOTS',
7709
- 'NO_PRICE',
7710
- 'MIXED_COST_CURRENCY'
7711
- ]
7712
- },
7713
- symbol: {
7714
- type: 'object',
7715
- nullable: true
7716
- },
7717
- accountId: {
7718
- type: 'object',
7719
- nullable: true
7720
- },
7721
- currency: {
7722
- type: 'object',
7723
- nullable: true
7724
- }
7725
- },
7726
- required: ['type']
7727
- } as const;
7728
-
7729
- export const $HoldingPnlResponseDto = {
7730
- type: 'object',
7731
- properties: {
7732
- asOfDate: {
7733
- type: 'string',
7734
- example: '2026-07-08'
7735
- },
7736
- baseCurrency: {
7737
- type: 'string',
7738
- example: 'CNY'
7739
- },
7740
- method: {
7741
- type: 'string',
7742
- description:
7743
- 'Realized-P&L lot-matching method (FIFO or average). Unrealized cost basis remains average regardless of this value (#473).',
7744
- enum: ['average', 'FIFO'],
7745
- example: 'average'
7746
- },
7747
- rows: {
7748
- type: 'array',
7749
- items: {
7750
- $ref: '#/components/schemas/HoldingPnlRowDto'
7751
- }
7752
- },
7753
- warnings: {
7754
- type: 'array',
7755
- items: {
7756
- $ref: '#/components/schemas/HoldingPnlWarningDto'
7757
- }
7758
- }
7759
- },
7760
- required: ['asOfDate', 'baseCurrency', 'method', 'rows', 'warnings']
7761
- } as const;
7762
-
7763
- export const $CurrencyBalanceDto = {
7764
- type: 'object',
7765
- properties: {
7766
- currency: {
7767
- type: 'string',
7768
- description: 'ISO 4217 currency code',
7769
- example: 'CNY'
7770
- },
7771
- balance: {
7772
- type: 'string',
7773
- description: 'Balance amount',
7774
- example: '500000.00'
7775
- }
7776
- },
7777
- required: ['currency', 'balance']
7778
- } as const;
7779
-
7780
- export const $TimeSeriesPointDto = {
7781
- type: 'object',
7782
- properties: {
7783
- date: {
7784
- type: 'string',
7785
- description: 'Date in YYYY-MM-DD format',
7786
- example: '2024-06-15'
7787
- },
7788
- value: {
7789
- type: 'string',
7790
- description: 'Value at this date (in base currency)',
7791
- example: '500000.00'
7792
- },
7793
- change: {
7794
- type: 'object',
7795
- description: 'Change from previous point',
7796
- example: '5000.00'
7797
- },
7798
- assets: {
7799
- type: 'string',
7800
- description: 'Total assets at this date (in base currency)',
7801
- example: '494338.00'
7802
- },
7803
- liabilities: {
7804
- type: 'string',
7805
- description: 'Total liabilities at this date (in base currency)',
7806
- example: '310098.00'
7807
- },
7808
- byCurrency: {
7809
- description: 'Multi-currency breakdown for this point',
7810
- type: 'array',
7811
- items: {
7812
- $ref: '#/components/schemas/CurrencyBalanceDto'
7813
- }
7814
- }
7815
- },
7816
- required: ['date', 'value']
7817
- } as const;
7818
-
7819
- export const $TrendSummaryDto = {
7820
- type: 'object',
7821
- properties: {
7822
- startValue: {
7823
- type: 'string',
7824
- description: 'Value at start of period',
7825
- example: '450000.00'
7826
- },
7827
- endValue: {
7828
- type: 'string',
7829
- description: 'Value at end of period',
7830
- example: '500000.00'
7831
- },
7832
- totalChange: {
7833
- type: 'string',
7834
- description: 'Total change over period',
7835
- example: '50000.00'
7836
- },
7837
- totalChangePercentage: {
7838
- type: 'string',
7839
- description: 'Total change percentage',
7840
- example: '+11.11%'
7841
- }
7842
- },
7843
- required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
7844
- } as const;
7845
-
7846
- export const $MultiCurrencyPointDto = {
7847
- type: 'object',
7848
- properties: {
7849
- date: {
7850
- type: 'string',
7851
- description: 'Date in YYYY-MM-DD format',
7852
- example: '2024-06-15'
7884
+ allOf: [
7885
+ {
7886
+ $ref: '#/components/schemas/MonetaryDto'
7887
+ }
7888
+ ]
7853
7889
  },
7854
- byCurrency: {
7855
- description: 'Balances by currency',
7856
- type: 'array',
7857
- items: {
7858
- $ref: '#/components/schemas/CurrencyBalanceDto'
7859
- }
7860
- }
7861
- },
7862
- required: ['date', 'byCurrency']
7863
- } as const;
7864
-
7865
- export const $PortfolioTrendsResponseDto = {
7866
- type: 'object',
7867
- properties: {
7868
- series: {
7869
- description: 'Time series data points',
7870
- type: 'array',
7871
- items: {
7872
- $ref: '#/components/schemas/TimeSeriesPointDto'
7873
- }
7890
+ costBasis: {
7891
+ description: 'Cost basis of held units',
7892
+ nullable: true,
7893
+ allOf: [
7894
+ {
7895
+ $ref: '#/components/schemas/MonetaryDto'
7896
+ }
7897
+ ]
7874
7898
  },
7875
- summary: {
7876
- description: 'Period summary',
7899
+ marketValue: {
7900
+ description: 'Market value at asOf price',
7901
+ nullable: true,
7877
7902
  allOf: [
7878
7903
  {
7879
- $ref: '#/components/schemas/TrendSummaryDto'
7904
+ $ref: '#/components/schemas/MonetaryDto'
7880
7905
  }
7881
7906
  ]
7882
7907
  },
7883
- period: {
7884
- type: 'string',
7885
- description: 'Period requested',
7886
- example: '6m'
7908
+ currentPrice: {
7909
+ description: 'Price used for market value',
7910
+ nullable: true,
7911
+ allOf: [
7912
+ {
7913
+ $ref: '#/components/schemas/CurrentPriceDto'
7914
+ }
7915
+ ]
7887
7916
  },
7888
- granularity: {
7889
- type: 'string',
7890
- description: 'Data granularity',
7891
- example: 'month'
7917
+ unrealizedPnlBase: {
7918
+ type: 'object',
7919
+ description:
7920
+ 'Unrealized P&L in base currency (Decimal string); null when any FX/price missing',
7921
+ nullable: true,
7922
+ example: '6000'
7892
7923
  },
7893
- currency: {
7894
- type: 'string',
7895
- description: 'Base currency for converted values',
7896
- example: 'CNY'
7924
+ unrealizedPnlPct: {
7925
+ type: 'object',
7926
+ description: 'Unrealized P&L % (Decimal string)',
7927
+ nullable: true,
7928
+ example: '25'
7897
7929
  },
7898
- byCurrency: {
7930
+ costFxRate: {
7931
+ description: 'Historical FX rate applied to cost basis',
7932
+ nullable: true,
7933
+ allOf: [
7934
+ {
7935
+ $ref: '#/components/schemas/FxRateDto'
7936
+ }
7937
+ ]
7938
+ },
7939
+ marketFxRate: {
7940
+ description: 'FX rate applied to market value',
7941
+ nullable: true,
7942
+ allOf: [
7943
+ {
7944
+ $ref: '#/components/schemas/FxRateDto'
7945
+ }
7946
+ ]
7947
+ },
7948
+ pctOfInvestedAssets: {
7949
+ type: 'object',
7899
7950
  description:
7900
- 'Multi-currency time series (each point has currency breakdown)',
7901
- type: 'array',
7902
- items: {
7903
- $ref: '#/components/schemas/MultiCurrencyPointDto'
7904
- }
7951
+ 'Share of invested assets % (Decimal string); only for invested chartTokens',
7952
+ nullable: true,
7953
+ example: '40'
7905
7954
  },
7906
- warnings: {
7907
- description: 'Exchange rate warnings',
7908
- type: 'array',
7909
- items: {
7910
- $ref: '#/components/schemas/ExchangeRateWarningDto'
7911
- }
7955
+ realizedPnl: {
7956
+ description:
7957
+ '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',
7958
+ nullable: true,
7959
+ allOf: [
7960
+ {
7961
+ $ref: '#/components/schemas/MonetaryDto'
7962
+ }
7963
+ ]
7912
7964
  }
7913
7965
  },
7914
- required: ['series', 'summary', 'period', 'granularity', 'currency']
7966
+ required: [
7967
+ 'accountId',
7968
+ 'accountPath',
7969
+ 'symbol',
7970
+ 'chartToken',
7971
+ 'assetClass',
7972
+ 'units'
7973
+ ]
7915
7974
  } as const;
7916
7975
 
7917
- export const $CashFlowPointDto = {
7976
+ export const $HoldingPnlWarningDto = {
7918
7977
  type: 'object',
7919
7978
  properties: {
7920
- month: {
7979
+ type: {
7921
7980
  type: 'string',
7922
- description: 'Month key (YYYY-MM)',
7923
- example: '2024-03'
7981
+ description: 'Warning type',
7982
+ example: 'MISSING_COST_FX_RATE',
7983
+ enum: [
7984
+ 'MISSING_COST_FX_RATE',
7985
+ 'MISSING_MARKET_FX_RATE',
7986
+ 'MISSING_SALE_PRICE',
7987
+ 'MISSING_REALIZED_FX_RATE',
7988
+ 'OVERSOLD_LOTS',
7989
+ 'NO_PRICE',
7990
+ 'MIXED_COST_CURRENCY'
7991
+ ]
7924
7992
  },
7925
- income: {
7926
- type: 'string',
7927
- description: 'Income in base currency (absolute, converted)',
7928
- example: '10000.00'
7993
+ symbol: {
7994
+ type: 'object',
7995
+ nullable: true
7929
7996
  },
7930
- expense: {
7931
- type: 'string',
7932
- description: 'Expense in base currency (absolute, converted)',
7933
- example: '5000.00'
7997
+ accountId: {
7998
+ type: 'object',
7999
+ nullable: true
7934
8000
  },
7935
- netSavings: {
7936
- type: 'string',
7937
- description: 'netSavings = income − expense (savings positive)',
7938
- example: '5000.00'
8001
+ currency: {
8002
+ type: 'object',
8003
+ nullable: true
7939
8004
  }
7940
8005
  },
7941
- required: ['month', 'income', 'expense', 'netSavings']
8006
+ required: ['type']
7942
8007
  } as const;
7943
8008
 
7944
- export const $CashFlowTrendSummaryDto = {
8009
+ export const $HoldingPnlResponseDto = {
7945
8010
  type: 'object',
7946
8011
  properties: {
7947
- totalIncome: {
7948
- type: 'string',
7949
- description: 'Total income across the period',
7950
- example: '60000.00'
7951
- },
7952
- totalExpense: {
8012
+ asOfDate: {
7953
8013
  type: 'string',
7954
- description: 'Total expense across the period',
7955
- example: '30000.00'
8014
+ example: '2026-07-08'
7956
8015
  },
7957
- totalNetSavings: {
8016
+ baseCurrency: {
7958
8017
  type: 'string',
7959
- description: 'income − expense across the period',
7960
- example: '30000.00'
8018
+ example: 'CNY'
7961
8019
  },
7962
- averageMonthlyNetSavings: {
8020
+ method: {
7963
8021
  type: 'string',
7964
8022
  description:
7965
- 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
7966
- example: '5000.00'
7967
- }
7968
- },
7969
- required: [
7970
- 'totalIncome',
7971
- 'totalExpense',
7972
- 'totalNetSavings',
7973
- 'averageMonthlyNetSavings'
7974
- ]
7975
- } as const;
7976
-
7977
- export const $CashFlowTrendsResponseDto = {
7978
- type: 'object',
7979
- properties: {
7980
- series: {
7981
- description:
7982
- 'Monthly cash-flow series (fixed N-month window, zero-filled)',
8023
+ 'Realized-P&L lot-matching method (FIFO or average). Unrealized cost basis remains average regardless of this value (#473).',
8024
+ enum: ['average', 'FIFO'],
8025
+ example: 'average'
8026
+ },
8027
+ rows: {
7983
8028
  type: 'array',
7984
8029
  items: {
7985
- $ref: '#/components/schemas/CashFlowPointDto'
8030
+ $ref: '#/components/schemas/HoldingPnlRowDto'
7986
8031
  }
7987
8032
  },
7988
- summary: {
7989
- description: 'Period totals',
7990
- allOf: [
7991
- {
7992
- $ref: '#/components/schemas/CashFlowTrendSummaryDto'
7993
- }
7994
- ]
7995
- },
7996
- period: {
7997
- type: 'string',
7998
- description: 'Period requested',
7999
- example: '6m'
8000
- },
8001
- granularity: {
8002
- type: 'string',
8003
- description: 'Data granularity (v1 returns month buckets)',
8004
- example: 'month'
8005
- },
8006
- currency: {
8007
- type: 'string',
8008
- description: 'Base currency for converted values',
8009
- example: 'CNY'
8010
- },
8011
8033
  warnings: {
8012
- description: 'Exchange rate warnings (e.g. missing rate for a currency)',
8013
8034
  type: 'array',
8014
8035
  items: {
8015
- $ref: '#/components/schemas/ExchangeRateWarningDto'
8036
+ $ref: '#/components/schemas/HoldingPnlWarningDto'
8016
8037
  }
8017
8038
  }
8018
8039
  },
8019
- required: ['series', 'summary', 'period', 'granularity', 'currency']
8020
- } as const;
8021
-
8022
- export const $GenerateSnapshotBody = {
8023
- type: 'object',
8024
- properties: {}
8025
- } as const;
8026
-
8027
- export const $GenerateSnapshotResponse = {
8028
- type: 'object',
8029
- properties: {}
8030
- } as const;
8031
-
8032
- export const $BackfillSnapshotsBody = {
8033
- type: 'object',
8034
- properties: {}
8035
- } as const;
8036
-
8037
- export const $BackfillSnapshotsResponse = {
8038
- type: 'object',
8039
- properties: {}
8040
+ required: ['asOfDate', 'baseCurrency', 'method', 'rows', 'warnings']
8040
8041
  } as const;
8041
8042
 
8042
8043
  export const $AnonymousLoginDto = {