@firela/api-types 0.0.0-canary.3ed455fd → 0.0.0-canary.421ffa2c

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