@firela/api-types 0.0.0-canary.830b29d0 → 0.0.0-canary.84b23d91

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