@firela/api-types 0.0.0-canary.2b8fcbd8 → 0.0.0-canary.2e2a26ba

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,
@@ -252,7 +288,11 @@ import type {
252
288
  HealthControllerResetCircuitBreakerData,
253
289
  HealthControllerResetCircuitBreakerResponse,
254
290
  HealthControllerGetMetricsResponse,
255
- InfoControllerGetInfoResponse
291
+ InfoControllerGetInfoResponse,
292
+ SymbolControllerSearchData,
293
+ SymbolControllerSearchResponse,
294
+ SymbolControllerGetQuoteData,
295
+ SymbolControllerGetQuoteResponse
256
296
  } from './types.gen';
257
297
 
258
298
  export class BeanAccountsService {
@@ -290,7 +330,7 @@ export class BeanAccountsService {
290
330
  * @param data.type Filter by account type
291
331
  * @param data.status Filter by status
292
332
  * @param data.isCustom Filter by custom (user-created) accounts only
293
- * @param data.search Search term for path or i18nKey
333
+ * @param data.search Search term for account path
294
334
  * @param data.limit Maximum number of results
295
335
  * @param data.offset Number of results to skip
296
336
  * @returns AccountListResponseDto Accounts retrieved successfully
@@ -452,6 +492,35 @@ export class BeanAccountsService {
452
492
  }
453
493
  });
454
494
  }
495
+
496
+ /**
497
+ * Post an opening-balance transaction
498
+ * Posts a double-entry opening-balance transaction against Equity:Opening-Balances for an existing Assets/Liabilities account. At most one active opening balance per account.
499
+ * @param data The data for the request.
500
+ * @param data.id Account UUID
501
+ * @param data.region Region code for tenant context
502
+ * @param data.requestBody
503
+ * @returns OpeningBalanceResultDto Opening-balance transaction created
504
+ * @throws ApiError
505
+ */
506
+ public static accountControllerAddOpeningBalance(
507
+ data: AccountControllerAddOpeningBalanceData
508
+ ): CancelablePromise<AccountControllerAddOpeningBalanceResponse> {
509
+ return __request(OpenAPI, {
510
+ method: 'POST',
511
+ url: '/api/v1/{region}/bean/accounts/{id}/opening-balance',
512
+ path: {
513
+ id: data.id,
514
+ region: data.region
515
+ },
516
+ body: data.requestBody,
517
+ mediaType: 'application/json',
518
+ errors: {
519
+ 404: 'Account not found',
520
+ 409: 'An opening balance already exists for this account'
521
+ }
522
+ });
523
+ }
455
524
  }
456
525
 
457
526
  export class BeanAccountStandardsService {
@@ -483,7 +552,7 @@ export class BeanAccountStandardsService {
483
552
 
484
553
  /**
485
554
  * Get template metadata for an account path
486
- * Returns extendable status and root type for a template path.
555
+ * Returns root type for a template path.
487
556
  * @param data The data for the request.
488
557
  * @param data.region Region code for tenant context
489
558
  * @param data.path Account path to check
@@ -569,6 +638,7 @@ export class BeanTransactionsService {
569
638
  * @param data.status Filter by transaction status
570
639
  * @param data.search Search in narration and payee fields (max 200 chars)
571
640
  * @param data.accountId Filter by account ID (transactions with postings to this account)
641
+ * @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
642
  * @returns TransactionListResponseDto Transaction list
573
643
  * @throws ApiError
574
644
  */
@@ -588,7 +658,8 @@ export class BeanTransactionsService {
588
658
  dateTo: data.dateTo,
589
659
  status: data.status,
590
660
  search: data.search,
591
- accountId: data.accountId
661
+ accountId: data.accountId,
662
+ category: data.category
592
663
  },
593
664
  errors: {
594
665
  400: 'Validation failed',
@@ -776,7 +847,7 @@ export class BeanBalancesService {
776
847
  * Query account balance
777
848
  * Calculate account balance at a specific date for a single currency
778
849
  * @param data The data for the request.
779
- * @param data.account Account name (e.g., "Assets:Bank:Checking")
850
+ * @param data.account Account name (e.g., "Assets:Checking")
780
851
  * @param data.region Region code for tenant context
781
852
  * @param data.date Date to calculate balance at (ISO 8601 format)
782
853
  * @param data.currency Currency to query (e.g., "USD", "CNY")
@@ -1497,155 +1568,322 @@ export class BeanCommoditiesService {
1497
1568
  }
1498
1569
  }
1499
1570
 
1500
- export class RecurringRulesService {
1571
+ export class BeanPricesService {
1501
1572
  /**
1502
- * Create a new recurring rule
1503
- * Creates a new recurring transaction rule for the authenticated user
1573
+ * Create a new price
1574
+ * Creates a new price entry for the authenticated user
1504
1575
  * @param data The data for the request.
1505
1576
  * @param data.region Region code for tenant context
1506
1577
  * @param data.requestBody
1507
- * @returns RecurringRuleResponseDto Rule created successfully
1578
+ * @returns PriceResponseDto Price created successfully
1508
1579
  * @throws ApiError
1509
1580
  */
1510
- public static recurringRuleControllerCreate(
1511
- data: RecurringRuleControllerCreateData
1512
- ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1581
+ public static priceControllerCreate(
1582
+ data: PriceControllerCreateData
1583
+ ): CancelablePromise<PriceControllerCreateResponse> {
1513
1584
  return __request(OpenAPI, {
1514
1585
  method: 'POST',
1515
- url: '/api/v1/{region}/bean/recurring-rules',
1586
+ url: '/api/v1/{region}/bean/prices',
1516
1587
  path: {
1517
1588
  region: data.region
1518
1589
  },
1519
1590
  body: data.requestBody,
1520
1591
  mediaType: 'application/json',
1521
1592
  errors: {
1522
- 400: 'Invalid input data (e.g., autoCreate without accounts)',
1523
- 409: 'Rule with same name already exists'
1593
+ 404: 'Currency or quoteCurrency commodity not found',
1594
+ 409: 'Price already exists for this currency pair and date'
1524
1595
  }
1525
1596
  });
1526
1597
  }
1527
1598
 
1528
1599
  /**
1529
- * List recurring rules
1530
- * Returns all recurring rules for the authenticated user with optional filtering
1600
+ * List user prices
1601
+ * Returns all price entries for the authenticated user with optional filtering
1531
1602
  * @param data The data for the request.
1532
1603
  * @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
1604
+ * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
1605
+ * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
1606
+ * @param data.dateFrom Filter prices from this date (ISO 8601 format)
1607
+ * @param data.dateTo Filter prices to this date (ISO 8601 format)
1608
+ * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
1609
+ * @param data.page Page number for pagination (default: 1)
1610
+ * @param data.limit Number of items per page (default: 20, max: 100)
1611
+ * @returns PriceListResponseDto Prices retrieved successfully
1537
1612
  * @throws ApiError
1538
1613
  */
1539
- public static recurringRuleControllerFindAll(
1540
- data: RecurringRuleControllerFindAllData
1541
- ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1614
+ public static priceControllerFindAll(
1615
+ data: PriceControllerFindAllData
1616
+ ): CancelablePromise<PriceControllerFindAllResponse> {
1542
1617
  return __request(OpenAPI, {
1543
1618
  method: 'GET',
1544
- url: '/api/v1/{region}/bean/recurring-rules',
1619
+ url: '/api/v1/{region}/bean/prices',
1545
1620
  path: {
1546
1621
  region: data.region
1547
1622
  },
1548
1623
  query: {
1549
- isActive: data.isActive,
1550
- frequency: data.frequency,
1551
- hasAutoCreate: data.hasAutoCreate
1624
+ currency: data.currency,
1625
+ quoteCurrency: data.quoteCurrency,
1626
+ dateFrom: data.dateFrom,
1627
+ dateTo: data.dateTo,
1628
+ search: data.search,
1629
+ page: data.page,
1630
+ limit: data.limit
1552
1631
  }
1553
1632
  });
1554
1633
  }
1555
1634
 
1556
1635
  /**
1557
- * Create recurring rule from transaction
1558
- * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1636
+ * Get price by ID
1637
+ * Returns a single price entry by its ID
1559
1638
  * @param data The data for the request.
1560
- * @param data.transactionId Source transaction ID
1639
+ * @param data.id Price ID
1561
1640
  * @param data.region Region code for tenant context
1562
- * @param data.requestBody
1563
- * @returns RecurringRuleResponseDto Rule created successfully
1641
+ * @returns PriceResponseDto Price retrieved successfully
1564
1642
  * @throws ApiError
1565
1643
  */
1566
- public static recurringRuleControllerCreateFromTransaction(
1567
- data: RecurringRuleControllerCreateFromTransactionData
1568
- ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1644
+ public static priceControllerFindOne(
1645
+ data: PriceControllerFindOneData
1646
+ ): CancelablePromise<PriceControllerFindOneResponse> {
1569
1647
  return __request(OpenAPI, {
1570
- method: 'POST',
1571
- url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1648
+ method: 'GET',
1649
+ url: '/api/v1/{region}/bean/prices/{id}',
1572
1650
  path: {
1573
- transactionId: data.transactionId,
1651
+ id: data.id,
1574
1652
  region: data.region
1575
1653
  },
1576
- body: data.requestBody,
1577
- mediaType: 'application/json',
1578
1654
  errors: {
1579
- 404: 'Transaction not found',
1580
- 409: 'Rule with same name already exists or transaction already linked'
1655
+ 404: 'Price not found'
1581
1656
  }
1582
1657
  });
1583
1658
  }
1584
1659
 
1585
1660
  /**
1586
- * Get recurring rule by ID
1587
- * Returns a specific recurring rule with its details
1661
+ * Update a price
1662
+ * Updates an existing price entry
1588
1663
  * @param data The data for the request.
1589
- * @param data.id Rule ID
1664
+ * @param data.id Price ID
1590
1665
  * @param data.region Region code for tenant context
1591
- * @returns RecurringRuleResponseDto Rule retrieved successfully
1666
+ * @param data.requestBody
1667
+ * @returns PriceResponseDto Price updated successfully
1592
1668
  * @throws ApiError
1593
1669
  */
1594
- public static recurringRuleControllerFindOne(
1595
- data: RecurringRuleControllerFindOneData
1596
- ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1670
+ public static priceControllerUpdate(
1671
+ data: PriceControllerUpdateData
1672
+ ): CancelablePromise<PriceControllerUpdateResponse> {
1597
1673
  return __request(OpenAPI, {
1598
- method: 'GET',
1599
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1674
+ method: 'PUT',
1675
+ url: '/api/v1/{region}/bean/prices/{id}',
1600
1676
  path: {
1601
1677
  id: data.id,
1602
1678
  region: data.region
1603
1679
  },
1680
+ body: data.requestBody,
1681
+ mediaType: 'application/json',
1604
1682
  errors: {
1605
- 404: 'Rule not found'
1683
+ 404: 'Price not found',
1684
+ 409: 'Updated price conflicts with existing price'
1606
1685
  }
1607
1686
  });
1608
1687
  }
1609
1688
 
1610
1689
  /**
1611
- * Update recurring rule
1612
- * Updates an existing recurring rule
1690
+ * Delete a price
1691
+ * Deletes a price entry (hard delete)
1613
1692
  * @param data The data for the request.
1614
- * @param data.id Rule ID
1693
+ * @param data.id Price ID
1615
1694
  * @param data.region Region code for tenant context
1616
- * @param data.requestBody
1617
- * @returns RecurringRuleResponseDto Rule updated successfully
1695
+ * @returns void Price deleted successfully
1618
1696
  * @throws ApiError
1619
1697
  */
1620
- public static recurringRuleControllerUpdate(
1621
- data: RecurringRuleControllerUpdateData
1622
- ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1698
+ public static priceControllerDelete(
1699
+ data: PriceControllerDeleteData
1700
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1623
1701
  return __request(OpenAPI, {
1624
- method: 'PATCH',
1625
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1702
+ method: 'DELETE',
1703
+ url: '/api/v1/{region}/bean/prices/{id}',
1626
1704
  path: {
1627
1705
  id: data.id,
1628
1706
  region: data.region
1629
1707
  },
1630
- body: data.requestBody,
1631
- mediaType: 'application/json',
1632
1708
  errors: {
1633
- 400: 'Invalid input data',
1634
- 404: 'Rule not found'
1709
+ 404: 'Price not found'
1635
1710
  }
1636
1711
  });
1637
1712
  }
1638
1713
 
1639
1714
  /**
1640
- * Delete recurring rule
1641
- * Soft deletes a recurring rule (sets isActive to false)
1715
+ * Bulk create prices
1716
+ * Creates multiple price entries at once (skips duplicates)
1642
1717
  * @param data The data for the request.
1643
- * @param data.id Rule ID
1644
1718
  * @param data.region Region code for tenant context
1645
- * @returns void Rule deleted successfully
1719
+ * @param data.requestBody
1720
+ * @returns PriceResponseDto Prices created successfully
1646
1721
  * @throws ApiError
1647
1722
  */
1648
- public static recurringRuleControllerDelete(
1723
+ public static priceControllerBulkCreate(
1724
+ data: PriceControllerBulkCreateData
1725
+ ): CancelablePromise<PriceControllerBulkCreateResponse> {
1726
+ return __request(OpenAPI, {
1727
+ method: 'POST',
1728
+ url: '/api/v1/{region}/bean/prices/bulk',
1729
+ path: {
1730
+ region: data.region
1731
+ },
1732
+ body: data.requestBody,
1733
+ mediaType: 'application/json'
1734
+ });
1735
+ }
1736
+ }
1737
+
1738
+ export class RecurringRulesService {
1739
+ /**
1740
+ * Create a new recurring rule
1741
+ * Creates a new recurring transaction rule for the authenticated user
1742
+ * @param data The data for the request.
1743
+ * @param data.region Region code for tenant context
1744
+ * @param data.requestBody
1745
+ * @returns RecurringRuleResponseDto Rule created successfully
1746
+ * @throws ApiError
1747
+ */
1748
+ public static recurringRuleControllerCreate(
1749
+ data: RecurringRuleControllerCreateData
1750
+ ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1751
+ return __request(OpenAPI, {
1752
+ method: 'POST',
1753
+ url: '/api/v1/{region}/bean/recurring-rules',
1754
+ path: {
1755
+ region: data.region
1756
+ },
1757
+ body: data.requestBody,
1758
+ mediaType: 'application/json',
1759
+ errors: {
1760
+ 400: 'Invalid input data (e.g., autoCreate without accounts)',
1761
+ 409: 'Rule with same name already exists'
1762
+ }
1763
+ });
1764
+ }
1765
+
1766
+ /**
1767
+ * List recurring rules
1768
+ * Returns all recurring rules for the authenticated user with optional filtering
1769
+ * @param data The data for the request.
1770
+ * @param data.region Region code for tenant context
1771
+ * @param data.isActive Filter by active status
1772
+ * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
1773
+ * @param data.hasAutoCreate Filter by autoCreate enabled
1774
+ * @returns RecurringRuleResponseDto Rules retrieved successfully
1775
+ * @throws ApiError
1776
+ */
1777
+ public static recurringRuleControllerFindAll(
1778
+ data: RecurringRuleControllerFindAllData
1779
+ ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1780
+ return __request(OpenAPI, {
1781
+ method: 'GET',
1782
+ url: '/api/v1/{region}/bean/recurring-rules',
1783
+ path: {
1784
+ region: data.region
1785
+ },
1786
+ query: {
1787
+ isActive: data.isActive,
1788
+ frequency: data.frequency,
1789
+ hasAutoCreate: data.hasAutoCreate
1790
+ }
1791
+ });
1792
+ }
1793
+
1794
+ /**
1795
+ * Create recurring rule from transaction
1796
+ * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1797
+ * @param data The data for the request.
1798
+ * @param data.transactionId Source transaction ID
1799
+ * @param data.region Region code for tenant context
1800
+ * @param data.requestBody
1801
+ * @returns RecurringRuleResponseDto Rule created successfully
1802
+ * @throws ApiError
1803
+ */
1804
+ public static recurringRuleControllerCreateFromTransaction(
1805
+ data: RecurringRuleControllerCreateFromTransactionData
1806
+ ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1807
+ return __request(OpenAPI, {
1808
+ method: 'POST',
1809
+ url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1810
+ path: {
1811
+ transactionId: data.transactionId,
1812
+ region: data.region
1813
+ },
1814
+ body: data.requestBody,
1815
+ mediaType: 'application/json',
1816
+ errors: {
1817
+ 404: 'Transaction not found',
1818
+ 409: 'Rule with same name already exists or transaction already linked'
1819
+ }
1820
+ });
1821
+ }
1822
+
1823
+ /**
1824
+ * Get recurring rule by ID
1825
+ * Returns a specific recurring rule with its details
1826
+ * @param data The data for the request.
1827
+ * @param data.id Rule ID
1828
+ * @param data.region Region code for tenant context
1829
+ * @returns RecurringRuleResponseDto Rule retrieved successfully
1830
+ * @throws ApiError
1831
+ */
1832
+ public static recurringRuleControllerFindOne(
1833
+ data: RecurringRuleControllerFindOneData
1834
+ ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1835
+ return __request(OpenAPI, {
1836
+ method: 'GET',
1837
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
1838
+ path: {
1839
+ id: data.id,
1840
+ region: data.region
1841
+ },
1842
+ errors: {
1843
+ 404: 'Rule not found'
1844
+ }
1845
+ });
1846
+ }
1847
+
1848
+ /**
1849
+ * Update recurring rule
1850
+ * Updates an existing recurring rule
1851
+ * @param data The data for the request.
1852
+ * @param data.id Rule ID
1853
+ * @param data.region Region code for tenant context
1854
+ * @param data.requestBody
1855
+ * @returns RecurringRuleResponseDto Rule updated successfully
1856
+ * @throws ApiError
1857
+ */
1858
+ public static recurringRuleControllerUpdate(
1859
+ data: RecurringRuleControllerUpdateData
1860
+ ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1861
+ return __request(OpenAPI, {
1862
+ method: 'PATCH',
1863
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
1864
+ path: {
1865
+ id: data.id,
1866
+ region: data.region
1867
+ },
1868
+ body: data.requestBody,
1869
+ mediaType: 'application/json',
1870
+ errors: {
1871
+ 400: 'Invalid input data',
1872
+ 404: 'Rule not found'
1873
+ }
1874
+ });
1875
+ }
1876
+
1877
+ /**
1878
+ * Delete recurring rule
1879
+ * Soft deletes a recurring rule (sets isActive to false)
1880
+ * @param data The data for the request.
1881
+ * @param data.id Rule ID
1882
+ * @param data.region Region code for tenant context
1883
+ * @returns void Rule deleted successfully
1884
+ * @throws ApiError
1885
+ */
1886
+ public static recurringRuleControllerDelete(
1649
1887
  data: RecurringRuleControllerDeleteData
1650
1888
  ): CancelablePromise<RecurringRuleControllerDeleteResponse> {
1651
1889
  return __request(OpenAPI, {
@@ -1927,279 +2165,158 @@ export class RecurringForecastService {
1927
2165
  }
1928
2166
  }
1929
2167
 
1930
- export class BeanTransactionRulesService {
2168
+ export class ReportingService {
1931
2169
  /**
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.
2170
+ * Get portfolio value trends
2171
+ *
2172
+ * Returns time series data of portfolio net worth.
2173
+ *
2174
+ * **Multi-currency Support:**
2175
+ * - `series[].byCurrency` - Currency breakdown for each data point
2176
+ * - `byCurrency` - Separate time series grouped by currency
2177
+ * - `warnings` - Exchange rate warnings if conversion failed
2178
+ *
2179
+ * **Parameters:**
2180
+ * - `period`: Time period (1m, 3m, 6m, 1y)
2181
+ * - `granularity`: Data granularity (day, week, month)
2182
+ *
1934
2183
  * @param data The data for the request.
1935
2184
  * @param data.region Region code for tenant context
1936
- * @param data.requestBody
1937
- * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2185
+ * @param data.period Time period
2186
+ * @param data.granularity Data granularity
2187
+ * @returns PortfolioTrendsResponseDto Trends retrieved successfully
1938
2188
  * @throws ApiError
1939
2189
  */
1940
- public static transactionRuleControllerCreate(
1941
- data: TransactionRuleControllerCreateData
1942
- ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2190
+ public static reportingControllerGetPortfolioTrends(
2191
+ data: ReportingControllerGetPortfolioTrendsData
2192
+ ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
1943
2193
  return __request(OpenAPI, {
1944
- method: 'POST',
1945
- url: '/api/v1/{region}/bean/transaction-rules',
2194
+ method: 'GET',
2195
+ url: '/api/v1/{region}/reporting/portfolio/trends',
1946
2196
  path: {
1947
2197
  region: data.region
1948
2198
  },
1949
- body: data.requestBody,
1950
- mediaType: 'application/json',
2199
+ query: {
2200
+ period: data.period,
2201
+ granularity: data.granularity
2202
+ },
1951
2203
  errors: {
1952
- 400: 'Validation failed',
1953
- 401: 'Unauthorized',
1954
- 409: 'Resource conflict - another process is updating this rule'
2204
+ 401: 'User not authenticated'
1955
2205
  }
1956
2206
  });
1957
2207
  }
1958
2208
 
1959
2209
  /**
1960
- * Get all transaction rules for user
2210
+ * Get cash-flow trends
2211
+ *
2212
+ * Monthly income / expense / netSavings over a fixed N-month window
2213
+ * (current month + N−1 prior). Missing months are zero-filled (flow metric).
2214
+ *
2215
+ * **Parameters:**
2216
+ * - `period`: 1m | 3m | 6m | 1y (default 6m)
2217
+ * - `granularity`: accepted for API symmetry; v1 returns month buckets
2218
+ *
1961
2219
  * @param data The data for the request.
1962
2220
  * @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
2221
+ * @param data.period Time period
2222
+ * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
2223
+ * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
1969
2224
  * @throws ApiError
1970
2225
  */
1971
- public static transactionRuleControllerList(
1972
- data: TransactionRuleControllerListData
1973
- ): CancelablePromise<TransactionRuleControllerListResponse> {
2226
+ public static reportingControllerGetCashFlowTrends(
2227
+ data: ReportingControllerGetCashFlowTrendsData
2228
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
1974
2229
  return __request(OpenAPI, {
1975
2230
  method: 'GET',
1976
- url: '/api/v1/{region}/bean/transaction-rules',
2231
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
1977
2232
  path: {
1978
2233
  region: data.region
1979
2234
  },
1980
2235
  query: {
1981
- limit: data.limit,
1982
- offset: data.offset,
1983
- enabled: data.enabled,
1984
- learningSource: data.learningSource,
1985
- autoApplyEnabled: data.autoApplyEnabled
2236
+ period: data.period,
2237
+ granularity: data.granularity
1986
2238
  },
1987
2239
  errors: {
1988
- 401: 'Unauthorized'
2240
+ 401: 'User not authenticated'
1989
2241
  }
1990
2242
  });
1991
2243
  }
1992
2244
 
1993
2245
  /**
1994
- * Validate transaction rule configuration
2246
+ * Generate portfolio snapshot
2247
+ *
2248
+ * Manually generate a portfolio snapshot for a specific date.
2249
+ *
2250
+ * **Multi-currency Support:**
2251
+ * - Fetches balances grouped by currency
2252
+ * - Uses user's baseCurrency setting for conversion
2253
+ * - Stores exchange rates and warnings
2254
+ *
2255
+ * **Use Cases:**
2256
+ * - Testing snapshot generation
2257
+ * - Force regeneration after data correction
2258
+ * - Initial setup for new users
2259
+ *
1995
2260
  * @param data The data for the request.
1996
2261
  * @param data.region Region code for tenant context
1997
- * @param data.requestBody
1998
- * @returns ValidateRuleResponseDto Validation result
2262
+ * @param data.requestBody Optional date (defaults to today)
2263
+ * @returns GenerateSnapshotResponse Snapshot generated successfully
1999
2264
  * @throws ApiError
2000
2265
  */
2001
- public static transactionRuleControllerValidate(
2002
- data: TransactionRuleControllerValidateData
2003
- ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2266
+ public static reportingControllerGenerateSnapshot(
2267
+ data: ReportingControllerGenerateSnapshotData
2268
+ ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
2004
2269
  return __request(OpenAPI, {
2005
2270
  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}',
2271
+ url: '/api/v1/{region}/reporting/snapshots/generate',
2135
2272
  path: {
2136
- ruleId: data.ruleId,
2137
2273
  region: data.region
2138
2274
  },
2139
2275
  body: data.requestBody,
2140
2276
  mediaType: 'application/json',
2141
2277
  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'
2278
+ 400: 'Invalid date format',
2279
+ 401: 'User not authenticated'
2174
2280
  }
2175
2281
  });
2176
2282
  }
2177
2283
 
2178
2284
  /**
2179
- * Test rule matching
2285
+ * Backfill portfolio snapshots
2286
+ *
2287
+ * Generate snapshots for a date range (historical data backfill).
2288
+ *
2289
+ * **Multi-currency Support:**
2290
+ * - Each snapshot includes multi-currency data
2291
+ * - Uses exchange rates available at generation time
2292
+ * - Warnings stored for missing exchange rates
2293
+ *
2294
+ * **Best Practices:**
2295
+ * - Use for initial setup after account configuration
2296
+ * - Run during low-traffic periods for large date ranges
2297
+ * - Existing snapshots are skipped (not regenerated)
2298
+ *
2180
2299
  * @param data The data for the request.
2181
- * @param data.ruleId Rule ID to test
2182
2300
  * @param data.region Region code for tenant context
2183
2301
  * @param data.requestBody
2184
- * @returns TestRuleResponseDto Test result
2302
+ * @returns BackfillSnapshotsResponse Backfill completed successfully
2185
2303
  * @throws ApiError
2186
2304
  */
2187
- public static transactionRuleControllerTest(
2188
- data: TransactionRuleControllerTestData
2189
- ): CancelablePromise<TransactionRuleControllerTestResponse> {
2305
+ public static reportingControllerBackfillSnapshots(
2306
+ data: ReportingControllerBackfillSnapshotsData
2307
+ ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
2190
2308
  return __request(OpenAPI, {
2191
2309
  method: 'POST',
2192
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2310
+ url: '/api/v1/{region}/reporting/snapshots/backfill',
2193
2311
  path: {
2194
- ruleId: data.ruleId,
2195
2312
  region: data.region
2196
2313
  },
2197
2314
  body: data.requestBody,
2198
2315
  mediaType: 'application/json',
2199
2316
  errors: {
2200
- 401: 'Unauthorized',
2201
- 403: 'Forbidden - not owner of rule',
2202
- 404: 'Rule not found'
2317
+ 400: 'Invalid date format or range',
2318
+ 401: 'User not authenticated',
2319
+ 409: 'Backfill already in progress for this user'
2203
2320
  }
2204
2321
  });
2205
2322
  }
@@ -2251,7 +2368,7 @@ export class UsersService {
2251
2368
  * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
2252
2369
  * @param data The data for the request.
2253
2370
  * @param data.requestBody
2254
- * @returns unknown User created successfully
2371
+ * @returns SignupResponseDto User created successfully
2255
2372
  * @throws ApiError
2256
2373
  */
2257
2374
  public static userControllerSignupUser(
@@ -2460,294 +2577,765 @@ export class PropertiesService {
2460
2577
  }
2461
2578
  }
2462
2579
 
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 {
2580
+ export class BeanTransactionRulesService {
2479
2581
  /**
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).
2582
+ * Create a new transaction rule (or upsert if upsertByPayee=true)
2583
+ * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2482
2584
  * @param data The data for the request.
2483
2585
  * @param data.region Region code for tenant context
2484
- * @param data.formData Bill file to import
2485
- * @returns ImportResultDto File imported successfully
2586
+ * @param data.requestBody
2587
+ * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2486
2588
  * @throws ApiError
2487
2589
  */
2488
- public static fileImportControllerImportFile(
2489
- data: FileImportControllerImportFileData
2490
- ): CancelablePromise<FileImportControllerImportFileResponse> {
2590
+ public static transactionRuleControllerCreate(
2591
+ data: TransactionRuleControllerCreateData
2592
+ ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2491
2593
  return __request(OpenAPI, {
2492
2594
  method: 'POST',
2493
- url: '/api/v1/{region}/bean/import/file',
2595
+ url: '/api/v1/{region}/bean/transaction-rules',
2494
2596
  path: {
2495
2597
  region: data.region
2496
2598
  },
2497
- formData: data.formData,
2498
- mediaType: 'multipart/form-data',
2599
+ body: data.requestBody,
2600
+ mediaType: 'application/json',
2499
2601
  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'
2602
+ 400: 'Validation failed',
2603
+ 401: 'Unauthorized',
2604
+ 409: 'Resource conflict - another process is updating this rule'
2504
2605
  }
2505
2606
  });
2506
2607
  }
2507
2608
 
2508
2609
  /**
2509
- * 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.
2610
+ * Get all transaction rules for user
2511
2611
  * @param data The data for the request.
2512
2612
  * @param data.region Region code for tenant context
2513
- * @param data.formData File to identify
2514
- * @returns IdentifyResultDto File identification result
2613
+ * @param data.limit Max results per page (default: 20, max: 100)
2614
+ * @param data.offset Pagination offset (default: 0)
2615
+ * @param data.enabled Filter by enabled status
2616
+ * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
2617
+ * @param data.autoApplyEnabled Filter by auto-apply status
2618
+ * @returns TransactionRuleListResponseDto List of rules
2515
2619
  * @throws ApiError
2516
2620
  */
2517
- public static fileImportControllerIdentifyFile(
2518
- data: FileImportControllerIdentifyFileData
2519
- ): CancelablePromise<FileImportControllerIdentifyFileResponse> {
2621
+ public static transactionRuleControllerList(
2622
+ data: TransactionRuleControllerListData
2623
+ ): CancelablePromise<TransactionRuleControllerListResponse> {
2624
+ return __request(OpenAPI, {
2625
+ method: 'GET',
2626
+ url: '/api/v1/{region}/bean/transaction-rules',
2627
+ path: {
2628
+ region: data.region
2629
+ },
2630
+ query: {
2631
+ limit: data.limit,
2632
+ offset: data.offset,
2633
+ enabled: data.enabled,
2634
+ learningSource: data.learningSource,
2635
+ autoApplyEnabled: data.autoApplyEnabled
2636
+ },
2637
+ errors: {
2638
+ 401: 'Unauthorized'
2639
+ }
2640
+ });
2641
+ }
2642
+
2643
+ /**
2644
+ * Validate transaction rule configuration
2645
+ * @param data The data for the request.
2646
+ * @param data.region Region code for tenant context
2647
+ * @param data.requestBody
2648
+ * @returns ValidateRuleResponseDto Validation result
2649
+ * @throws ApiError
2650
+ */
2651
+ public static transactionRuleControllerValidate(
2652
+ data: TransactionRuleControllerValidateData
2653
+ ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2520
2654
  return __request(OpenAPI, {
2521
2655
  method: 'POST',
2522
- url: '/api/v1/{region}/bean/import/identify',
2656
+ url: '/api/v1/{region}/bean/transaction-rules/validate',
2657
+ path: {
2658
+ region: data.region
2659
+ },
2660
+ body: data.requestBody,
2661
+ mediaType: 'application/json',
2662
+ errors: {
2663
+ 400: 'Validation failed',
2664
+ 401: 'Unauthorized'
2665
+ }
2666
+ });
2667
+ }
2668
+
2669
+ /**
2670
+ * Bulk create transaction rules
2671
+ * @param data The data for the request.
2672
+ * @param data.region Region code for tenant context
2673
+ * @param data.requestBody
2674
+ * @returns BulkCreateRulesResponseDto Bulk create completed
2675
+ * @throws ApiError
2676
+ */
2677
+ public static transactionRuleControllerBulkCreate(
2678
+ data: TransactionRuleControllerBulkCreateData
2679
+ ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2680
+ return __request(OpenAPI, {
2681
+ method: 'POST',
2682
+ url: '/api/v1/{region}/bean/transaction-rules/bulk',
2683
+ path: {
2684
+ region: data.region
2685
+ },
2686
+ body: data.requestBody,
2687
+ mediaType: 'application/json',
2688
+ errors: {
2689
+ 400: 'Invalid bulk create data',
2690
+ 401: 'Unauthorized'
2691
+ }
2692
+ });
2693
+ }
2694
+
2695
+ /**
2696
+ * Export transaction rules
2697
+ * @param data The data for the request.
2698
+ * @param data.format Export format (currently only JSON supported)
2699
+ * @param data.region Region code for tenant context
2700
+ * @returns ExportRulesResponseDto Exported rules
2701
+ * @throws ApiError
2702
+ */
2703
+ public static transactionRuleControllerExport(
2704
+ data: TransactionRuleControllerExportData
2705
+ ): CancelablePromise<TransactionRuleControllerExportResponse> {
2706
+ return __request(OpenAPI, {
2707
+ method: 'GET',
2708
+ url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2709
+ path: {
2710
+ format: data.format,
2711
+ region: data.region
2712
+ },
2713
+ errors: {
2714
+ 400: 'Unsupported format',
2715
+ 401: 'Unauthorized'
2716
+ }
2717
+ });
2718
+ }
2719
+
2720
+ /**
2721
+ * Get transaction rule statistics
2722
+ * @param data The data for the request.
2723
+ * @param data.period Statistics time period
2724
+ * @param data.region Region code for tenant context
2725
+ * @returns RuleStatisticsResponseDto Rule statistics
2726
+ * @throws ApiError
2727
+ */
2728
+ public static transactionRuleControllerGetStatistics(
2729
+ data: TransactionRuleControllerGetStatisticsData
2730
+ ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2731
+ return __request(OpenAPI, {
2732
+ method: 'GET',
2733
+ url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2734
+ path: {
2735
+ period: data.period,
2736
+ region: data.region
2737
+ },
2738
+ errors: {
2739
+ 401: 'Unauthorized'
2740
+ }
2741
+ });
2742
+ }
2743
+
2744
+ /**
2745
+ * Get transaction rule detail
2746
+ * @param data The data for the request.
2747
+ * @param data.ruleId Rule ID
2748
+ * @param data.region Region code for tenant context
2749
+ * @returns TransactionRuleResponseDto Rule details
2750
+ * @throws ApiError
2751
+ */
2752
+ public static transactionRuleControllerGetDetail(
2753
+ data: TransactionRuleControllerGetDetailData
2754
+ ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2755
+ return __request(OpenAPI, {
2756
+ method: 'GET',
2757
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2758
+ path: {
2759
+ ruleId: data.ruleId,
2760
+ region: data.region
2761
+ },
2762
+ errors: {
2763
+ 401: 'Unauthorized',
2764
+ 403: 'Forbidden - not owner of rule',
2765
+ 404: 'Rule not found'
2766
+ }
2767
+ });
2768
+ }
2769
+
2770
+ /**
2771
+ * Update a transaction rule
2772
+ * @param data The data for the request.
2773
+ * @param data.ruleId Rule ID to update
2774
+ * @param data.region Region code for tenant context
2775
+ * @param data.requestBody
2776
+ * @returns TransactionRuleResponseDto Rule updated successfully
2777
+ * @throws ApiError
2778
+ */
2779
+ public static transactionRuleControllerUpdate(
2780
+ data: TransactionRuleControllerUpdateData
2781
+ ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2782
+ return __request(OpenAPI, {
2783
+ method: 'PUT',
2784
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2785
+ path: {
2786
+ ruleId: data.ruleId,
2787
+ region: data.region
2788
+ },
2789
+ body: data.requestBody,
2790
+ mediaType: 'application/json',
2791
+ errors: {
2792
+ 400: 'Validation failed',
2793
+ 401: 'Unauthorized',
2794
+ 403: 'Forbidden - not owner of rule',
2795
+ 404: 'Rule not found',
2796
+ 409: 'Resource conflict - rule is being modified by another process'
2797
+ }
2798
+ });
2799
+ }
2800
+
2801
+ /**
2802
+ * Delete a transaction rule
2803
+ * @param data The data for the request.
2804
+ * @param data.ruleId Rule ID to delete
2805
+ * @param data.region Region code for tenant context
2806
+ * @returns void Rule deleted successfully
2807
+ * @throws ApiError
2808
+ */
2809
+ public static transactionRuleControllerDelete(
2810
+ data: TransactionRuleControllerDeleteData
2811
+ ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2812
+ return __request(OpenAPI, {
2813
+ method: 'DELETE',
2814
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2815
+ path: {
2816
+ ruleId: data.ruleId,
2817
+ region: data.region
2818
+ },
2819
+ errors: {
2820
+ 401: 'Unauthorized',
2821
+ 403: 'Forbidden - not owner of rule',
2822
+ 404: 'Rule not found',
2823
+ 409: 'Resource conflict - rule is being modified by another process'
2824
+ }
2825
+ });
2826
+ }
2827
+
2828
+ /**
2829
+ * Test rule matching
2830
+ * @param data The data for the request.
2831
+ * @param data.ruleId Rule ID to test
2832
+ * @param data.region Region code for tenant context
2833
+ * @param data.requestBody
2834
+ * @returns TestRuleResponseDto Test result
2835
+ * @throws ApiError
2836
+ */
2837
+ public static transactionRuleControllerTest(
2838
+ data: TransactionRuleControllerTestData
2839
+ ): CancelablePromise<TransactionRuleControllerTestResponse> {
2840
+ return __request(OpenAPI, {
2841
+ method: 'POST',
2842
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2843
+ path: {
2844
+ ruleId: data.ruleId,
2845
+ region: data.region
2846
+ },
2847
+ body: data.requestBody,
2848
+ mediaType: 'application/json',
2849
+ errors: {
2850
+ 401: 'Unauthorized',
2851
+ 403: 'Forbidden - not owner of rule',
2852
+ 404: 'Rule not found'
2853
+ }
2854
+ });
2855
+ }
2856
+ }
2857
+
2858
+ export class LifeEventsService {
2859
+ /**
2860
+ * Create a new life event
2861
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2862
+ * @param data The data for the request.
2863
+ * @param data.region Region code for tenant context (decorative for life events)
2864
+ * @param data.requestBody
2865
+ * @returns EventResponseDto Life event created successfully
2866
+ * @throws ApiError
2867
+ */
2868
+ public static eventControllerCreate(
2869
+ data: EventControllerCreateData
2870
+ ): CancelablePromise<EventControllerCreateResponse> {
2871
+ return __request(OpenAPI, {
2872
+ method: 'POST',
2873
+ url: '/api/v1/{region}/bean/events',
2874
+ path: {
2875
+ region: data.region
2876
+ },
2877
+ body: data.requestBody,
2878
+ mediaType: 'application/json',
2879
+ errors: {
2880
+ 409: 'Life event already exists for this (userId, type, date) combination'
2881
+ }
2882
+ });
2883
+ }
2884
+
2885
+ /**
2886
+ * List user life events
2887
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2888
+ * @param data The data for the request.
2889
+ * @param data.region Region code for tenant context (decorative for life events)
2890
+ * @param data.type Filter by life event type (exact match)
2891
+ * @param data.q Search term for description (case-insensitive partial match)
2892
+ * @param data.from Filter life events from this date (ISO 8601 format)
2893
+ * @param data.to Filter life events to this date (ISO 8601 format)
2894
+ * @param data.page Page number for pagination (default: 1)
2895
+ * @param data.limit Number of items per page (default: 20, max: 100)
2896
+ * @returns EventListResponseDto Life events retrieved successfully
2897
+ * @throws ApiError
2898
+ */
2899
+ public static eventControllerFindAll(
2900
+ data: EventControllerFindAllData
2901
+ ): CancelablePromise<EventControllerFindAllResponse> {
2902
+ return __request(OpenAPI, {
2903
+ method: 'GET',
2904
+ url: '/api/v1/{region}/bean/events',
2905
+ path: {
2906
+ region: data.region
2907
+ },
2908
+ query: {
2909
+ type: data.type,
2910
+ q: data.q,
2911
+ from: data.from,
2912
+ to: data.to,
2913
+ page: data.page,
2914
+ limit: data.limit
2915
+ }
2916
+ });
2917
+ }
2918
+
2919
+ /**
2920
+ * Get life event by ID
2921
+ * Returns a single life event by its ID. Returns ETag header.
2922
+ * @param data The data for the request.
2923
+ * @param data.id Life event ID
2924
+ * @param data.region Region code for tenant context (decorative for life events)
2925
+ * @returns EventResponseDto Life event retrieved successfully
2926
+ * @throws ApiError
2927
+ */
2928
+ public static eventControllerFindOne(
2929
+ data: EventControllerFindOneData
2930
+ ): CancelablePromise<EventControllerFindOneResponse> {
2931
+ return __request(OpenAPI, {
2932
+ method: 'GET',
2933
+ url: '/api/v1/{region}/bean/events/{id}',
2934
+ path: {
2935
+ id: data.id,
2936
+ region: data.region
2937
+ },
2938
+ errors: {
2939
+ 404: 'Life event not found'
2940
+ }
2941
+ });
2942
+ }
2943
+
2944
+ /**
2945
+ * Update a life event
2946
+ * Updates an existing life event. If If-Match header is provided, performs optimistic concurrency check; mismatched updatedAt returns 412.
2947
+ * @param data The data for the request.
2948
+ * @param data.id Life event ID
2949
+ * @param data.region Region code for tenant context (decorative for life events)
2950
+ * @param data.requestBody
2951
+ * @returns EventResponseDto Life event updated successfully
2952
+ * @throws ApiError
2953
+ */
2954
+ public static eventControllerUpdate(
2955
+ data: EventControllerUpdateData
2956
+ ): CancelablePromise<EventControllerUpdateResponse> {
2957
+ return __request(OpenAPI, {
2958
+ method: 'PUT',
2959
+ url: '/api/v1/{region}/bean/events/{id}',
2523
2960
  path: {
2961
+ id: data.id,
2524
2962
  region: data.region
2525
2963
  },
2526
- formData: data.formData,
2527
- mediaType: 'multipart/form-data',
2964
+ body: data.requestBody,
2965
+ mediaType: 'application/json',
2528
2966
  errors: {
2529
- 400: 'Bad request - No file uploaded'
2967
+ 400: 'If-Match header is not a valid ISO 8601 date',
2968
+ 404: 'Life event not found',
2969
+ 409: 'Updated event conflicts with an existing (userId, type, date) combination',
2970
+ 412: 'If-Match precondition failed (updatedAt mismatch)'
2530
2971
  }
2531
2972
  });
2532
2973
  }
2533
2974
 
2534
2975
  /**
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.
2976
+ * Delete a life event
2977
+ * Deletes a life event entry (hard delete). Returns 204.
2537
2978
  * @param data The data for the request.
2538
- * @param data.region Region code for tenant context
2539
- * @param data.formData Beancount file to import
2540
- * @returns unknown Beancount file imported successfully
2979
+ * @param data.id Life event ID
2980
+ * @param data.region Region code for tenant context (decorative for life events)
2981
+ * @returns void Life event deleted successfully
2541
2982
  * @throws ApiError
2542
2983
  */
2543
- public static fileImportControllerImportBeancount(
2544
- data: FileImportControllerImportBeancountData
2545
- ): CancelablePromise<FileImportControllerImportBeancountResponse> {
2984
+ public static eventControllerDelete(
2985
+ data: EventControllerDeleteData
2986
+ ): CancelablePromise<EventControllerDeleteResponse> {
2546
2987
  return __request(OpenAPI, {
2547
- method: 'POST',
2548
- url: '/api/v1/{region}/bean/import/beancount',
2988
+ method: 'DELETE',
2989
+ url: '/api/v1/{region}/bean/events/{id}',
2549
2990
  path: {
2991
+ id: data.id,
2550
2992
  region: data.region
2551
2993
  },
2552
- formData: data.formData,
2553
- mediaType: 'multipart/form-data',
2554
2994
  errors: {
2555
- 400: 'Bad request - invalid file or no file uploaded'
2995
+ 404: 'Life event not found'
2556
2996
  }
2557
2997
  });
2558
2998
  }
2559
2999
 
2560
3000
  /**
2561
- * Get importer configuration
2562
- * Returns the current configuration for the specified importer. Creates default configuration if none exists.
3001
+ * Slice time-series by a life event (Phase 79)
3002
+ * Returns aggregated time-series for postings matching accountPattern within the half-open date range of the given life event.
2563
3003
  * @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
- * @param data.region Region code for tenant context
2566
- * @returns ImporterConfigDto Configuration retrieved successfully
3004
+ * @param data.id Life event ID
3005
+ * @param data.accountPattern
3006
+ * @param data.granularity
3007
+ * @param data.region Region code for tenant context (decorative for life events)
3008
+ * @returns unknown Time-series sliced by the life event range
2567
3009
  * @throws ApiError
2568
3010
  */
2569
- public static importerConfigControllerGetConfig(
2570
- data: ImporterConfigControllerGetConfigData
2571
- ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
3011
+ public static eventControllerGetSlice(
3012
+ data: EventControllerGetSliceData
3013
+ ): CancelablePromise<EventControllerGetSliceResponse> {
2572
3014
  return __request(OpenAPI, {
2573
3015
  method: 'GET',
2574
- url: '/api/v1/{region}/bean/import/config/{importerId}',
3016
+ url: '/api/v1/{region}/bean/events/{id}/slice',
2575
3017
  path: {
2576
- importerId: data.importerId,
3018
+ id: data.id,
2577
3019
  region: data.region
2578
3020
  },
3021
+ query: {
3022
+ accountPattern: data.accountPattern,
3023
+ granularity: data.granularity
3024
+ },
2579
3025
  errors: {
2580
- 400: 'Invalid input - Unsupported importer',
2581
- 401: 'Unauthorized - Authentication required'
3026
+ 400: 'accountPattern query param is empty',
3027
+ 404: 'Life event not found'
2582
3028
  }
2583
3029
  });
2584
3030
  }
3031
+ }
2585
3032
 
3033
+ export class OnboardingService {
2586
3034
  /**
2587
- * Update importer configuration
2588
- * Updates the configuration for the specified importer. Partial updates are supported.
3035
+ * Bootstrap core accounts + register asset accounts with opening balances (ADR-0113)
2589
3036
  * @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
2591
3037
  * @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
3038
+ * @param data.requestBody
3039
+ * @returns unknown Onboarding bootstrap result.
2594
3040
  * @throws ApiError
2595
3041
  */
2596
- public static importerConfigControllerUpdateConfig(
2597
- data: ImporterConfigControllerUpdateConfigData
2598
- ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
3042
+ public static onboardingControllerBootstrap(
3043
+ data: OnboardingControllerBootstrapData
3044
+ ): CancelablePromise<OnboardingControllerBootstrapResponse> {
2599
3045
  return __request(OpenAPI, {
2600
- method: 'PUT',
2601
- url: '/api/v1/{region}/bean/import/config/{importerId}',
3046
+ method: 'POST',
3047
+ url: '/api/v1/{region}/bean/onboarding',
2602
3048
  path: {
2603
- importerId: data.importerId,
2604
3049
  region: data.region
2605
3050
  },
2606
3051
  body: data.requestBody,
2607
3052
  mediaType: 'application/json',
2608
3053
  errors: {
2609
- 400: 'Invalid input - Validation failed',
2610
- 404: 'Configuration not found'
3054
+ 422: 'Invalid region/account path/duplicate paths.'
2611
3055
  }
2612
3056
  });
2613
3057
  }
3058
+ }
2614
3059
 
3060
+ export class BalanceReconciliationService {
2615
3061
  /**
2616
- * Reset configuration to default
2617
- * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
3062
+ * Preview reconciliation (book vs actual)
3063
+ * Computes book balance, diff, Beancount-inferred tolerance, and suggested action without persisting.
2618
3064
  * @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
2620
- * @param data.region Region code for tenant context
2621
- * @returns ImporterConfigDto Configuration reset successfully
3065
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3066
+ * @param data.requestBody
3067
+ * @returns ReconciliationComputeResultDto Reconciliation preview
2622
3068
  * @throws ApiError
2623
3069
  */
2624
- public static importerConfigControllerResetConfig(
2625
- data: ImporterConfigControllerResetConfigData
2626
- ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
3070
+ public static reconciliationControllerCompute(
3071
+ data: ReconciliationControllerComputeData
3072
+ ): CancelablePromise<ReconciliationControllerComputeResponse> {
2627
3073
  return __request(OpenAPI, {
2628
3074
  method: 'POST',
2629
- url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
3075
+ url: '/api/v1/{region}/bean/reconciliations',
2630
3076
  path: {
2631
- importerId: data.importerId,
2632
3077
  region: data.region
2633
3078
  },
3079
+ body: data.requestBody,
3080
+ mediaType: 'application/json',
2634
3081
  errors: {
2635
- 400: 'Invalid input - Unsupported importer'
3082
+ 404: 'Account not found'
2636
3083
  }
2637
3084
  });
2638
3085
  }
2639
- }
2640
3086
 
2641
- export class BeanPlatformsService {
2642
3087
  /**
2643
- * Get all platforms with statistics
2644
- * @returns unknown List of platforms with binding and account counts
3088
+ * Record a balance assertion
3089
+ * Persists the reconciliation as a BeanBalance assertion (amount = actual, diffAmount = book − actual). Re-reconciling the same day/currency upserts.
3090
+ * @param data The data for the request.
3091
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3092
+ * @param data.requestBody
3093
+ * @returns ReconciliationRecordDto Balance assertion recorded
2645
3094
  * @throws ApiError
2646
3095
  */
2647
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
3096
+ public static reconciliationControllerAssert(
3097
+ data: ReconciliationControllerAssertData
3098
+ ): CancelablePromise<ReconciliationControllerAssertResponse> {
2648
3099
  return __request(OpenAPI, {
2649
- method: 'GET',
2650
- url: '/api/v1/bean/platforms'
3100
+ method: 'POST',
3101
+ url: '/api/v1/{region}/bean/reconciliations/assert',
3102
+ path: {
3103
+ region: data.region
3104
+ },
3105
+ body: data.requestBody,
3106
+ mediaType: 'application/json',
3107
+ errors: {
3108
+ 404: 'Account not found'
3109
+ }
2651
3110
  });
2652
3111
  }
2653
3112
 
2654
3113
  /**
2655
- * Create a new platform
3114
+ * Generate a pad adjusting entry
3115
+ * When book is outside tolerance, synthesizes a Beancount pad transaction (flag P) booking the diff from source_account and persists it. Source defaults to Equity:Opening-Balances.
2656
3116
  * @param data The data for the request.
3117
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2657
3118
  * @param data.requestBody
2658
- * @returns unknown Platform created successfully
3119
+ * @returns PadResultDto Pad adjusting entry generated
2659
3120
  * @throws ApiError
2660
3121
  */
2661
- public static platformControllerCreate(
2662
- data: PlatformControllerCreateData
2663
- ): CancelablePromise<PlatformControllerCreateResponse> {
3122
+ public static reconciliationControllerPad(
3123
+ data: ReconciliationControllerPadData
3124
+ ): CancelablePromise<ReconciliationControllerPadResponse> {
2664
3125
  return __request(OpenAPI, {
2665
3126
  method: 'POST',
2666
- url: '/api/v1/bean/platforms',
3127
+ url: '/api/v1/{region}/bean/reconciliations/pad',
3128
+ path: {
3129
+ region: data.region
3130
+ },
2667
3131
  body: data.requestBody,
2668
3132
  mediaType: 'application/json',
2669
3133
  errors: {
2670
- 409: 'Platform already exists'
3134
+ 400: 'Book already within tolerance — no pad needed',
3135
+ 404: 'Account not found'
2671
3136
  }
2672
3137
  });
2673
3138
  }
2674
3139
 
2675
3140
  /**
2676
- * Get platform list for current user
2677
- * @returns unknown List of platforms with user binding status
3141
+ * List reconciliation history for an account
3142
+ * Returns recorded balance assertions (most recent first). The latest drives the account-detail "Last <date>" badge.
3143
+ * @param data The data for the request.
3144
+ * @param data.accountId BeanAccount id
3145
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3146
+ * @returns ReconciliationRecordDto Reconciliation history
2678
3147
  * @throws ApiError
2679
3148
  */
2680
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3149
+ public static reconciliationControllerHistory(
3150
+ data: ReconciliationControllerHistoryData
3151
+ ): CancelablePromise<ReconciliationControllerHistoryResponse> {
2681
3152
  return __request(OpenAPI, {
2682
3153
  method: 'GET',
2683
- url: '/api/v1/bean/platforms/list'
3154
+ url: '/api/v1/{region}/bean/accounts/{accountId}/reconciliations',
3155
+ path: {
3156
+ accountId: data.accountId,
3157
+ region: data.region
3158
+ },
3159
+ errors: {
3160
+ 404: 'Account not found'
3161
+ }
2684
3162
  });
2685
3163
  }
3164
+ }
2686
3165
 
3166
+ export class BeanExportService {
2687
3167
  /**
2688
- * Match platforms by name or alias
3168
+ * Export Beancount ledger as ZIP
3169
+ * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
3170
+ * @returns unknown
3171
+ * @throws ApiError
3172
+ */
3173
+ public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
3174
+ return __request(OpenAPI, {
3175
+ method: 'GET',
3176
+ url: '/api/v1/{region}/bean/export/beancount'
3177
+ });
3178
+ }
3179
+ }
3180
+
3181
+ export class BeanImportService {
3182
+ /**
3183
+ * Import a bill file
3184
+ * 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).
2689
3185
  * @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
3186
+ * @param data.region Region code for tenant context
3187
+ * @param data.formData Bill file to import
3188
+ * @returns ImportResultDto File imported successfully
2693
3189
  * @throws ApiError
2694
3190
  */
2695
- public static platformControllerMatchPlatforms(
2696
- data: PlatformControllerMatchPlatformsData
2697
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3191
+ public static fileImportControllerImportFile(
3192
+ data: FileImportControllerImportFileData
3193
+ ): CancelablePromise<FileImportControllerImportFileResponse> {
3194
+ return __request(OpenAPI, {
3195
+ method: 'POST',
3196
+ url: '/api/v1/{region}/bean/import/file',
3197
+ path: {
3198
+ region: data.region
3199
+ },
3200
+ formData: data.formData,
3201
+ mediaType: 'multipart/form-data',
3202
+ errors: {
3203
+ 400: 'Bad request - file-format-unsupported or file-import-failed',
3204
+ 413: 'Payload too large - file exceeds 50MB limit',
3205
+ 429: 'Too many requests - user already has import in progress',
3206
+ 500: 'Internal server error - DATABASE_ERROR'
3207
+ }
3208
+ });
3209
+ }
3210
+
3211
+ /**
3212
+ * Identify file type
3213
+ * 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.
3214
+ * @param data The data for the request.
3215
+ * @param data.region Region code for tenant context
3216
+ * @param data.formData File to identify
3217
+ * @returns IdentifyResultDto File identification result
3218
+ * @throws ApiError
3219
+ */
3220
+ public static fileImportControllerIdentifyFile(
3221
+ data: FileImportControllerIdentifyFileData
3222
+ ): CancelablePromise<FileImportControllerIdentifyFileResponse> {
3223
+ return __request(OpenAPI, {
3224
+ method: 'POST',
3225
+ url: '/api/v1/{region}/bean/import/identify',
3226
+ path: {
3227
+ region: data.region
3228
+ },
3229
+ formData: data.formData,
3230
+ mediaType: 'multipart/form-data',
3231
+ errors: {
3232
+ 400: 'Bad request - No file uploaded'
3233
+ }
3234
+ });
3235
+ }
3236
+
3237
+ /**
3238
+ * Import a Beancount file in community format
3239
+ * 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.
3240
+ * @param data The data for the request.
3241
+ * @param data.region Region code for tenant context
3242
+ * @param data.formData Beancount file to import
3243
+ * @returns unknown Beancount file imported successfully
3244
+ * @throws ApiError
3245
+ */
3246
+ public static fileImportControllerImportBeancount(
3247
+ data: FileImportControllerImportBeancountData
3248
+ ): CancelablePromise<FileImportControllerImportBeancountResponse> {
3249
+ return __request(OpenAPI, {
3250
+ method: 'POST',
3251
+ url: '/api/v1/{region}/bean/import/beancount',
3252
+ path: {
3253
+ region: data.region
3254
+ },
3255
+ formData: data.formData,
3256
+ mediaType: 'multipart/form-data',
3257
+ errors: {
3258
+ 400: 'Bad request - invalid file or no file uploaded'
3259
+ }
3260
+ });
3261
+ }
3262
+
3263
+ /**
3264
+ * Get importer configuration
3265
+ * Returns the current configuration for the specified importer. Creates default configuration if none exists.
3266
+ * @param data The data for the request.
3267
+ * @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
3268
+ * @param data.region Region code for tenant context
3269
+ * @returns ImporterConfigDto Configuration retrieved successfully
3270
+ * @throws ApiError
3271
+ */
3272
+ public static importerConfigControllerGetConfig(
3273
+ data: ImporterConfigControllerGetConfigData
3274
+ ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
2698
3275
  return __request(OpenAPI, {
2699
3276
  method: 'GET',
2700
- url: '/api/v1/bean/platforms/match',
2701
- query: {
2702
- q: data.q,
3277
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
3278
+ path: {
3279
+ importerId: data.importerId,
2703
3280
  region: data.region
3281
+ },
3282
+ errors: {
3283
+ 400: 'Invalid input - Unsupported importer',
3284
+ 401: 'Unauthorized - Authentication required'
2704
3285
  }
2705
3286
  });
2706
3287
  }
2707
3288
 
2708
3289
  /**
2709
- * Update a platform
3290
+ * Update importer configuration
3291
+ * Updates the configuration for the specified importer. Partial updates are supported.
2710
3292
  * @param data The data for the request.
2711
- * @param data.id Platform ID
2712
- * @param data.requestBody
2713
- * @returns unknown Platform updated successfully
3293
+ * @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
3294
+ * @param data.region Region code for tenant context
3295
+ * @param data.requestBody Partial configuration update. Only provided fields will be updated.
3296
+ * @returns ImporterConfigDto Configuration updated successfully
2714
3297
  * @throws ApiError
2715
3298
  */
2716
- public static platformControllerUpdate(
2717
- data: PlatformControllerUpdateData
2718
- ): CancelablePromise<PlatformControllerUpdateResponse> {
3299
+ public static importerConfigControllerUpdateConfig(
3300
+ data: ImporterConfigControllerUpdateConfigData
3301
+ ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
2719
3302
  return __request(OpenAPI, {
2720
3303
  method: 'PUT',
2721
- url: '/api/v1/bean/platforms/{id}',
3304
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
2722
3305
  path: {
2723
- id: data.id
3306
+ importerId: data.importerId,
3307
+ region: data.region
2724
3308
  },
2725
3309
  body: data.requestBody,
2726
3310
  mediaType: 'application/json',
2727
3311
  errors: {
2728
- 404: 'Platform not found'
3312
+ 400: 'Invalid input - Validation failed',
3313
+ 404: 'Configuration not found'
2729
3314
  }
2730
3315
  });
2731
3316
  }
2732
3317
 
2733
3318
  /**
2734
- * Delete a platform
3319
+ * Reset configuration to default
3320
+ * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
2735
3321
  * @param data The data for the request.
2736
- * @param data.id Platform ID
2737
- * @returns void Platform deleted successfully
3322
+ * @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
3323
+ * @param data.region Region code for tenant context
3324
+ * @returns ImporterConfigDto Configuration reset successfully
2738
3325
  * @throws ApiError
2739
3326
  */
2740
- public static platformControllerDelete(
2741
- data: PlatformControllerDeleteData
2742
- ): CancelablePromise<PlatformControllerDeleteResponse> {
3327
+ public static importerConfigControllerResetConfig(
3328
+ data: ImporterConfigControllerResetConfigData
3329
+ ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
2743
3330
  return __request(OpenAPI, {
2744
- method: 'DELETE',
2745
- url: '/api/v1/bean/platforms/{id}',
3331
+ method: 'POST',
3332
+ url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
2746
3333
  path: {
2747
- id: data.id
3334
+ importerId: data.importerId,
3335
+ region: data.region
2748
3336
  },
2749
3337
  errors: {
2750
- 404: 'Platform not found'
3338
+ 400: 'Invalid input - Unsupported importer'
2751
3339
  }
2752
3340
  });
2753
3341
  }
@@ -2853,6 +3441,101 @@ export class ProviderSyncService {
2853
3441
  }
2854
3442
  }
2855
3443
 
3444
+ export class ExternalAccountLinksService {
3445
+ /**
3446
+ * Create an external account → BeanAccount mapping (ADR-0113)
3447
+ * @param data The data for the request.
3448
+ * @param data.region Region code for tenant context
3449
+ * @param data.requestBody
3450
+ * @returns ExternalAccountLinkResponseDto Link created.
3451
+ * @throws ApiError
3452
+ */
3453
+ public static externalAccountLinkControllerCreate(
3454
+ data: ExternalAccountLinkControllerCreateData
3455
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
3456
+ return __request(OpenAPI, {
3457
+ method: 'POST',
3458
+ url: '/api/v1/{region}/bean/external-account-links',
3459
+ path: {
3460
+ region: data.region
3461
+ },
3462
+ body: data.requestBody,
3463
+ mediaType: 'application/json',
3464
+ errors: {
3465
+ 422: 'beanAccountId not owned, or an active link already exists.'
3466
+ }
3467
+ });
3468
+ }
3469
+
3470
+ /**
3471
+ * List the user's active external account links
3472
+ * @param data The data for the request.
3473
+ * @param data.provider
3474
+ * @param data.region Region code for tenant context
3475
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
3476
+ * @throws ApiError
3477
+ */
3478
+ public static externalAccountLinkControllerFindAll(
3479
+ data: ExternalAccountLinkControllerFindAllData
3480
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
3481
+ return __request(OpenAPI, {
3482
+ method: 'GET',
3483
+ url: '/api/v1/{region}/bean/external-account-links',
3484
+ path: {
3485
+ region: data.region
3486
+ },
3487
+ query: {
3488
+ provider: data.provider
3489
+ }
3490
+ });
3491
+ }
3492
+
3493
+ /**
3494
+ * Get a single external account link
3495
+ * @param data The data for the request.
3496
+ * @param data.id
3497
+ * @param data.region Region code for tenant context
3498
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
3499
+ * @throws ApiError
3500
+ */
3501
+ public static externalAccountLinkControllerFindOne(
3502
+ data: ExternalAccountLinkControllerFindOneData
3503
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
3504
+ return __request(OpenAPI, {
3505
+ method: 'GET',
3506
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3507
+ path: {
3508
+ id: data.id,
3509
+ region: data.region
3510
+ },
3511
+ errors: {
3512
+ 422: 'Link not found or not owned by the user.'
3513
+ }
3514
+ });
3515
+ }
3516
+
3517
+ /**
3518
+ * Soft-delete (disconnect) an external account link
3519
+ * @param data The data for the request.
3520
+ * @param data.id
3521
+ * @param data.region Region code for tenant context
3522
+ * @returns void Link soft-deleted; historical transactions are unaffected.
3523
+ * @throws ApiError
3524
+ */
3525
+ public static externalAccountLinkControllerRemove(
3526
+ data: ExternalAccountLinkControllerRemoveData
3527
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
3528
+ return __request(OpenAPI, {
3529
+ method: 'DELETE',
3530
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3531
+ path: {
3532
+ id: data.id,
3533
+ region: data.region
3534
+ }
3535
+ });
3536
+ }
3537
+ }
3538
+
2856
3539
  export class ImportTelemetryService {
2857
3540
  /**
2858
3541
  * Receive anonymous parser failure telemetry
@@ -3011,411 +3694,270 @@ export class BeanNlpService {
3011
3694
  }
3012
3695
  }
3013
3696
 
3014
- export class DashboardService {
3015
- /**
3016
- * Get net worth overview
3017
- * Returns total net worth with breakdown of assets and liabilities
3018
- * @param data The data for the request.
3019
- * @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
3022
- * @throws ApiError
3023
- */
3024
- public static dashboardControllerGetNetWorth(
3025
- data: DashboardControllerGetNetWorthData
3026
- ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3027
- return __request(OpenAPI, {
3028
- method: 'GET',
3029
- url: '/api/v1/{region}/dashboard/net-worth',
3030
- path: {
3031
- region: data.region
3032
- },
3033
- query: {
3034
- date: data.date
3035
- },
3036
- errors: {
3037
- 401: 'User not authenticated'
3038
- }
3039
- });
3040
- }
3041
-
3697
+ export class BeanPlatformsService {
3042
3698
  /**
3043
- * Get accounts grouped by platform
3044
- * Returns accounts with balances grouped by financial platform
3045
- * @param data The data for the request.
3046
- * @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.
3699
+ * Get all platforms with statistics
3700
+ * @returns unknown List of platforms with binding and account counts
3051
3701
  * @throws ApiError
3052
3702
  */
3053
- public static dashboardControllerGetAccounts(
3054
- data: DashboardControllerGetAccountsData
3055
- ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3703
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
3056
3704
  return __request(OpenAPI, {
3057
3705
  method: 'GET',
3058
- url: '/api/v1/{region}/dashboard/accounts',
3059
- path: {
3060
- region: data.region
3061
- },
3062
- query: {
3063
- groupBy: data.groupBy,
3064
- date: data.date,
3065
- accountId: data.accountId
3066
- },
3067
- errors: {
3068
- 401: 'User not authenticated'
3069
- }
3706
+ url: '/api/v1/bean/platforms'
3070
3707
  });
3071
3708
  }
3072
3709
 
3073
3710
  /**
3074
- * Get cash flow summary
3075
- * Returns income, expenses, and savings for a monthly period
3711
+ * Create a new platform
3076
3712
  * @param data The data for the request.
3077
- * @param data.period Period in YYYY-MM format
3078
- * @param data.region Region code for tenant context
3079
- * @returns CashFlowResponseDto Cash flow retrieved successfully
3713
+ * @param data.requestBody
3714
+ * @returns unknown Platform created successfully
3080
3715
  * @throws ApiError
3081
3716
  */
3082
- public static dashboardControllerGetCashFlow(
3083
- data: DashboardControllerGetCashFlowData
3084
- ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3717
+ public static platformControllerCreate(
3718
+ data: PlatformControllerCreateData
3719
+ ): CancelablePromise<PlatformControllerCreateResponse> {
3085
3720
  return __request(OpenAPI, {
3086
- method: 'GET',
3087
- url: '/api/v1/{region}/dashboard/cash-flow',
3088
- path: {
3089
- region: data.region
3090
- },
3091
- query: {
3092
- period: data.period
3093
- },
3721
+ method: 'POST',
3722
+ url: '/api/v1/bean/platforms',
3723
+ body: data.requestBody,
3724
+ mediaType: 'application/json',
3094
3725
  errors: {
3095
- 400: 'Invalid period format',
3096
- 401: 'User not authenticated'
3726
+ 409: 'Platform already exists'
3097
3727
  }
3098
3728
  });
3099
3729
  }
3100
- }
3101
3730
 
3102
- export class InvestmentService {
3103
3731
  /**
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).
3106
- * @param data The data for the request.
3107
- * @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
3732
+ * Get platform list for current user
3733
+ * @returns PlatformListItemDto List of platforms with user binding status
3112
3734
  * @throws ApiError
3113
3735
  */
3114
- public static holdingPnlControllerGetHoldingPnl(
3115
- data: HoldingPnlControllerGetHoldingPnlData
3116
- ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3736
+ public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3117
3737
  return __request(OpenAPI, {
3118
3738
  method: 'GET',
3119
- url: '/api/v1/{region}/investment/holdings/pnl',
3120
- path: {
3121
- region: data.region
3122
- },
3123
- query: {
3124
- asOf: data.asOf,
3125
- accountId: data.accountId,
3126
- method: data.method
3127
- },
3128
- errors: {
3129
- 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3130
- 401: 'User not authenticated'
3131
- }
3132
- });
3133
- }
3134
- }
3135
-
3136
- export class BeanPricesService {
3137
- /**
3138
- * Create a new price
3139
- * Creates a new price entry for the authenticated user
3140
- * @param data The data for the request.
3141
- * @param data.region Region code for tenant context
3142
- * @param data.requestBody
3143
- * @returns PriceResponseDto Price created successfully
3144
- * @throws ApiError
3145
- */
3146
- public static priceControllerCreate(
3147
- data: PriceControllerCreateData
3148
- ): CancelablePromise<PriceControllerCreateResponse> {
3149
- return __request(OpenAPI, {
3150
- method: 'POST',
3151
- url: '/api/v1/{region}/bean/prices',
3152
- path: {
3153
- region: data.region
3154
- },
3155
- body: data.requestBody,
3156
- mediaType: 'application/json',
3157
- errors: {
3158
- 404: 'Currency or quoteCurrency commodity not found',
3159
- 409: 'Price already exists for this currency pair and date'
3160
- }
3739
+ url: '/api/v1/bean/platforms/list'
3161
3740
  });
3162
3741
  }
3163
3742
 
3164
3743
  /**
3165
- * List user prices
3166
- * Returns all price entries for the authenticated user with optional filtering
3744
+ * Match platforms by name or alias
3167
3745
  * @param data The data for the request.
3168
- * @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
3746
+ * @param data.q Search query Chinese name, English name, or abbreviation
3747
+ * @param data.region Region code for category override lookup
3748
+ * @returns PlatformMatchResponseDto Matching platforms with overall match type and truncation flag
3177
3749
  * @throws ApiError
3178
3750
  */
3179
- public static priceControllerFindAll(
3180
- data: PriceControllerFindAllData
3181
- ): CancelablePromise<PriceControllerFindAllResponse> {
3751
+ public static platformControllerMatchPlatforms(
3752
+ data: PlatformControllerMatchPlatformsData
3753
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3182
3754
  return __request(OpenAPI, {
3183
3755
  method: 'GET',
3184
- url: '/api/v1/{region}/bean/prices',
3185
- path: {
3186
- region: data.region
3187
- },
3756
+ url: '/api/v1/bean/platforms/match',
3188
3757
  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
3758
+ q: data.q,
3759
+ region: data.region
3196
3760
  }
3197
3761
  });
3198
3762
  }
3199
3763
 
3200
3764
  /**
3201
- * Get price by ID
3202
- * Returns a single price entry by its ID
3765
+ * Update a platform
3203
3766
  * @param data The data for the request.
3204
- * @param data.id Price ID
3205
- * @param data.region Region code for tenant context
3206
- * @returns PriceResponseDto Price retrieved successfully
3767
+ * @param data.id Platform ID
3768
+ * @param data.requestBody
3769
+ * @returns unknown Platform updated successfully
3207
3770
  * @throws ApiError
3208
3771
  */
3209
- public static priceControllerFindOne(
3210
- data: PriceControllerFindOneData
3211
- ): CancelablePromise<PriceControllerFindOneResponse> {
3772
+ public static platformControllerUpdate(
3773
+ data: PlatformControllerUpdateData
3774
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
3212
3775
  return __request(OpenAPI, {
3213
- method: 'GET',
3214
- url: '/api/v1/{region}/bean/prices/{id}',
3776
+ method: 'PUT',
3777
+ url: '/api/v1/bean/platforms/{id}',
3215
3778
  path: {
3216
- id: data.id,
3217
- region: data.region
3779
+ id: data.id
3218
3780
  },
3781
+ body: data.requestBody,
3782
+ mediaType: 'application/json',
3219
3783
  errors: {
3220
- 404: 'Price not found'
3784
+ 404: 'Platform not found'
3221
3785
  }
3222
3786
  });
3223
3787
  }
3224
3788
 
3225
3789
  /**
3226
- * Update a price
3227
- * Updates an existing price entry
3790
+ * Delete a platform
3228
3791
  * @param data The data for the request.
3229
- * @param data.id Price ID
3230
- * @param data.region Region code for tenant context
3231
- * @param data.requestBody
3232
- * @returns PriceResponseDto Price updated successfully
3792
+ * @param data.id Platform ID
3793
+ * @returns void Platform deleted successfully
3233
3794
  * @throws ApiError
3234
3795
  */
3235
- public static priceControllerUpdate(
3236
- data: PriceControllerUpdateData
3237
- ): CancelablePromise<PriceControllerUpdateResponse> {
3796
+ public static platformControllerDelete(
3797
+ data: PlatformControllerDeleteData
3798
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
3238
3799
  return __request(OpenAPI, {
3239
- method: 'PUT',
3240
- url: '/api/v1/{region}/bean/prices/{id}',
3800
+ method: 'DELETE',
3801
+ url: '/api/v1/bean/platforms/{id}',
3241
3802
  path: {
3242
- id: data.id,
3243
- region: data.region
3803
+ id: data.id
3244
3804
  },
3245
- body: data.requestBody,
3246
- mediaType: 'application/json',
3247
3805
  errors: {
3248
- 404: 'Price not found',
3249
- 409: 'Updated price conflicts with existing price'
3806
+ 404: 'Platform not found'
3250
3807
  }
3251
3808
  });
3252
3809
  }
3810
+ }
3253
3811
 
3812
+ export class DashboardService {
3254
3813
  /**
3255
- * Delete a price
3256
- * Deletes a price entry (hard delete)
3814
+ * Get net worth overview
3815
+ * Returns total net worth with breakdown of assets and liabilities
3257
3816
  * @param data The data for the request.
3258
- * @param data.id Price ID
3259
3817
  * @param data.region Region code for tenant context
3260
- * @returns void Price deleted successfully
3818
+ * @param data.date Date for balance calculation (ISO 8601 format)
3819
+ * @returns NetWorthResponseDto Net worth retrieved successfully
3261
3820
  * @throws ApiError
3262
3821
  */
3263
- public static priceControllerDelete(
3264
- data: PriceControllerDeleteData
3265
- ): CancelablePromise<PriceControllerDeleteResponse> {
3822
+ public static dashboardControllerGetNetWorth(
3823
+ data: DashboardControllerGetNetWorthData
3824
+ ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3266
3825
  return __request(OpenAPI, {
3267
- method: 'DELETE',
3268
- url: '/api/v1/{region}/bean/prices/{id}',
3826
+ method: 'GET',
3827
+ url: '/api/v1/{region}/dashboard/net-worth',
3269
3828
  path: {
3270
- id: data.id,
3271
3829
  region: data.region
3272
3830
  },
3831
+ query: {
3832
+ date: data.date
3833
+ },
3273
3834
  errors: {
3274
- 404: 'Price not found'
3835
+ 401: 'User not authenticated'
3275
3836
  }
3276
3837
  });
3277
3838
  }
3278
3839
 
3279
3840
  /**
3280
- * Bulk create prices
3281
- * Creates multiple price entries at once (skips duplicates)
3841
+ * Get accounts grouped by platform
3842
+ * Returns accounts with balances grouped by financial platform
3282
3843
  * @param data The data for the request.
3283
3844
  * @param data.region Region code for tenant context
3284
- * @param data.requestBody
3285
- * @returns PriceResponseDto Prices created successfully
3845
+ * @param data.groupBy Grouping strategy
3846
+ * @param data.date Date for balance calculation (ISO 8601 format)
3847
+ * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
3848
+ * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
3286
3849
  * @throws ApiError
3287
3850
  */
3288
- public static priceControllerBulkCreate(
3289
- data: PriceControllerBulkCreateData
3290
- ): CancelablePromise<PriceControllerBulkCreateResponse> {
3851
+ public static dashboardControllerGetAccounts(
3852
+ data: DashboardControllerGetAccountsData
3853
+ ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3291
3854
  return __request(OpenAPI, {
3292
- method: 'POST',
3293
- url: '/api/v1/{region}/bean/prices/bulk',
3855
+ method: 'GET',
3856
+ url: '/api/v1/{region}/dashboard/accounts',
3294
3857
  path: {
3295
3858
  region: data.region
3296
3859
  },
3297
- body: data.requestBody,
3298
- mediaType: 'application/json'
3860
+ query: {
3861
+ groupBy: data.groupBy,
3862
+ date: data.date,
3863
+ accountId: data.accountId
3864
+ },
3865
+ errors: {
3866
+ 401: 'User not authenticated'
3867
+ }
3299
3868
  });
3300
3869
  }
3301
- }
3302
3870
 
3303
- export class ReportingService {
3304
3871
  /**
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
- *
3872
+ * Get cash flow summary
3873
+ * Returns income, expenses, and savings for a monthly period
3318
3874
  * @param data The data for the request.
3875
+ * @param data.period Period in YYYY-MM format
3319
3876
  * @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
3877
+ * @returns CashFlowResponseDto Cash flow retrieved successfully
3323
3878
  * @throws ApiError
3324
3879
  */
3325
- public static reportingControllerGetPortfolioTrends(
3326
- data: ReportingControllerGetPortfolioTrendsData
3327
- ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
3880
+ public static dashboardControllerGetCashFlow(
3881
+ data: DashboardControllerGetCashFlowData
3882
+ ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3328
3883
  return __request(OpenAPI, {
3329
3884
  method: 'GET',
3330
- url: '/api/v1/{region}/reporting/portfolio/trends',
3885
+ url: '/api/v1/{region}/dashboard/cash-flow',
3331
3886
  path: {
3332
3887
  region: data.region
3333
3888
  },
3334
3889
  query: {
3335
- period: data.period,
3336
- granularity: data.granularity
3890
+ period: data.period
3337
3891
  },
3338
3892
  errors: {
3893
+ 400: 'Invalid period format',
3339
3894
  401: 'User not authenticated'
3340
3895
  }
3341
3896
  });
3342
3897
  }
3343
3898
 
3344
3899
  /**
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
- *
3900
+ * Get expenses/income grouped by functional category
3901
+ * Returns amounts pre-aggregated by functional category (account-path Group segment) with server-side multi-currency conversion. flow=expense (default) aggregates ^Expenses: accounts; flow=income aggregates ^Income: accounts (issue #518)
3359
3902
  * @param data The data for the request.
3360
3903
  * @param data.region Region code for tenant context
3361
- * @param data.requestBody Optional date (defaults to today)
3362
- * @returns GenerateSnapshotResponse Snapshot generated successfully
3904
+ * @param data.groupBy Grouping strategy
3905
+ * @param data.period Time window (1m = current calendar month)
3906
+ * @param data.flow Account root to aggregate (expense → ^Expenses:, income → ^Income:)
3907
+ * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3363
3908
  * @throws ApiError
3364
3909
  */
3365
- public static reportingControllerGenerateSnapshot(
3366
- data: ReportingControllerGenerateSnapshotData
3367
- ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
3910
+ public static dashboardControllerGetExpenses(
3911
+ data: DashboardControllerGetExpensesData
3912
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3368
3913
  return __request(OpenAPI, {
3369
- method: 'POST',
3370
- url: '/api/v1/{region}/reporting/snapshots/generate',
3914
+ method: 'GET',
3915
+ url: '/api/v1/{region}/dashboard/expenses',
3371
3916
  path: {
3372
3917
  region: data.region
3373
3918
  },
3374
- body: data.requestBody,
3375
- mediaType: 'application/json',
3919
+ query: {
3920
+ groupBy: data.groupBy,
3921
+ period: data.period,
3922
+ flow: data.flow
3923
+ },
3376
3924
  errors: {
3377
- 400: 'Invalid date format',
3925
+ 400: 'Invalid groupBy or period',
3378
3926
  401: 'User not authenticated'
3379
3927
  }
3380
3928
  });
3381
3929
  }
3930
+ }
3382
3931
 
3932
+ export class InvestmentService {
3383
3933
  /**
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
- *
3934
+ * Get per-holding unrealized + realized P&L
3935
+ * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3398
3936
  * @param data The data for the request.
3399
3937
  * @param data.region Region code for tenant context
3400
- * @param data.requestBody
3401
- * @returns BackfillSnapshotsResponse Backfill completed successfully
3938
+ * @param data.asOf As-of date (ISO 8601), defaults to today
3939
+ * @param data.accountId Scope to a single account
3940
+ * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
3941
+ * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3402
3942
  * @throws ApiError
3403
3943
  */
3404
- public static reportingControllerBackfillSnapshots(
3405
- data: ReportingControllerBackfillSnapshotsData
3406
- ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
3944
+ public static holdingPnlControllerGetHoldingPnl(
3945
+ data: HoldingPnlControllerGetHoldingPnlData
3946
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3407
3947
  return __request(OpenAPI, {
3408
- method: 'POST',
3409
- url: '/api/v1/{region}/reporting/snapshots/backfill',
3948
+ method: 'GET',
3949
+ url: '/api/v1/{region}/investment/holdings/pnl',
3410
3950
  path: {
3411
3951
  region: data.region
3412
3952
  },
3413
- body: data.requestBody,
3414
- mediaType: 'application/json',
3953
+ query: {
3954
+ asOf: data.asOf,
3955
+ accountId: data.accountId,
3956
+ method: data.method
3957
+ },
3415
3958
  errors: {
3416
- 400: 'Invalid date format or range',
3417
- 401: 'User not authenticated',
3418
- 409: 'Backfill already in progress for this user'
3959
+ 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3960
+ 401: 'User not authenticated'
3419
3961
  }
3420
3962
  });
3421
3963
  }
@@ -3444,7 +3986,7 @@ export class AuthService {
3444
3986
  * Anonymous login with access token
3445
3987
  * @param data The data for the request.
3446
3988
  * @param data.requestBody
3447
- * @returns unknown Login successful
3989
+ * @returns AnonymousLoginResponseDto Login successful
3448
3990
  * @throws ApiError
3449
3991
  */
3450
3992
  public static authControllerAccessTokenLogin(
@@ -3631,3 +4173,53 @@ export class InfoService {
3631
4173
  });
3632
4174
  }
3633
4175
  }
4176
+
4177
+ export class MarketDataService {
4178
+ /**
4179
+ * Search market symbols by name or code
4180
+ * Ranked search over the openbb catalog. Empty `q` returns [].
4181
+ * @param data The data for the request.
4182
+ * @param data.q Search term — matched against symbol and instrument name. Empty string returns [].
4183
+ * @param data.limit Maximum number of results (clamped 1..50)
4184
+ * @param data.exchange Filter by exchange code (e.g. US, HK, SS, SZ)
4185
+ * @param data.assetType Filter by OpenBB asset_type (e.g. stock, etf)
4186
+ * @returns SymbolSearchResultDto Ranked search results
4187
+ * @throws ApiError
4188
+ */
4189
+ public static symbolControllerSearch(
4190
+ data: SymbolControllerSearchData
4191
+ ): CancelablePromise<SymbolControllerSearchResponse> {
4192
+ return __request(OpenAPI, {
4193
+ method: 'GET',
4194
+ url: '/api/v1/market/symbols/search',
4195
+ query: {
4196
+ q: data.q,
4197
+ limit: data.limit,
4198
+ exchange: data.exchange,
4199
+ assetType: data.assetType
4200
+ }
4201
+ });
4202
+ }
4203
+
4204
+ /**
4205
+ * Get a market symbol quote
4206
+ * @param data The data for the request.
4207
+ * @param data.symbol
4208
+ * @returns SymbolQuoteDto Symbol quote
4209
+ * @throws ApiError
4210
+ */
4211
+ public static symbolControllerGetQuote(
4212
+ data: SymbolControllerGetQuoteData
4213
+ ): CancelablePromise<SymbolControllerGetQuoteResponse> {
4214
+ return __request(OpenAPI, {
4215
+ method: 'GET',
4216
+ url: '/api/v1/market/symbols/{symbol}/quote',
4217
+ path: {
4218
+ symbol: data.symbol
4219
+ },
4220
+ errors: {
4221
+ 404: 'Symbol not found in the openbb catalog'
4222
+ }
4223
+ });
4224
+ }
4225
+ }