@firela/api-types 0.0.0-canary.19fa1e7e → 0.0.0-canary.1f73c8b3

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,26 @@ 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,
174
196
  EventControllerCreateData,
175
197
  EventControllerCreateResponse,
176
198
  EventControllerFindAllData,
@@ -183,6 +205,16 @@ import type {
183
205
  EventControllerDeleteResponse,
184
206
  EventControllerGetSliceData,
185
207
  EventControllerGetSliceResponse,
208
+ OnboardingControllerBootstrapData,
209
+ OnboardingControllerBootstrapResponse,
210
+ ReconciliationControllerComputeData,
211
+ ReconciliationControllerComputeResponse,
212
+ ReconciliationControllerAssertData,
213
+ ReconciliationControllerAssertResponse,
214
+ ReconciliationControllerPadData,
215
+ ReconciliationControllerPadResponse,
216
+ ReconciliationControllerHistoryData,
217
+ ReconciliationControllerHistoryResponse,
186
218
  ExportControllerExportBeancountResponse,
187
219
  FileImportControllerImportFileData,
188
220
  FileImportControllerImportFileResponse,
@@ -196,22 +228,20 @@ import type {
196
228
  ImporterConfigControllerUpdateConfigResponse,
197
229
  ImporterConfigControllerResetConfigData,
198
230
  ImporterConfigControllerResetConfigResponse,
199
- PlatformControllerFindAllResponse,
200
- PlatformControllerCreateData,
201
- PlatformControllerCreateResponse,
202
- PlatformControllerGetPlatformListResponse,
203
- PlatformControllerMatchPlatformsData,
204
- PlatformControllerMatchPlatformsResponse,
205
- PlatformControllerUpdateData,
206
- PlatformControllerUpdateResponse,
207
- PlatformControllerDeleteData,
208
- PlatformControllerDeleteResponse,
209
231
  ProviderSyncControllerSyncData,
210
232
  ProviderSyncControllerSyncResponse,
211
233
  ProviderSyncControllerGetSupportedProvidersData,
212
234
  ProviderSyncControllerGetSupportedProvidersResponse,
213
235
  ProviderSyncControllerIsProviderSupportedData,
214
236
  ProviderSyncControllerIsProviderSupportedResponse,
237
+ ExternalAccountLinkControllerCreateData,
238
+ ExternalAccountLinkControllerCreateResponse,
239
+ ExternalAccountLinkControllerFindAllData,
240
+ ExternalAccountLinkControllerFindAllResponse,
241
+ ExternalAccountLinkControllerFindOneData,
242
+ ExternalAccountLinkControllerFindOneResponse,
243
+ ExternalAccountLinkControllerRemoveData,
244
+ ExternalAccountLinkControllerRemoveResponse,
215
245
  TelemetryControllerReportTelemetryData,
216
246
  TelemetryControllerReportTelemetryResponse,
217
247
  TelemetryControllerReportCoverageMissData,
@@ -224,6 +254,16 @@ import type {
224
254
  NlpControllerClearSessionResponse,
225
255
  NlpControllerGetSessionData,
226
256
  NlpControllerGetSessionResponse,
257
+ PlatformControllerFindAllResponse,
258
+ PlatformControllerCreateData,
259
+ PlatformControllerCreateResponse,
260
+ PlatformControllerGetPlatformListResponse,
261
+ PlatformControllerMatchPlatformsData,
262
+ PlatformControllerMatchPlatformsResponse,
263
+ PlatformControllerUpdateData,
264
+ PlatformControllerUpdateResponse,
265
+ PlatformControllerDeleteData,
266
+ PlatformControllerDeleteResponse,
227
267
  DashboardControllerGetNetWorthData,
228
268
  DashboardControllerGetNetWorthResponse,
229
269
  DashboardControllerGetAccountsData,
@@ -234,26 +274,6 @@ import type {
234
274
  DashboardControllerGetExpensesResponse,
235
275
  HoldingPnlControllerGetHoldingPnlData,
236
276
  HoldingPnlControllerGetHoldingPnlResponse,
237
- PriceControllerCreateData,
238
- PriceControllerCreateResponse,
239
- PriceControllerFindAllData,
240
- PriceControllerFindAllResponse,
241
- PriceControllerFindOneData,
242
- PriceControllerFindOneResponse,
243
- PriceControllerUpdateData,
244
- PriceControllerUpdateResponse,
245
- PriceControllerDeleteData,
246
- PriceControllerDeleteResponse,
247
- PriceControllerBulkCreateData,
248
- PriceControllerBulkCreateResponse,
249
- ReportingControllerGetPortfolioTrendsData,
250
- ReportingControllerGetPortfolioTrendsResponse,
251
- ReportingControllerGetCashFlowTrendsData,
252
- ReportingControllerGetCashFlowTrendsResponse,
253
- ReportingControllerGenerateSnapshotData,
254
- ReportingControllerGenerateSnapshotResponse,
255
- ReportingControllerBackfillSnapshotsData,
256
- ReportingControllerBackfillSnapshotsResponse,
257
277
  ApiKeysControllerCreateApiKeyResponse,
258
278
  AuthControllerAccessTokenLoginData,
259
279
  AuthControllerAccessTokenLoginResponse,
@@ -268,7 +288,11 @@ import type {
268
288
  HealthControllerResetCircuitBreakerData,
269
289
  HealthControllerResetCircuitBreakerResponse,
270
290
  HealthControllerGetMetricsResponse,
271
- InfoControllerGetInfoResponse
291
+ InfoControllerGetInfoResponse,
292
+ SymbolControllerSearchData,
293
+ SymbolControllerSearchResponse,
294
+ SymbolControllerGetQuoteData,
295
+ SymbolControllerGetQuoteResponse
272
296
  } from './types.gen';
273
297
 
274
298
  export class BeanAccountsService {
@@ -306,7 +330,7 @@ export class BeanAccountsService {
306
330
  * @param data.type Filter by account type
307
331
  * @param data.status Filter by status
308
332
  * @param data.isCustom Filter by custom (user-created) accounts only
309
- * @param data.search Search term for path or i18nKey
333
+ * @param data.search Search term for account path
310
334
  * @param data.limit Maximum number of results
311
335
  * @param data.offset Number of results to skip
312
336
  * @returns AccountListResponseDto Accounts retrieved successfully
@@ -387,7 +411,7 @@ export class BeanAccountsService {
387
411
 
388
412
  /**
389
413
  * Delete account
390
- * Deletes an account (only if no transactions)
414
+ * Deletes an account (only if no active transactions; voided/superseded residual postings are cleaned up)
391
415
  * @param data The data for the request.
392
416
  * @param data.id Account UUID
393
417
  * @param data.region Region code for tenant context
@@ -406,7 +430,7 @@ export class BeanAccountsService {
406
430
  },
407
431
  errors: {
408
432
  404: 'Account not found',
409
- 409: 'Account has transactions and cannot be deleted'
433
+ 409: 'Account has active transactions and cannot be deleted'
410
434
  }
411
435
  });
412
436
  }
@@ -468,6 +492,35 @@ export class BeanAccountsService {
468
492
  }
469
493
  });
470
494
  }
495
+
496
+ /**
497
+ * Post an opening-balance transaction
498
+ * 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.
499
+ * @param data The data for the request.
500
+ * @param data.id Account UUID
501
+ * @param data.region Region code for tenant context
502
+ * @param data.requestBody
503
+ * @returns OpeningBalanceResultDto Opening-balance transaction created
504
+ * @throws ApiError
505
+ */
506
+ public static accountControllerAddOpeningBalance(
507
+ data: AccountControllerAddOpeningBalanceData
508
+ ): CancelablePromise<AccountControllerAddOpeningBalanceResponse> {
509
+ return __request(OpenAPI, {
510
+ method: 'POST',
511
+ url: '/api/v1/{region}/bean/accounts/{id}/opening-balance',
512
+ path: {
513
+ id: data.id,
514
+ region: data.region
515
+ },
516
+ body: data.requestBody,
517
+ mediaType: 'application/json',
518
+ errors: {
519
+ 404: 'Account not found',
520
+ 409: 'An opening balance already exists for this account'
521
+ }
522
+ });
523
+ }
471
524
  }
472
525
 
473
526
  export class BeanAccountStandardsService {
@@ -499,7 +552,7 @@ export class BeanAccountStandardsService {
499
552
 
500
553
  /**
501
554
  * Get template metadata for an account path
502
- * Returns extendable status and root type for a template path.
555
+ * Returns root type for a template path.
503
556
  * @param data The data for the request.
504
557
  * @param data.region Region code for tenant context
505
558
  * @param data.path Account path to check
@@ -794,7 +847,7 @@ export class BeanBalancesService {
794
847
  * Query account balance
795
848
  * Calculate account balance at a specific date for a single currency
796
849
  * @param data The data for the request.
797
- * @param data.account Account name (e.g., "Assets:Bank:Checking")
850
+ * @param data.account Account name (e.g., "Assets:Checking")
798
851
  * @param data.region Region code for tenant context
799
852
  * @param data.date Date to calculate balance at (ISO 8601 format)
800
853
  * @param data.currency Currency to query (e.g., "USD", "CNY")
@@ -1515,153 +1568,320 @@ export class BeanCommoditiesService {
1515
1568
  }
1516
1569
  }
1517
1570
 
1518
- export class RecurringRulesService {
1571
+ export class BeanPricesService {
1519
1572
  /**
1520
- * Create a new recurring rule
1521
- * Creates a new recurring transaction rule for the authenticated user
1573
+ * Create a new price
1574
+ * Creates a new price entry for the authenticated user
1522
1575
  * @param data The data for the request.
1523
1576
  * @param data.region Region code for tenant context
1524
1577
  * @param data.requestBody
1525
- * @returns RecurringRuleResponseDto Rule created successfully
1578
+ * @returns PriceResponseDto Price created successfully
1526
1579
  * @throws ApiError
1527
1580
  */
1528
- public static recurringRuleControllerCreate(
1529
- data: RecurringRuleControllerCreateData
1530
- ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1581
+ public static priceControllerCreate(
1582
+ data: PriceControllerCreateData
1583
+ ): CancelablePromise<PriceControllerCreateResponse> {
1531
1584
  return __request(OpenAPI, {
1532
1585
  method: 'POST',
1533
- url: '/api/v1/{region}/bean/recurring-rules',
1586
+ url: '/api/v1/{region}/bean/prices',
1534
1587
  path: {
1535
1588
  region: data.region
1536
1589
  },
1537
1590
  body: data.requestBody,
1538
1591
  mediaType: 'application/json',
1539
1592
  errors: {
1540
- 400: 'Invalid input data (e.g., autoCreate without accounts)',
1541
- 409: 'Rule with same name already exists'
1593
+ 404: 'Currency or quoteCurrency commodity not found',
1594
+ 409: 'Price already exists for this currency pair and date'
1542
1595
  }
1543
1596
  });
1544
1597
  }
1545
1598
 
1546
1599
  /**
1547
- * List recurring rules
1548
- * Returns all recurring rules for the authenticated user with optional filtering
1600
+ * List user prices
1601
+ * Returns all price entries for the authenticated user with optional filtering
1549
1602
  * @param data The data for the request.
1550
1603
  * @param data.region Region code for tenant context
1551
- * @param data.isActive Filter by active status
1552
- * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
1553
- * @param data.hasAutoCreate Filter by autoCreate enabled
1554
- * @returns RecurringRuleResponseDto Rules retrieved successfully
1604
+ * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
1605
+ * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
1606
+ * @param data.dateFrom Filter prices from this date (ISO 8601 format)
1607
+ * @param data.dateTo Filter prices to this date (ISO 8601 format)
1608
+ * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
1609
+ * @param data.page Page number for pagination (default: 1)
1610
+ * @param data.limit Number of items per page (default: 20, max: 100)
1611
+ * @returns PriceListResponseDto Prices retrieved successfully
1555
1612
  * @throws ApiError
1556
1613
  */
1557
- public static recurringRuleControllerFindAll(
1558
- data: RecurringRuleControllerFindAllData
1559
- ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1614
+ public static priceControllerFindAll(
1615
+ data: PriceControllerFindAllData
1616
+ ): CancelablePromise<PriceControllerFindAllResponse> {
1560
1617
  return __request(OpenAPI, {
1561
1618
  method: 'GET',
1562
- url: '/api/v1/{region}/bean/recurring-rules',
1619
+ url: '/api/v1/{region}/bean/prices',
1563
1620
  path: {
1564
1621
  region: data.region
1565
1622
  },
1566
1623
  query: {
1567
- isActive: data.isActive,
1568
- frequency: data.frequency,
1569
- hasAutoCreate: data.hasAutoCreate
1624
+ currency: data.currency,
1625
+ quoteCurrency: data.quoteCurrency,
1626
+ dateFrom: data.dateFrom,
1627
+ dateTo: data.dateTo,
1628
+ search: data.search,
1629
+ page: data.page,
1630
+ limit: data.limit
1570
1631
  }
1571
1632
  });
1572
1633
  }
1573
1634
 
1574
1635
  /**
1575
- * Create recurring rule from transaction
1576
- * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1636
+ * Get price by ID
1637
+ * Returns a single price entry by its ID
1577
1638
  * @param data The data for the request.
1578
- * @param data.transactionId Source transaction ID
1639
+ * @param data.id Price ID
1579
1640
  * @param data.region Region code for tenant context
1580
- * @param data.requestBody
1581
- * @returns RecurringRuleResponseDto Rule created successfully
1641
+ * @returns PriceResponseDto Price retrieved successfully
1582
1642
  * @throws ApiError
1583
1643
  */
1584
- public static recurringRuleControllerCreateFromTransaction(
1585
- data: RecurringRuleControllerCreateFromTransactionData
1586
- ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1644
+ public static priceControllerFindOne(
1645
+ data: PriceControllerFindOneData
1646
+ ): CancelablePromise<PriceControllerFindOneResponse> {
1587
1647
  return __request(OpenAPI, {
1588
- method: 'POST',
1589
- url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1648
+ method: 'GET',
1649
+ url: '/api/v1/{region}/bean/prices/{id}',
1590
1650
  path: {
1591
- transactionId: data.transactionId,
1651
+ id: data.id,
1592
1652
  region: data.region
1593
1653
  },
1594
- body: data.requestBody,
1595
- mediaType: 'application/json',
1596
1654
  errors: {
1597
- 404: 'Transaction not found',
1598
- 409: 'Rule with same name already exists or transaction already linked'
1655
+ 404: 'Price not found'
1599
1656
  }
1600
1657
  });
1601
1658
  }
1602
1659
 
1603
1660
  /**
1604
- * Get recurring rule by ID
1605
- * Returns a specific recurring rule with its details
1661
+ * Update a price
1662
+ * Updates an existing price entry
1606
1663
  * @param data The data for the request.
1607
- * @param data.id Rule ID
1664
+ * @param data.id Price ID
1608
1665
  * @param data.region Region code for tenant context
1609
- * @returns RecurringRuleResponseDto Rule retrieved successfully
1666
+ * @param data.requestBody
1667
+ * @returns PriceResponseDto Price updated successfully
1610
1668
  * @throws ApiError
1611
1669
  */
1612
- public static recurringRuleControllerFindOne(
1613
- data: RecurringRuleControllerFindOneData
1614
- ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1670
+ public static priceControllerUpdate(
1671
+ data: PriceControllerUpdateData
1672
+ ): CancelablePromise<PriceControllerUpdateResponse> {
1615
1673
  return __request(OpenAPI, {
1616
- method: 'GET',
1617
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1674
+ method: 'PUT',
1675
+ url: '/api/v1/{region}/bean/prices/{id}',
1618
1676
  path: {
1619
1677
  id: data.id,
1620
1678
  region: data.region
1621
1679
  },
1680
+ body: data.requestBody,
1681
+ mediaType: 'application/json',
1622
1682
  errors: {
1623
- 404: 'Rule not found'
1683
+ 404: 'Price not found',
1684
+ 409: 'Updated price conflicts with existing price'
1624
1685
  }
1625
1686
  });
1626
1687
  }
1627
1688
 
1628
1689
  /**
1629
- * Update recurring rule
1630
- * Updates an existing recurring rule
1690
+ * Delete a price
1691
+ * Deletes a price entry (hard delete)
1631
1692
  * @param data The data for the request.
1632
- * @param data.id Rule ID
1693
+ * @param data.id Price ID
1633
1694
  * @param data.region Region code for tenant context
1634
- * @param data.requestBody
1635
- * @returns RecurringRuleResponseDto Rule updated successfully
1695
+ * @returns void Price deleted successfully
1636
1696
  * @throws ApiError
1637
1697
  */
1638
- public static recurringRuleControllerUpdate(
1639
- data: RecurringRuleControllerUpdateData
1640
- ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1698
+ public static priceControllerDelete(
1699
+ data: PriceControllerDeleteData
1700
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1641
1701
  return __request(OpenAPI, {
1642
- method: 'PATCH',
1643
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1702
+ method: 'DELETE',
1703
+ url: '/api/v1/{region}/bean/prices/{id}',
1644
1704
  path: {
1645
1705
  id: data.id,
1646
1706
  region: data.region
1647
1707
  },
1648
- body: data.requestBody,
1649
- mediaType: 'application/json',
1650
1708
  errors: {
1651
- 400: 'Invalid input data',
1652
- 404: 'Rule not found'
1709
+ 404: 'Price not found'
1653
1710
  }
1654
1711
  });
1655
1712
  }
1656
1713
 
1657
1714
  /**
1658
- * Delete recurring rule
1659
- * Soft deletes a recurring rule (sets isActive to false)
1715
+ * Bulk create prices
1716
+ * Creates multiple price entries at once (skips duplicates)
1660
1717
  * @param data The data for the request.
1661
- * @param data.id Rule ID
1662
1718
  * @param data.region Region code for tenant context
1663
- * @returns void Rule deleted successfully
1664
- * @throws ApiError
1719
+ * @param data.requestBody
1720
+ * @returns PriceResponseDto Prices created successfully
1721
+ * @throws ApiError
1722
+ */
1723
+ public static priceControllerBulkCreate(
1724
+ data: PriceControllerBulkCreateData
1725
+ ): CancelablePromise<PriceControllerBulkCreateResponse> {
1726
+ return __request(OpenAPI, {
1727
+ method: 'POST',
1728
+ url: '/api/v1/{region}/bean/prices/bulk',
1729
+ path: {
1730
+ region: data.region
1731
+ },
1732
+ body: data.requestBody,
1733
+ mediaType: 'application/json'
1734
+ });
1735
+ }
1736
+ }
1737
+
1738
+ export class RecurringRulesService {
1739
+ /**
1740
+ * Create a new recurring rule
1741
+ * Creates a new recurring transaction rule for the authenticated user
1742
+ * @param data The data for the request.
1743
+ * @param data.region Region code for tenant context
1744
+ * @param data.requestBody
1745
+ * @returns RecurringRuleResponseDto Rule created successfully
1746
+ * @throws ApiError
1747
+ */
1748
+ public static recurringRuleControllerCreate(
1749
+ data: RecurringRuleControllerCreateData
1750
+ ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1751
+ return __request(OpenAPI, {
1752
+ method: 'POST',
1753
+ url: '/api/v1/{region}/bean/recurring-rules',
1754
+ path: {
1755
+ region: data.region
1756
+ },
1757
+ body: data.requestBody,
1758
+ mediaType: 'application/json',
1759
+ errors: {
1760
+ 400: 'Invalid input data (e.g., autoCreate without accounts)',
1761
+ 409: 'Rule with same name already exists'
1762
+ }
1763
+ });
1764
+ }
1765
+
1766
+ /**
1767
+ * List recurring rules
1768
+ * Returns all recurring rules for the authenticated user with optional filtering
1769
+ * @param data The data for the request.
1770
+ * @param data.region Region code for tenant context
1771
+ * @param data.isActive Filter by active status
1772
+ * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
1773
+ * @param data.hasAutoCreate Filter by autoCreate enabled
1774
+ * @returns RecurringRuleResponseDto Rules retrieved successfully
1775
+ * @throws ApiError
1776
+ */
1777
+ public static recurringRuleControllerFindAll(
1778
+ data: RecurringRuleControllerFindAllData
1779
+ ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1780
+ return __request(OpenAPI, {
1781
+ method: 'GET',
1782
+ url: '/api/v1/{region}/bean/recurring-rules',
1783
+ path: {
1784
+ region: data.region
1785
+ },
1786
+ query: {
1787
+ isActive: data.isActive,
1788
+ frequency: data.frequency,
1789
+ hasAutoCreate: data.hasAutoCreate
1790
+ }
1791
+ });
1792
+ }
1793
+
1794
+ /**
1795
+ * Create recurring rule from transaction
1796
+ * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1797
+ * @param data The data for the request.
1798
+ * @param data.transactionId Source transaction ID
1799
+ * @param data.region Region code for tenant context
1800
+ * @param data.requestBody
1801
+ * @returns RecurringRuleResponseDto Rule created successfully
1802
+ * @throws ApiError
1803
+ */
1804
+ public static recurringRuleControllerCreateFromTransaction(
1805
+ data: RecurringRuleControllerCreateFromTransactionData
1806
+ ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1807
+ return __request(OpenAPI, {
1808
+ method: 'POST',
1809
+ url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1810
+ path: {
1811
+ transactionId: data.transactionId,
1812
+ region: data.region
1813
+ },
1814
+ body: data.requestBody,
1815
+ mediaType: 'application/json',
1816
+ errors: {
1817
+ 404: 'Transaction not found',
1818
+ 409: 'Rule with same name already exists or transaction already linked'
1819
+ }
1820
+ });
1821
+ }
1822
+
1823
+ /**
1824
+ * Get recurring rule by ID
1825
+ * Returns a specific recurring rule with its details
1826
+ * @param data The data for the request.
1827
+ * @param data.id Rule ID
1828
+ * @param data.region Region code for tenant context
1829
+ * @returns RecurringRuleResponseDto Rule retrieved successfully
1830
+ * @throws ApiError
1831
+ */
1832
+ public static recurringRuleControllerFindOne(
1833
+ data: RecurringRuleControllerFindOneData
1834
+ ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1835
+ return __request(OpenAPI, {
1836
+ method: 'GET',
1837
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
1838
+ path: {
1839
+ id: data.id,
1840
+ region: data.region
1841
+ },
1842
+ errors: {
1843
+ 404: 'Rule not found'
1844
+ }
1845
+ });
1846
+ }
1847
+
1848
+ /**
1849
+ * Update recurring rule
1850
+ * Updates an existing recurring rule
1851
+ * @param data The data for the request.
1852
+ * @param data.id Rule ID
1853
+ * @param data.region Region code for tenant context
1854
+ * @param data.requestBody
1855
+ * @returns RecurringRuleResponseDto Rule updated successfully
1856
+ * @throws ApiError
1857
+ */
1858
+ public static recurringRuleControllerUpdate(
1859
+ data: RecurringRuleControllerUpdateData
1860
+ ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1861
+ return __request(OpenAPI, {
1862
+ method: 'PATCH',
1863
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
1864
+ path: {
1865
+ id: data.id,
1866
+ region: data.region
1867
+ },
1868
+ body: data.requestBody,
1869
+ mediaType: 'application/json',
1870
+ errors: {
1871
+ 400: 'Invalid input data',
1872
+ 404: 'Rule not found'
1873
+ }
1874
+ });
1875
+ }
1876
+
1877
+ /**
1878
+ * Delete recurring rule
1879
+ * Soft deletes a recurring rule (sets isActive to false)
1880
+ * @param data The data for the request.
1881
+ * @param data.id Rule ID
1882
+ * @param data.region Region code for tenant context
1883
+ * @returns void Rule deleted successfully
1884
+ * @throws ApiError
1665
1885
  */
1666
1886
  public static recurringRuleControllerDelete(
1667
1887
  data: RecurringRuleControllerDeleteData
@@ -1945,279 +2165,158 @@ export class RecurringForecastService {
1945
2165
  }
1946
2166
  }
1947
2167
 
1948
- export class BeanTransactionRulesService {
2168
+ export class ReportingService {
1949
2169
  /**
1950
- * Create a new transaction rule (or upsert if upsertByPayee=true)
1951
- * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2170
+ * Get portfolio value trends
2171
+ *
2172
+ * Returns time series data of portfolio net worth.
2173
+ *
2174
+ * **Multi-currency Support:**
2175
+ * - `series[].byCurrency` - Currency breakdown for each data point
2176
+ * - `byCurrency` - Separate time series grouped by currency
2177
+ * - `warnings` - Exchange rate warnings if conversion failed
2178
+ *
2179
+ * **Parameters:**
2180
+ * - `period`: Time period (1m, 3m, 6m, 1y)
2181
+ * - `granularity`: Data granularity (day, week, month)
2182
+ *
1952
2183
  * @param data The data for the request.
1953
2184
  * @param data.region Region code for tenant context
1954
- * @param data.requestBody
1955
- * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2185
+ * @param data.period Time period
2186
+ * @param data.granularity Data granularity
2187
+ * @returns PortfolioTrendsResponseDto Trends retrieved successfully
1956
2188
  * @throws ApiError
1957
2189
  */
1958
- public static transactionRuleControllerCreate(
1959
- data: TransactionRuleControllerCreateData
1960
- ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2190
+ public static reportingControllerGetPortfolioTrends(
2191
+ data: ReportingControllerGetPortfolioTrendsData
2192
+ ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
1961
2193
  return __request(OpenAPI, {
1962
- method: 'POST',
1963
- url: '/api/v1/{region}/bean/transaction-rules',
2194
+ method: 'GET',
2195
+ url: '/api/v1/{region}/reporting/portfolio/trends',
1964
2196
  path: {
1965
2197
  region: data.region
1966
2198
  },
1967
- body: data.requestBody,
1968
- mediaType: 'application/json',
2199
+ query: {
2200
+ period: data.period,
2201
+ granularity: data.granularity
2202
+ },
1969
2203
  errors: {
1970
- 400: 'Validation failed',
1971
- 401: 'Unauthorized',
1972
- 409: 'Resource conflict - another process is updating this rule'
2204
+ 401: 'User not authenticated'
1973
2205
  }
1974
2206
  });
1975
2207
  }
1976
2208
 
1977
2209
  /**
1978
- * Get all transaction rules for user
2210
+ * Get cash-flow trends
2211
+ *
2212
+ * Monthly income / expense / netSavings over a fixed N-month window
2213
+ * (current month + N−1 prior). Missing months are zero-filled (flow metric).
2214
+ *
2215
+ * **Parameters:**
2216
+ * - `period`: 1m | 3m | 6m | 1y (default 6m)
2217
+ * - `granularity`: accepted for API symmetry; v1 returns month buckets
2218
+ *
1979
2219
  * @param data The data for the request.
1980
2220
  * @param data.region Region code for tenant context
1981
- * @param data.limit Max results per page (default: 20, max: 100)
1982
- * @param data.offset Pagination offset (default: 0)
1983
- * @param data.enabled Filter by enabled status
1984
- * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
1985
- * @param data.autoApplyEnabled Filter by auto-apply status
1986
- * @returns TransactionRuleListResponseDto List of rules
2221
+ * @param data.period Time period
2222
+ * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
2223
+ * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
1987
2224
  * @throws ApiError
1988
2225
  */
1989
- public static transactionRuleControllerList(
1990
- data: TransactionRuleControllerListData
1991
- ): CancelablePromise<TransactionRuleControllerListResponse> {
2226
+ public static reportingControllerGetCashFlowTrends(
2227
+ data: ReportingControllerGetCashFlowTrendsData
2228
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
1992
2229
  return __request(OpenAPI, {
1993
2230
  method: 'GET',
1994
- url: '/api/v1/{region}/bean/transaction-rules',
2231
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
1995
2232
  path: {
1996
2233
  region: data.region
1997
2234
  },
1998
2235
  query: {
1999
- limit: data.limit,
2000
- offset: data.offset,
2001
- enabled: data.enabled,
2002
- learningSource: data.learningSource,
2003
- autoApplyEnabled: data.autoApplyEnabled
2236
+ period: data.period,
2237
+ granularity: data.granularity
2004
2238
  },
2005
2239
  errors: {
2006
- 401: 'Unauthorized'
2240
+ 401: 'User not authenticated'
2007
2241
  }
2008
2242
  });
2009
2243
  }
2010
2244
 
2011
2245
  /**
2012
- * Validate transaction rule configuration
2013
- * @param data The data for the request.
2014
- * @param data.region Region code for tenant context
2015
- * @param data.requestBody
2016
- * @returns ValidateRuleResponseDto Validation result
2017
- * @throws ApiError
2018
- */
2019
- public static transactionRuleControllerValidate(
2020
- data: TransactionRuleControllerValidateData
2021
- ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2022
- return __request(OpenAPI, {
2023
- method: 'POST',
2024
- url: '/api/v1/{region}/bean/transaction-rules/validate',
2025
- path: {
2026
- region: data.region
2027
- },
2028
- body: data.requestBody,
2029
- mediaType: 'application/json',
2030
- errors: {
2031
- 400: 'Validation failed',
2032
- 401: 'Unauthorized'
2033
- }
2034
- });
2035
- }
2036
-
2037
- /**
2038
- * Bulk create transaction rules
2246
+ * Generate portfolio snapshot
2247
+ *
2248
+ * Manually generate a portfolio snapshot for a specific date.
2249
+ *
2250
+ * **Multi-currency Support:**
2251
+ * - Fetches balances grouped by currency
2252
+ * - Uses user's baseCurrency setting for conversion
2253
+ * - Stores exchange rates and warnings
2254
+ *
2255
+ * **Use Cases:**
2256
+ * - Testing snapshot generation
2257
+ * - Force regeneration after data correction
2258
+ * - Initial setup for new users
2259
+ *
2039
2260
  * @param data The data for the request.
2040
2261
  * @param data.region Region code for tenant context
2041
- * @param data.requestBody
2042
- * @returns BulkCreateRulesResponseDto Bulk create completed
2262
+ * @param data.requestBody Optional date (defaults to today)
2263
+ * @returns GenerateSnapshotResponse Snapshot generated successfully
2043
2264
  * @throws ApiError
2044
2265
  */
2045
- public static transactionRuleControllerBulkCreate(
2046
- data: TransactionRuleControllerBulkCreateData
2047
- ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2266
+ public static reportingControllerGenerateSnapshot(
2267
+ data: ReportingControllerGenerateSnapshotData
2268
+ ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
2048
2269
  return __request(OpenAPI, {
2049
2270
  method: 'POST',
2050
- url: '/api/v1/{region}/bean/transaction-rules/bulk',
2051
- path: {
2052
- region: data.region
2053
- },
2054
- body: data.requestBody,
2055
- mediaType: 'application/json',
2056
- errors: {
2057
- 400: 'Invalid bulk create data',
2058
- 401: 'Unauthorized'
2059
- }
2060
- });
2061
- }
2062
-
2063
- /**
2064
- * Export transaction rules
2065
- * @param data The data for the request.
2066
- * @param data.format Export format (currently only JSON supported)
2067
- * @param data.region Region code for tenant context
2068
- * @returns ExportRulesResponseDto Exported rules
2069
- * @throws ApiError
2070
- */
2071
- public static transactionRuleControllerExport(
2072
- data: TransactionRuleControllerExportData
2073
- ): CancelablePromise<TransactionRuleControllerExportResponse> {
2074
- return __request(OpenAPI, {
2075
- method: 'GET',
2076
- url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2077
- path: {
2078
- format: data.format,
2079
- region: data.region
2080
- },
2081
- errors: {
2082
- 400: 'Unsupported format',
2083
- 401: 'Unauthorized'
2084
- }
2085
- });
2086
- }
2087
-
2088
- /**
2089
- * Get transaction rule statistics
2090
- * @param data The data for the request.
2091
- * @param data.period Statistics time period
2092
- * @param data.region Region code for tenant context
2093
- * @returns RuleStatisticsResponseDto Rule statistics
2094
- * @throws ApiError
2095
- */
2096
- public static transactionRuleControllerGetStatistics(
2097
- data: TransactionRuleControllerGetStatisticsData
2098
- ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2099
- return __request(OpenAPI, {
2100
- method: 'GET',
2101
- url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2102
- path: {
2103
- period: data.period,
2104
- region: data.region
2105
- },
2106
- errors: {
2107
- 401: 'Unauthorized'
2108
- }
2109
- });
2110
- }
2111
-
2112
- /**
2113
- * Get transaction rule detail
2114
- * @param data The data for the request.
2115
- * @param data.ruleId Rule ID
2116
- * @param data.region Region code for tenant context
2117
- * @returns TransactionRuleResponseDto Rule details
2118
- * @throws ApiError
2119
- */
2120
- public static transactionRuleControllerGetDetail(
2121
- data: TransactionRuleControllerGetDetailData
2122
- ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2123
- return __request(OpenAPI, {
2124
- method: 'GET',
2125
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2126
- path: {
2127
- ruleId: data.ruleId,
2128
- region: data.region
2129
- },
2130
- errors: {
2131
- 401: 'Unauthorized',
2132
- 403: 'Forbidden - not owner of rule',
2133
- 404: 'Rule not found'
2134
- }
2135
- });
2136
- }
2137
-
2138
- /**
2139
- * Update a transaction rule
2140
- * @param data The data for the request.
2141
- * @param data.ruleId Rule ID to update
2142
- * @param data.region Region code for tenant context
2143
- * @param data.requestBody
2144
- * @returns TransactionRuleResponseDto Rule updated successfully
2145
- * @throws ApiError
2146
- */
2147
- public static transactionRuleControllerUpdate(
2148
- data: TransactionRuleControllerUpdateData
2149
- ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2150
- return __request(OpenAPI, {
2151
- method: 'PUT',
2152
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2271
+ url: '/api/v1/{region}/reporting/snapshots/generate',
2153
2272
  path: {
2154
- ruleId: data.ruleId,
2155
2273
  region: data.region
2156
2274
  },
2157
2275
  body: data.requestBody,
2158
2276
  mediaType: 'application/json',
2159
2277
  errors: {
2160
- 400: 'Validation failed',
2161
- 401: 'Unauthorized',
2162
- 403: 'Forbidden - not owner of rule',
2163
- 404: 'Rule not found',
2164
- 409: 'Resource conflict - rule is being modified by another process'
2165
- }
2166
- });
2167
- }
2168
-
2169
- /**
2170
- * Delete a transaction rule
2171
- * @param data The data for the request.
2172
- * @param data.ruleId Rule ID to delete
2173
- * @param data.region Region code for tenant context
2174
- * @returns void Rule deleted successfully
2175
- * @throws ApiError
2176
- */
2177
- public static transactionRuleControllerDelete(
2178
- data: TransactionRuleControllerDeleteData
2179
- ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2180
- return __request(OpenAPI, {
2181
- method: 'DELETE',
2182
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2183
- path: {
2184
- ruleId: data.ruleId,
2185
- region: data.region
2186
- },
2187
- errors: {
2188
- 401: 'Unauthorized',
2189
- 403: 'Forbidden - not owner of rule',
2190
- 404: 'Rule not found',
2191
- 409: 'Resource conflict - rule is being modified by another process'
2278
+ 400: 'Invalid date format',
2279
+ 401: 'User not authenticated'
2192
2280
  }
2193
2281
  });
2194
2282
  }
2195
2283
 
2196
2284
  /**
2197
- * Test rule matching
2285
+ * Backfill portfolio snapshots
2286
+ *
2287
+ * Generate snapshots for a date range (historical data backfill).
2288
+ *
2289
+ * **Multi-currency Support:**
2290
+ * - Each snapshot includes multi-currency data
2291
+ * - Uses exchange rates available at generation time
2292
+ * - Warnings stored for missing exchange rates
2293
+ *
2294
+ * **Best Practices:**
2295
+ * - Use for initial setup after account configuration
2296
+ * - Run during low-traffic periods for large date ranges
2297
+ * - Existing snapshots are skipped (not regenerated)
2298
+ *
2198
2299
  * @param data The data for the request.
2199
- * @param data.ruleId Rule ID to test
2200
2300
  * @param data.region Region code for tenant context
2201
2301
  * @param data.requestBody
2202
- * @returns TestRuleResponseDto Test result
2302
+ * @returns BackfillSnapshotsResponse Backfill completed successfully
2203
2303
  * @throws ApiError
2204
2304
  */
2205
- public static transactionRuleControllerTest(
2206
- data: TransactionRuleControllerTestData
2207
- ): CancelablePromise<TransactionRuleControllerTestResponse> {
2305
+ public static reportingControllerBackfillSnapshots(
2306
+ data: ReportingControllerBackfillSnapshotsData
2307
+ ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
2208
2308
  return __request(OpenAPI, {
2209
2309
  method: 'POST',
2210
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2310
+ url: '/api/v1/{region}/reporting/snapshots/backfill',
2211
2311
  path: {
2212
- ruleId: data.ruleId,
2213
2312
  region: data.region
2214
2313
  },
2215
2314
  body: data.requestBody,
2216
2315
  mediaType: 'application/json',
2217
2316
  errors: {
2218
- 401: 'Unauthorized',
2219
- 403: 'Forbidden - not owner of rule',
2220
- 404: 'Rule not found'
2317
+ 400: 'Invalid date format or range',
2318
+ 401: 'User not authenticated',
2319
+ 409: 'Backfill already in progress for this user'
2221
2320
  }
2222
2321
  });
2223
2322
  }
@@ -2269,7 +2368,7 @@ export class UsersService {
2269
2368
  * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
2270
2369
  * @param data The data for the request.
2271
2370
  * @param data.requestBody
2272
- * @returns unknown User created successfully
2371
+ * @returns SignupResponseDto User created successfully
2273
2372
  * @throws ApiError
2274
2373
  */
2275
2374
  public static userControllerSignupUser(
@@ -2478,52 +2577,330 @@ export class PropertiesService {
2478
2577
  }
2479
2578
  }
2480
2579
 
2481
- export class LifeEventsService {
2580
+ export class BeanTransactionRulesService {
2482
2581
  /**
2483
- * Create a new life event
2484
- * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2582
+ * Create a new transaction rule (or upsert if upsertByPayee=true)
2583
+ * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2485
2584
  * @param data The data for the request.
2486
- * @param data.region Region code for tenant context (decorative for life events)
2585
+ * @param data.region Region code for tenant context
2487
2586
  * @param data.requestBody
2488
- * @returns EventResponseDto Life event created successfully
2587
+ * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2489
2588
  * @throws ApiError
2490
2589
  */
2491
- public static eventControllerCreate(
2492
- data: EventControllerCreateData
2493
- ): CancelablePromise<EventControllerCreateResponse> {
2590
+ public static transactionRuleControllerCreate(
2591
+ data: TransactionRuleControllerCreateData
2592
+ ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2494
2593
  return __request(OpenAPI, {
2495
2594
  method: 'POST',
2496
- url: '/api/v1/{region}/bean/events',
2595
+ url: '/api/v1/{region}/bean/transaction-rules',
2497
2596
  path: {
2498
2597
  region: data.region
2499
2598
  },
2500
2599
  body: data.requestBody,
2501
2600
  mediaType: 'application/json',
2502
2601
  errors: {
2503
- 409: 'Life event already exists for this (userId, type, date) combination'
2602
+ 400: 'Validation failed',
2603
+ 401: 'Unauthorized',
2604
+ 409: 'Resource conflict - another process is updating this rule'
2504
2605
  }
2505
2606
  });
2506
2607
  }
2507
2608
 
2508
2609
  /**
2509
- * List user life events
2510
- * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2610
+ * Get all transaction rules for user
2511
2611
  * @param data The data for the request.
2512
- * @param data.region Region code for tenant context (decorative for life events)
2513
- * @param data.type Filter by life event type (exact match)
2514
- * @param data.q Search term for description (case-insensitive partial match)
2515
- * @param data.from Filter life events from this date (ISO 8601 format)
2516
- * @param data.to Filter life events to this date (ISO 8601 format)
2517
- * @param data.page Page number for pagination (default: 1)
2518
- * @param data.limit Number of items per page (default: 20, max: 100)
2519
- * @returns EventListResponseDto Life events retrieved successfully
2612
+ * @param data.region Region code for tenant context
2613
+ * @param data.limit Max results per page (default: 20, max: 100)
2614
+ * @param data.offset Pagination offset (default: 0)
2615
+ * @param data.enabled Filter by enabled status
2616
+ * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
2617
+ * @param data.autoApplyEnabled Filter by auto-apply status
2618
+ * @returns TransactionRuleListResponseDto List of rules
2520
2619
  * @throws ApiError
2521
2620
  */
2522
- public static eventControllerFindAll(
2523
- data: EventControllerFindAllData
2524
- ): CancelablePromise<EventControllerFindAllResponse> {
2525
- return __request(OpenAPI, {
2526
- method: 'GET',
2621
+ public static transactionRuleControllerList(
2622
+ data: TransactionRuleControllerListData
2623
+ ): CancelablePromise<TransactionRuleControllerListResponse> {
2624
+ return __request(OpenAPI, {
2625
+ method: 'GET',
2626
+ url: '/api/v1/{region}/bean/transaction-rules',
2627
+ path: {
2628
+ region: data.region
2629
+ },
2630
+ query: {
2631
+ limit: data.limit,
2632
+ offset: data.offset,
2633
+ enabled: data.enabled,
2634
+ learningSource: data.learningSource,
2635
+ autoApplyEnabled: data.autoApplyEnabled
2636
+ },
2637
+ errors: {
2638
+ 401: 'Unauthorized'
2639
+ }
2640
+ });
2641
+ }
2642
+
2643
+ /**
2644
+ * Validate transaction rule configuration
2645
+ * @param data The data for the request.
2646
+ * @param data.region Region code for tenant context
2647
+ * @param data.requestBody
2648
+ * @returns ValidateRuleResponseDto Validation result
2649
+ * @throws ApiError
2650
+ */
2651
+ public static transactionRuleControllerValidate(
2652
+ data: TransactionRuleControllerValidateData
2653
+ ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2654
+ return __request(OpenAPI, {
2655
+ method: 'POST',
2656
+ url: '/api/v1/{region}/bean/transaction-rules/validate',
2657
+ path: {
2658
+ region: data.region
2659
+ },
2660
+ body: data.requestBody,
2661
+ mediaType: 'application/json',
2662
+ errors: {
2663
+ 400: 'Validation failed',
2664
+ 401: 'Unauthorized'
2665
+ }
2666
+ });
2667
+ }
2668
+
2669
+ /**
2670
+ * Bulk create transaction rules
2671
+ * @param data The data for the request.
2672
+ * @param data.region Region code for tenant context
2673
+ * @param data.requestBody
2674
+ * @returns BulkCreateRulesResponseDto Bulk create completed
2675
+ * @throws ApiError
2676
+ */
2677
+ public static transactionRuleControllerBulkCreate(
2678
+ data: TransactionRuleControllerBulkCreateData
2679
+ ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2680
+ return __request(OpenAPI, {
2681
+ method: 'POST',
2682
+ url: '/api/v1/{region}/bean/transaction-rules/bulk',
2683
+ path: {
2684
+ region: data.region
2685
+ },
2686
+ body: data.requestBody,
2687
+ mediaType: 'application/json',
2688
+ errors: {
2689
+ 400: 'Invalid bulk create data',
2690
+ 401: 'Unauthorized'
2691
+ }
2692
+ });
2693
+ }
2694
+
2695
+ /**
2696
+ * Export transaction rules
2697
+ * @param data The data for the request.
2698
+ * @param data.format Export format (currently only JSON supported)
2699
+ * @param data.region Region code for tenant context
2700
+ * @returns ExportRulesResponseDto Exported rules
2701
+ * @throws ApiError
2702
+ */
2703
+ public static transactionRuleControllerExport(
2704
+ data: TransactionRuleControllerExportData
2705
+ ): CancelablePromise<TransactionRuleControllerExportResponse> {
2706
+ return __request(OpenAPI, {
2707
+ method: 'GET',
2708
+ url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2709
+ path: {
2710
+ format: data.format,
2711
+ region: data.region
2712
+ },
2713
+ errors: {
2714
+ 400: 'Unsupported format',
2715
+ 401: 'Unauthorized'
2716
+ }
2717
+ });
2718
+ }
2719
+
2720
+ /**
2721
+ * Get transaction rule statistics
2722
+ * @param data The data for the request.
2723
+ * @param data.period Statistics time period
2724
+ * @param data.region Region code for tenant context
2725
+ * @returns RuleStatisticsResponseDto Rule statistics
2726
+ * @throws ApiError
2727
+ */
2728
+ public static transactionRuleControllerGetStatistics(
2729
+ data: TransactionRuleControllerGetStatisticsData
2730
+ ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2731
+ return __request(OpenAPI, {
2732
+ method: 'GET',
2733
+ url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2734
+ path: {
2735
+ period: data.period,
2736
+ region: data.region
2737
+ },
2738
+ errors: {
2739
+ 401: 'Unauthorized'
2740
+ }
2741
+ });
2742
+ }
2743
+
2744
+ /**
2745
+ * Get transaction rule detail
2746
+ * @param data The data for the request.
2747
+ * @param data.ruleId Rule ID
2748
+ * @param data.region Region code for tenant context
2749
+ * @returns TransactionRuleResponseDto Rule details
2750
+ * @throws ApiError
2751
+ */
2752
+ public static transactionRuleControllerGetDetail(
2753
+ data: TransactionRuleControllerGetDetailData
2754
+ ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2755
+ return __request(OpenAPI, {
2756
+ method: 'GET',
2757
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2758
+ path: {
2759
+ ruleId: data.ruleId,
2760
+ region: data.region
2761
+ },
2762
+ errors: {
2763
+ 401: 'Unauthorized',
2764
+ 403: 'Forbidden - not owner of rule',
2765
+ 404: 'Rule not found'
2766
+ }
2767
+ });
2768
+ }
2769
+
2770
+ /**
2771
+ * Update a transaction rule
2772
+ * @param data The data for the request.
2773
+ * @param data.ruleId Rule ID to update
2774
+ * @param data.region Region code for tenant context
2775
+ * @param data.requestBody
2776
+ * @returns TransactionRuleResponseDto Rule updated successfully
2777
+ * @throws ApiError
2778
+ */
2779
+ public static transactionRuleControllerUpdate(
2780
+ data: TransactionRuleControllerUpdateData
2781
+ ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2782
+ return __request(OpenAPI, {
2783
+ method: 'PUT',
2784
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2785
+ path: {
2786
+ ruleId: data.ruleId,
2787
+ region: data.region
2788
+ },
2789
+ body: data.requestBody,
2790
+ mediaType: 'application/json',
2791
+ errors: {
2792
+ 400: 'Validation failed',
2793
+ 401: 'Unauthorized',
2794
+ 403: 'Forbidden - not owner of rule',
2795
+ 404: 'Rule not found',
2796
+ 409: 'Resource conflict - rule is being modified by another process'
2797
+ }
2798
+ });
2799
+ }
2800
+
2801
+ /**
2802
+ * Delete a transaction rule
2803
+ * @param data The data for the request.
2804
+ * @param data.ruleId Rule ID to delete
2805
+ * @param data.region Region code for tenant context
2806
+ * @returns void Rule deleted successfully
2807
+ * @throws ApiError
2808
+ */
2809
+ public static transactionRuleControllerDelete(
2810
+ data: TransactionRuleControllerDeleteData
2811
+ ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2812
+ return __request(OpenAPI, {
2813
+ method: 'DELETE',
2814
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2815
+ path: {
2816
+ ruleId: data.ruleId,
2817
+ region: data.region
2818
+ },
2819
+ errors: {
2820
+ 401: 'Unauthorized',
2821
+ 403: 'Forbidden - not owner of rule',
2822
+ 404: 'Rule not found',
2823
+ 409: 'Resource conflict - rule is being modified by another process'
2824
+ }
2825
+ });
2826
+ }
2827
+
2828
+ /**
2829
+ * Test rule matching
2830
+ * @param data The data for the request.
2831
+ * @param data.ruleId Rule ID to test
2832
+ * @param data.region Region code for tenant context
2833
+ * @param data.requestBody
2834
+ * @returns TestRuleResponseDto Test result
2835
+ * @throws ApiError
2836
+ */
2837
+ public static transactionRuleControllerTest(
2838
+ data: TransactionRuleControllerTestData
2839
+ ): CancelablePromise<TransactionRuleControllerTestResponse> {
2840
+ return __request(OpenAPI, {
2841
+ method: 'POST',
2842
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2843
+ path: {
2844
+ ruleId: data.ruleId,
2845
+ region: data.region
2846
+ },
2847
+ body: data.requestBody,
2848
+ mediaType: 'application/json',
2849
+ errors: {
2850
+ 401: 'Unauthorized',
2851
+ 403: 'Forbidden - not owner of rule',
2852
+ 404: 'Rule not found'
2853
+ }
2854
+ });
2855
+ }
2856
+ }
2857
+
2858
+ export class LifeEventsService {
2859
+ /**
2860
+ * Create a new life event
2861
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2862
+ * @param data The data for the request.
2863
+ * @param data.region Region code for tenant context (decorative for life events)
2864
+ * @param data.requestBody
2865
+ * @returns EventResponseDto Life event created successfully
2866
+ * @throws ApiError
2867
+ */
2868
+ public static eventControllerCreate(
2869
+ data: EventControllerCreateData
2870
+ ): CancelablePromise<EventControllerCreateResponse> {
2871
+ return __request(OpenAPI, {
2872
+ method: 'POST',
2873
+ url: '/api/v1/{region}/bean/events',
2874
+ path: {
2875
+ region: data.region
2876
+ },
2877
+ body: data.requestBody,
2878
+ mediaType: 'application/json',
2879
+ errors: {
2880
+ 409: 'Life event already exists for this (userId, type, date) combination'
2881
+ }
2882
+ });
2883
+ }
2884
+
2885
+ /**
2886
+ * List user life events
2887
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2888
+ * @param data The data for the request.
2889
+ * @param data.region Region code for tenant context (decorative for life events)
2890
+ * @param data.type Filter by life event type (exact match)
2891
+ * @param data.q Search term for description (case-insensitive partial match)
2892
+ * @param data.from Filter life events from this date (ISO 8601 format)
2893
+ * @param data.to Filter life events to this date (ISO 8601 format)
2894
+ * @param data.page Page number for pagination (default: 1)
2895
+ * @param data.limit Number of items per page (default: 20, max: 100)
2896
+ * @returns EventListResponseDto Life events retrieved successfully
2897
+ * @throws ApiError
2898
+ */
2899
+ public static eventControllerFindAll(
2900
+ data: EventControllerFindAllData
2901
+ ): CancelablePromise<EventControllerFindAllResponse> {
2902
+ return __request(OpenAPI, {
2903
+ method: 'GET',
2527
2904
  url: '/api/v1/{region}/bean/events',
2528
2905
  path: {
2529
2906
  region: data.region
@@ -2653,6 +3030,139 @@ export class LifeEventsService {
2653
3030
  }
2654
3031
  }
2655
3032
 
3033
+ export class OnboardingService {
3034
+ /**
3035
+ * Bootstrap core accounts + register asset accounts with opening balances (ADR-0113)
3036
+ * @param data The data for the request.
3037
+ * @param data.region Region code for tenant context
3038
+ * @param data.requestBody
3039
+ * @returns unknown Onboarding bootstrap result.
3040
+ * @throws ApiError
3041
+ */
3042
+ public static onboardingControllerBootstrap(
3043
+ data: OnboardingControllerBootstrapData
3044
+ ): CancelablePromise<OnboardingControllerBootstrapResponse> {
3045
+ return __request(OpenAPI, {
3046
+ method: 'POST',
3047
+ url: '/api/v1/{region}/bean/onboarding',
3048
+ path: {
3049
+ region: data.region
3050
+ },
3051
+ body: data.requestBody,
3052
+ mediaType: 'application/json',
3053
+ errors: {
3054
+ 422: 'Invalid region/account path/duplicate paths.'
3055
+ }
3056
+ });
3057
+ }
3058
+ }
3059
+
3060
+ export class BalanceReconciliationService {
3061
+ /**
3062
+ * Preview reconciliation (book vs actual)
3063
+ * Computes book balance, diff, Beancount-inferred tolerance, and suggested action without persisting.
3064
+ * @param data The data for the request.
3065
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3066
+ * @param data.requestBody
3067
+ * @returns ReconciliationComputeResultDto Reconciliation preview
3068
+ * @throws ApiError
3069
+ */
3070
+ public static reconciliationControllerCompute(
3071
+ data: ReconciliationControllerComputeData
3072
+ ): CancelablePromise<ReconciliationControllerComputeResponse> {
3073
+ return __request(OpenAPI, {
3074
+ method: 'POST',
3075
+ url: '/api/v1/{region}/bean/reconciliations',
3076
+ path: {
3077
+ region: data.region
3078
+ },
3079
+ body: data.requestBody,
3080
+ mediaType: 'application/json',
3081
+ errors: {
3082
+ 404: 'Account not found'
3083
+ }
3084
+ });
3085
+ }
3086
+
3087
+ /**
3088
+ * Record a balance assertion
3089
+ * Persists the reconciliation as a BeanBalance assertion (amount = actual, diffAmount = book − actual). Re-reconciling the same day/currency upserts.
3090
+ * @param data The data for the request.
3091
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3092
+ * @param data.requestBody
3093
+ * @returns ReconciliationRecordDto Balance assertion recorded
3094
+ * @throws ApiError
3095
+ */
3096
+ public static reconciliationControllerAssert(
3097
+ data: ReconciliationControllerAssertData
3098
+ ): CancelablePromise<ReconciliationControllerAssertResponse> {
3099
+ return __request(OpenAPI, {
3100
+ method: 'POST',
3101
+ url: '/api/v1/{region}/bean/reconciliations/assert',
3102
+ path: {
3103
+ region: data.region
3104
+ },
3105
+ body: data.requestBody,
3106
+ mediaType: 'application/json',
3107
+ errors: {
3108
+ 404: 'Account not found'
3109
+ }
3110
+ });
3111
+ }
3112
+
3113
+ /**
3114
+ * Generate a pad adjusting entry
3115
+ * 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.
3116
+ * @param data The data for the request.
3117
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3118
+ * @param data.requestBody
3119
+ * @returns PadResultDto Pad adjusting entry generated
3120
+ * @throws ApiError
3121
+ */
3122
+ public static reconciliationControllerPad(
3123
+ data: ReconciliationControllerPadData
3124
+ ): CancelablePromise<ReconciliationControllerPadResponse> {
3125
+ return __request(OpenAPI, {
3126
+ method: 'POST',
3127
+ url: '/api/v1/{region}/bean/reconciliations/pad',
3128
+ path: {
3129
+ region: data.region
3130
+ },
3131
+ body: data.requestBody,
3132
+ mediaType: 'application/json',
3133
+ errors: {
3134
+ 400: 'Book already within tolerance — no pad needed',
3135
+ 404: 'Account not found'
3136
+ }
3137
+ });
3138
+ }
3139
+
3140
+ /**
3141
+ * List reconciliation history for an account
3142
+ * Returns recorded balance assertions (most recent first). The latest drives the account-detail "Last <date>" badge.
3143
+ * @param data The data for the request.
3144
+ * @param data.accountId BeanAccount id
3145
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3146
+ * @returns ReconciliationRecordDto Reconciliation history
3147
+ * @throws ApiError
3148
+ */
3149
+ public static reconciliationControllerHistory(
3150
+ data: ReconciliationControllerHistoryData
3151
+ ): CancelablePromise<ReconciliationControllerHistoryResponse> {
3152
+ return __request(OpenAPI, {
3153
+ method: 'GET',
3154
+ url: '/api/v1/{region}/bean/accounts/{accountId}/reconciliations',
3155
+ path: {
3156
+ accountId: data.accountId,
3157
+ region: data.region
3158
+ },
3159
+ errors: {
3160
+ 404: 'Account not found'
3161
+ }
3162
+ });
3163
+ }
3164
+ }
3165
+
2656
3166
  export class BeanExportService {
2657
3167
  /**
2658
3168
  * Export Beancount ledger as ZIP
@@ -2831,216 +3341,196 @@ export class BeanImportService {
2831
3341
  }
2832
3342
  }
2833
3343
 
2834
- export class BeanPlatformsService {
2835
- /**
2836
- * Get all platforms with statistics
2837
- * @returns unknown List of platforms with binding and account counts
2838
- * @throws ApiError
2839
- */
2840
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2841
- return __request(OpenAPI, {
2842
- method: 'GET',
2843
- url: '/api/v1/bean/platforms'
2844
- });
2845
- }
2846
-
3344
+ export class ProviderSyncService {
2847
3345
  /**
2848
- * Create a new platform
3346
+ * Sync transactions from financial data provider
3347
+ *
3348
+ * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
3349
+ *
3350
+ * **Supported Providers:**
3351
+ * - **plaid**: Plaid API (US, Canada, Europe)
3352
+ * - **teller**: Teller API (US)
3353
+ * - **truelayer**: TrueLayer Open Banking (UK, Europe)
3354
+ * - **gocardless**: GoCardless Bank Account Data (Europe)
3355
+ * - **simplefin**: SimpleFIN (Self-hosted)
3356
+ * - **yodlee**: Yodlee (Global)
3357
+ * - **beancount-direct**: Beancount format transactions
3358
+ * - **parsed-bill**: Client-side parsed bill transactions
3359
+ *
3360
+ * **Processing Flow:**
3361
+ * 1. Transform raw data via provider adapter
3362
+ * 2. Validate transaction format
3363
+ * 3. Deduplicate using originalId
3364
+ * 4. Classify using rule engine
3365
+ * 5. Route low-confidence to Review Center
3366
+ * 6. Persist validated transactions
3367
+ *
2849
3368
  * @param data The data for the request.
3369
+ * @param data.providerName Provider name
3370
+ * @param data.region Region code for tenant context
2850
3371
  * @param data.requestBody
2851
- * @returns unknown Platform created successfully
3372
+ * @returns ProviderSyncResponseDto Sync completed successfully
2852
3373
  * @throws ApiError
2853
3374
  */
2854
- public static platformControllerCreate(
2855
- data: PlatformControllerCreateData
2856
- ): CancelablePromise<PlatformControllerCreateResponse> {
3375
+ public static providerSyncControllerSync(
3376
+ data: ProviderSyncControllerSyncData
3377
+ ): CancelablePromise<ProviderSyncControllerSyncResponse> {
2857
3378
  return __request(OpenAPI, {
2858
3379
  method: 'POST',
2859
- url: '/api/v1/bean/platforms',
3380
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3381
+ path: {
3382
+ providerName: data.providerName,
3383
+ region: data.region
3384
+ },
2860
3385
  body: data.requestBody,
2861
3386
  mediaType: 'application/json',
2862
3387
  errors: {
2863
- 409: 'Platform already exists'
3388
+ 400: 'Invalid request data',
3389
+ 401: 'Missing or invalid authentication',
3390
+ 404: 'Provider not supported'
2864
3391
  }
2865
3392
  });
2866
3393
  }
2867
3394
 
2868
3395
  /**
2869
- * Get platform list for current user
2870
- * @returns unknown List of platforms with user binding status
2871
- * @throws ApiError
2872
- */
2873
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
2874
- return __request(OpenAPI, {
2875
- method: 'GET',
2876
- url: '/api/v1/bean/platforms/list'
2877
- });
2878
- }
2879
-
2880
- /**
2881
- * Match platforms by name or alias
3396
+ * Get supported providers
3397
+ * Returns a list of all providers supported by the sync endpoint.
2882
3398
  * @param data The data for the request.
2883
- * @param data.q Search query — Chinese name, English name, or abbreviation
2884
- * @param data.region Region code for category override lookup
2885
- * @returns unknown List of matching platforms with suggested segment names
3399
+ * @param data.region Region code for tenant context
3400
+ * @returns SupportedProvidersResponseDto List of supported providers
2886
3401
  * @throws ApiError
2887
3402
  */
2888
- public static platformControllerMatchPlatforms(
2889
- data: PlatformControllerMatchPlatformsData
2890
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3403
+ public static providerSyncControllerGetSupportedProviders(
3404
+ data: ProviderSyncControllerGetSupportedProvidersData
3405
+ ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
2891
3406
  return __request(OpenAPI, {
2892
3407
  method: 'GET',
2893
- url: '/api/v1/bean/platforms/match',
2894
- query: {
2895
- q: data.q,
2896
- region: data.region
2897
- }
2898
- });
2899
- }
2900
-
2901
- /**
2902
- * Update a platform
2903
- * @param data The data for the request.
2904
- * @param data.id Platform ID
2905
- * @param data.requestBody
2906
- * @returns unknown Platform updated successfully
2907
- * @throws ApiError
2908
- */
2909
- public static platformControllerUpdate(
2910
- data: PlatformControllerUpdateData
2911
- ): CancelablePromise<PlatformControllerUpdateResponse> {
2912
- return __request(OpenAPI, {
2913
- method: 'PUT',
2914
- url: '/api/v1/bean/platforms/{id}',
3408
+ url: '/api/v1/{region}/bean/import/provider/supported',
2915
3409
  path: {
2916
- id: data.id
3410
+ region: data.region
2917
3411
  },
2918
- body: data.requestBody,
2919
- mediaType: 'application/json',
2920
3412
  errors: {
2921
- 404: 'Platform not found'
3413
+ 401: 'Missing or invalid authentication'
2922
3414
  }
2923
3415
  });
2924
3416
  }
2925
3417
 
2926
3418
  /**
2927
- * Delete a platform
3419
+ * Check if provider is supported
3420
+ * Returns whether a specific provider is supported.
2928
3421
  * @param data The data for the request.
2929
- * @param data.id Platform ID
2930
- * @returns void Platform deleted successfully
3422
+ * @param data.providerName Provider name to check
3423
+ * @param data.region Region code for tenant context
3424
+ * @returns unknown Provider support status
2931
3425
  * @throws ApiError
2932
3426
  */
2933
- public static platformControllerDelete(
2934
- data: PlatformControllerDeleteData
2935
- ): CancelablePromise<PlatformControllerDeleteResponse> {
3427
+ public static providerSyncControllerIsProviderSupported(
3428
+ data: ProviderSyncControllerIsProviderSupportedData
3429
+ ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
2936
3430
  return __request(OpenAPI, {
2937
- method: 'DELETE',
2938
- url: '/api/v1/bean/platforms/{id}',
3431
+ method: 'GET',
3432
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
2939
3433
  path: {
2940
- id: data.id
3434
+ providerName: data.providerName,
3435
+ region: data.region
2941
3436
  },
2942
3437
  errors: {
2943
- 404: 'Platform not found'
3438
+ 401: 'Missing or invalid authentication'
2944
3439
  }
2945
3440
  });
2946
3441
  }
2947
3442
  }
2948
3443
 
2949
- export class ProviderSyncService {
3444
+ export class ExternalAccountLinksService {
2950
3445
  /**
2951
- * Sync transactions from financial data provider
2952
- *
2953
- * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
2954
- *
2955
- * **Supported Providers:**
2956
- * - **plaid**: Plaid API (US, Canada, Europe)
2957
- * - **teller**: Teller API (US)
2958
- * - **truelayer**: TrueLayer Open Banking (UK, Europe)
2959
- * - **gocardless**: GoCardless Bank Account Data (Europe)
2960
- * - **simplefin**: SimpleFIN (Self-hosted)
2961
- * - **yodlee**: Yodlee (Global)
2962
- * - **beancount-direct**: Beancount format transactions
2963
- * - **parsed-bill**: Client-side parsed bill transactions
2964
- *
2965
- * **Processing Flow:**
2966
- * 1. Transform raw data via provider adapter
2967
- * 2. Validate transaction format
2968
- * 3. Deduplicate using originalId
2969
- * 4. Classify using rule engine
2970
- * 5. Route low-confidence to Review Center
2971
- * 6. Persist validated transactions
2972
- *
3446
+ * Create an external account → BeanAccount mapping (ADR-0113)
2973
3447
  * @param data The data for the request.
2974
- * @param data.providerName Provider name
2975
3448
  * @param data.region Region code for tenant context
2976
3449
  * @param data.requestBody
2977
- * @returns ProviderSyncResponseDto Sync completed successfully
3450
+ * @returns ExternalAccountLinkResponseDto Link created.
2978
3451
  * @throws ApiError
2979
3452
  */
2980
- public static providerSyncControllerSync(
2981
- data: ProviderSyncControllerSyncData
2982
- ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3453
+ public static externalAccountLinkControllerCreate(
3454
+ data: ExternalAccountLinkControllerCreateData
3455
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
2983
3456
  return __request(OpenAPI, {
2984
3457
  method: 'POST',
2985
- url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3458
+ url: '/api/v1/{region}/bean/external-account-links',
2986
3459
  path: {
2987
- providerName: data.providerName,
2988
3460
  region: data.region
2989
3461
  },
2990
3462
  body: data.requestBody,
2991
3463
  mediaType: 'application/json',
2992
3464
  errors: {
2993
- 400: 'Invalid request data',
2994
- 401: 'Missing or invalid authentication',
2995
- 404: 'Provider not supported'
3465
+ 422: 'beanAccountId not owned, or an active link already exists.'
2996
3466
  }
2997
3467
  });
2998
3468
  }
2999
3469
 
3000
3470
  /**
3001
- * Get supported providers
3002
- * Returns a list of all providers supported by the sync endpoint.
3471
+ * List the user's active external account links
3003
3472
  * @param data The data for the request.
3473
+ * @param data.provider
3004
3474
  * @param data.region Region code for tenant context
3005
- * @returns SupportedProvidersResponseDto List of supported providers
3475
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
3006
3476
  * @throws ApiError
3007
3477
  */
3008
- public static providerSyncControllerGetSupportedProviders(
3009
- data: ProviderSyncControllerGetSupportedProvidersData
3010
- ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3478
+ public static externalAccountLinkControllerFindAll(
3479
+ data: ExternalAccountLinkControllerFindAllData
3480
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
3011
3481
  return __request(OpenAPI, {
3012
3482
  method: 'GET',
3013
- url: '/api/v1/{region}/bean/import/provider/supported',
3483
+ url: '/api/v1/{region}/bean/external-account-links',
3014
3484
  path: {
3015
3485
  region: data.region
3016
3486
  },
3017
- errors: {
3018
- 401: 'Missing or invalid authentication'
3487
+ query: {
3488
+ provider: data.provider
3019
3489
  }
3020
3490
  });
3021
3491
  }
3022
3492
 
3023
3493
  /**
3024
- * Check if provider is supported
3025
- * Returns whether a specific provider is supported.
3494
+ * Get a single external account link
3026
3495
  * @param data The data for the request.
3027
- * @param data.providerName Provider name to check
3496
+ * @param data.id
3028
3497
  * @param data.region Region code for tenant context
3029
- * @returns unknown Provider support status
3498
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
3030
3499
  * @throws ApiError
3031
3500
  */
3032
- public static providerSyncControllerIsProviderSupported(
3033
- data: ProviderSyncControllerIsProviderSupportedData
3034
- ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3501
+ public static externalAccountLinkControllerFindOne(
3502
+ data: ExternalAccountLinkControllerFindOneData
3503
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
3035
3504
  return __request(OpenAPI, {
3036
3505
  method: 'GET',
3037
- url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
3506
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3038
3507
  path: {
3039
- providerName: data.providerName,
3508
+ id: data.id,
3040
3509
  region: data.region
3041
3510
  },
3042
3511
  errors: {
3043
- 401: 'Missing or invalid authentication'
3512
+ 422: 'Link not found or not owned by the user.'
3513
+ }
3514
+ });
3515
+ }
3516
+
3517
+ /**
3518
+ * Soft-delete (disconnect) an external account link
3519
+ * @param data The data for the request.
3520
+ * @param data.id
3521
+ * @param data.region Region code for tenant context
3522
+ * @returns void Link soft-deleted; historical transactions are unaffected.
3523
+ * @throws ApiError
3524
+ */
3525
+ public static externalAccountLinkControllerRemove(
3526
+ data: ExternalAccountLinkControllerRemoveData
3527
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
3528
+ return __request(OpenAPI, {
3529
+ method: 'DELETE',
3530
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3531
+ path: {
3532
+ id: data.id,
3533
+ region: data.region
3044
3534
  }
3045
3535
  });
3046
3536
  }
@@ -3204,359 +3694,173 @@ export class BeanNlpService {
3204
3694
  }
3205
3695
  }
3206
3696
 
3207
- export class DashboardService {
3208
- /**
3209
- * Get net worth overview
3210
- * Returns total net worth with breakdown of assets and liabilities
3211
- * @param data The data for the request.
3212
- * @param data.region Region code for tenant context
3213
- * @param data.date Date for balance calculation (ISO 8601 format)
3214
- * @returns NetWorthResponseDto Net worth retrieved successfully
3215
- * @throws ApiError
3216
- */
3217
- public static dashboardControllerGetNetWorth(
3218
- data: DashboardControllerGetNetWorthData
3219
- ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3220
- return __request(OpenAPI, {
3221
- method: 'GET',
3222
- url: '/api/v1/{region}/dashboard/net-worth',
3223
- path: {
3224
- region: data.region
3225
- },
3226
- query: {
3227
- date: data.date
3228
- },
3229
- errors: {
3230
- 401: 'User not authenticated'
3231
- }
3232
- });
3233
- }
3234
-
3235
- /**
3236
- * Get accounts grouped by platform
3237
- * Returns accounts with balances grouped by financial platform
3238
- * @param data The data for the request.
3239
- * @param data.region Region code for tenant context
3240
- * @param data.groupBy Grouping strategy
3241
- * @param data.date Date for balance calculation (ISO 8601 format)
3242
- * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
3243
- * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
3244
- * @throws ApiError
3245
- */
3246
- public static dashboardControllerGetAccounts(
3247
- data: DashboardControllerGetAccountsData
3248
- ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3249
- return __request(OpenAPI, {
3250
- method: 'GET',
3251
- url: '/api/v1/{region}/dashboard/accounts',
3252
- path: {
3253
- region: data.region
3254
- },
3255
- query: {
3256
- groupBy: data.groupBy,
3257
- date: data.date,
3258
- accountId: data.accountId
3259
- },
3260
- errors: {
3261
- 401: 'User not authenticated'
3262
- }
3263
- });
3264
- }
3265
-
3266
- /**
3267
- * Get cash flow summary
3268
- * Returns income, expenses, and savings for a monthly period
3269
- * @param data The data for the request.
3270
- * @param data.period Period in YYYY-MM format
3271
- * @param data.region Region code for tenant context
3272
- * @returns CashFlowResponseDto Cash flow retrieved successfully
3273
- * @throws ApiError
3274
- */
3275
- public static dashboardControllerGetCashFlow(
3276
- data: DashboardControllerGetCashFlowData
3277
- ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3278
- return __request(OpenAPI, {
3279
- method: 'GET',
3280
- url: '/api/v1/{region}/dashboard/cash-flow',
3281
- path: {
3282
- region: data.region
3283
- },
3284
- query: {
3285
- period: data.period
3286
- },
3287
- errors: {
3288
- 400: 'Invalid period format',
3289
- 401: 'User not authenticated'
3290
- }
3291
- });
3292
- }
3293
-
3294
- /**
3295
- * Get expenses grouped by functional category
3296
- * Returns expenses pre-aggregated by functional category (account-path Group segment) with server-side multi-currency conversion
3297
- * @param data The data for the request.
3298
- * @param data.region Region code for tenant context
3299
- * @param data.groupBy Grouping strategy
3300
- * @param data.period Time window (1m = current calendar month)
3301
- * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3302
- * @throws ApiError
3303
- */
3304
- public static dashboardControllerGetExpenses(
3305
- data: DashboardControllerGetExpensesData
3306
- ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3307
- return __request(OpenAPI, {
3308
- method: 'GET',
3309
- url: '/api/v1/{region}/dashboard/expenses',
3310
- path: {
3311
- region: data.region
3312
- },
3313
- query: {
3314
- groupBy: data.groupBy,
3315
- period: data.period
3316
- },
3317
- errors: {
3318
- 400: 'Invalid groupBy or period',
3319
- 401: 'User not authenticated'
3320
- }
3321
- });
3322
- }
3323
- }
3324
-
3325
- export class InvestmentService {
3697
+ export class BeanPlatformsService {
3326
3698
  /**
3327
- * Get per-holding unrealized + realized P&L
3328
- * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3329
- * @param data The data for the request.
3330
- * @param data.region Region code for tenant context
3331
- * @param data.asOf As-of date (ISO 8601), defaults to today
3332
- * @param data.accountId Scope to a single account
3333
- * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
3334
- * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3699
+ * Get all platforms with statistics
3700
+ * @returns unknown List of platforms with binding and account counts
3335
3701
  * @throws ApiError
3336
3702
  */
3337
- public static holdingPnlControllerGetHoldingPnl(
3338
- data: HoldingPnlControllerGetHoldingPnlData
3339
- ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3703
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
3340
3704
  return __request(OpenAPI, {
3341
3705
  method: 'GET',
3342
- url: '/api/v1/{region}/investment/holdings/pnl',
3343
- path: {
3344
- region: data.region
3345
- },
3346
- query: {
3347
- asOf: data.asOf,
3348
- accountId: data.accountId,
3349
- method: data.method
3350
- },
3351
- errors: {
3352
- 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3353
- 401: 'User not authenticated'
3354
- }
3706
+ url: '/api/v1/bean/platforms'
3355
3707
  });
3356
3708
  }
3357
- }
3358
3709
 
3359
- export class BeanPricesService {
3360
3710
  /**
3361
- * Create a new price
3362
- * Creates a new price entry for the authenticated user
3711
+ * Create a new platform
3363
3712
  * @param data The data for the request.
3364
- * @param data.region Region code for tenant context
3365
3713
  * @param data.requestBody
3366
- * @returns PriceResponseDto Price created successfully
3714
+ * @returns unknown Platform created successfully
3367
3715
  * @throws ApiError
3368
3716
  */
3369
- public static priceControllerCreate(
3370
- data: PriceControllerCreateData
3371
- ): CancelablePromise<PriceControllerCreateResponse> {
3717
+ public static platformControllerCreate(
3718
+ data: PlatformControllerCreateData
3719
+ ): CancelablePromise<PlatformControllerCreateResponse> {
3372
3720
  return __request(OpenAPI, {
3373
3721
  method: 'POST',
3374
- url: '/api/v1/{region}/bean/prices',
3375
- path: {
3376
- region: data.region
3377
- },
3722
+ url: '/api/v1/bean/platforms',
3378
3723
  body: data.requestBody,
3379
3724
  mediaType: 'application/json',
3380
3725
  errors: {
3381
- 404: 'Currency or quoteCurrency commodity not found',
3382
- 409: 'Price already exists for this currency pair and date'
3726
+ 409: 'Platform already exists'
3383
3727
  }
3384
3728
  });
3385
3729
  }
3386
3730
 
3387
3731
  /**
3388
- * List user prices
3389
- * Returns all price entries for the authenticated user with optional filtering
3390
- * @param data The data for the request.
3391
- * @param data.region Region code for tenant context
3392
- * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
3393
- * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
3394
- * @param data.dateFrom Filter prices from this date (ISO 8601 format)
3395
- * @param data.dateTo Filter prices to this date (ISO 8601 format)
3396
- * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
3397
- * @param data.page Page number for pagination (default: 1)
3398
- * @param data.limit Number of items per page (default: 20, max: 100)
3399
- * @returns PriceListResponseDto Prices retrieved successfully
3732
+ * Get platform list for current user
3733
+ * @returns PlatformListItemDto List of platforms with user binding status
3400
3734
  * @throws ApiError
3401
3735
  */
3402
- public static priceControllerFindAll(
3403
- data: PriceControllerFindAllData
3404
- ): CancelablePromise<PriceControllerFindAllResponse> {
3736
+ public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3405
3737
  return __request(OpenAPI, {
3406
3738
  method: 'GET',
3407
- url: '/api/v1/{region}/bean/prices',
3408
- path: {
3409
- region: data.region
3410
- },
3411
- query: {
3412
- currency: data.currency,
3413
- quoteCurrency: data.quoteCurrency,
3414
- dateFrom: data.dateFrom,
3415
- dateTo: data.dateTo,
3416
- search: data.search,
3417
- page: data.page,
3418
- limit: data.limit
3419
- }
3739
+ url: '/api/v1/bean/platforms/list'
3420
3740
  });
3421
3741
  }
3422
3742
 
3423
3743
  /**
3424
- * Get price by ID
3425
- * Returns a single price entry by its ID
3744
+ * Match platforms by name or alias
3426
3745
  * @param data The data for the request.
3427
- * @param data.id Price ID
3428
- * @param data.region Region code for tenant context
3429
- * @returns PriceResponseDto Price retrieved successfully
3746
+ * @param data.q Search query — Chinese name, English name, or abbreviation
3747
+ * @param data.region Region code for category override lookup
3748
+ * @returns PlatformMatchResponseDto Matching platforms with overall match type and truncation flag
3430
3749
  * @throws ApiError
3431
3750
  */
3432
- public static priceControllerFindOne(
3433
- data: PriceControllerFindOneData
3434
- ): CancelablePromise<PriceControllerFindOneResponse> {
3751
+ public static platformControllerMatchPlatforms(
3752
+ data: PlatformControllerMatchPlatformsData
3753
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3435
3754
  return __request(OpenAPI, {
3436
3755
  method: 'GET',
3437
- url: '/api/v1/{region}/bean/prices/{id}',
3438
- path: {
3439
- id: data.id,
3756
+ url: '/api/v1/bean/platforms/match',
3757
+ query: {
3758
+ q: data.q,
3440
3759
  region: data.region
3441
- },
3442
- errors: {
3443
- 404: 'Price not found'
3444
3760
  }
3445
3761
  });
3446
3762
  }
3447
3763
 
3448
3764
  /**
3449
- * Update a price
3450
- * Updates an existing price entry
3765
+ * Update a platform
3451
3766
  * @param data The data for the request.
3452
- * @param data.id Price ID
3453
- * @param data.region Region code for tenant context
3767
+ * @param data.id Platform ID
3454
3768
  * @param data.requestBody
3455
- * @returns PriceResponseDto Price updated successfully
3769
+ * @returns unknown Platform updated successfully
3456
3770
  * @throws ApiError
3457
3771
  */
3458
- public static priceControllerUpdate(
3459
- data: PriceControllerUpdateData
3460
- ): CancelablePromise<PriceControllerUpdateResponse> {
3772
+ public static platformControllerUpdate(
3773
+ data: PlatformControllerUpdateData
3774
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
3461
3775
  return __request(OpenAPI, {
3462
3776
  method: 'PUT',
3463
- url: '/api/v1/{region}/bean/prices/{id}',
3777
+ url: '/api/v1/bean/platforms/{id}',
3464
3778
  path: {
3465
- id: data.id,
3466
- region: data.region
3779
+ id: data.id
3467
3780
  },
3468
3781
  body: data.requestBody,
3469
3782
  mediaType: 'application/json',
3470
3783
  errors: {
3471
- 404: 'Price not found',
3472
- 409: 'Updated price conflicts with existing price'
3784
+ 404: 'Platform not found'
3473
3785
  }
3474
3786
  });
3475
3787
  }
3476
3788
 
3477
3789
  /**
3478
- * Delete a price
3479
- * Deletes a price entry (hard delete)
3790
+ * Delete a platform
3480
3791
  * @param data The data for the request.
3481
- * @param data.id Price ID
3482
- * @param data.region Region code for tenant context
3483
- * @returns void Price deleted successfully
3792
+ * @param data.id Platform ID
3793
+ * @returns void Platform deleted successfully
3484
3794
  * @throws ApiError
3485
3795
  */
3486
- public static priceControllerDelete(
3487
- data: PriceControllerDeleteData
3488
- ): CancelablePromise<PriceControllerDeleteResponse> {
3796
+ public static platformControllerDelete(
3797
+ data: PlatformControllerDeleteData
3798
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
3489
3799
  return __request(OpenAPI, {
3490
3800
  method: 'DELETE',
3491
- url: '/api/v1/{region}/bean/prices/{id}',
3801
+ url: '/api/v1/bean/platforms/{id}',
3492
3802
  path: {
3493
- id: data.id,
3494
- region: data.region
3803
+ id: data.id
3495
3804
  },
3496
3805
  errors: {
3497
- 404: 'Price not found'
3806
+ 404: 'Platform not found'
3498
3807
  }
3499
3808
  });
3500
3809
  }
3810
+ }
3501
3811
 
3812
+ export class DashboardService {
3502
3813
  /**
3503
- * Bulk create prices
3504
- * Creates multiple price entries at once (skips duplicates)
3814
+ * Get net worth overview
3815
+ * Returns total net worth with breakdown of assets and liabilities
3505
3816
  * @param data The data for the request.
3506
3817
  * @param data.region Region code for tenant context
3507
- * @param data.requestBody
3508
- * @returns PriceResponseDto Prices created successfully
3818
+ * @param data.date Date for balance calculation (ISO 8601 format)
3819
+ * @returns NetWorthResponseDto Net worth retrieved successfully
3509
3820
  * @throws ApiError
3510
3821
  */
3511
- public static priceControllerBulkCreate(
3512
- data: PriceControllerBulkCreateData
3513
- ): CancelablePromise<PriceControllerBulkCreateResponse> {
3822
+ public static dashboardControllerGetNetWorth(
3823
+ data: DashboardControllerGetNetWorthData
3824
+ ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3514
3825
  return __request(OpenAPI, {
3515
- method: 'POST',
3516
- url: '/api/v1/{region}/bean/prices/bulk',
3826
+ method: 'GET',
3827
+ url: '/api/v1/{region}/dashboard/net-worth',
3517
3828
  path: {
3518
3829
  region: data.region
3519
3830
  },
3520
- body: data.requestBody,
3521
- mediaType: 'application/json'
3831
+ query: {
3832
+ date: data.date
3833
+ },
3834
+ errors: {
3835
+ 401: 'User not authenticated'
3836
+ }
3522
3837
  });
3523
3838
  }
3524
- }
3525
3839
 
3526
- export class ReportingService {
3527
3840
  /**
3528
- * Get portfolio value trends
3529
- *
3530
- * Returns time series data of portfolio net worth.
3531
- *
3532
- * **Multi-currency Support:**
3533
- * - `series[].byCurrency` - Currency breakdown for each data point
3534
- * - `byCurrency` - Separate time series grouped by currency
3535
- * - `warnings` - Exchange rate warnings if conversion failed
3536
- *
3537
- * **Parameters:**
3538
- * - `period`: Time period (1m, 3m, 6m, 1y)
3539
- * - `granularity`: Data granularity (day, week, month)
3540
- *
3841
+ * Get accounts grouped by platform
3842
+ * Returns accounts with balances grouped by financial platform
3541
3843
  * @param data The data for the request.
3542
3844
  * @param data.region Region code for tenant context
3543
- * @param data.period Time period
3544
- * @param data.granularity Data granularity
3545
- * @returns PortfolioTrendsResponseDto Trends retrieved successfully
3845
+ * @param data.groupBy Grouping strategy
3846
+ * @param data.date Date for balance calculation (ISO 8601 format)
3847
+ * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
3848
+ * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
3546
3849
  * @throws ApiError
3547
3850
  */
3548
- public static reportingControllerGetPortfolioTrends(
3549
- data: ReportingControllerGetPortfolioTrendsData
3550
- ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
3851
+ public static dashboardControllerGetAccounts(
3852
+ data: DashboardControllerGetAccountsData
3853
+ ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3551
3854
  return __request(OpenAPI, {
3552
3855
  method: 'GET',
3553
- url: '/api/v1/{region}/reporting/portfolio/trends',
3856
+ url: '/api/v1/{region}/dashboard/accounts',
3554
3857
  path: {
3555
3858
  region: data.region
3556
3859
  },
3557
3860
  query: {
3558
- period: data.period,
3559
- granularity: data.granularity
3861
+ groupBy: data.groupBy,
3862
+ date: data.date,
3863
+ accountId: data.accountId
3560
3864
  },
3561
3865
  errors: {
3562
3866
  401: 'User not authenticated'
@@ -3565,116 +3869,95 @@ export class ReportingService {
3565
3869
  }
3566
3870
 
3567
3871
  /**
3568
- * Get cash-flow trends
3569
- *
3570
- * Monthly income / expense / netSavings over a fixed N-month window
3571
- * (current month + N−1 prior). Missing months are zero-filled (flow metric).
3572
- *
3573
- * **Parameters:**
3574
- * - `period`: 1m | 3m | 6m | 1y (default 6m)
3575
- * - `granularity`: accepted for API symmetry; v1 returns month buckets
3576
- *
3872
+ * Get cash flow summary
3873
+ * Returns income, expenses, and savings for a monthly period
3577
3874
  * @param data The data for the request.
3875
+ * @param data.period Period in YYYY-MM format
3578
3876
  * @param data.region Region code for tenant context
3579
- * @param data.period Time period
3580
- * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
3581
- * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
3877
+ * @returns CashFlowResponseDto Cash flow retrieved successfully
3582
3878
  * @throws ApiError
3583
3879
  */
3584
- public static reportingControllerGetCashFlowTrends(
3585
- data: ReportingControllerGetCashFlowTrendsData
3586
- ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
3880
+ public static dashboardControllerGetCashFlow(
3881
+ data: DashboardControllerGetCashFlowData
3882
+ ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3587
3883
  return __request(OpenAPI, {
3588
3884
  method: 'GET',
3589
- url: '/api/v1/{region}/reporting/cash-flow/trends',
3885
+ url: '/api/v1/{region}/dashboard/cash-flow',
3590
3886
  path: {
3591
3887
  region: data.region
3592
3888
  },
3593
3889
  query: {
3594
- period: data.period,
3595
- granularity: data.granularity
3890
+ period: data.period
3596
3891
  },
3597
3892
  errors: {
3893
+ 400: 'Invalid period format',
3598
3894
  401: 'User not authenticated'
3599
3895
  }
3600
3896
  });
3601
3897
  }
3602
3898
 
3603
3899
  /**
3604
- * Generate portfolio snapshot
3605
- *
3606
- * Manually generate a portfolio snapshot for a specific date.
3607
- *
3608
- * **Multi-currency Support:**
3609
- * - Fetches balances grouped by currency
3610
- * - Uses user's baseCurrency setting for conversion
3611
- * - Stores exchange rates and warnings
3612
- *
3613
- * **Use Cases:**
3614
- * - Testing snapshot generation
3615
- * - Force regeneration after data correction
3616
- * - Initial setup for new users
3617
- *
3900
+ * Get expenses/income grouped by functional category
3901
+ * 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)
3618
3902
  * @param data The data for the request.
3619
3903
  * @param data.region Region code for tenant context
3620
- * @param data.requestBody Optional date (defaults to today)
3621
- * @returns GenerateSnapshotResponse Snapshot generated successfully
3904
+ * @param data.groupBy Grouping strategy
3905
+ * @param data.period Time window (1m = current calendar month)
3906
+ * @param data.flow Account root to aggregate (expense → ^Expenses:, income → ^Income:)
3907
+ * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3622
3908
  * @throws ApiError
3623
3909
  */
3624
- public static reportingControllerGenerateSnapshot(
3625
- data: ReportingControllerGenerateSnapshotData
3626
- ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
3910
+ public static dashboardControllerGetExpenses(
3911
+ data: DashboardControllerGetExpensesData
3912
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3627
3913
  return __request(OpenAPI, {
3628
- method: 'POST',
3629
- url: '/api/v1/{region}/reporting/snapshots/generate',
3914
+ method: 'GET',
3915
+ url: '/api/v1/{region}/dashboard/expenses',
3630
3916
  path: {
3631
3917
  region: data.region
3632
3918
  },
3633
- body: data.requestBody,
3634
- mediaType: 'application/json',
3919
+ query: {
3920
+ groupBy: data.groupBy,
3921
+ period: data.period,
3922
+ flow: data.flow
3923
+ },
3635
3924
  errors: {
3636
- 400: 'Invalid date format',
3925
+ 400: 'Invalid groupBy or period',
3637
3926
  401: 'User not authenticated'
3638
3927
  }
3639
3928
  });
3640
3929
  }
3930
+ }
3641
3931
 
3932
+ export class InvestmentService {
3642
3933
  /**
3643
- * Backfill portfolio snapshots
3644
- *
3645
- * Generate snapshots for a date range (historical data backfill).
3646
- *
3647
- * **Multi-currency Support:**
3648
- * - Each snapshot includes multi-currency data
3649
- * - Uses exchange rates available at generation time
3650
- * - Warnings stored for missing exchange rates
3651
- *
3652
- * **Best Practices:**
3653
- * - Use for initial setup after account configuration
3654
- * - Run during low-traffic periods for large date ranges
3655
- * - Existing snapshots are skipped (not regenerated)
3656
- *
3934
+ * Get per-holding unrealized + realized P&L
3935
+ * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3657
3936
  * @param data The data for the request.
3658
3937
  * @param data.region Region code for tenant context
3659
- * @param data.requestBody
3660
- * @returns BackfillSnapshotsResponse Backfill completed successfully
3938
+ * @param data.asOf As-of date (ISO 8601), defaults to today
3939
+ * @param data.accountId Scope to a single account
3940
+ * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
3941
+ * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3661
3942
  * @throws ApiError
3662
3943
  */
3663
- public static reportingControllerBackfillSnapshots(
3664
- data: ReportingControllerBackfillSnapshotsData
3665
- ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
3944
+ public static holdingPnlControllerGetHoldingPnl(
3945
+ data: HoldingPnlControllerGetHoldingPnlData
3946
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3666
3947
  return __request(OpenAPI, {
3667
- method: 'POST',
3668
- url: '/api/v1/{region}/reporting/snapshots/backfill',
3948
+ method: 'GET',
3949
+ url: '/api/v1/{region}/investment/holdings/pnl',
3669
3950
  path: {
3670
3951
  region: data.region
3671
3952
  },
3672
- body: data.requestBody,
3673
- mediaType: 'application/json',
3953
+ query: {
3954
+ asOf: data.asOf,
3955
+ accountId: data.accountId,
3956
+ method: data.method
3957
+ },
3674
3958
  errors: {
3675
- 400: 'Invalid date format or range',
3676
- 401: 'User not authenticated',
3677
- 409: 'Backfill already in progress for this user'
3959
+ 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3960
+ 401: 'User not authenticated'
3678
3961
  }
3679
3962
  });
3680
3963
  }
@@ -3703,7 +3986,7 @@ export class AuthService {
3703
3986
  * Anonymous login with access token
3704
3987
  * @param data The data for the request.
3705
3988
  * @param data.requestBody
3706
- * @returns unknown Login successful
3989
+ * @returns AnonymousLoginResponseDto Login successful
3707
3990
  * @throws ApiError
3708
3991
  */
3709
3992
  public static authControllerAccessTokenLogin(
@@ -3890,3 +4173,53 @@ export class InfoService {
3890
4173
  });
3891
4174
  }
3892
4175
  }
4176
+
4177
+ export class MarketDataService {
4178
+ /**
4179
+ * Search market symbols by name or code
4180
+ * Ranked search over the openbb catalog. Empty `q` returns [].
4181
+ * @param data The data for the request.
4182
+ * @param data.q Search term — matched against symbol and instrument name. Empty string returns [].
4183
+ * @param data.limit Maximum number of results (clamped 1..50)
4184
+ * @param data.exchange Filter by exchange code (e.g. US, HK, SS, SZ)
4185
+ * @param data.assetType Filter by OpenBB asset_type (e.g. stock, etf)
4186
+ * @returns SymbolSearchResultDto Ranked search results
4187
+ * @throws ApiError
4188
+ */
4189
+ public static symbolControllerSearch(
4190
+ data: SymbolControllerSearchData
4191
+ ): CancelablePromise<SymbolControllerSearchResponse> {
4192
+ return __request(OpenAPI, {
4193
+ method: 'GET',
4194
+ url: '/api/v1/market/symbols/search',
4195
+ query: {
4196
+ q: data.q,
4197
+ limit: data.limit,
4198
+ exchange: data.exchange,
4199
+ assetType: data.assetType
4200
+ }
4201
+ });
4202
+ }
4203
+
4204
+ /**
4205
+ * Get a market symbol quote
4206
+ * @param data The data for the request.
4207
+ * @param data.symbol
4208
+ * @returns SymbolQuoteDto Symbol quote
4209
+ * @throws ApiError
4210
+ */
4211
+ public static symbolControllerGetQuote(
4212
+ data: SymbolControllerGetQuoteData
4213
+ ): CancelablePromise<SymbolControllerGetQuoteResponse> {
4214
+ return __request(OpenAPI, {
4215
+ method: 'GET',
4216
+ url: '/api/v1/market/symbols/{symbol}/quote',
4217
+ path: {
4218
+ symbol: data.symbol
4219
+ },
4220
+ errors: {
4221
+ 404: 'Symbol not found in the openbb catalog'
4222
+ }
4223
+ });
4224
+ }
4225
+ }