@firela/api-types 0.0.0-canary.e1146c01 → 0.0.0-canary.e8d26ec2

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.
@@ -17,6 +17,8 @@ import type {
17
17
  AccountControllerCloseResponse,
18
18
  AccountControllerReopenData,
19
19
  AccountControllerReopenResponse,
20
+ AccountControllerAddOpeningBalanceData,
21
+ AccountControllerAddOpeningBalanceResponse,
20
22
  AccountStandardsControllerGetTemplatesData,
21
23
  AccountStandardsControllerGetTemplatesResponse,
22
24
  AccountStandardsControllerGetTemplateMetadataData,
@@ -97,6 +99,18 @@ import type {
97
99
  CommodityControllerGetOrCreateResponse,
98
100
  CommodityControllerBulkCreateData,
99
101
  CommodityControllerBulkCreateResponse,
102
+ PriceControllerCreateData,
103
+ PriceControllerCreateResponse,
104
+ PriceControllerFindAllData,
105
+ PriceControllerFindAllResponse,
106
+ PriceControllerFindOneData,
107
+ PriceControllerFindOneResponse,
108
+ PriceControllerUpdateData,
109
+ PriceControllerUpdateResponse,
110
+ PriceControllerDeleteData,
111
+ PriceControllerDeleteResponse,
112
+ PriceControllerBulkCreateData,
113
+ PriceControllerBulkCreateResponse,
100
114
  RecurringRuleControllerCreateData,
101
115
  RecurringRuleControllerCreateResponse,
102
116
  RecurringRuleControllerFindAllData,
@@ -129,26 +143,14 @@ import type {
129
143
  ExpectedTransactionControllerEnterNowResponse,
130
144
  ForecastControllerGetForecastData,
131
145
  ForecastControllerGetForecastResponse,
132
- TransactionRuleControllerCreateData,
133
- TransactionRuleControllerCreateResponse,
134
- TransactionRuleControllerListData,
135
- TransactionRuleControllerListResponse,
136
- TransactionRuleControllerValidateData,
137
- TransactionRuleControllerValidateResponse,
138
- TransactionRuleControllerBulkCreateData,
139
- TransactionRuleControllerBulkCreateResponse,
140
- TransactionRuleControllerExportData,
141
- TransactionRuleControllerExportResponse,
142
- TransactionRuleControllerGetStatisticsData,
143
- TransactionRuleControllerGetStatisticsResponse,
144
- TransactionRuleControllerGetDetailData,
145
- TransactionRuleControllerGetDetailResponse,
146
- TransactionRuleControllerUpdateData,
147
- TransactionRuleControllerUpdateResponse,
148
- TransactionRuleControllerDeleteData,
149
- TransactionRuleControllerDeleteResponse,
150
- TransactionRuleControllerTestData,
151
- TransactionRuleControllerTestResponse,
146
+ ReportingControllerGetPortfolioTrendsData,
147
+ ReportingControllerGetPortfolioTrendsResponse,
148
+ ReportingControllerGetCashFlowTrendsData,
149
+ ReportingControllerGetCashFlowTrendsResponse,
150
+ ReportingControllerGenerateSnapshotData,
151
+ ReportingControllerGenerateSnapshotResponse,
152
+ ReportingControllerBackfillSnapshotsData,
153
+ ReportingControllerBackfillSnapshotsResponse,
152
154
  UserControllerDeleteOwnUserData,
153
155
  UserControllerDeleteOwnUserResponse,
154
156
  UserControllerGetUserData,
@@ -171,6 +173,48 @@ import type {
171
173
  PropertyControllerUpdateResponse,
172
174
  PropertyControllerDeleteData,
173
175
  PropertyControllerDeleteResponse,
176
+ TransactionRuleControllerCreateData,
177
+ TransactionRuleControllerCreateResponse,
178
+ TransactionRuleControllerListData,
179
+ TransactionRuleControllerListResponse,
180
+ TransactionRuleControllerValidateData,
181
+ TransactionRuleControllerValidateResponse,
182
+ TransactionRuleControllerBulkCreateData,
183
+ TransactionRuleControllerBulkCreateResponse,
184
+ TransactionRuleControllerExportData,
185
+ TransactionRuleControllerExportResponse,
186
+ TransactionRuleControllerGetStatisticsData,
187
+ TransactionRuleControllerGetStatisticsResponse,
188
+ TransactionRuleControllerGetDetailData,
189
+ TransactionRuleControllerGetDetailResponse,
190
+ TransactionRuleControllerUpdateData,
191
+ TransactionRuleControllerUpdateResponse,
192
+ TransactionRuleControllerDeleteData,
193
+ TransactionRuleControllerDeleteResponse,
194
+ TransactionRuleControllerTestData,
195
+ TransactionRuleControllerTestResponse,
196
+ EventControllerCreateData,
197
+ EventControllerCreateResponse,
198
+ EventControllerFindAllData,
199
+ EventControllerFindAllResponse,
200
+ EventControllerFindOneData,
201
+ EventControllerFindOneResponse,
202
+ EventControllerUpdateData,
203
+ EventControllerUpdateResponse,
204
+ EventControllerDeleteData,
205
+ EventControllerDeleteResponse,
206
+ EventControllerGetSliceData,
207
+ EventControllerGetSliceResponse,
208
+ OnboardingControllerBootstrapData,
209
+ OnboardingControllerBootstrapResponse,
210
+ ReconciliationControllerComputeData,
211
+ ReconciliationControllerComputeResponse,
212
+ ReconciliationControllerAssertData,
213
+ ReconciliationControllerAssertResponse,
214
+ ReconciliationControllerPadData,
215
+ ReconciliationControllerPadResponse,
216
+ ReconciliationControllerHistoryData,
217
+ ReconciliationControllerHistoryResponse,
174
218
  ExportControllerExportBeancountResponse,
175
219
  FileImportControllerImportFileData,
176
220
  FileImportControllerImportFileResponse,
@@ -184,42 +228,52 @@ import type {
184
228
  ImporterConfigControllerUpdateConfigResponse,
185
229
  ImporterConfigControllerResetConfigData,
186
230
  ImporterConfigControllerResetConfigResponse,
187
- PlatformControllerFindAllResponse,
188
- PlatformControllerCreateData,
189
- PlatformControllerCreateResponse,
190
- PlatformControllerGetPlatformListResponse,
191
- PlatformControllerMatchPlatformsData,
192
- PlatformControllerMatchPlatformsResponse,
193
- PlatformControllerUpdateData,
194
- PlatformControllerUpdateResponse,
195
- PlatformControllerDeleteData,
196
- PlatformControllerDeleteResponse,
197
231
  ProviderSyncControllerSyncData,
198
232
  ProviderSyncControllerSyncResponse,
199
233
  ProviderSyncControllerGetSupportedProvidersData,
200
234
  ProviderSyncControllerGetSupportedProvidersResponse,
201
235
  ProviderSyncControllerIsProviderSupportedData,
202
236
  ProviderSyncControllerIsProviderSupportedResponse,
237
+ ExternalAccountLinkControllerCreateData,
238
+ ExternalAccountLinkControllerCreateResponse,
239
+ ExternalAccountLinkControllerFindAllData,
240
+ ExternalAccountLinkControllerFindAllResponse,
241
+ ExternalAccountLinkControllerFindOneData,
242
+ ExternalAccountLinkControllerFindOneResponse,
243
+ ExternalAccountLinkControllerRemoveData,
244
+ ExternalAccountLinkControllerRemoveResponse,
203
245
  TelemetryControllerReportTelemetryData,
204
246
  TelemetryControllerReportTelemetryResponse,
247
+ TelemetryControllerReportCoverageMissData,
248
+ TelemetryControllerReportCoverageMissResponse,
249
+ TelemetryControllerGetCoverageMetricsData,
250
+ TelemetryControllerGetCoverageMetricsResponse,
205
251
  NlpControllerProcessNaturalLanguageData,
206
252
  NlpControllerProcessNaturalLanguageResponse,
207
253
  NlpControllerClearSessionData,
208
254
  NlpControllerClearSessionResponse,
209
255
  NlpControllerGetSessionData,
210
256
  NlpControllerGetSessionResponse,
257
+ PlatformControllerFindAllResponse,
258
+ PlatformControllerCreateData,
259
+ PlatformControllerCreateResponse,
260
+ PlatformControllerGetPlatformListResponse,
261
+ PlatformControllerMatchPlatformsData,
262
+ PlatformControllerMatchPlatformsResponse,
263
+ PlatformControllerUpdateData,
264
+ PlatformControllerUpdateResponse,
265
+ PlatformControllerDeleteData,
266
+ PlatformControllerDeleteResponse,
211
267
  DashboardControllerGetNetWorthData,
212
268
  DashboardControllerGetNetWorthResponse,
213
269
  DashboardControllerGetAccountsData,
214
270
  DashboardControllerGetAccountsResponse,
215
271
  DashboardControllerGetCashFlowData,
216
272
  DashboardControllerGetCashFlowResponse,
217
- ReportingControllerGetPortfolioTrendsData,
218
- ReportingControllerGetPortfolioTrendsResponse,
219
- ReportingControllerGenerateSnapshotData,
220
- ReportingControllerGenerateSnapshotResponse,
221
- ReportingControllerBackfillSnapshotsData,
222
- ReportingControllerBackfillSnapshotsResponse,
273
+ DashboardControllerGetExpensesData,
274
+ DashboardControllerGetExpensesResponse,
275
+ HoldingPnlControllerGetHoldingPnlData,
276
+ HoldingPnlControllerGetHoldingPnlResponse,
223
277
  ApiKeysControllerCreateApiKeyResponse,
224
278
  AuthControllerAccessTokenLoginData,
225
279
  AuthControllerAccessTokenLoginResponse,
@@ -272,7 +326,7 @@ export class BeanAccountsService {
272
326
  * @param data.type Filter by account type
273
327
  * @param data.status Filter by status
274
328
  * @param data.isCustom Filter by custom (user-created) accounts only
275
- * @param data.search Search term for path or i18nKey
329
+ * @param data.search Search term for account path
276
330
  * @param data.limit Maximum number of results
277
331
  * @param data.offset Number of results to skip
278
332
  * @returns AccountListResponseDto Accounts retrieved successfully
@@ -434,6 +488,35 @@ export class BeanAccountsService {
434
488
  }
435
489
  });
436
490
  }
491
+
492
+ /**
493
+ * Post an opening-balance transaction
494
+ * Posts a double-entry opening-balance transaction against Equity:Opening-Balances for an existing Assets/Liabilities account. At most one active opening balance per account.
495
+ * @param data The data for the request.
496
+ * @param data.id Account UUID
497
+ * @param data.region Region code for tenant context
498
+ * @param data.requestBody
499
+ * @returns OpeningBalanceResultDto Opening-balance transaction created
500
+ * @throws ApiError
501
+ */
502
+ public static accountControllerAddOpeningBalance(
503
+ data: AccountControllerAddOpeningBalanceData
504
+ ): CancelablePromise<AccountControllerAddOpeningBalanceResponse> {
505
+ return __request(OpenAPI, {
506
+ method: 'POST',
507
+ url: '/api/v1/{region}/bean/accounts/{id}/opening-balance',
508
+ path: {
509
+ id: data.id,
510
+ region: data.region
511
+ },
512
+ body: data.requestBody,
513
+ mediaType: 'application/json',
514
+ errors: {
515
+ 404: 'Account not found',
516
+ 409: 'An opening balance already exists for this account'
517
+ }
518
+ });
519
+ }
437
520
  }
438
521
 
439
522
  export class BeanAccountStandardsService {
@@ -465,7 +548,7 @@ export class BeanAccountStandardsService {
465
548
 
466
549
  /**
467
550
  * Get template metadata for an account path
468
- * Returns extendable status and root type for a template path.
551
+ * Returns root type for a template path.
469
552
  * @param data The data for the request.
470
553
  * @param data.region Region code for tenant context
471
554
  * @param data.path Account path to check
@@ -551,6 +634,7 @@ export class BeanTransactionsService {
551
634
  * @param data.status Filter by transaction status
552
635
  * @param data.search Search in narration and payee fields (max 200 chars)
553
636
  * @param data.accountId Filter by account ID (transactions with postings to this account)
637
+ * @param data.category Filter by ADR-0075 functional category (Group segment); matches any posting to an Expenses/Income account whose derived Group segment equals this value
554
638
  * @returns TransactionListResponseDto Transaction list
555
639
  * @throws ApiError
556
640
  */
@@ -570,7 +654,8 @@ export class BeanTransactionsService {
570
654
  dateTo: data.dateTo,
571
655
  status: data.status,
572
656
  search: data.search,
573
- accountId: data.accountId
657
+ accountId: data.accountId,
658
+ category: data.category
574
659
  },
575
660
  errors: {
576
661
  400: 'Validation failed',
@@ -758,7 +843,7 @@ export class BeanBalancesService {
758
843
  * Query account balance
759
844
  * Calculate account balance at a specific date for a single currency
760
845
  * @param data The data for the request.
761
- * @param data.account Account name (e.g., "Assets:Bank:Checking")
846
+ * @param data.account Account name (e.g., "Assets:Checking")
762
847
  * @param data.region Region code for tenant context
763
848
  * @param data.date Date to calculate balance at (ISO 8601 format)
764
849
  * @param data.currency Currency to query (e.g., "USD", "CNY")
@@ -1479,6 +1564,173 @@ export class BeanCommoditiesService {
1479
1564
  }
1480
1565
  }
1481
1566
 
1567
+ export class BeanPricesService {
1568
+ /**
1569
+ * Create a new price
1570
+ * Creates a new price entry for the authenticated user
1571
+ * @param data The data for the request.
1572
+ * @param data.region Region code for tenant context
1573
+ * @param data.requestBody
1574
+ * @returns PriceResponseDto Price created successfully
1575
+ * @throws ApiError
1576
+ */
1577
+ public static priceControllerCreate(
1578
+ data: PriceControllerCreateData
1579
+ ): CancelablePromise<PriceControllerCreateResponse> {
1580
+ return __request(OpenAPI, {
1581
+ method: 'POST',
1582
+ url: '/api/v1/{region}/bean/prices',
1583
+ path: {
1584
+ region: data.region
1585
+ },
1586
+ body: data.requestBody,
1587
+ mediaType: 'application/json',
1588
+ errors: {
1589
+ 404: 'Currency or quoteCurrency commodity not found',
1590
+ 409: 'Price already exists for this currency pair and date'
1591
+ }
1592
+ });
1593
+ }
1594
+
1595
+ /**
1596
+ * List user prices
1597
+ * Returns all price entries for the authenticated user with optional filtering
1598
+ * @param data The data for the request.
1599
+ * @param data.region Region code for tenant context
1600
+ * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
1601
+ * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
1602
+ * @param data.dateFrom Filter prices from this date (ISO 8601 format)
1603
+ * @param data.dateTo Filter prices to this date (ISO 8601 format)
1604
+ * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
1605
+ * @param data.page Page number for pagination (default: 1)
1606
+ * @param data.limit Number of items per page (default: 20, max: 100)
1607
+ * @returns PriceListResponseDto Prices retrieved successfully
1608
+ * @throws ApiError
1609
+ */
1610
+ public static priceControllerFindAll(
1611
+ data: PriceControllerFindAllData
1612
+ ): CancelablePromise<PriceControllerFindAllResponse> {
1613
+ return __request(OpenAPI, {
1614
+ method: 'GET',
1615
+ url: '/api/v1/{region}/bean/prices',
1616
+ path: {
1617
+ region: data.region
1618
+ },
1619
+ query: {
1620
+ currency: data.currency,
1621
+ quoteCurrency: data.quoteCurrency,
1622
+ dateFrom: data.dateFrom,
1623
+ dateTo: data.dateTo,
1624
+ search: data.search,
1625
+ page: data.page,
1626
+ limit: data.limit
1627
+ }
1628
+ });
1629
+ }
1630
+
1631
+ /**
1632
+ * Get price by ID
1633
+ * Returns a single price entry by its ID
1634
+ * @param data The data for the request.
1635
+ * @param data.id Price ID
1636
+ * @param data.region Region code for tenant context
1637
+ * @returns PriceResponseDto Price retrieved successfully
1638
+ * @throws ApiError
1639
+ */
1640
+ public static priceControllerFindOne(
1641
+ data: PriceControllerFindOneData
1642
+ ): CancelablePromise<PriceControllerFindOneResponse> {
1643
+ return __request(OpenAPI, {
1644
+ method: 'GET',
1645
+ url: '/api/v1/{region}/bean/prices/{id}',
1646
+ path: {
1647
+ id: data.id,
1648
+ region: data.region
1649
+ },
1650
+ errors: {
1651
+ 404: 'Price not found'
1652
+ }
1653
+ });
1654
+ }
1655
+
1656
+ /**
1657
+ * Update a price
1658
+ * Updates an existing price entry
1659
+ * @param data The data for the request.
1660
+ * @param data.id Price ID
1661
+ * @param data.region Region code for tenant context
1662
+ * @param data.requestBody
1663
+ * @returns PriceResponseDto Price updated successfully
1664
+ * @throws ApiError
1665
+ */
1666
+ public static priceControllerUpdate(
1667
+ data: PriceControllerUpdateData
1668
+ ): CancelablePromise<PriceControllerUpdateResponse> {
1669
+ return __request(OpenAPI, {
1670
+ method: 'PUT',
1671
+ url: '/api/v1/{region}/bean/prices/{id}',
1672
+ path: {
1673
+ id: data.id,
1674
+ region: data.region
1675
+ },
1676
+ body: data.requestBody,
1677
+ mediaType: 'application/json',
1678
+ errors: {
1679
+ 404: 'Price not found',
1680
+ 409: 'Updated price conflicts with existing price'
1681
+ }
1682
+ });
1683
+ }
1684
+
1685
+ /**
1686
+ * Delete a price
1687
+ * Deletes a price entry (hard delete)
1688
+ * @param data The data for the request.
1689
+ * @param data.id Price ID
1690
+ * @param data.region Region code for tenant context
1691
+ * @returns void Price deleted successfully
1692
+ * @throws ApiError
1693
+ */
1694
+ public static priceControllerDelete(
1695
+ data: PriceControllerDeleteData
1696
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1697
+ return __request(OpenAPI, {
1698
+ method: 'DELETE',
1699
+ url: '/api/v1/{region}/bean/prices/{id}',
1700
+ path: {
1701
+ id: data.id,
1702
+ region: data.region
1703
+ },
1704
+ errors: {
1705
+ 404: 'Price not found'
1706
+ }
1707
+ });
1708
+ }
1709
+
1710
+ /**
1711
+ * Bulk create prices
1712
+ * Creates multiple price entries at once (skips duplicates)
1713
+ * @param data The data for the request.
1714
+ * @param data.region Region code for tenant context
1715
+ * @param data.requestBody
1716
+ * @returns PriceResponseDto Prices created successfully
1717
+ * @throws ApiError
1718
+ */
1719
+ public static priceControllerBulkCreate(
1720
+ data: PriceControllerBulkCreateData
1721
+ ): CancelablePromise<PriceControllerBulkCreateResponse> {
1722
+ return __request(OpenAPI, {
1723
+ method: 'POST',
1724
+ url: '/api/v1/{region}/bean/prices/bulk',
1725
+ path: {
1726
+ region: data.region
1727
+ },
1728
+ body: data.requestBody,
1729
+ mediaType: 'application/json'
1730
+ });
1731
+ }
1732
+ }
1733
+
1482
1734
  export class RecurringRulesService {
1483
1735
  /**
1484
1736
  * Create a new recurring rule
@@ -1909,279 +2161,158 @@ export class RecurringForecastService {
1909
2161
  }
1910
2162
  }
1911
2163
 
1912
- export class BeanTransactionRulesService {
2164
+ export class ReportingService {
1913
2165
  /**
1914
- * Create a new transaction rule (or upsert if upsertByPayee=true)
1915
- * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2166
+ * Get portfolio value trends
2167
+ *
2168
+ * Returns time series data of portfolio net worth.
2169
+ *
2170
+ * **Multi-currency Support:**
2171
+ * - `series[].byCurrency` - Currency breakdown for each data point
2172
+ * - `byCurrency` - Separate time series grouped by currency
2173
+ * - `warnings` - Exchange rate warnings if conversion failed
2174
+ *
2175
+ * **Parameters:**
2176
+ * - `period`: Time period (1m, 3m, 6m, 1y)
2177
+ * - `granularity`: Data granularity (day, week, month)
2178
+ *
1916
2179
  * @param data The data for the request.
1917
2180
  * @param data.region Region code for tenant context
1918
- * @param data.requestBody
1919
- * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2181
+ * @param data.period Time period
2182
+ * @param data.granularity Data granularity
2183
+ * @returns PortfolioTrendsResponseDto Trends retrieved successfully
1920
2184
  * @throws ApiError
1921
2185
  */
1922
- public static transactionRuleControllerCreate(
1923
- data: TransactionRuleControllerCreateData
1924
- ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2186
+ public static reportingControllerGetPortfolioTrends(
2187
+ data: ReportingControllerGetPortfolioTrendsData
2188
+ ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
1925
2189
  return __request(OpenAPI, {
1926
- method: 'POST',
1927
- url: '/api/v1/{region}/bean/transaction-rules',
2190
+ method: 'GET',
2191
+ url: '/api/v1/{region}/reporting/portfolio/trends',
1928
2192
  path: {
1929
2193
  region: data.region
1930
2194
  },
1931
- body: data.requestBody,
1932
- mediaType: 'application/json',
2195
+ query: {
2196
+ period: data.period,
2197
+ granularity: data.granularity
2198
+ },
1933
2199
  errors: {
1934
- 400: 'Validation failed',
1935
- 401: 'Unauthorized',
1936
- 409: 'Resource conflict - another process is updating this rule'
2200
+ 401: 'User not authenticated'
1937
2201
  }
1938
2202
  });
1939
2203
  }
1940
2204
 
1941
2205
  /**
1942
- * Get all transaction rules for user
2206
+ * Get cash-flow trends
2207
+ *
2208
+ * Monthly income / expense / netSavings over a fixed N-month window
2209
+ * (current month + N−1 prior). Missing months are zero-filled (flow metric).
2210
+ *
2211
+ * **Parameters:**
2212
+ * - `period`: 1m | 3m | 6m | 1y (default 6m)
2213
+ * - `granularity`: accepted for API symmetry; v1 returns month buckets
2214
+ *
1943
2215
  * @param data The data for the request.
1944
2216
  * @param data.region Region code for tenant context
1945
- * @param data.limit Max results per page (default: 20, max: 100)
1946
- * @param data.offset Pagination offset (default: 0)
1947
- * @param data.enabled Filter by enabled status
1948
- * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
1949
- * @param data.autoApplyEnabled Filter by auto-apply status
1950
- * @returns TransactionRuleListResponseDto List of rules
2217
+ * @param data.period Time period
2218
+ * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
2219
+ * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
1951
2220
  * @throws ApiError
1952
2221
  */
1953
- public static transactionRuleControllerList(
1954
- data: TransactionRuleControllerListData
1955
- ): CancelablePromise<TransactionRuleControllerListResponse> {
2222
+ public static reportingControllerGetCashFlowTrends(
2223
+ data: ReportingControllerGetCashFlowTrendsData
2224
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
1956
2225
  return __request(OpenAPI, {
1957
2226
  method: 'GET',
1958
- url: '/api/v1/{region}/bean/transaction-rules',
2227
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
1959
2228
  path: {
1960
2229
  region: data.region
1961
2230
  },
1962
2231
  query: {
1963
- limit: data.limit,
1964
- offset: data.offset,
1965
- enabled: data.enabled,
1966
- learningSource: data.learningSource,
1967
- autoApplyEnabled: data.autoApplyEnabled
1968
- },
1969
- errors: {
1970
- 401: 'Unauthorized'
1971
- }
1972
- });
1973
- }
1974
-
1975
- /**
1976
- * Validate transaction rule configuration
1977
- * @param data The data for the request.
1978
- * @param data.region Region code for tenant context
1979
- * @param data.requestBody
1980
- * @returns ValidateRuleResponseDto Validation result
1981
- * @throws ApiError
1982
- */
1983
- public static transactionRuleControllerValidate(
1984
- data: TransactionRuleControllerValidateData
1985
- ): CancelablePromise<TransactionRuleControllerValidateResponse> {
1986
- return __request(OpenAPI, {
1987
- method: 'POST',
1988
- url: '/api/v1/{region}/bean/transaction-rules/validate',
1989
- path: {
1990
- region: data.region
1991
- },
1992
- body: data.requestBody,
1993
- mediaType: 'application/json',
1994
- errors: {
1995
- 400: 'Validation failed',
1996
- 401: 'Unauthorized'
1997
- }
1998
- });
1999
- }
2000
-
2001
- /**
2002
- * Bulk create transaction rules
2003
- * @param data The data for the request.
2004
- * @param data.region Region code for tenant context
2005
- * @param data.requestBody
2006
- * @returns BulkCreateRulesResponseDto Bulk create completed
2007
- * @throws ApiError
2008
- */
2009
- public static transactionRuleControllerBulkCreate(
2010
- data: TransactionRuleControllerBulkCreateData
2011
- ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2012
- return __request(OpenAPI, {
2013
- method: 'POST',
2014
- url: '/api/v1/{region}/bean/transaction-rules/bulk',
2015
- path: {
2016
- region: data.region
2017
- },
2018
- body: data.requestBody,
2019
- mediaType: 'application/json',
2020
- errors: {
2021
- 400: 'Invalid bulk create data',
2022
- 401: 'Unauthorized'
2023
- }
2024
- });
2025
- }
2026
-
2027
- /**
2028
- * Export transaction rules
2029
- * @param data The data for the request.
2030
- * @param data.format Export format (currently only JSON supported)
2031
- * @param data.region Region code for tenant context
2032
- * @returns ExportRulesResponseDto Exported rules
2033
- * @throws ApiError
2034
- */
2035
- public static transactionRuleControllerExport(
2036
- data: TransactionRuleControllerExportData
2037
- ): CancelablePromise<TransactionRuleControllerExportResponse> {
2038
- return __request(OpenAPI, {
2039
- method: 'GET',
2040
- url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2041
- path: {
2042
- format: data.format,
2043
- region: data.region
2044
- },
2045
- errors: {
2046
- 400: 'Unsupported format',
2047
- 401: 'Unauthorized'
2048
- }
2049
- });
2050
- }
2051
-
2052
- /**
2053
- * Get transaction rule statistics
2054
- * @param data The data for the request.
2055
- * @param data.period Statistics time period
2056
- * @param data.region Region code for tenant context
2057
- * @returns RuleStatisticsResponseDto Rule statistics
2058
- * @throws ApiError
2059
- */
2060
- public static transactionRuleControllerGetStatistics(
2061
- data: TransactionRuleControllerGetStatisticsData
2062
- ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2063
- return __request(OpenAPI, {
2064
- method: 'GET',
2065
- url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2066
- path: {
2067
2232
  period: data.period,
2068
- region: data.region
2069
- },
2070
- errors: {
2071
- 401: 'Unauthorized'
2072
- }
2073
- });
2074
- }
2075
-
2076
- /**
2077
- * Get transaction rule detail
2078
- * @param data The data for the request.
2079
- * @param data.ruleId Rule ID
2080
- * @param data.region Region code for tenant context
2081
- * @returns TransactionRuleResponseDto Rule details
2082
- * @throws ApiError
2083
- */
2084
- public static transactionRuleControllerGetDetail(
2085
- data: TransactionRuleControllerGetDetailData
2086
- ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2087
- return __request(OpenAPI, {
2088
- method: 'GET',
2089
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2090
- path: {
2091
- ruleId: data.ruleId,
2092
- region: data.region
2233
+ granularity: data.granularity
2093
2234
  },
2094
2235
  errors: {
2095
- 401: 'Unauthorized',
2096
- 403: 'Forbidden - not owner of rule',
2097
- 404: 'Rule not found'
2236
+ 401: 'User not authenticated'
2098
2237
  }
2099
2238
  });
2100
2239
  }
2101
2240
 
2102
2241
  /**
2103
- * Update a transaction rule
2242
+ * Generate portfolio snapshot
2243
+ *
2244
+ * Manually generate a portfolio snapshot for a specific date.
2245
+ *
2246
+ * **Multi-currency Support:**
2247
+ * - Fetches balances grouped by currency
2248
+ * - Uses user's baseCurrency setting for conversion
2249
+ * - Stores exchange rates and warnings
2250
+ *
2251
+ * **Use Cases:**
2252
+ * - Testing snapshot generation
2253
+ * - Force regeneration after data correction
2254
+ * - Initial setup for new users
2255
+ *
2104
2256
  * @param data The data for the request.
2105
- * @param data.ruleId Rule ID to update
2106
2257
  * @param data.region Region code for tenant context
2107
- * @param data.requestBody
2108
- * @returns TransactionRuleResponseDto Rule updated successfully
2258
+ * @param data.requestBody Optional date (defaults to today)
2259
+ * @returns GenerateSnapshotResponse Snapshot generated successfully
2109
2260
  * @throws ApiError
2110
2261
  */
2111
- public static transactionRuleControllerUpdate(
2112
- data: TransactionRuleControllerUpdateData
2113
- ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2262
+ public static reportingControllerGenerateSnapshot(
2263
+ data: ReportingControllerGenerateSnapshotData
2264
+ ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
2114
2265
  return __request(OpenAPI, {
2115
- method: 'PUT',
2116
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2266
+ method: 'POST',
2267
+ url: '/api/v1/{region}/reporting/snapshots/generate',
2117
2268
  path: {
2118
- ruleId: data.ruleId,
2119
2269
  region: data.region
2120
2270
  },
2121
2271
  body: data.requestBody,
2122
2272
  mediaType: 'application/json',
2123
2273
  errors: {
2124
- 400: 'Validation failed',
2125
- 401: 'Unauthorized',
2126
- 403: 'Forbidden - not owner of rule',
2127
- 404: 'Rule not found',
2128
- 409: 'Resource conflict - rule is being modified by another process'
2129
- }
2130
- });
2131
- }
2132
-
2133
- /**
2134
- * Delete a transaction rule
2135
- * @param data The data for the request.
2136
- * @param data.ruleId Rule ID to delete
2137
- * @param data.region Region code for tenant context
2138
- * @returns void Rule deleted successfully
2139
- * @throws ApiError
2140
- */
2141
- public static transactionRuleControllerDelete(
2142
- data: TransactionRuleControllerDeleteData
2143
- ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2144
- return __request(OpenAPI, {
2145
- method: 'DELETE',
2146
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2147
- path: {
2148
- ruleId: data.ruleId,
2149
- region: data.region
2150
- },
2151
- errors: {
2152
- 401: 'Unauthorized',
2153
- 403: 'Forbidden - not owner of rule',
2154
- 404: 'Rule not found',
2155
- 409: 'Resource conflict - rule is being modified by another process'
2274
+ 400: 'Invalid date format',
2275
+ 401: 'User not authenticated'
2156
2276
  }
2157
2277
  });
2158
2278
  }
2159
2279
 
2160
2280
  /**
2161
- * Test rule matching
2281
+ * Backfill portfolio snapshots
2282
+ *
2283
+ * Generate snapshots for a date range (historical data backfill).
2284
+ *
2285
+ * **Multi-currency Support:**
2286
+ * - Each snapshot includes multi-currency data
2287
+ * - Uses exchange rates available at generation time
2288
+ * - Warnings stored for missing exchange rates
2289
+ *
2290
+ * **Best Practices:**
2291
+ * - Use for initial setup after account configuration
2292
+ * - Run during low-traffic periods for large date ranges
2293
+ * - Existing snapshots are skipped (not regenerated)
2294
+ *
2162
2295
  * @param data The data for the request.
2163
- * @param data.ruleId Rule ID to test
2164
2296
  * @param data.region Region code for tenant context
2165
2297
  * @param data.requestBody
2166
- * @returns TestRuleResponseDto Test result
2298
+ * @returns BackfillSnapshotsResponse Backfill completed successfully
2167
2299
  * @throws ApiError
2168
2300
  */
2169
- public static transactionRuleControllerTest(
2170
- data: TransactionRuleControllerTestData
2171
- ): CancelablePromise<TransactionRuleControllerTestResponse> {
2301
+ public static reportingControllerBackfillSnapshots(
2302
+ data: ReportingControllerBackfillSnapshotsData
2303
+ ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
2172
2304
  return __request(OpenAPI, {
2173
2305
  method: 'POST',
2174
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2306
+ url: '/api/v1/{region}/reporting/snapshots/backfill',
2175
2307
  path: {
2176
- ruleId: data.ruleId,
2177
2308
  region: data.region
2178
2309
  },
2179
2310
  body: data.requestBody,
2180
2311
  mediaType: 'application/json',
2181
2312
  errors: {
2182
- 401: 'Unauthorized',
2183
- 403: 'Forbidden - not owner of rule',
2184
- 404: 'Rule not found'
2313
+ 400: 'Invalid date format or range',
2314
+ 401: 'User not authenticated',
2315
+ 409: 'Backfill already in progress for this user'
2185
2316
  }
2186
2317
  });
2187
2318
  }
@@ -2233,7 +2364,7 @@ export class UsersService {
2233
2364
  * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
2234
2365
  * @param data The data for the request.
2235
2366
  * @param data.requestBody
2236
- * @returns unknown User created successfully
2367
+ * @returns SignupResponseDto User created successfully
2237
2368
  * @throws ApiError
2238
2369
  */
2239
2370
  public static userControllerSignupUser(
@@ -2442,22 +2573,608 @@ export class PropertiesService {
2442
2573
  }
2443
2574
  }
2444
2575
 
2445
- export class BeanExportService {
2576
+ export class BeanTransactionRulesService {
2446
2577
  /**
2447
- * Export Beancount ledger as ZIP
2448
- * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
2449
- * @returns unknown
2578
+ * Create a new transaction rule (or upsert if upsertByPayee=true)
2579
+ * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2580
+ * @param data The data for the request.
2581
+ * @param data.region Region code for tenant context
2582
+ * @param data.requestBody
2583
+ * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2450
2584
  * @throws ApiError
2451
2585
  */
2452
- public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
2586
+ public static transactionRuleControllerCreate(
2587
+ data: TransactionRuleControllerCreateData
2588
+ ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2453
2589
  return __request(OpenAPI, {
2454
- method: 'GET',
2455
- url: '/api/v1/{region}/bean/export/beancount'
2456
- });
2457
- }
2458
- }
2459
-
2460
- export class BeanImportService {
2590
+ method: 'POST',
2591
+ url: '/api/v1/{region}/bean/transaction-rules',
2592
+ path: {
2593
+ region: data.region
2594
+ },
2595
+ body: data.requestBody,
2596
+ mediaType: 'application/json',
2597
+ errors: {
2598
+ 400: 'Validation failed',
2599
+ 401: 'Unauthorized',
2600
+ 409: 'Resource conflict - another process is updating this rule'
2601
+ }
2602
+ });
2603
+ }
2604
+
2605
+ /**
2606
+ * Get all transaction rules for user
2607
+ * @param data The data for the request.
2608
+ * @param data.region Region code for tenant context
2609
+ * @param data.limit Max results per page (default: 20, max: 100)
2610
+ * @param data.offset Pagination offset (default: 0)
2611
+ * @param data.enabled Filter by enabled status
2612
+ * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
2613
+ * @param data.autoApplyEnabled Filter by auto-apply status
2614
+ * @returns TransactionRuleListResponseDto List of rules
2615
+ * @throws ApiError
2616
+ */
2617
+ public static transactionRuleControllerList(
2618
+ data: TransactionRuleControllerListData
2619
+ ): CancelablePromise<TransactionRuleControllerListResponse> {
2620
+ return __request(OpenAPI, {
2621
+ method: 'GET',
2622
+ url: '/api/v1/{region}/bean/transaction-rules',
2623
+ path: {
2624
+ region: data.region
2625
+ },
2626
+ query: {
2627
+ limit: data.limit,
2628
+ offset: data.offset,
2629
+ enabled: data.enabled,
2630
+ learningSource: data.learningSource,
2631
+ autoApplyEnabled: data.autoApplyEnabled
2632
+ },
2633
+ errors: {
2634
+ 401: 'Unauthorized'
2635
+ }
2636
+ });
2637
+ }
2638
+
2639
+ /**
2640
+ * Validate transaction rule configuration
2641
+ * @param data The data for the request.
2642
+ * @param data.region Region code for tenant context
2643
+ * @param data.requestBody
2644
+ * @returns ValidateRuleResponseDto Validation result
2645
+ * @throws ApiError
2646
+ */
2647
+ public static transactionRuleControllerValidate(
2648
+ data: TransactionRuleControllerValidateData
2649
+ ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2650
+ return __request(OpenAPI, {
2651
+ method: 'POST',
2652
+ url: '/api/v1/{region}/bean/transaction-rules/validate',
2653
+ path: {
2654
+ region: data.region
2655
+ },
2656
+ body: data.requestBody,
2657
+ mediaType: 'application/json',
2658
+ errors: {
2659
+ 400: 'Validation failed',
2660
+ 401: 'Unauthorized'
2661
+ }
2662
+ });
2663
+ }
2664
+
2665
+ /**
2666
+ * Bulk create transaction rules
2667
+ * @param data The data for the request.
2668
+ * @param data.region Region code for tenant context
2669
+ * @param data.requestBody
2670
+ * @returns BulkCreateRulesResponseDto Bulk create completed
2671
+ * @throws ApiError
2672
+ */
2673
+ public static transactionRuleControllerBulkCreate(
2674
+ data: TransactionRuleControllerBulkCreateData
2675
+ ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2676
+ return __request(OpenAPI, {
2677
+ method: 'POST',
2678
+ url: '/api/v1/{region}/bean/transaction-rules/bulk',
2679
+ path: {
2680
+ region: data.region
2681
+ },
2682
+ body: data.requestBody,
2683
+ mediaType: 'application/json',
2684
+ errors: {
2685
+ 400: 'Invalid bulk create data',
2686
+ 401: 'Unauthorized'
2687
+ }
2688
+ });
2689
+ }
2690
+
2691
+ /**
2692
+ * Export transaction rules
2693
+ * @param data The data for the request.
2694
+ * @param data.format Export format (currently only JSON supported)
2695
+ * @param data.region Region code for tenant context
2696
+ * @returns ExportRulesResponseDto Exported rules
2697
+ * @throws ApiError
2698
+ */
2699
+ public static transactionRuleControllerExport(
2700
+ data: TransactionRuleControllerExportData
2701
+ ): CancelablePromise<TransactionRuleControllerExportResponse> {
2702
+ return __request(OpenAPI, {
2703
+ method: 'GET',
2704
+ url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2705
+ path: {
2706
+ format: data.format,
2707
+ region: data.region
2708
+ },
2709
+ errors: {
2710
+ 400: 'Unsupported format',
2711
+ 401: 'Unauthorized'
2712
+ }
2713
+ });
2714
+ }
2715
+
2716
+ /**
2717
+ * Get transaction rule statistics
2718
+ * @param data The data for the request.
2719
+ * @param data.period Statistics time period
2720
+ * @param data.region Region code for tenant context
2721
+ * @returns RuleStatisticsResponseDto Rule statistics
2722
+ * @throws ApiError
2723
+ */
2724
+ public static transactionRuleControllerGetStatistics(
2725
+ data: TransactionRuleControllerGetStatisticsData
2726
+ ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2727
+ return __request(OpenAPI, {
2728
+ method: 'GET',
2729
+ url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2730
+ path: {
2731
+ period: data.period,
2732
+ region: data.region
2733
+ },
2734
+ errors: {
2735
+ 401: 'Unauthorized'
2736
+ }
2737
+ });
2738
+ }
2739
+
2740
+ /**
2741
+ * Get transaction rule detail
2742
+ * @param data The data for the request.
2743
+ * @param data.ruleId Rule ID
2744
+ * @param data.region Region code for tenant context
2745
+ * @returns TransactionRuleResponseDto Rule details
2746
+ * @throws ApiError
2747
+ */
2748
+ public static transactionRuleControllerGetDetail(
2749
+ data: TransactionRuleControllerGetDetailData
2750
+ ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2751
+ return __request(OpenAPI, {
2752
+ method: 'GET',
2753
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2754
+ path: {
2755
+ ruleId: data.ruleId,
2756
+ region: data.region
2757
+ },
2758
+ errors: {
2759
+ 401: 'Unauthorized',
2760
+ 403: 'Forbidden - not owner of rule',
2761
+ 404: 'Rule not found'
2762
+ }
2763
+ });
2764
+ }
2765
+
2766
+ /**
2767
+ * Update a transaction rule
2768
+ * @param data The data for the request.
2769
+ * @param data.ruleId Rule ID to update
2770
+ * @param data.region Region code for tenant context
2771
+ * @param data.requestBody
2772
+ * @returns TransactionRuleResponseDto Rule updated successfully
2773
+ * @throws ApiError
2774
+ */
2775
+ public static transactionRuleControllerUpdate(
2776
+ data: TransactionRuleControllerUpdateData
2777
+ ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2778
+ return __request(OpenAPI, {
2779
+ method: 'PUT',
2780
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2781
+ path: {
2782
+ ruleId: data.ruleId,
2783
+ region: data.region
2784
+ },
2785
+ body: data.requestBody,
2786
+ mediaType: 'application/json',
2787
+ errors: {
2788
+ 400: 'Validation failed',
2789
+ 401: 'Unauthorized',
2790
+ 403: 'Forbidden - not owner of rule',
2791
+ 404: 'Rule not found',
2792
+ 409: 'Resource conflict - rule is being modified by another process'
2793
+ }
2794
+ });
2795
+ }
2796
+
2797
+ /**
2798
+ * Delete a transaction rule
2799
+ * @param data The data for the request.
2800
+ * @param data.ruleId Rule ID to delete
2801
+ * @param data.region Region code for tenant context
2802
+ * @returns void Rule deleted successfully
2803
+ * @throws ApiError
2804
+ */
2805
+ public static transactionRuleControllerDelete(
2806
+ data: TransactionRuleControllerDeleteData
2807
+ ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2808
+ return __request(OpenAPI, {
2809
+ method: 'DELETE',
2810
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2811
+ path: {
2812
+ ruleId: data.ruleId,
2813
+ region: data.region
2814
+ },
2815
+ errors: {
2816
+ 401: 'Unauthorized',
2817
+ 403: 'Forbidden - not owner of rule',
2818
+ 404: 'Rule not found',
2819
+ 409: 'Resource conflict - rule is being modified by another process'
2820
+ }
2821
+ });
2822
+ }
2823
+
2824
+ /**
2825
+ * Test rule matching
2826
+ * @param data The data for the request.
2827
+ * @param data.ruleId Rule ID to test
2828
+ * @param data.region Region code for tenant context
2829
+ * @param data.requestBody
2830
+ * @returns TestRuleResponseDto Test result
2831
+ * @throws ApiError
2832
+ */
2833
+ public static transactionRuleControllerTest(
2834
+ data: TransactionRuleControllerTestData
2835
+ ): CancelablePromise<TransactionRuleControllerTestResponse> {
2836
+ return __request(OpenAPI, {
2837
+ method: 'POST',
2838
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2839
+ path: {
2840
+ ruleId: data.ruleId,
2841
+ region: data.region
2842
+ },
2843
+ body: data.requestBody,
2844
+ mediaType: 'application/json',
2845
+ errors: {
2846
+ 401: 'Unauthorized',
2847
+ 403: 'Forbidden - not owner of rule',
2848
+ 404: 'Rule not found'
2849
+ }
2850
+ });
2851
+ }
2852
+ }
2853
+
2854
+ export class LifeEventsService {
2855
+ /**
2856
+ * Create a new life event
2857
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2858
+ * @param data The data for the request.
2859
+ * @param data.region Region code for tenant context (decorative for life events)
2860
+ * @param data.requestBody
2861
+ * @returns EventResponseDto Life event created successfully
2862
+ * @throws ApiError
2863
+ */
2864
+ public static eventControllerCreate(
2865
+ data: EventControllerCreateData
2866
+ ): CancelablePromise<EventControllerCreateResponse> {
2867
+ return __request(OpenAPI, {
2868
+ method: 'POST',
2869
+ url: '/api/v1/{region}/bean/events',
2870
+ path: {
2871
+ region: data.region
2872
+ },
2873
+ body: data.requestBody,
2874
+ mediaType: 'application/json',
2875
+ errors: {
2876
+ 409: 'Life event already exists for this (userId, type, date) combination'
2877
+ }
2878
+ });
2879
+ }
2880
+
2881
+ /**
2882
+ * List user life events
2883
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2884
+ * @param data The data for the request.
2885
+ * @param data.region Region code for tenant context (decorative for life events)
2886
+ * @param data.type Filter by life event type (exact match)
2887
+ * @param data.q Search term for description (case-insensitive partial match)
2888
+ * @param data.from Filter life events from this date (ISO 8601 format)
2889
+ * @param data.to Filter life events to this date (ISO 8601 format)
2890
+ * @param data.page Page number for pagination (default: 1)
2891
+ * @param data.limit Number of items per page (default: 20, max: 100)
2892
+ * @returns EventListResponseDto Life events retrieved successfully
2893
+ * @throws ApiError
2894
+ */
2895
+ public static eventControllerFindAll(
2896
+ data: EventControllerFindAllData
2897
+ ): CancelablePromise<EventControllerFindAllResponse> {
2898
+ return __request(OpenAPI, {
2899
+ method: 'GET',
2900
+ url: '/api/v1/{region}/bean/events',
2901
+ path: {
2902
+ region: data.region
2903
+ },
2904
+ query: {
2905
+ type: data.type,
2906
+ q: data.q,
2907
+ from: data.from,
2908
+ to: data.to,
2909
+ page: data.page,
2910
+ limit: data.limit
2911
+ }
2912
+ });
2913
+ }
2914
+
2915
+ /**
2916
+ * Get life event by ID
2917
+ * Returns a single life event by its ID. Returns ETag header.
2918
+ * @param data The data for the request.
2919
+ * @param data.id Life event ID
2920
+ * @param data.region Region code for tenant context (decorative for life events)
2921
+ * @returns EventResponseDto Life event retrieved successfully
2922
+ * @throws ApiError
2923
+ */
2924
+ public static eventControllerFindOne(
2925
+ data: EventControllerFindOneData
2926
+ ): CancelablePromise<EventControllerFindOneResponse> {
2927
+ return __request(OpenAPI, {
2928
+ method: 'GET',
2929
+ url: '/api/v1/{region}/bean/events/{id}',
2930
+ path: {
2931
+ id: data.id,
2932
+ region: data.region
2933
+ },
2934
+ errors: {
2935
+ 404: 'Life event not found'
2936
+ }
2937
+ });
2938
+ }
2939
+
2940
+ /**
2941
+ * Update a life event
2942
+ * Updates an existing life event. If If-Match header is provided, performs optimistic concurrency check; mismatched updatedAt returns 412.
2943
+ * @param data The data for the request.
2944
+ * @param data.id Life event ID
2945
+ * @param data.region Region code for tenant context (decorative for life events)
2946
+ * @param data.requestBody
2947
+ * @returns EventResponseDto Life event updated successfully
2948
+ * @throws ApiError
2949
+ */
2950
+ public static eventControllerUpdate(
2951
+ data: EventControllerUpdateData
2952
+ ): CancelablePromise<EventControllerUpdateResponse> {
2953
+ return __request(OpenAPI, {
2954
+ method: 'PUT',
2955
+ url: '/api/v1/{region}/bean/events/{id}',
2956
+ path: {
2957
+ id: data.id,
2958
+ region: data.region
2959
+ },
2960
+ body: data.requestBody,
2961
+ mediaType: 'application/json',
2962
+ errors: {
2963
+ 400: 'If-Match header is not a valid ISO 8601 date',
2964
+ 404: 'Life event not found',
2965
+ 409: 'Updated event conflicts with an existing (userId, type, date) combination',
2966
+ 412: 'If-Match precondition failed (updatedAt mismatch)'
2967
+ }
2968
+ });
2969
+ }
2970
+
2971
+ /**
2972
+ * Delete a life event
2973
+ * Deletes a life event entry (hard delete). Returns 204.
2974
+ * @param data The data for the request.
2975
+ * @param data.id Life event ID
2976
+ * @param data.region Region code for tenant context (decorative for life events)
2977
+ * @returns void Life event deleted successfully
2978
+ * @throws ApiError
2979
+ */
2980
+ public static eventControllerDelete(
2981
+ data: EventControllerDeleteData
2982
+ ): CancelablePromise<EventControllerDeleteResponse> {
2983
+ return __request(OpenAPI, {
2984
+ method: 'DELETE',
2985
+ url: '/api/v1/{region}/bean/events/{id}',
2986
+ path: {
2987
+ id: data.id,
2988
+ region: data.region
2989
+ },
2990
+ errors: {
2991
+ 404: 'Life event not found'
2992
+ }
2993
+ });
2994
+ }
2995
+
2996
+ /**
2997
+ * Slice time-series by a life event (Phase 79)
2998
+ * Returns aggregated time-series for postings matching accountPattern within the half-open date range of the given life event.
2999
+ * @param data The data for the request.
3000
+ * @param data.id Life event ID
3001
+ * @param data.accountPattern
3002
+ * @param data.granularity
3003
+ * @param data.region Region code for tenant context (decorative for life events)
3004
+ * @returns unknown Time-series sliced by the life event range
3005
+ * @throws ApiError
3006
+ */
3007
+ public static eventControllerGetSlice(
3008
+ data: EventControllerGetSliceData
3009
+ ): CancelablePromise<EventControllerGetSliceResponse> {
3010
+ return __request(OpenAPI, {
3011
+ method: 'GET',
3012
+ url: '/api/v1/{region}/bean/events/{id}/slice',
3013
+ path: {
3014
+ id: data.id,
3015
+ region: data.region
3016
+ },
3017
+ query: {
3018
+ accountPattern: data.accountPattern,
3019
+ granularity: data.granularity
3020
+ },
3021
+ errors: {
3022
+ 400: 'accountPattern query param is empty',
3023
+ 404: 'Life event not found'
3024
+ }
3025
+ });
3026
+ }
3027
+ }
3028
+
3029
+ export class OnboardingService {
3030
+ /**
3031
+ * Bootstrap core accounts + register asset accounts with opening balances (ADR-0113)
3032
+ * @param data The data for the request.
3033
+ * @param data.region Region code for tenant context
3034
+ * @param data.requestBody
3035
+ * @returns unknown Onboarding bootstrap result.
3036
+ * @throws ApiError
3037
+ */
3038
+ public static onboardingControllerBootstrap(
3039
+ data: OnboardingControllerBootstrapData
3040
+ ): CancelablePromise<OnboardingControllerBootstrapResponse> {
3041
+ return __request(OpenAPI, {
3042
+ method: 'POST',
3043
+ url: '/api/v1/{region}/bean/onboarding',
3044
+ path: {
3045
+ region: data.region
3046
+ },
3047
+ body: data.requestBody,
3048
+ mediaType: 'application/json',
3049
+ errors: {
3050
+ 422: 'Invalid region/account path/duplicate paths.'
3051
+ }
3052
+ });
3053
+ }
3054
+ }
3055
+
3056
+ export class BalanceReconciliationService {
3057
+ /**
3058
+ * Preview reconciliation (book vs actual)
3059
+ * Computes book balance, diff, Beancount-inferred tolerance, and suggested action without persisting.
3060
+ * @param data The data for the request.
3061
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3062
+ * @param data.requestBody
3063
+ * @returns ReconciliationComputeResultDto Reconciliation preview
3064
+ * @throws ApiError
3065
+ */
3066
+ public static reconciliationControllerCompute(
3067
+ data: ReconciliationControllerComputeData
3068
+ ): CancelablePromise<ReconciliationControllerComputeResponse> {
3069
+ return __request(OpenAPI, {
3070
+ method: 'POST',
3071
+ url: '/api/v1/{region}/bean/reconciliations',
3072
+ path: {
3073
+ region: data.region
3074
+ },
3075
+ body: data.requestBody,
3076
+ mediaType: 'application/json',
3077
+ errors: {
3078
+ 404: 'Account not found'
3079
+ }
3080
+ });
3081
+ }
3082
+
3083
+ /**
3084
+ * Record a balance assertion
3085
+ * Persists the reconciliation as a BeanBalance assertion (amount = actual, diffAmount = book − actual). Re-reconciling the same day/currency upserts.
3086
+ * @param data The data for the request.
3087
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3088
+ * @param data.requestBody
3089
+ * @returns ReconciliationRecordDto Balance assertion recorded
3090
+ * @throws ApiError
3091
+ */
3092
+ public static reconciliationControllerAssert(
3093
+ data: ReconciliationControllerAssertData
3094
+ ): CancelablePromise<ReconciliationControllerAssertResponse> {
3095
+ return __request(OpenAPI, {
3096
+ method: 'POST',
3097
+ url: '/api/v1/{region}/bean/reconciliations/assert',
3098
+ path: {
3099
+ region: data.region
3100
+ },
3101
+ body: data.requestBody,
3102
+ mediaType: 'application/json',
3103
+ errors: {
3104
+ 404: 'Account not found'
3105
+ }
3106
+ });
3107
+ }
3108
+
3109
+ /**
3110
+ * Generate a pad adjusting entry
3111
+ * When book is outside tolerance, synthesizes a Beancount pad transaction (flag P) booking the diff from source_account and persists it. Source defaults to Equity:Opening-Balances.
3112
+ * @param data The data for the request.
3113
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3114
+ * @param data.requestBody
3115
+ * @returns PadResultDto Pad adjusting entry generated
3116
+ * @throws ApiError
3117
+ */
3118
+ public static reconciliationControllerPad(
3119
+ data: ReconciliationControllerPadData
3120
+ ): CancelablePromise<ReconciliationControllerPadResponse> {
3121
+ return __request(OpenAPI, {
3122
+ method: 'POST',
3123
+ url: '/api/v1/{region}/bean/reconciliations/pad',
3124
+ path: {
3125
+ region: data.region
3126
+ },
3127
+ body: data.requestBody,
3128
+ mediaType: 'application/json',
3129
+ errors: {
3130
+ 400: 'Book already within tolerance — no pad needed',
3131
+ 404: 'Account not found'
3132
+ }
3133
+ });
3134
+ }
3135
+
3136
+ /**
3137
+ * List reconciliation history for an account
3138
+ * Returns recorded balance assertions (most recent first). The latest drives the account-detail "Last <date>" badge.
3139
+ * @param data The data for the request.
3140
+ * @param data.accountId BeanAccount id
3141
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3142
+ * @returns ReconciliationRecordDto Reconciliation history
3143
+ * @throws ApiError
3144
+ */
3145
+ public static reconciliationControllerHistory(
3146
+ data: ReconciliationControllerHistoryData
3147
+ ): CancelablePromise<ReconciliationControllerHistoryResponse> {
3148
+ return __request(OpenAPI, {
3149
+ method: 'GET',
3150
+ url: '/api/v1/{region}/bean/accounts/{accountId}/reconciliations',
3151
+ path: {
3152
+ accountId: data.accountId,
3153
+ region: data.region
3154
+ },
3155
+ errors: {
3156
+ 404: 'Account not found'
3157
+ }
3158
+ });
3159
+ }
3160
+ }
3161
+
3162
+ export class BeanExportService {
3163
+ /**
3164
+ * Export Beancount ledger as ZIP
3165
+ * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
3166
+ * @returns unknown
3167
+ * @throws ApiError
3168
+ */
3169
+ public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
3170
+ return __request(OpenAPI, {
3171
+ method: 'GET',
3172
+ url: '/api/v1/{region}/bean/export/beancount'
3173
+ });
3174
+ }
3175
+ }
3176
+
3177
+ export class BeanImportService {
2461
3178
  /**
2462
3179
  * Import a bill file
2463
3180
  * Upload and process a bill file (CSV, PDF, OFX, etc.). The system automatically identifies the file type, extracts transactions, validates them, and stores only validated transactions to the database. Maximum file size: 50MB. Only 1 import per user at a time (concurrent imports rejected with 429).
@@ -2620,216 +3337,196 @@ export class BeanImportService {
2620
3337
  }
2621
3338
  }
2622
3339
 
2623
- export class BeanPlatformsService {
2624
- /**
2625
- * Get all platforms with statistics
2626
- * @returns unknown List of platforms with binding and account counts
2627
- * @throws ApiError
2628
- */
2629
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2630
- return __request(OpenAPI, {
2631
- method: 'GET',
2632
- url: '/api/v1/bean/platforms'
2633
- });
2634
- }
2635
-
3340
+ export class ProviderSyncService {
2636
3341
  /**
2637
- * Create a new platform
3342
+ * Sync transactions from financial data provider
3343
+ *
3344
+ * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
3345
+ *
3346
+ * **Supported Providers:**
3347
+ * - **plaid**: Plaid API (US, Canada, Europe)
3348
+ * - **teller**: Teller API (US)
3349
+ * - **truelayer**: TrueLayer Open Banking (UK, Europe)
3350
+ * - **gocardless**: GoCardless Bank Account Data (Europe)
3351
+ * - **simplefin**: SimpleFIN (Self-hosted)
3352
+ * - **yodlee**: Yodlee (Global)
3353
+ * - **beancount-direct**: Beancount format transactions
3354
+ * - **parsed-bill**: Client-side parsed bill transactions
3355
+ *
3356
+ * **Processing Flow:**
3357
+ * 1. Transform raw data via provider adapter
3358
+ * 2. Validate transaction format
3359
+ * 3. Deduplicate using originalId
3360
+ * 4. Classify using rule engine
3361
+ * 5. Route low-confidence to Review Center
3362
+ * 6. Persist validated transactions
3363
+ *
2638
3364
  * @param data The data for the request.
3365
+ * @param data.providerName Provider name
3366
+ * @param data.region Region code for tenant context
2639
3367
  * @param data.requestBody
2640
- * @returns unknown Platform created successfully
3368
+ * @returns ProviderSyncResponseDto Sync completed successfully
2641
3369
  * @throws ApiError
2642
3370
  */
2643
- public static platformControllerCreate(
2644
- data: PlatformControllerCreateData
2645
- ): CancelablePromise<PlatformControllerCreateResponse> {
3371
+ public static providerSyncControllerSync(
3372
+ data: ProviderSyncControllerSyncData
3373
+ ): CancelablePromise<ProviderSyncControllerSyncResponse> {
2646
3374
  return __request(OpenAPI, {
2647
3375
  method: 'POST',
2648
- url: '/api/v1/bean/platforms',
3376
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3377
+ path: {
3378
+ providerName: data.providerName,
3379
+ region: data.region
3380
+ },
2649
3381
  body: data.requestBody,
2650
3382
  mediaType: 'application/json',
2651
3383
  errors: {
2652
- 409: 'Platform already exists'
3384
+ 400: 'Invalid request data',
3385
+ 401: 'Missing or invalid authentication',
3386
+ 404: 'Provider not supported'
2653
3387
  }
2654
3388
  });
2655
3389
  }
2656
3390
 
2657
3391
  /**
2658
- * Get platform list for current user
2659
- * @returns unknown List of platforms with user binding status
2660
- * @throws ApiError
2661
- */
2662
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
2663
- return __request(OpenAPI, {
2664
- method: 'GET',
2665
- url: '/api/v1/bean/platforms/list'
2666
- });
2667
- }
2668
-
2669
- /**
2670
- * Match platforms by name or alias
3392
+ * Get supported providers
3393
+ * Returns a list of all providers supported by the sync endpoint.
2671
3394
  * @param data The data for the request.
2672
- * @param data.q Search query — Chinese name, English name, or abbreviation
2673
- * @param data.region Region code for category override lookup
2674
- * @returns unknown List of matching platforms with suggested segment names
3395
+ * @param data.region Region code for tenant context
3396
+ * @returns SupportedProvidersResponseDto List of supported providers
2675
3397
  * @throws ApiError
2676
3398
  */
2677
- public static platformControllerMatchPlatforms(
2678
- data: PlatformControllerMatchPlatformsData
2679
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3399
+ public static providerSyncControllerGetSupportedProviders(
3400
+ data: ProviderSyncControllerGetSupportedProvidersData
3401
+ ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
2680
3402
  return __request(OpenAPI, {
2681
3403
  method: 'GET',
2682
- url: '/api/v1/bean/platforms/match',
2683
- query: {
2684
- q: data.q,
3404
+ url: '/api/v1/{region}/bean/import/provider/supported',
3405
+ path: {
2685
3406
  region: data.region
3407
+ },
3408
+ errors: {
3409
+ 401: 'Missing or invalid authentication'
2686
3410
  }
2687
3411
  });
2688
3412
  }
2689
3413
 
2690
3414
  /**
2691
- * Update a platform
3415
+ * Check if provider is supported
3416
+ * Returns whether a specific provider is supported.
2692
3417
  * @param data The data for the request.
2693
- * @param data.id Platform ID
2694
- * @param data.requestBody
2695
- * @returns unknown Platform updated successfully
3418
+ * @param data.providerName Provider name to check
3419
+ * @param data.region Region code for tenant context
3420
+ * @returns unknown Provider support status
2696
3421
  * @throws ApiError
2697
3422
  */
2698
- public static platformControllerUpdate(
2699
- data: PlatformControllerUpdateData
2700
- ): CancelablePromise<PlatformControllerUpdateResponse> {
3423
+ public static providerSyncControllerIsProviderSupported(
3424
+ data: ProviderSyncControllerIsProviderSupportedData
3425
+ ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
2701
3426
  return __request(OpenAPI, {
2702
- method: 'PUT',
2703
- url: '/api/v1/bean/platforms/{id}',
3427
+ method: 'GET',
3428
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
2704
3429
  path: {
2705
- id: data.id
3430
+ providerName: data.providerName,
3431
+ region: data.region
2706
3432
  },
2707
- body: data.requestBody,
2708
- mediaType: 'application/json',
2709
3433
  errors: {
2710
- 404: 'Platform not found'
3434
+ 401: 'Missing or invalid authentication'
2711
3435
  }
2712
3436
  });
2713
3437
  }
3438
+ }
2714
3439
 
3440
+ export class ExternalAccountLinksService {
2715
3441
  /**
2716
- * Delete a platform
3442
+ * Create an external account → BeanAccount mapping (ADR-0113)
2717
3443
  * @param data The data for the request.
2718
- * @param data.id Platform ID
2719
- * @returns void Platform deleted successfully
3444
+ * @param data.region Region code for tenant context
3445
+ * @param data.requestBody
3446
+ * @returns ExternalAccountLinkResponseDto Link created.
2720
3447
  * @throws ApiError
2721
3448
  */
2722
- public static platformControllerDelete(
2723
- data: PlatformControllerDeleteData
2724
- ): CancelablePromise<PlatformControllerDeleteResponse> {
3449
+ public static externalAccountLinkControllerCreate(
3450
+ data: ExternalAccountLinkControllerCreateData
3451
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
2725
3452
  return __request(OpenAPI, {
2726
- method: 'DELETE',
2727
- url: '/api/v1/bean/platforms/{id}',
3453
+ method: 'POST',
3454
+ url: '/api/v1/{region}/bean/external-account-links',
2728
3455
  path: {
2729
- id: data.id
3456
+ region: data.region
2730
3457
  },
3458
+ body: data.requestBody,
3459
+ mediaType: 'application/json',
2731
3460
  errors: {
2732
- 404: 'Platform not found'
3461
+ 422: 'beanAccountId not owned, or an active link already exists.'
2733
3462
  }
2734
3463
  });
2735
3464
  }
2736
- }
2737
3465
 
2738
- export class ProviderSyncService {
2739
3466
  /**
2740
- * Sync transactions from financial data provider
2741
- *
2742
- * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
2743
- *
2744
- * **Supported Providers:**
2745
- * - **plaid**: Plaid API (US, Canada, Europe)
2746
- * - **teller**: Teller API (US)
2747
- * - **truelayer**: TrueLayer Open Banking (UK, Europe)
2748
- * - **gocardless**: GoCardless Bank Account Data (Europe)
2749
- * - **simplefin**: SimpleFIN (Self-hosted)
2750
- * - **yodlee**: Yodlee (Global)
2751
- * - **beancount-direct**: Beancount format transactions
2752
- * - **parsed-bill**: Client-side parsed bill transactions
2753
- *
2754
- * **Processing Flow:**
2755
- * 1. Transform raw data via provider adapter
2756
- * 2. Validate transaction format
2757
- * 3. Deduplicate using originalId
2758
- * 4. Classify using rule engine
2759
- * 5. Route low-confidence to Review Center
2760
- * 6. Persist validated transactions
2761
- *
3467
+ * List the user's active external account links
2762
3468
  * @param data The data for the request.
2763
- * @param data.providerName Provider name
2764
- * @param data.region Region code
2765
- * @param data.requestBody
2766
- * @returns ProviderSyncResponseDto Sync completed successfully
3469
+ * @param data.provider
3470
+ * @param data.region Region code for tenant context
3471
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
2767
3472
  * @throws ApiError
2768
3473
  */
2769
- public static providerSyncControllerSync(
2770
- data: ProviderSyncControllerSyncData
2771
- ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3474
+ public static externalAccountLinkControllerFindAll(
3475
+ data: ExternalAccountLinkControllerFindAllData
3476
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
2772
3477
  return __request(OpenAPI, {
2773
- method: 'POST',
2774
- url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3478
+ method: 'GET',
3479
+ url: '/api/v1/{region}/bean/external-account-links',
2775
3480
  path: {
2776
- providerName: data.providerName,
2777
3481
  region: data.region
2778
3482
  },
2779
- body: data.requestBody,
2780
- mediaType: 'application/json',
2781
- errors: {
2782
- 400: 'Invalid request data',
2783
- 401: 'Missing or invalid authentication',
2784
- 404: 'Provider not supported'
3483
+ query: {
3484
+ provider: data.provider
2785
3485
  }
2786
3486
  });
2787
3487
  }
2788
3488
 
2789
3489
  /**
2790
- * Get supported providers
2791
- * Returns a list of all providers supported by the sync endpoint.
3490
+ * Get a single external account link
2792
3491
  * @param data The data for the request.
3492
+ * @param data.id
2793
3493
  * @param data.region Region code for tenant context
2794
- * @returns SupportedProvidersResponseDto List of supported providers
3494
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
2795
3495
  * @throws ApiError
2796
3496
  */
2797
- public static providerSyncControllerGetSupportedProviders(
2798
- data: ProviderSyncControllerGetSupportedProvidersData
2799
- ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3497
+ public static externalAccountLinkControllerFindOne(
3498
+ data: ExternalAccountLinkControllerFindOneData
3499
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
2800
3500
  return __request(OpenAPI, {
2801
3501
  method: 'GET',
2802
- url: '/api/v1/{region}/bean/import/provider/supported',
3502
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
2803
3503
  path: {
3504
+ id: data.id,
2804
3505
  region: data.region
2805
3506
  },
2806
3507
  errors: {
2807
- 401: 'Missing or invalid authentication'
3508
+ 422: 'Link not found or not owned by the user.'
2808
3509
  }
2809
3510
  });
2810
3511
  }
2811
3512
 
2812
3513
  /**
2813
- * Check if provider is supported
2814
- * Returns whether a specific provider is supported.
3514
+ * Soft-delete (disconnect) an external account link
2815
3515
  * @param data The data for the request.
2816
- * @param data.providerName Provider name to check
3516
+ * @param data.id
2817
3517
  * @param data.region Region code for tenant context
2818
- * @returns unknown Provider support status
3518
+ * @returns void Link soft-deleted; historical transactions are unaffected.
2819
3519
  * @throws ApiError
2820
3520
  */
2821
- public static providerSyncControllerIsProviderSupported(
2822
- data: ProviderSyncControllerIsProviderSupportedData
2823
- ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3521
+ public static externalAccountLinkControllerRemove(
3522
+ data: ExternalAccountLinkControllerRemoveData
3523
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
2824
3524
  return __request(OpenAPI, {
2825
- method: 'GET',
2826
- url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
3525
+ method: 'DELETE',
3526
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
2827
3527
  path: {
2828
- providerName: data.providerName,
3528
+ id: data.id,
2829
3529
  region: data.region
2830
- },
2831
- errors: {
2832
- 401: 'Missing or invalid authentication'
2833
3530
  }
2834
3531
  });
2835
3532
  }
@@ -2860,6 +3557,54 @@ export class ImportTelemetryService {
2860
3557
  }
2861
3558
  });
2862
3559
  }
3560
+
3561
+ /**
3562
+ * Receive anonymous zero-hit coverage miss report
3563
+ * @param data The data for the request.
3564
+ * @param data.region Region code for tenant context
3565
+ * @param data.requestBody
3566
+ * @returns unknown Coverage miss report received
3567
+ * @throws ApiError
3568
+ */
3569
+ public static telemetryControllerReportCoverageMiss(
3570
+ data: TelemetryControllerReportCoverageMissData
3571
+ ): CancelablePromise<TelemetryControllerReportCoverageMissResponse> {
3572
+ return __request(OpenAPI, {
3573
+ method: 'POST',
3574
+ url: '/api/v1/{region}/bean/import/parser-coverage-miss',
3575
+ path: {
3576
+ region: data.region
3577
+ },
3578
+ body: data.requestBody,
3579
+ mediaType: 'application/json',
3580
+ errors: {
3581
+ 401: 'Unauthorized'
3582
+ }
3583
+ });
3584
+ }
3585
+
3586
+ /**
3587
+ * Coverage metrics (uncovered format aggregation)
3588
+ * @param data The data for the request.
3589
+ * @param data.region Region code for tenant context
3590
+ * @param data.topN Top-N uncovered formats (default 10)
3591
+ * @returns unknown Coverage metrics
3592
+ * @throws ApiError
3593
+ */
3594
+ public static telemetryControllerGetCoverageMetrics(
3595
+ data: TelemetryControllerGetCoverageMetricsData
3596
+ ): CancelablePromise<TelemetryControllerGetCoverageMetricsResponse> {
3597
+ return __request(OpenAPI, {
3598
+ method: 'GET',
3599
+ url: '/api/v1/{region}/bean/import/parser-coverage-metrics',
3600
+ path: {
3601
+ region: data.region
3602
+ },
3603
+ query: {
3604
+ topN: data.topN
3605
+ }
3606
+ });
3607
+ }
2863
3608
  }
2864
3609
 
2865
3610
  export class BeanNlpService {
@@ -2945,6 +3690,121 @@ export class BeanNlpService {
2945
3690
  }
2946
3691
  }
2947
3692
 
3693
+ export class BeanPlatformsService {
3694
+ /**
3695
+ * Get all platforms with statistics
3696
+ * @returns unknown List of platforms with binding and account counts
3697
+ * @throws ApiError
3698
+ */
3699
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
3700
+ return __request(OpenAPI, {
3701
+ method: 'GET',
3702
+ url: '/api/v1/bean/platforms'
3703
+ });
3704
+ }
3705
+
3706
+ /**
3707
+ * Create a new platform
3708
+ * @param data The data for the request.
3709
+ * @param data.requestBody
3710
+ * @returns unknown Platform created successfully
3711
+ * @throws ApiError
3712
+ */
3713
+ public static platformControllerCreate(
3714
+ data: PlatformControllerCreateData
3715
+ ): CancelablePromise<PlatformControllerCreateResponse> {
3716
+ return __request(OpenAPI, {
3717
+ method: 'POST',
3718
+ url: '/api/v1/bean/platforms',
3719
+ body: data.requestBody,
3720
+ mediaType: 'application/json',
3721
+ errors: {
3722
+ 409: 'Platform already exists'
3723
+ }
3724
+ });
3725
+ }
3726
+
3727
+ /**
3728
+ * Get platform list for current user
3729
+ * @returns PlatformListItemDto List of platforms with user binding status
3730
+ * @throws ApiError
3731
+ */
3732
+ public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3733
+ return __request(OpenAPI, {
3734
+ method: 'GET',
3735
+ url: '/api/v1/bean/platforms/list'
3736
+ });
3737
+ }
3738
+
3739
+ /**
3740
+ * Match platforms by name or alias
3741
+ * @param data The data for the request.
3742
+ * @param data.q Search query — Chinese name, English name, or abbreviation
3743
+ * @param data.region Region code for category override lookup
3744
+ * @returns PlatformMatchResponseDto Matching platforms with overall match type and truncation flag
3745
+ * @throws ApiError
3746
+ */
3747
+ public static platformControllerMatchPlatforms(
3748
+ data: PlatformControllerMatchPlatformsData
3749
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3750
+ return __request(OpenAPI, {
3751
+ method: 'GET',
3752
+ url: '/api/v1/bean/platforms/match',
3753
+ query: {
3754
+ q: data.q,
3755
+ region: data.region
3756
+ }
3757
+ });
3758
+ }
3759
+
3760
+ /**
3761
+ * Update a platform
3762
+ * @param data The data for the request.
3763
+ * @param data.id Platform ID
3764
+ * @param data.requestBody
3765
+ * @returns unknown Platform updated successfully
3766
+ * @throws ApiError
3767
+ */
3768
+ public static platformControllerUpdate(
3769
+ data: PlatformControllerUpdateData
3770
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
3771
+ return __request(OpenAPI, {
3772
+ method: 'PUT',
3773
+ url: '/api/v1/bean/platforms/{id}',
3774
+ path: {
3775
+ id: data.id
3776
+ },
3777
+ body: data.requestBody,
3778
+ mediaType: 'application/json',
3779
+ errors: {
3780
+ 404: 'Platform not found'
3781
+ }
3782
+ });
3783
+ }
3784
+
3785
+ /**
3786
+ * Delete a platform
3787
+ * @param data The data for the request.
3788
+ * @param data.id Platform ID
3789
+ * @returns void Platform deleted successfully
3790
+ * @throws ApiError
3791
+ */
3792
+ public static platformControllerDelete(
3793
+ data: PlatformControllerDeleteData
3794
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
3795
+ return __request(OpenAPI, {
3796
+ method: 'DELETE',
3797
+ url: '/api/v1/bean/platforms/{id}',
3798
+ path: {
3799
+ id: data.id
3800
+ },
3801
+ errors: {
3802
+ 404: 'Platform not found'
3803
+ }
3804
+ });
3805
+ }
3806
+ }
3807
+
2948
3808
  export class DashboardService {
2949
3809
  /**
2950
3810
  * Get net worth overview
@@ -2980,6 +3840,7 @@ export class DashboardService {
2980
3840
  * @param data.region Region code for tenant context
2981
3841
  * @param data.groupBy Grouping strategy
2982
3842
  * @param data.date Date for balance calculation (ISO 8601 format)
3843
+ * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
2983
3844
  * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
2984
3845
  * @throws ApiError
2985
3846
  */
@@ -2994,7 +3855,8 @@ export class DashboardService {
2994
3855
  },
2995
3856
  query: {
2996
3857
  groupBy: data.groupBy,
2997
- date: data.date
3858
+ date: data.date,
3859
+ accountId: data.accountId
2998
3860
  },
2999
3861
  errors: {
3000
3862
  401: 'User not authenticated'
@@ -3029,124 +3891,69 @@ export class DashboardService {
3029
3891
  }
3030
3892
  });
3031
3893
  }
3032
- }
3033
3894
 
3034
- export class ReportingService {
3035
3895
  /**
3036
- * Get portfolio value trends
3037
- *
3038
- * Returns time series data of portfolio net worth.
3039
- *
3040
- * **Multi-currency Support:**
3041
- * - `series[].byCurrency` - Currency breakdown for each data point
3042
- * - `byCurrency` - Separate time series grouped by currency
3043
- * - `warnings` - Exchange rate warnings if conversion failed
3044
- *
3045
- * **Parameters:**
3046
- * - `period`: Time period (1m, 3m, 6m, 1y)
3047
- * - `granularity`: Data granularity (day, week, month)
3048
- *
3896
+ * Get expenses/income grouped by functional category
3897
+ * Returns amounts pre-aggregated by functional category (account-path Group segment) with server-side multi-currency conversion. flow=expense (default) aggregates ^Expenses: accounts; flow=income aggregates ^Income: accounts (issue #518)
3049
3898
  * @param data The data for the request.
3050
3899
  * @param data.region Region code for tenant context
3051
- * @param data.period Time period
3052
- * @param data.granularity Data granularity
3053
- * @returns PortfolioTrendsResponseDto Trends retrieved successfully
3900
+ * @param data.groupBy Grouping strategy
3901
+ * @param data.period Time window (1m = current calendar month)
3902
+ * @param data.flow Account root to aggregate (expense → ^Expenses:, income → ^Income:)
3903
+ * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3054
3904
  * @throws ApiError
3055
3905
  */
3056
- public static reportingControllerGetPortfolioTrends(
3057
- data: ReportingControllerGetPortfolioTrendsData
3058
- ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
3906
+ public static dashboardControllerGetExpenses(
3907
+ data: DashboardControllerGetExpensesData
3908
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3059
3909
  return __request(OpenAPI, {
3060
3910
  method: 'GET',
3061
- url: '/api/v1/{region}/reporting/portfolio/trends',
3911
+ url: '/api/v1/{region}/dashboard/expenses',
3062
3912
  path: {
3063
3913
  region: data.region
3064
3914
  },
3065
3915
  query: {
3916
+ groupBy: data.groupBy,
3066
3917
  period: data.period,
3067
- granularity: data.granularity
3918
+ flow: data.flow
3068
3919
  },
3069
3920
  errors: {
3921
+ 400: 'Invalid groupBy or period',
3070
3922
  401: 'User not authenticated'
3071
3923
  }
3072
3924
  });
3073
3925
  }
3926
+ }
3074
3927
 
3928
+ export class InvestmentService {
3075
3929
  /**
3076
- * Generate portfolio snapshot
3077
- *
3078
- * Manually generate a portfolio snapshot for a specific date.
3079
- *
3080
- * **Multi-currency Support:**
3081
- * - Fetches balances grouped by currency
3082
- * - Uses user's baseCurrency setting for conversion
3083
- * - Stores exchange rates and warnings
3084
- *
3085
- * **Use Cases:**
3086
- * - Testing snapshot generation
3087
- * - Force regeneration after data correction
3088
- * - Initial setup for new users
3089
- *
3930
+ * Get per-holding unrealized + realized P&L
3931
+ * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3090
3932
  * @param data The data for the request.
3091
3933
  * @param data.region Region code for tenant context
3092
- * @param data.requestBody Optional date (defaults to today)
3093
- * @returns GenerateSnapshotResponse Snapshot generated successfully
3934
+ * @param data.asOf As-of date (ISO 8601), defaults to today
3935
+ * @param data.accountId Scope to a single account
3936
+ * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
3937
+ * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3094
3938
  * @throws ApiError
3095
3939
  */
3096
- public static reportingControllerGenerateSnapshot(
3097
- data: ReportingControllerGenerateSnapshotData
3098
- ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
3940
+ public static holdingPnlControllerGetHoldingPnl(
3941
+ data: HoldingPnlControllerGetHoldingPnlData
3942
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3099
3943
  return __request(OpenAPI, {
3100
- method: 'POST',
3101
- url: '/api/v1/{region}/reporting/snapshots/generate',
3944
+ method: 'GET',
3945
+ url: '/api/v1/{region}/investment/holdings/pnl',
3102
3946
  path: {
3103
3947
  region: data.region
3104
3948
  },
3105
- body: data.requestBody,
3106
- mediaType: 'application/json',
3107
- errors: {
3108
- 400: 'Invalid date format',
3109
- 401: 'User not authenticated'
3110
- }
3111
- });
3112
- }
3113
-
3114
- /**
3115
- * Backfill portfolio snapshots
3116
- *
3117
- * Generate snapshots for a date range (historical data backfill).
3118
- *
3119
- * **Multi-currency Support:**
3120
- * - Each snapshot includes multi-currency data
3121
- * - Uses exchange rates available at generation time
3122
- * - Warnings stored for missing exchange rates
3123
- *
3124
- * **Best Practices:**
3125
- * - Use for initial setup after account configuration
3126
- * - Run during low-traffic periods for large date ranges
3127
- * - Existing snapshots are skipped (not regenerated)
3128
- *
3129
- * @param data The data for the request.
3130
- * @param data.region Region code for tenant context
3131
- * @param data.requestBody
3132
- * @returns BackfillSnapshotsResponse Backfill completed successfully
3133
- * @throws ApiError
3134
- */
3135
- public static reportingControllerBackfillSnapshots(
3136
- data: ReportingControllerBackfillSnapshotsData
3137
- ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
3138
- return __request(OpenAPI, {
3139
- method: 'POST',
3140
- url: '/api/v1/{region}/reporting/snapshots/backfill',
3141
- path: {
3142
- region: data.region
3949
+ query: {
3950
+ asOf: data.asOf,
3951
+ accountId: data.accountId,
3952
+ method: data.method
3143
3953
  },
3144
- body: data.requestBody,
3145
- mediaType: 'application/json',
3146
3954
  errors: {
3147
- 400: 'Invalid date format or range',
3148
- 401: 'User not authenticated',
3149
- 409: 'Backfill already in progress for this user'
3955
+ 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3956
+ 401: 'User not authenticated'
3150
3957
  }
3151
3958
  });
3152
3959
  }
@@ -3175,7 +3982,7 @@ export class AuthService {
3175
3982
  * Anonymous login with access token
3176
3983
  * @param data The data for the request.
3177
3984
  * @param data.requestBody
3178
- * @returns unknown Login successful
3985
+ * @returns AnonymousLoginResponseDto Login successful
3179
3986
  * @throws ApiError
3180
3987
  */
3181
3988
  public static authControllerAccessTokenLogin(