@firela/api-types 0.0.0-canary.ff71bd6f → 0.0.0-canary.ffdf0021

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,
@@ -29,6 +31,8 @@ import type {
29
31
  TransactionControllerListResponse,
30
32
  TransactionControllerCreateBatchData,
31
33
  TransactionControllerCreateBatchResponse,
34
+ TransactionControllerCorrectData,
35
+ TransactionControllerCorrectResponse,
32
36
  TransactionControllerSuggestTagsData,
33
37
  TransactionControllerSuggestTagsResponse,
34
38
  TransactionControllerGetDetailData,
@@ -95,6 +99,18 @@ import type {
95
99
  CommodityControllerGetOrCreateResponse,
96
100
  CommodityControllerBulkCreateData,
97
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,
98
114
  RecurringRuleControllerCreateData,
99
115
  RecurringRuleControllerCreateResponse,
100
116
  RecurringRuleControllerFindAllData,
@@ -127,26 +143,14 @@ import type {
127
143
  ExpectedTransactionControllerEnterNowResponse,
128
144
  ForecastControllerGetForecastData,
129
145
  ForecastControllerGetForecastResponse,
130
- TransactionRuleControllerCreateData,
131
- TransactionRuleControllerCreateResponse,
132
- TransactionRuleControllerListData,
133
- TransactionRuleControllerListResponse,
134
- TransactionRuleControllerValidateData,
135
- TransactionRuleControllerValidateResponse,
136
- TransactionRuleControllerBulkCreateData,
137
- TransactionRuleControllerBulkCreateResponse,
138
- TransactionRuleControllerExportData,
139
- TransactionRuleControllerExportResponse,
140
- TransactionRuleControllerGetStatisticsData,
141
- TransactionRuleControllerGetStatisticsResponse,
142
- TransactionRuleControllerGetDetailData,
143
- TransactionRuleControllerGetDetailResponse,
144
- TransactionRuleControllerUpdateData,
145
- TransactionRuleControllerUpdateResponse,
146
- TransactionRuleControllerDeleteData,
147
- TransactionRuleControllerDeleteResponse,
148
- TransactionRuleControllerTestData,
149
- TransactionRuleControllerTestResponse,
146
+ ReportingControllerGetPortfolioTrendsData,
147
+ ReportingControllerGetPortfolioTrendsResponse,
148
+ ReportingControllerGetCashFlowTrendsData,
149
+ ReportingControllerGetCashFlowTrendsResponse,
150
+ ReportingControllerGenerateSnapshotData,
151
+ ReportingControllerGenerateSnapshotResponse,
152
+ ReportingControllerBackfillSnapshotsData,
153
+ ReportingControllerBackfillSnapshotsResponse,
150
154
  UserControllerDeleteOwnUserData,
151
155
  UserControllerDeleteOwnUserResponse,
152
156
  UserControllerGetUserData,
@@ -169,6 +173,50 @@ import type {
169
173
  PropertyControllerUpdateResponse,
170
174
  PropertyControllerDeleteData,
171
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,
172
220
  ExportControllerExportBeancountResponse,
173
221
  FileImportControllerImportFileData,
174
222
  FileImportControllerImportFileResponse,
@@ -182,45 +230,58 @@ import type {
182
230
  ImporterConfigControllerUpdateConfigResponse,
183
231
  ImporterConfigControllerResetConfigData,
184
232
  ImporterConfigControllerResetConfigResponse,
185
- PlatformControllerFindAllResponse,
186
- PlatformControllerCreateData,
187
- PlatformControllerCreateResponse,
188
- PlatformControllerGetPlatformListResponse,
189
- PlatformControllerMatchPlatformsData,
190
- PlatformControllerMatchPlatformsResponse,
191
- PlatformControllerUpdateData,
192
- PlatformControllerUpdateResponse,
193
- PlatformControllerDeleteData,
194
- PlatformControllerDeleteResponse,
195
233
  ProviderSyncControllerSyncData,
196
234
  ProviderSyncControllerSyncResponse,
197
235
  ProviderSyncControllerGetSupportedProvidersData,
198
236
  ProviderSyncControllerGetSupportedProvidersResponse,
199
237
  ProviderSyncControllerIsProviderSupportedData,
200
238
  ProviderSyncControllerIsProviderSupportedResponse,
239
+ ExternalAccountLinkControllerCreateData,
240
+ ExternalAccountLinkControllerCreateResponse,
241
+ ExternalAccountLinkControllerFindAllData,
242
+ ExternalAccountLinkControllerFindAllResponse,
243
+ ExternalAccountLinkControllerFindOneData,
244
+ ExternalAccountLinkControllerFindOneResponse,
245
+ ExternalAccountLinkControllerRemoveData,
246
+ ExternalAccountLinkControllerRemoveResponse,
201
247
  TelemetryControllerReportTelemetryData,
202
248
  TelemetryControllerReportTelemetryResponse,
249
+ TelemetryControllerReportCoverageMissData,
250
+ TelemetryControllerReportCoverageMissResponse,
251
+ TelemetryControllerGetCoverageMetricsData,
252
+ TelemetryControllerGetCoverageMetricsResponse,
203
253
  NlpControllerProcessNaturalLanguageData,
204
254
  NlpControllerProcessNaturalLanguageResponse,
205
255
  NlpControllerClearSessionData,
206
256
  NlpControllerClearSessionResponse,
207
257
  NlpControllerGetSessionData,
208
258
  NlpControllerGetSessionResponse,
259
+ PlatformControllerFindAllResponse,
260
+ PlatformControllerCreateData,
261
+ PlatformControllerCreateResponse,
262
+ PlatformControllerGetPlatformListData,
263
+ PlatformControllerGetPlatformListResponse,
264
+ PlatformControllerMatchPlatformsData,
265
+ PlatformControllerMatchPlatformsResponse,
266
+ PlatformControllerUpdateData,
267
+ PlatformControllerUpdateResponse,
268
+ PlatformControllerDeleteData,
269
+ PlatformControllerDeleteResponse,
209
270
  DashboardControllerGetNetWorthData,
210
271
  DashboardControllerGetNetWorthResponse,
211
272
  DashboardControllerGetAccountsData,
212
273
  DashboardControllerGetAccountsResponse,
213
274
  DashboardControllerGetCashFlowData,
214
275
  DashboardControllerGetCashFlowResponse,
215
- ReportingControllerGetPortfolioTrendsData,
216
- ReportingControllerGetPortfolioTrendsResponse,
217
- ReportingControllerGenerateSnapshotData,
218
- ReportingControllerGenerateSnapshotResponse,
219
- ReportingControllerBackfillSnapshotsData,
220
- ReportingControllerBackfillSnapshotsResponse,
276
+ DashboardControllerGetExpensesData,
277
+ DashboardControllerGetExpensesResponse,
278
+ HoldingPnlControllerGetHoldingPnlData,
279
+ HoldingPnlControllerGetHoldingPnlResponse,
221
280
  ApiKeysControllerCreateApiKeyResponse,
222
281
  AuthControllerAccessTokenLoginData,
223
282
  AuthControllerAccessTokenLoginResponse,
283
+ ParserContributionControllerCreateData,
284
+ ParserContributionControllerCreateResponse,
224
285
  CacheControllerFlushCacheResponse,
225
286
  ExchangeRateControllerGetExchangeRateData,
226
287
  ExchangeRateControllerGetExchangeRateResponse,
@@ -232,7 +293,11 @@ import type {
232
293
  HealthControllerResetCircuitBreakerData,
233
294
  HealthControllerResetCircuitBreakerResponse,
234
295
  HealthControllerGetMetricsResponse,
235
- InfoControllerGetInfoResponse
296
+ InfoControllerGetInfoResponse,
297
+ SymbolControllerSearchData,
298
+ SymbolControllerSearchResponse,
299
+ SymbolControllerGetQuoteData,
300
+ SymbolControllerGetQuoteResponse
236
301
  } from './types.gen';
237
302
 
238
303
  export class BeanAccountsService {
@@ -270,7 +335,7 @@ export class BeanAccountsService {
270
335
  * @param data.type Filter by account type
271
336
  * @param data.status Filter by status
272
337
  * @param data.isCustom Filter by custom (user-created) accounts only
273
- * @param data.search Search term for path or i18nKey
338
+ * @param data.search Search term for account path
274
339
  * @param data.limit Maximum number of results
275
340
  * @param data.offset Number of results to skip
276
341
  * @returns AccountListResponseDto Accounts retrieved successfully
@@ -351,7 +416,7 @@ export class BeanAccountsService {
351
416
 
352
417
  /**
353
418
  * Delete account
354
- * Deletes an account (only if no transactions)
419
+ * Deletes an account (only if no active transactions; voided/superseded residual postings are cleaned up)
355
420
  * @param data The data for the request.
356
421
  * @param data.id Account UUID
357
422
  * @param data.region Region code for tenant context
@@ -370,7 +435,7 @@ export class BeanAccountsService {
370
435
  },
371
436
  errors: {
372
437
  404: 'Account not found',
373
- 409: 'Account has transactions and cannot be deleted'
438
+ 409: 'Account has active transactions and cannot be deleted'
374
439
  }
375
440
  });
376
441
  }
@@ -432,6 +497,35 @@ export class BeanAccountsService {
432
497
  }
433
498
  });
434
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
+ }
435
529
  }
436
530
 
437
531
  export class BeanAccountStandardsService {
@@ -463,7 +557,7 @@ export class BeanAccountStandardsService {
463
557
 
464
558
  /**
465
559
  * Get template metadata for an account path
466
- * Returns extendable status and root type for a template path.
560
+ * Returns root type for a template path.
467
561
  * @param data The data for the request.
468
562
  * @param data.region Region code for tenant context
469
563
  * @param data.path Account path to check
@@ -549,6 +643,8 @@ export class BeanTransactionsService {
549
643
  * @param data.status Filter by transaction status
550
644
  * @param data.search Search in narration and payee fields (max 200 chars)
551
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.
552
648
  * @returns TransactionListResponseDto Transaction list
553
649
  * @throws ApiError
554
650
  */
@@ -568,7 +664,9 @@ export class BeanTransactionsService {
568
664
  dateTo: data.dateTo,
569
665
  status: data.status,
570
666
  search: data.search,
571
- accountId: data.accountId
667
+ accountId: data.accountId,
668
+ category: data.category,
669
+ flow: data.flow
572
670
  },
573
671
  errors: {
574
672
  400: 'Validation failed',
@@ -605,6 +703,36 @@ export class BeanTransactionsService {
605
703
  });
606
704
  }
607
705
 
706
+ /**
707
+ * Correct (supersede) a transaction
708
+ * Atomically voids the original (SUPERSEDED) and creates a replacement through the full validation pipeline.
709
+ * @param data The data for the request.
710
+ * @param data.id Original transaction ID to correct
711
+ * @param data.region Region code for tenant context
712
+ * @param data.requestBody
713
+ * @returns TransactionDetailDto Corrected transaction created
714
+ * @throws ApiError
715
+ */
716
+ public static transactionControllerCorrect(
717
+ data: TransactionControllerCorrectData
718
+ ): CancelablePromise<TransactionControllerCorrectResponse> {
719
+ return __request(OpenAPI, {
720
+ method: 'POST',
721
+ url: '/api/v1/{region}/bean/transactions/{id}/correct',
722
+ path: {
723
+ id: data.id,
724
+ region: data.region
725
+ },
726
+ body: data.requestBody,
727
+ mediaType: 'application/json',
728
+ errors: {
729
+ 404: 'Original transaction not found',
730
+ 409: 'Original no longer ACTIVE (concurrent modification)',
731
+ 422: 'Pipeline validation failed (does not balance, invalid accounts)'
732
+ }
733
+ });
734
+ }
735
+
608
736
  /**
609
737
  * Suggest transaction tags
610
738
  * Returns distinct tags from the user ACTIVE transactions, sorted by usage, for autocomplete. Optional q performs a case-insensitive prefix match.
@@ -726,7 +854,7 @@ export class BeanBalancesService {
726
854
  * Query account balance
727
855
  * Calculate account balance at a specific date for a single currency
728
856
  * @param data The data for the request.
729
- * @param data.account Account name (e.g., "Assets:Bank:Checking")
857
+ * @param data.account Account name (e.g., "Assets:Checking")
730
858
  * @param data.region Region code for tenant context
731
859
  * @param data.date Date to calculate balance at (ISO 8601 format)
732
860
  * @param data.currency Currency to query (e.g., "USD", "CNY")
@@ -1447,6 +1575,173 @@ export class BeanCommoditiesService {
1447
1575
  }
1448
1576
  }
1449
1577
 
1578
+ export class BeanPricesService {
1579
+ /**
1580
+ * Create a new price
1581
+ * Creates a new price entry for the authenticated user
1582
+ * @param data The data for the request.
1583
+ * @param data.region Region code for tenant context
1584
+ * @param data.requestBody
1585
+ * @returns PriceResponseDto Price created successfully
1586
+ * @throws ApiError
1587
+ */
1588
+ public static priceControllerCreate(
1589
+ data: PriceControllerCreateData
1590
+ ): CancelablePromise<PriceControllerCreateResponse> {
1591
+ return __request(OpenAPI, {
1592
+ method: 'POST',
1593
+ url: '/api/v1/{region}/bean/prices',
1594
+ path: {
1595
+ region: data.region
1596
+ },
1597
+ body: data.requestBody,
1598
+ mediaType: 'application/json',
1599
+ errors: {
1600
+ 404: 'Currency or quoteCurrency commodity not found',
1601
+ 409: 'Price already exists for this currency pair and date'
1602
+ }
1603
+ });
1604
+ }
1605
+
1606
+ /**
1607
+ * List user prices
1608
+ * Returns all price entries for the authenticated user with optional filtering
1609
+ * @param data The data for the request.
1610
+ * @param data.region Region code for tenant context
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
1619
+ * @throws ApiError
1620
+ */
1621
+ public static priceControllerFindAll(
1622
+ data: PriceControllerFindAllData
1623
+ ): CancelablePromise<PriceControllerFindAllResponse> {
1624
+ return __request(OpenAPI, {
1625
+ method: 'GET',
1626
+ url: '/api/v1/{region}/bean/prices',
1627
+ path: {
1628
+ region: data.region
1629
+ },
1630
+ query: {
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
1638
+ }
1639
+ });
1640
+ }
1641
+
1642
+ /**
1643
+ * Get price by ID
1644
+ * Returns a single price entry by its ID
1645
+ * @param data The data for the request.
1646
+ * @param data.id Price ID
1647
+ * @param data.region Region code for tenant context
1648
+ * @returns PriceResponseDto Price retrieved successfully
1649
+ * @throws ApiError
1650
+ */
1651
+ public static priceControllerFindOne(
1652
+ data: PriceControllerFindOneData
1653
+ ): CancelablePromise<PriceControllerFindOneResponse> {
1654
+ return __request(OpenAPI, {
1655
+ method: 'GET',
1656
+ url: '/api/v1/{region}/bean/prices/{id}',
1657
+ path: {
1658
+ id: data.id,
1659
+ region: data.region
1660
+ },
1661
+ errors: {
1662
+ 404: 'Price not found'
1663
+ }
1664
+ });
1665
+ }
1666
+
1667
+ /**
1668
+ * Update a price
1669
+ * Updates an existing price entry
1670
+ * @param data The data for the request.
1671
+ * @param data.id Price ID
1672
+ * @param data.region Region code for tenant context
1673
+ * @param data.requestBody
1674
+ * @returns PriceResponseDto Price updated successfully
1675
+ * @throws ApiError
1676
+ */
1677
+ public static priceControllerUpdate(
1678
+ data: PriceControllerUpdateData
1679
+ ): CancelablePromise<PriceControllerUpdateResponse> {
1680
+ return __request(OpenAPI, {
1681
+ method: 'PUT',
1682
+ url: '/api/v1/{region}/bean/prices/{id}',
1683
+ path: {
1684
+ id: data.id,
1685
+ region: data.region
1686
+ },
1687
+ body: data.requestBody,
1688
+ mediaType: 'application/json',
1689
+ errors: {
1690
+ 404: 'Price not found',
1691
+ 409: 'Updated price conflicts with existing price'
1692
+ }
1693
+ });
1694
+ }
1695
+
1696
+ /**
1697
+ * Delete a price
1698
+ * Deletes a price entry (hard delete)
1699
+ * @param data The data for the request.
1700
+ * @param data.id Price ID
1701
+ * @param data.region Region code for tenant context
1702
+ * @returns void Price deleted successfully
1703
+ * @throws ApiError
1704
+ */
1705
+ public static priceControllerDelete(
1706
+ data: PriceControllerDeleteData
1707
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1708
+ return __request(OpenAPI, {
1709
+ method: 'DELETE',
1710
+ url: '/api/v1/{region}/bean/prices/{id}',
1711
+ path: {
1712
+ id: data.id,
1713
+ region: data.region
1714
+ },
1715
+ errors: {
1716
+ 404: 'Price not found'
1717
+ }
1718
+ });
1719
+ }
1720
+
1721
+ /**
1722
+ * Bulk create prices
1723
+ * Creates multiple price entries at once (skips duplicates)
1724
+ * @param data The data for the request.
1725
+ * @param data.region Region code for tenant context
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
+
1450
1745
  export class RecurringRulesService {
1451
1746
  /**
1452
1747
  * Create a new recurring rule
@@ -1877,279 +2172,158 @@ export class RecurringForecastService {
1877
2172
  }
1878
2173
  }
1879
2174
 
1880
- export class BeanTransactionRulesService {
2175
+ export class ReportingService {
1881
2176
  /**
1882
- * Create a new transaction rule (or upsert if upsertByPayee=true)
1883
- * 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
+ *
1884
2190
  * @param data The data for the request.
1885
2191
  * @param data.region Region code for tenant context
1886
- * @param data.requestBody
1887
- * @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
1888
2195
  * @throws ApiError
1889
2196
  */
1890
- public static transactionRuleControllerCreate(
1891
- data: TransactionRuleControllerCreateData
1892
- ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2197
+ public static reportingControllerGetPortfolioTrends(
2198
+ data: ReportingControllerGetPortfolioTrendsData
2199
+ ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
1893
2200
  return __request(OpenAPI, {
1894
- method: 'POST',
1895
- url: '/api/v1/{region}/bean/transaction-rules',
1896
- path: {
1897
- region: data.region
1898
- },
1899
- body: data.requestBody,
1900
- mediaType: 'application/json',
1901
- errors: {
1902
- 400: 'Validation failed',
1903
- 401: 'Unauthorized',
1904
- 409: 'Resource conflict - another process is updating this rule'
1905
- }
1906
- });
1907
- }
1908
-
1909
- /**
1910
- * Get all transaction rules for user
1911
- * @param data The data for the request.
1912
- * @param data.region Region code for tenant context
1913
- * @param data.limit Max results per page (default: 20, max: 100)
1914
- * @param data.offset Pagination offset (default: 0)
1915
- * @param data.enabled Filter by enabled status
1916
- * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
1917
- * @param data.autoApplyEnabled Filter by auto-apply status
1918
- * @returns TransactionRuleListResponseDto List of rules
1919
- * @throws ApiError
1920
- */
1921
- public static transactionRuleControllerList(
1922
- data: TransactionRuleControllerListData
1923
- ): CancelablePromise<TransactionRuleControllerListResponse> {
1924
- return __request(OpenAPI, {
1925
- method: 'GET',
1926
- url: '/api/v1/{region}/bean/transaction-rules',
2201
+ method: 'GET',
2202
+ url: '/api/v1/{region}/reporting/portfolio/trends',
1927
2203
  path: {
1928
2204
  region: data.region
1929
2205
  },
1930
2206
  query: {
1931
- limit: data.limit,
1932
- offset: data.offset,
1933
- enabled: data.enabled,
1934
- learningSource: data.learningSource,
1935
- autoApplyEnabled: data.autoApplyEnabled
1936
- },
1937
- errors: {
1938
- 401: 'Unauthorized'
1939
- }
1940
- });
1941
- }
1942
-
1943
- /**
1944
- * Validate transaction rule configuration
1945
- * @param data The data for the request.
1946
- * @param data.region Region code for tenant context
1947
- * @param data.requestBody
1948
- * @returns ValidateRuleResponseDto Validation result
1949
- * @throws ApiError
1950
- */
1951
- public static transactionRuleControllerValidate(
1952
- data: TransactionRuleControllerValidateData
1953
- ): CancelablePromise<TransactionRuleControllerValidateResponse> {
1954
- return __request(OpenAPI, {
1955
- method: 'POST',
1956
- url: '/api/v1/{region}/bean/transaction-rules/validate',
1957
- path: {
1958
- region: data.region
1959
- },
1960
- body: data.requestBody,
1961
- mediaType: 'application/json',
1962
- errors: {
1963
- 400: 'Validation failed',
1964
- 401: 'Unauthorized'
1965
- }
1966
- });
1967
- }
1968
-
1969
- /**
1970
- * Bulk create transaction rules
1971
- * @param data The data for the request.
1972
- * @param data.region Region code for tenant context
1973
- * @param data.requestBody
1974
- * @returns BulkCreateRulesResponseDto Bulk create completed
1975
- * @throws ApiError
1976
- */
1977
- public static transactionRuleControllerBulkCreate(
1978
- data: TransactionRuleControllerBulkCreateData
1979
- ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
1980
- return __request(OpenAPI, {
1981
- method: 'POST',
1982
- url: '/api/v1/{region}/bean/transaction-rules/bulk',
1983
- path: {
1984
- region: data.region
2207
+ period: data.period,
2208
+ granularity: data.granularity
1985
2209
  },
1986
- body: data.requestBody,
1987
- mediaType: 'application/json',
1988
2210
  errors: {
1989
- 400: 'Invalid bulk create data',
1990
- 401: 'Unauthorized'
2211
+ 401: 'User not authenticated'
1991
2212
  }
1992
2213
  });
1993
2214
  }
1994
2215
 
1995
2216
  /**
1996
- * Export transaction rules
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
+ *
1997
2226
  * @param data The data for the request.
1998
- * @param data.format Export format (currently only JSON supported)
1999
2227
  * @param data.region Region code for tenant context
2000
- * @returns ExportRulesResponseDto Exported 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
2001
2231
  * @throws ApiError
2002
2232
  */
2003
- public static transactionRuleControllerExport(
2004
- data: TransactionRuleControllerExportData
2005
- ): CancelablePromise<TransactionRuleControllerExportResponse> {
2233
+ public static reportingControllerGetCashFlowTrends(
2234
+ data: ReportingControllerGetCashFlowTrendsData
2235
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
2006
2236
  return __request(OpenAPI, {
2007
2237
  method: 'GET',
2008
- url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2238
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
2009
2239
  path: {
2010
- format: data.format,
2011
2240
  region: data.region
2012
2241
  },
2013
- errors: {
2014
- 400: 'Unsupported format',
2015
- 401: 'Unauthorized'
2016
- }
2017
- });
2018
- }
2019
-
2020
- /**
2021
- * Get transaction rule statistics
2022
- * @param data The data for the request.
2023
- * @param data.period Statistics time period
2024
- * @param data.region Region code for tenant context
2025
- * @returns RuleStatisticsResponseDto Rule statistics
2026
- * @throws ApiError
2027
- */
2028
- public static transactionRuleControllerGetStatistics(
2029
- data: TransactionRuleControllerGetStatisticsData
2030
- ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2031
- return __request(OpenAPI, {
2032
- method: 'GET',
2033
- url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2034
- path: {
2242
+ query: {
2035
2243
  period: data.period,
2036
- region: data.region
2037
- },
2038
- errors: {
2039
- 401: 'Unauthorized'
2040
- }
2041
- });
2042
- }
2043
-
2044
- /**
2045
- * Get transaction rule detail
2046
- * @param data The data for the request.
2047
- * @param data.ruleId Rule ID
2048
- * @param data.region Region code for tenant context
2049
- * @returns TransactionRuleResponseDto Rule details
2050
- * @throws ApiError
2051
- */
2052
- public static transactionRuleControllerGetDetail(
2053
- data: TransactionRuleControllerGetDetailData
2054
- ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2055
- return __request(OpenAPI, {
2056
- method: 'GET',
2057
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2058
- path: {
2059
- ruleId: data.ruleId,
2060
- region: data.region
2244
+ granularity: data.granularity
2061
2245
  },
2062
2246
  errors: {
2063
- 401: 'Unauthorized',
2064
- 403: 'Forbidden - not owner of rule',
2065
- 404: 'Rule not found'
2247
+ 401: 'User not authenticated'
2066
2248
  }
2067
2249
  });
2068
2250
  }
2069
2251
 
2070
2252
  /**
2071
- * Update a transaction rule
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
+ *
2072
2267
  * @param data The data for the request.
2073
- * @param data.ruleId Rule ID to update
2074
2268
  * @param data.region Region code for tenant context
2075
- * @param data.requestBody
2076
- * @returns TransactionRuleResponseDto Rule updated successfully
2269
+ * @param data.requestBody Optional date (defaults to today)
2270
+ * @returns GenerateSnapshotResponse Snapshot generated successfully
2077
2271
  * @throws ApiError
2078
2272
  */
2079
- public static transactionRuleControllerUpdate(
2080
- data: TransactionRuleControllerUpdateData
2081
- ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2273
+ public static reportingControllerGenerateSnapshot(
2274
+ data: ReportingControllerGenerateSnapshotData
2275
+ ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
2082
2276
  return __request(OpenAPI, {
2083
- method: 'PUT',
2084
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2277
+ method: 'POST',
2278
+ url: '/api/v1/{region}/reporting/snapshots/generate',
2085
2279
  path: {
2086
- ruleId: data.ruleId,
2087
2280
  region: data.region
2088
2281
  },
2089
2282
  body: data.requestBody,
2090
2283
  mediaType: 'application/json',
2091
2284
  errors: {
2092
- 400: 'Validation failed',
2093
- 401: 'Unauthorized',
2094
- 403: 'Forbidden - not owner of rule',
2095
- 404: 'Rule not found',
2096
- 409: 'Resource conflict - rule is being modified by another process'
2097
- }
2098
- });
2099
- }
2100
-
2101
- /**
2102
- * Delete a transaction rule
2103
- * @param data The data for the request.
2104
- * @param data.ruleId Rule ID to delete
2105
- * @param data.region Region code for tenant context
2106
- * @returns void Rule deleted successfully
2107
- * @throws ApiError
2108
- */
2109
- public static transactionRuleControllerDelete(
2110
- data: TransactionRuleControllerDeleteData
2111
- ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2112
- return __request(OpenAPI, {
2113
- method: 'DELETE',
2114
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2115
- path: {
2116
- ruleId: data.ruleId,
2117
- region: data.region
2118
- },
2119
- errors: {
2120
- 401: 'Unauthorized',
2121
- 403: 'Forbidden - not owner of rule',
2122
- 404: 'Rule not found',
2123
- 409: 'Resource conflict - rule is being modified by another process'
2285
+ 400: 'Invalid date format',
2286
+ 401: 'User not authenticated'
2124
2287
  }
2125
2288
  });
2126
2289
  }
2127
2290
 
2128
2291
  /**
2129
- * 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
+ *
2130
2306
  * @param data The data for the request.
2131
- * @param data.ruleId Rule ID to test
2132
2307
  * @param data.region Region code for tenant context
2133
2308
  * @param data.requestBody
2134
- * @returns TestRuleResponseDto Test result
2309
+ * @returns BackfillSnapshotsResponse Backfill completed successfully
2135
2310
  * @throws ApiError
2136
2311
  */
2137
- public static transactionRuleControllerTest(
2138
- data: TransactionRuleControllerTestData
2139
- ): CancelablePromise<TransactionRuleControllerTestResponse> {
2312
+ public static reportingControllerBackfillSnapshots(
2313
+ data: ReportingControllerBackfillSnapshotsData
2314
+ ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
2140
2315
  return __request(OpenAPI, {
2141
2316
  method: 'POST',
2142
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2317
+ url: '/api/v1/{region}/reporting/snapshots/backfill',
2143
2318
  path: {
2144
- ruleId: data.ruleId,
2145
2319
  region: data.region
2146
2320
  },
2147
2321
  body: data.requestBody,
2148
2322
  mediaType: 'application/json',
2149
2323
  errors: {
2150
- 401: 'Unauthorized',
2151
- 403: 'Forbidden - not owner of rule',
2152
- 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'
2153
2327
  }
2154
2328
  });
2155
2329
  }
@@ -2181,7 +2355,7 @@ export class UsersService {
2181
2355
  * Get current authenticated user
2182
2356
  * @param data The data for the request.
2183
2357
  * @param data.acceptLanguage
2184
- * @returns unknown User retrieved successfully
2358
+ * @returns UserResponseDto User retrieved successfully
2185
2359
  * @throws ApiError
2186
2360
  */
2187
2361
  public static userControllerGetUser(
@@ -2201,7 +2375,7 @@ export class UsersService {
2201
2375
  * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
2202
2376
  * @param data The data for the request.
2203
2377
  * @param data.requestBody
2204
- * @returns unknown User created successfully
2378
+ * @returns SignupResponseDto User created successfully
2205
2379
  * @throws ApiError
2206
2380
  */
2207
2381
  public static userControllerSignupUser(
@@ -2410,10 +2584,624 @@ export class PropertiesService {
2410
2584
  }
2411
2585
  }
2412
2586
 
2413
- export class BeanExportService {
2587
+ export class BeanTransactionRulesService {
2414
2588
  /**
2415
- * Export Beancount ledger as ZIP
2416
- * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
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.
2591
+ * @param data The data for the request.
2592
+ * @param data.region Region code for tenant context
2593
+ * @param data.requestBody
2594
+ * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2595
+ * @throws ApiError
2596
+ */
2597
+ public static transactionRuleControllerCreate(
2598
+ data: TransactionRuleControllerCreateData
2599
+ ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2600
+ return __request(OpenAPI, {
2601
+ method: 'POST',
2602
+ url: '/api/v1/{region}/bean/transaction-rules',
2603
+ path: {
2604
+ region: data.region
2605
+ },
2606
+ body: data.requestBody,
2607
+ mediaType: 'application/json',
2608
+ errors: {
2609
+ 400: 'Validation failed',
2610
+ 401: 'Unauthorized',
2611
+ 409: 'Resource conflict - another process is updating this rule'
2612
+ }
2613
+ });
2614
+ }
2615
+
2616
+ /**
2617
+ * Get all transaction rules for user
2618
+ * @param data The data for the request.
2619
+ * @param data.region Region code for tenant context
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
2626
+ * @throws ApiError
2627
+ */
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',
2634
+ path: {
2635
+ region: data.region
2636
+ },
2637
+ query: {
2638
+ limit: data.limit,
2639
+ offset: data.offset,
2640
+ enabled: data.enabled,
2641
+ learningSource: data.learningSource,
2642
+ autoApplyEnabled: data.autoApplyEnabled
2643
+ },
2644
+ errors: {
2645
+ 401: 'Unauthorized'
2646
+ }
2647
+ });
2648
+ }
2649
+
2650
+ /**
2651
+ * Validate transaction rule configuration
2652
+ * @param data The data for the request.
2653
+ * @param data.region Region code for tenant context
2654
+ * @param data.requestBody
2655
+ * @returns ValidateRuleResponseDto Validation result
2656
+ * @throws ApiError
2657
+ */
2658
+ public static transactionRuleControllerValidate(
2659
+ data: TransactionRuleControllerValidateData
2660
+ ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2661
+ return __request(OpenAPI, {
2662
+ method: 'POST',
2663
+ url: '/api/v1/{region}/bean/transaction-rules/validate',
2664
+ path: {
2665
+ region: data.region
2666
+ },
2667
+ body: data.requestBody,
2668
+ mediaType: 'application/json',
2669
+ errors: {
2670
+ 400: 'Validation failed',
2671
+ 401: 'Unauthorized'
2672
+ }
2673
+ });
2674
+ }
2675
+
2676
+ /**
2677
+ * Bulk create transaction rules
2678
+ * @param data The data for the request.
2679
+ * @param data.region Region code for tenant context
2680
+ * @param data.requestBody
2681
+ * @returns BulkCreateRulesResponseDto Bulk create completed
2682
+ * @throws ApiError
2683
+ */
2684
+ public static transactionRuleControllerBulkCreate(
2685
+ data: TransactionRuleControllerBulkCreateData
2686
+ ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2687
+ return __request(OpenAPI, {
2688
+ method: 'POST',
2689
+ url: '/api/v1/{region}/bean/transaction-rules/bulk',
2690
+ path: {
2691
+ region: data.region
2692
+ },
2693
+ body: data.requestBody,
2694
+ mediaType: 'application/json',
2695
+ errors: {
2696
+ 400: 'Invalid bulk create data',
2697
+ 401: 'Unauthorized'
2698
+ }
2699
+ });
2700
+ }
2701
+
2702
+ /**
2703
+ * Export transaction rules
2704
+ * @param data The data for the request.
2705
+ * @param data.format Export format (currently only JSON supported)
2706
+ * @param data.region Region code for tenant context
2707
+ * @returns ExportRulesResponseDto Exported rules
2708
+ * @throws ApiError
2709
+ */
2710
+ public static transactionRuleControllerExport(
2711
+ data: TransactionRuleControllerExportData
2712
+ ): CancelablePromise<TransactionRuleControllerExportResponse> {
2713
+ return __request(OpenAPI, {
2714
+ method: 'GET',
2715
+ url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2716
+ path: {
2717
+ format: data.format,
2718
+ region: data.region
2719
+ },
2720
+ errors: {
2721
+ 400: 'Unsupported format',
2722
+ 401: 'Unauthorized'
2723
+ }
2724
+ });
2725
+ }
2726
+
2727
+ /**
2728
+ * Get transaction rule statistics
2729
+ * @param data The data for the request.
2730
+ * @param data.period Statistics time period
2731
+ * @param data.region Region code for tenant context
2732
+ * @returns RuleStatisticsResponseDto Rule statistics
2733
+ * @throws ApiError
2734
+ */
2735
+ public static transactionRuleControllerGetStatistics(
2736
+ data: TransactionRuleControllerGetStatisticsData
2737
+ ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2738
+ return __request(OpenAPI, {
2739
+ method: 'GET',
2740
+ url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2741
+ path: {
2742
+ period: data.period,
2743
+ region: data.region
2744
+ },
2745
+ errors: {
2746
+ 401: 'Unauthorized'
2747
+ }
2748
+ });
2749
+ }
2750
+
2751
+ /**
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
2757
+ * @throws ApiError
2758
+ */
2759
+ public static transactionRuleControllerGetDetail(
2760
+ data: TransactionRuleControllerGetDetailData
2761
+ ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2762
+ return __request(OpenAPI, {
2763
+ method: 'GET',
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
+ }
2774
+ });
2775
+ }
2776
+
2777
+ /**
2778
+ * Update a transaction rule
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
2782
+ * @param data.requestBody
2783
+ * @returns TransactionRuleResponseDto Rule updated successfully
2784
+ * @throws ApiError
2785
+ */
2786
+ public static transactionRuleControllerUpdate(
2787
+ data: TransactionRuleControllerUpdateData
2788
+ ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2789
+ return __request(OpenAPI, {
2790
+ method: 'PUT',
2791
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2792
+ path: {
2793
+ ruleId: data.ruleId,
2794
+ region: data.region
2795
+ },
2796
+ body: data.requestBody,
2797
+ mediaType: 'application/json',
2798
+ errors: {
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'
2804
+ }
2805
+ });
2806
+ }
2807
+
2808
+ /**
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
2814
+ * @throws ApiError
2815
+ */
2816
+ public static transactionRuleControllerDelete(
2817
+ data: TransactionRuleControllerDeleteData
2818
+ ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2819
+ return __request(OpenAPI, {
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
+ }
2832
+ });
2833
+ }
2834
+
2835
+ /**
2836
+ * Test rule matching
2837
+ * @param data The data for the request.
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
2842
+ * @throws ApiError
2843
+ */
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> {
2879
+ return __request(OpenAPI, {
2880
+ method: 'GET',
2881
+ url: '/api/v1/{region}/bean/categories',
2882
+ path: {
2883
+ region: data.region
2884
+ },
2885
+ query: {
2886
+ scenario: data.scenario,
2887
+ routeBearing: data.routeBearing
2888
+ }
2889
+ });
2890
+ }
2891
+ }
2892
+
2893
+ export class LifeEventsService {
2894
+ /**
2895
+ * Create a new life event
2896
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2897
+ * @param data The data for the request.
2898
+ * @param data.region Region code for tenant context (decorative for life events)
2899
+ * @param data.requestBody
2900
+ * @returns EventResponseDto Life event created successfully
2901
+ * @throws ApiError
2902
+ */
2903
+ public static eventControllerCreate(
2904
+ data: EventControllerCreateData
2905
+ ): CancelablePromise<EventControllerCreateResponse> {
2906
+ return __request(OpenAPI, {
2907
+ method: 'POST',
2908
+ url: '/api/v1/{region}/bean/events',
2909
+ path: {
2910
+ region: data.region
2911
+ },
2912
+ body: data.requestBody,
2913
+ mediaType: 'application/json',
2914
+ errors: {
2915
+ 409: 'Life event already exists for this (userId, type, date) combination'
2916
+ }
2917
+ });
2918
+ }
2919
+
2920
+ /**
2921
+ * List user life events
2922
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2923
+ * @param data The data for the request.
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
2932
+ * @throws ApiError
2933
+ */
2934
+ public static eventControllerFindAll(
2935
+ data: EventControllerFindAllData
2936
+ ): CancelablePromise<EventControllerFindAllResponse> {
2937
+ return __request(OpenAPI, {
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.
2417
3205
  * @returns unknown
2418
3206
  * @throws ApiError
2419
3207
  */
@@ -2476,438 +3264,588 @@ export class BeanImportService {
2476
3264
  formData: data.formData,
2477
3265
  mediaType: 'multipart/form-data',
2478
3266
  errors: {
2479
- 400: 'Bad request - No file uploaded'
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',
3368
+ path: {
3369
+ importerId: data.importerId,
3370
+ region: data.region
3371
+ },
3372
+ errors: {
3373
+ 400: 'Invalid input - Unsupported importer'
3374
+ }
3375
+ });
3376
+ }
3377
+ }
3378
+
3379
+ export class ProviderSyncService {
3380
+ /**
3381
+ * Sync transactions from financial data provider
3382
+ *
3383
+ * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
3384
+ *
3385
+ * **Supported Providers:**
3386
+ * - **plaid**: Plaid API (US, Canada, Europe)
3387
+ * - **teller**: Teller API (US)
3388
+ * - **truelayer**: TrueLayer Open Banking (UK, Europe)
3389
+ * - **gocardless**: GoCardless Bank Account Data (Europe)
3390
+ * - **simplefin**: SimpleFIN (Self-hosted)
3391
+ * - **yodlee**: Yodlee (Global)
3392
+ * - **beancount-direct**: Beancount format transactions
3393
+ * - **parsed-bill**: Client-side parsed bill transactions
3394
+ *
3395
+ * **Processing Flow:**
3396
+ * 1. Transform raw data via provider adapter
3397
+ * 2. Validate transaction format
3398
+ * 3. Deduplicate using originalId
3399
+ * 4. Classify using rule engine
3400
+ * 5. Route low-confidence to Review Center
3401
+ * 6. Persist validated transactions
3402
+ *
3403
+ * @param data The data for the request.
3404
+ * @param data.providerName Provider name
3405
+ * @param data.region Region code for tenant context
3406
+ * @param data.requestBody
3407
+ * @returns ProviderSyncResponseDto Sync completed successfully
3408
+ * @throws ApiError
3409
+ */
3410
+ public static providerSyncControllerSync(
3411
+ data: ProviderSyncControllerSyncData
3412
+ ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3413
+ return __request(OpenAPI, {
3414
+ method: 'POST',
3415
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3416
+ path: {
3417
+ providerName: data.providerName,
3418
+ region: data.region
3419
+ },
3420
+ body: data.requestBody,
3421
+ mediaType: 'application/json',
3422
+ errors: {
3423
+ 400: 'Invalid request data',
3424
+ 401: 'Missing or invalid authentication',
3425
+ 404: 'Provider not supported'
3426
+ }
3427
+ });
3428
+ }
3429
+
3430
+ /**
3431
+ * Get supported providers
3432
+ * Returns a list of all providers supported by the sync endpoint.
3433
+ * @param data The data for the request.
3434
+ * @param data.region Region code for tenant context
3435
+ * @returns SupportedProvidersResponseDto List of supported providers
3436
+ * @throws ApiError
3437
+ */
3438
+ public static providerSyncControllerGetSupportedProviders(
3439
+ data: ProviderSyncControllerGetSupportedProvidersData
3440
+ ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3441
+ return __request(OpenAPI, {
3442
+ method: 'GET',
3443
+ url: '/api/v1/{region}/bean/import/provider/supported',
3444
+ path: {
3445
+ region: data.region
3446
+ },
3447
+ errors: {
3448
+ 401: 'Missing or invalid authentication'
3449
+ }
3450
+ });
3451
+ }
3452
+
3453
+ /**
3454
+ * Check if provider is supported
3455
+ * Returns whether a specific provider is supported.
3456
+ * @param data The data for the request.
3457
+ * @param data.providerName Provider name to check
3458
+ * @param data.region Region code for tenant context
3459
+ * @returns unknown Provider support status
3460
+ * @throws ApiError
3461
+ */
3462
+ public static providerSyncControllerIsProviderSupported(
3463
+ data: ProviderSyncControllerIsProviderSupportedData
3464
+ ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3465
+ return __request(OpenAPI, {
3466
+ method: 'GET',
3467
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
3468
+ path: {
3469
+ providerName: data.providerName,
3470
+ region: data.region
3471
+ },
3472
+ errors: {
3473
+ 401: 'Missing or invalid authentication'
2480
3474
  }
2481
3475
  });
2482
3476
  }
3477
+ }
2483
3478
 
3479
+ export class ExternalAccountLinksService {
2484
3480
  /**
2485
- * Import a Beancount file in community format
2486
- * 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.
3481
+ * Create an external account BeanAccount mapping (ADR-0113)
2487
3482
  * @param data The data for the request.
2488
3483
  * @param data.region Region code for tenant context
2489
- * @param data.formData Beancount file to import
2490
- * @returns unknown Beancount file imported successfully
3484
+ * @param data.requestBody
3485
+ * @returns ExternalAccountLinkResponseDto Link created.
2491
3486
  * @throws ApiError
2492
3487
  */
2493
- public static fileImportControllerImportBeancount(
2494
- data: FileImportControllerImportBeancountData
2495
- ): CancelablePromise<FileImportControllerImportBeancountResponse> {
3488
+ public static externalAccountLinkControllerCreate(
3489
+ data: ExternalAccountLinkControllerCreateData
3490
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
2496
3491
  return __request(OpenAPI, {
2497
3492
  method: 'POST',
2498
- url: '/api/v1/{region}/bean/import/beancount',
3493
+ url: '/api/v1/{region}/bean/external-account-links',
2499
3494
  path: {
2500
3495
  region: data.region
2501
3496
  },
2502
- formData: data.formData,
2503
- mediaType: 'multipart/form-data',
3497
+ body: data.requestBody,
3498
+ mediaType: 'application/json',
2504
3499
  errors: {
2505
- 400: 'Bad request - invalid file or no file uploaded'
3500
+ 422: 'beanAccountId not owned, or an active link already exists.'
2506
3501
  }
2507
3502
  });
2508
3503
  }
2509
3504
 
2510
3505
  /**
2511
- * Get importer configuration
2512
- * Returns the current configuration for the specified importer. Creates default configuration if none exists.
3506
+ * List the user's active external account links
2513
3507
  * @param data The data for the request.
2514
- * @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
3508
+ * @param data.provider
2515
3509
  * @param data.region Region code for tenant context
2516
- * @returns ImporterConfigDto Configuration retrieved successfully
3510
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
2517
3511
  * @throws ApiError
2518
3512
  */
2519
- public static importerConfigControllerGetConfig(
2520
- data: ImporterConfigControllerGetConfigData
2521
- ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
3513
+ public static externalAccountLinkControllerFindAll(
3514
+ data: ExternalAccountLinkControllerFindAllData
3515
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
2522
3516
  return __request(OpenAPI, {
2523
3517
  method: 'GET',
2524
- url: '/api/v1/{region}/bean/import/config/{importerId}',
3518
+ url: '/api/v1/{region}/bean/external-account-links',
2525
3519
  path: {
2526
- importerId: data.importerId,
2527
3520
  region: data.region
2528
3521
  },
2529
- errors: {
2530
- 400: 'Invalid input - Unsupported importer',
2531
- 401: 'Unauthorized - Authentication required'
3522
+ query: {
3523
+ provider: data.provider
2532
3524
  }
2533
3525
  });
2534
3526
  }
2535
3527
 
2536
3528
  /**
2537
- * Update importer configuration
2538
- * Updates the configuration for the specified importer. Partial updates are supported.
3529
+ * Get a single external account link
2539
3530
  * @param data The data for the request.
2540
- * @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
3531
+ * @param data.id
2541
3532
  * @param data.region Region code for tenant context
2542
- * @param data.requestBody Partial configuration update. Only provided fields will be updated.
2543
- * @returns ImporterConfigDto Configuration updated successfully
3533
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
2544
3534
  * @throws ApiError
2545
3535
  */
2546
- public static importerConfigControllerUpdateConfig(
2547
- data: ImporterConfigControllerUpdateConfigData
2548
- ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
3536
+ public static externalAccountLinkControllerFindOne(
3537
+ data: ExternalAccountLinkControllerFindOneData
3538
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
2549
3539
  return __request(OpenAPI, {
2550
- method: 'PUT',
2551
- url: '/api/v1/{region}/bean/import/config/{importerId}',
3540
+ method: 'GET',
3541
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
2552
3542
  path: {
2553
- importerId: data.importerId,
3543
+ id: data.id,
2554
3544
  region: data.region
2555
3545
  },
2556
- body: data.requestBody,
2557
- mediaType: 'application/json',
2558
3546
  errors: {
2559
- 400: 'Invalid input - Validation failed',
2560
- 404: 'Configuration not found'
3547
+ 422: 'Link not found or not owned by the user.'
2561
3548
  }
2562
3549
  });
2563
3550
  }
2564
3551
 
2565
3552
  /**
2566
- * Reset configuration to default
2567
- * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
3553
+ * Soft-delete (disconnect) an external account link
2568
3554
  * @param data The data for the request.
2569
- * @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
3555
+ * @param data.id
2570
3556
  * @param data.region Region code for tenant context
2571
- * @returns ImporterConfigDto Configuration reset successfully
3557
+ * @returns void Link soft-deleted; historical transactions are unaffected.
2572
3558
  * @throws ApiError
2573
3559
  */
2574
- public static importerConfigControllerResetConfig(
2575
- data: ImporterConfigControllerResetConfigData
2576
- ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
3560
+ public static externalAccountLinkControllerRemove(
3561
+ data: ExternalAccountLinkControllerRemoveData
3562
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
2577
3563
  return __request(OpenAPI, {
2578
- method: 'POST',
2579
- url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
3564
+ method: 'DELETE',
3565
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
2580
3566
  path: {
2581
- importerId: data.importerId,
3567
+ id: data.id,
2582
3568
  region: data.region
2583
- },
2584
- errors: {
2585
- 400: 'Invalid input - Unsupported importer'
2586
3569
  }
2587
3570
  });
2588
3571
  }
2589
3572
  }
2590
3573
 
2591
- export class BeanPlatformsService {
2592
- /**
2593
- * Get all platforms with statistics
2594
- * @returns unknown List of platforms with binding and account counts
2595
- * @throws ApiError
2596
- */
2597
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2598
- return __request(OpenAPI, {
2599
- method: 'GET',
2600
- url: '/api/v1/bean/platforms'
2601
- });
2602
- }
2603
-
3574
+ export class ImportTelemetryService {
2604
3575
  /**
2605
- * Create a new platform
3576
+ * Receive anonymous parser failure telemetry
2606
3577
  * @param data The data for the request.
3578
+ * @param data.region Region code for tenant context
2607
3579
  * @param data.requestBody
2608
- * @returns unknown Platform created successfully
3580
+ * @returns unknown Telemetry report received
2609
3581
  * @throws ApiError
2610
3582
  */
2611
- public static platformControllerCreate(
2612
- data: PlatformControllerCreateData
2613
- ): CancelablePromise<PlatformControllerCreateResponse> {
3583
+ public static telemetryControllerReportTelemetry(
3584
+ data: TelemetryControllerReportTelemetryData
3585
+ ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
2614
3586
  return __request(OpenAPI, {
2615
3587
  method: 'POST',
2616
- url: '/api/v1/bean/platforms',
3588
+ url: '/api/v1/{region}/bean/import/parser-telemetry',
3589
+ path: {
3590
+ region: data.region
3591
+ },
2617
3592
  body: data.requestBody,
2618
3593
  mediaType: 'application/json',
2619
3594
  errors: {
2620
- 409: 'Platform already exists'
3595
+ 401: 'Unauthorized'
2621
3596
  }
2622
3597
  });
2623
3598
  }
2624
3599
 
2625
3600
  /**
2626
- * Get platform list for current user
2627
- * @returns unknown List of platforms with user binding status
3601
+ * Receive anonymous zero-hit coverage miss report
3602
+ * @param data The data for the request.
3603
+ * @param data.region Region code for tenant context
3604
+ * @param data.requestBody
3605
+ * @returns unknown Coverage miss report received
2628
3606
  * @throws ApiError
2629
3607
  */
2630
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3608
+ public static telemetryControllerReportCoverageMiss(
3609
+ data: TelemetryControllerReportCoverageMissData
3610
+ ): CancelablePromise<TelemetryControllerReportCoverageMissResponse> {
2631
3611
  return __request(OpenAPI, {
2632
- method: 'GET',
2633
- url: '/api/v1/bean/platforms/list'
3612
+ method: 'POST',
3613
+ url: '/api/v1/{region}/bean/import/parser-coverage-miss',
3614
+ path: {
3615
+ region: data.region
3616
+ },
3617
+ body: data.requestBody,
3618
+ mediaType: 'application/json',
3619
+ errors: {
3620
+ 401: 'Unauthorized'
3621
+ }
2634
3622
  });
2635
3623
  }
2636
3624
 
2637
3625
  /**
2638
- * Match platforms by name or alias
3626
+ * Coverage metrics (uncovered format aggregation)
2639
3627
  * @param data The data for the request.
2640
- * @param data.q Search query Chinese name, English name, or abbreviation
2641
- * @param data.region Region code for category override lookup
2642
- * @returns unknown List of matching platforms with suggested segment names
3628
+ * @param data.region Region code for tenant context
3629
+ * @param data.topN Top-N uncovered formats (default 10)
3630
+ * @returns unknown Coverage metrics
2643
3631
  * @throws ApiError
2644
3632
  */
2645
- public static platformControllerMatchPlatforms(
2646
- data: PlatformControllerMatchPlatformsData
2647
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3633
+ public static telemetryControllerGetCoverageMetrics(
3634
+ data: TelemetryControllerGetCoverageMetricsData
3635
+ ): CancelablePromise<TelemetryControllerGetCoverageMetricsResponse> {
2648
3636
  return __request(OpenAPI, {
2649
3637
  method: 'GET',
2650
- url: '/api/v1/bean/platforms/match',
2651
- query: {
2652
- q: data.q,
3638
+ url: '/api/v1/{region}/bean/import/parser-coverage-metrics',
3639
+ path: {
2653
3640
  region: data.region
3641
+ },
3642
+ query: {
3643
+ topN: data.topN
2654
3644
  }
2655
3645
  });
2656
3646
  }
3647
+ }
2657
3648
 
3649
+ export class BeanNlpService {
2658
3650
  /**
2659
- * Update a platform
3651
+ * Process natural language input
3652
+ * Parse natural language text (Chinese/English) describing a transaction. Supports multi-turn dialogue for collecting missing information. When confidence < 0.75, returns "confirm" action requiring user verification. User can reply with confirmation words (确认/yes/ok) or provide corrections. Examples: "yesterday Starbucks spent 35 yuan", "today lunch 28 yuan", "spent $50 at Walmart"
2660
3653
  * @param data The data for the request.
2661
- * @param data.id Platform ID
2662
- * @param data.requestBody
2663
- * @returns unknown Platform updated successfully
3654
+ * @param data.region Region code for tenant context
3655
+ * @param data.requestBody Natural language transaction input with optional session ID
3656
+ * @returns NlpResponseDto NLP processing result - either created transaction or asking for more info
2664
3657
  * @throws ApiError
2665
3658
  */
2666
- public static platformControllerUpdate(
2667
- data: PlatformControllerUpdateData
2668
- ): CancelablePromise<PlatformControllerUpdateResponse> {
3659
+ public static nlpControllerProcessNaturalLanguage(
3660
+ data: NlpControllerProcessNaturalLanguageData
3661
+ ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
2669
3662
  return __request(OpenAPI, {
2670
- method: 'PUT',
2671
- url: '/api/v1/bean/platforms/{id}',
3663
+ method: 'POST',
3664
+ url: '/api/v1/{region}/bean/nlp/process',
2672
3665
  path: {
2673
- id: data.id
3666
+ region: data.region
2674
3667
  },
2675
3668
  body: data.requestBody,
2676
3669
  mediaType: 'application/json',
2677
3670
  errors: {
2678
- 404: 'Platform not found'
3671
+ 400: 'Invalid input',
3672
+ 401: 'Unauthorized'
2679
3673
  }
2680
3674
  });
2681
3675
  }
2682
3676
 
2683
3677
  /**
2684
- * Delete a platform
3678
+ * Clear dialogue session
3679
+ * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
2685
3680
  * @param data The data for the request.
2686
- * @param data.id Platform ID
2687
- * @returns void Platform deleted successfully
3681
+ * @param data.region Region code for tenant context
3682
+ * @param data.sessionId Specific session ID to clear (defaults to user session)
3683
+ * @returns void Session cleared successfully
2688
3684
  * @throws ApiError
2689
3685
  */
2690
- public static platformControllerDelete(
2691
- data: PlatformControllerDeleteData
2692
- ): CancelablePromise<PlatformControllerDeleteResponse> {
3686
+ public static nlpControllerClearSession(
3687
+ data: NlpControllerClearSessionData
3688
+ ): CancelablePromise<NlpControllerClearSessionResponse> {
2693
3689
  return __request(OpenAPI, {
2694
3690
  method: 'DELETE',
2695
- url: '/api/v1/bean/platforms/{id}',
3691
+ url: '/api/v1/{region}/bean/nlp/session',
2696
3692
  path: {
2697
- id: data.id
3693
+ region: data.region
3694
+ },
3695
+ query: {
3696
+ sessionId: data.sessionId
2698
3697
  },
2699
3698
  errors: {
2700
- 404: 'Platform not found'
3699
+ 401: 'Unauthorized'
2701
3700
  }
2702
3701
  });
2703
3702
  }
2704
- }
2705
3703
 
2706
- export class ProviderSyncService {
2707
3704
  /**
2708
- * Sync transactions from financial data provider
2709
- *
2710
- * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
2711
- *
2712
- * **Supported Providers:**
2713
- * - **plaid**: Plaid API (US, Canada, Europe)
2714
- * - **teller**: Teller API (US)
2715
- * - **truelayer**: TrueLayer Open Banking (UK, Europe)
2716
- * - **gocardless**: GoCardless Bank Account Data (Europe)
2717
- * - **simplefin**: SimpleFIN (Self-hosted)
2718
- * - **yodlee**: Yodlee (Global)
2719
- * - **beancount-direct**: Beancount format transactions
2720
- * - **parsed-bill**: Client-side parsed bill transactions
2721
- *
2722
- * **Processing Flow:**
2723
- * 1. Transform raw data via provider adapter
2724
- * 2. Validate transaction format
2725
- * 3. Deduplicate using originalId
2726
- * 4. Classify using rule engine
2727
- * 5. Route low-confidence to Review Center
2728
- * 6. Persist validated transactions
2729
- *
3705
+ * Get current session state
3706
+ * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
2730
3707
  * @param data The data for the request.
2731
- * @param data.providerName Provider name
2732
- * @param data.region Region code
2733
- * @param data.requestBody
2734
- * @returns ProviderSyncResponseDto Sync completed successfully
3708
+ * @param data.region Region code for tenant context
3709
+ * @param data.sessionId Specific session ID to get (defaults to user session)
3710
+ * @returns unknown Current session state (or null if no active session)
2735
3711
  * @throws ApiError
2736
3712
  */
2737
- public static providerSyncControllerSync(
2738
- data: ProviderSyncControllerSyncData
2739
- ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3713
+ public static nlpControllerGetSession(
3714
+ data: NlpControllerGetSessionData
3715
+ ): CancelablePromise<NlpControllerGetSessionResponse> {
2740
3716
  return __request(OpenAPI, {
2741
- method: 'POST',
2742
- url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3717
+ method: 'GET',
3718
+ url: '/api/v1/{region}/bean/nlp/session',
2743
3719
  path: {
2744
- providerName: data.providerName,
2745
3720
  region: data.region
2746
3721
  },
2747
- body: data.requestBody,
2748
- mediaType: 'application/json',
3722
+ query: {
3723
+ sessionId: data.sessionId
3724
+ },
2749
3725
  errors: {
2750
- 400: 'Invalid request data',
2751
- 401: 'Missing or invalid authentication',
2752
- 404: 'Provider not supported'
3726
+ 401: 'Unauthorized'
2753
3727
  }
2754
3728
  });
2755
3729
  }
3730
+ }
2756
3731
 
3732
+ export class BeanPlatformsService {
2757
3733
  /**
2758
- * Get supported providers
2759
- * Returns a list of all providers supported by the sync endpoint.
2760
- * @param data The data for the request.
2761
- * @param data.region Region code for tenant context
2762
- * @returns SupportedProvidersResponseDto List of supported providers
3734
+ * Get all platforms with statistics
3735
+ * @returns unknown List of platforms with binding and account counts
2763
3736
  * @throws ApiError
2764
3737
  */
2765
- public static providerSyncControllerGetSupportedProviders(
2766
- data: ProviderSyncControllerGetSupportedProvidersData
2767
- ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3738
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2768
3739
  return __request(OpenAPI, {
2769
3740
  method: 'GET',
2770
- url: '/api/v1/{region}/bean/import/provider/supported',
2771
- path: {
2772
- region: data.region
2773
- },
2774
- errors: {
2775
- 401: 'Missing or invalid authentication'
2776
- }
3741
+ url: '/api/v1/bean/platforms'
2777
3742
  });
2778
3743
  }
2779
3744
 
2780
3745
  /**
2781
- * Check if provider is supported
2782
- * Returns whether a specific provider is supported.
3746
+ * Create a new platform
2783
3747
  * @param data The data for the request.
2784
- * @param data.providerName Provider name to check
2785
- * @param data.region Region code for tenant context
2786
- * @returns unknown Provider support status
3748
+ * @param data.requestBody
3749
+ * @returns unknown Platform created successfully
2787
3750
  * @throws ApiError
2788
3751
  */
2789
- public static providerSyncControllerIsProviderSupported(
2790
- data: ProviderSyncControllerIsProviderSupportedData
2791
- ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3752
+ public static platformControllerCreate(
3753
+ data: PlatformControllerCreateData
3754
+ ): CancelablePromise<PlatformControllerCreateResponse> {
2792
3755
  return __request(OpenAPI, {
2793
- method: 'GET',
2794
- url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
2795
- path: {
2796
- providerName: data.providerName,
2797
- region: data.region
2798
- },
3756
+ method: 'POST',
3757
+ url: '/api/v1/bean/platforms',
3758
+ body: data.requestBody,
3759
+ mediaType: 'application/json',
2799
3760
  errors: {
2800
- 401: 'Missing or invalid authentication'
3761
+ 409: 'Platform already exists'
2801
3762
  }
2802
3763
  });
2803
3764
  }
2804
- }
2805
3765
 
2806
- export class ImportTelemetryService {
2807
3766
  /**
2808
- * Receive anonymous parser failure telemetry
3767
+ * Get platform list for current user
2809
3768
  * @param data The data for the request.
2810
- * @param data.region Region code for tenant context
2811
- * @param data.requestBody
2812
- * @returns unknown Telemetry report received
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
2813
3771
  * @throws ApiError
2814
3772
  */
2815
- public static telemetryControllerReportTelemetry(
2816
- data: TelemetryControllerReportTelemetryData
2817
- ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
3773
+ public static platformControllerGetPlatformList(
3774
+ data: PlatformControllerGetPlatformListData = {}
3775
+ ): CancelablePromise<PlatformControllerGetPlatformListResponse> {
2818
3776
  return __request(OpenAPI, {
2819
- method: 'POST',
2820
- url: '/api/v1/{region}/bean/import/parser-telemetry',
2821
- path: {
3777
+ method: 'GET',
3778
+ url: '/api/v1/bean/platforms/list',
3779
+ query: {
2822
3780
  region: data.region
2823
- },
2824
- body: data.requestBody,
2825
- mediaType: 'application/json',
2826
- errors: {
2827
- 401: 'Unauthorized'
2828
3781
  }
2829
3782
  });
2830
3783
  }
2831
- }
2832
3784
 
2833
- export class BeanNlpService {
2834
3785
  /**
2835
- * Process natural language input
2836
- * Parse natural language text (Chinese/English) describing a transaction. Supports multi-turn dialogue for collecting missing information. When confidence < 0.75, returns "confirm" action requiring user verification. User can reply with confirmation words (确认/yes/ok) or provide corrections. Examples: "yesterday Starbucks spent 35 yuan", "today lunch 28 yuan", "spent $50 at Walmart"
3786
+ * Match platforms by name or alias
2837
3787
  * @param data The data for the request.
2838
- * @param data.region Region code for tenant context
2839
- * @param data.requestBody Natural language transaction input with optional session ID
2840
- * @returns NlpResponseDto NLP processing result - either created transaction or asking for more info
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
2841
3791
  * @throws ApiError
2842
3792
  */
2843
- public static nlpControllerProcessNaturalLanguage(
2844
- data: NlpControllerProcessNaturalLanguageData
2845
- ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
3793
+ public static platformControllerMatchPlatforms(
3794
+ data: PlatformControllerMatchPlatformsData
3795
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
2846
3796
  return __request(OpenAPI, {
2847
- method: 'POST',
2848
- url: '/api/v1/{region}/bean/nlp/process',
2849
- path: {
3797
+ method: 'GET',
3798
+ url: '/api/v1/bean/platforms/match',
3799
+ query: {
3800
+ q: data.q,
2850
3801
  region: data.region
2851
- },
2852
- body: data.requestBody,
2853
- mediaType: 'application/json',
2854
- errors: {
2855
- 400: 'Invalid input',
2856
- 401: 'Unauthorized'
2857
3802
  }
2858
3803
  });
2859
3804
  }
2860
3805
 
2861
3806
  /**
2862
- * Clear dialogue session
2863
- * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
3807
+ * Update a platform
2864
3808
  * @param data The data for the request.
2865
- * @param data.region Region code for tenant context
2866
- * @param data.sessionId Specific session ID to clear (defaults to user session)
2867
- * @returns void Session cleared successfully
3809
+ * @param data.id Platform ID
3810
+ * @param data.requestBody
3811
+ * @returns unknown Platform updated successfully
2868
3812
  * @throws ApiError
2869
3813
  */
2870
- public static nlpControllerClearSession(
2871
- data: NlpControllerClearSessionData
2872
- ): CancelablePromise<NlpControllerClearSessionResponse> {
3814
+ public static platformControllerUpdate(
3815
+ data: PlatformControllerUpdateData
3816
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
2873
3817
  return __request(OpenAPI, {
2874
- method: 'DELETE',
2875
- url: '/api/v1/{region}/bean/nlp/session',
3818
+ method: 'PUT',
3819
+ url: '/api/v1/bean/platforms/{id}',
2876
3820
  path: {
2877
- region: data.region
2878
- },
2879
- query: {
2880
- sessionId: data.sessionId
3821
+ id: data.id
2881
3822
  },
3823
+ body: data.requestBody,
3824
+ mediaType: 'application/json',
2882
3825
  errors: {
2883
- 401: 'Unauthorized'
3826
+ 404: 'Platform not found'
2884
3827
  }
2885
3828
  });
2886
3829
  }
2887
3830
 
2888
3831
  /**
2889
- * Get current session state
2890
- * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
3832
+ * Delete a platform
2891
3833
  * @param data The data for the request.
2892
- * @param data.region Region code for tenant context
2893
- * @param data.sessionId Specific session ID to get (defaults to user session)
2894
- * @returns unknown Current session state (or null if no active session)
3834
+ * @param data.id Platform ID
3835
+ * @returns void Platform deleted successfully
2895
3836
  * @throws ApiError
2896
3837
  */
2897
- public static nlpControllerGetSession(
2898
- data: NlpControllerGetSessionData
2899
- ): CancelablePromise<NlpControllerGetSessionResponse> {
3838
+ public static platformControllerDelete(
3839
+ data: PlatformControllerDeleteData
3840
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
2900
3841
  return __request(OpenAPI, {
2901
- method: 'GET',
2902
- url: '/api/v1/{region}/bean/nlp/session',
3842
+ method: 'DELETE',
3843
+ url: '/api/v1/bean/platforms/{id}',
2903
3844
  path: {
2904
- region: data.region
2905
- },
2906
- query: {
2907
- sessionId: data.sessionId
3845
+ id: data.id
2908
3846
  },
2909
3847
  errors: {
2910
- 401: 'Unauthorized'
3848
+ 404: 'Platform not found'
2911
3849
  }
2912
3850
  });
2913
3851
  }
@@ -2948,6 +3886,7 @@ export class DashboardService {
2948
3886
  * @param data.region Region code for tenant context
2949
3887
  * @param data.groupBy Grouping strategy
2950
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)
2951
3890
  * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
2952
3891
  * @throws ApiError
2953
3892
  */
@@ -2962,7 +3901,8 @@ export class DashboardService {
2962
3901
  },
2963
3902
  query: {
2964
3903
  groupBy: data.groupBy,
2965
- date: data.date
3904
+ date: data.date,
3905
+ accountId: data.accountId
2966
3906
  },
2967
3907
  errors: {
2968
3908
  401: 'User not authenticated'
@@ -2997,124 +3937,69 @@ export class DashboardService {
2997
3937
  }
2998
3938
  });
2999
3939
  }
3000
- }
3001
3940
 
3002
- export class ReportingService {
3003
3941
  /**
3004
- * Get portfolio value trends
3005
- *
3006
- * Returns time series data of portfolio net worth.
3007
- *
3008
- * **Multi-currency Support:**
3009
- * - `series[].byCurrency` - Currency breakdown for each data point
3010
- * - `byCurrency` - Separate time series grouped by currency
3011
- * - `warnings` - Exchange rate warnings if conversion failed
3012
- *
3013
- * **Parameters:**
3014
- * - `period`: Time period (1m, 3m, 6m, 1y)
3015
- * - `granularity`: Data granularity (day, week, month)
3016
- *
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)
3017
3944
  * @param data The data for the request.
3018
3945
  * @param data.region Region code for tenant context
3019
- * @param data.period Time period
3020
- * @param data.granularity Data granularity
3021
- * @returns PortfolioTrendsResponseDto Trends retrieved 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
3022
3950
  * @throws ApiError
3023
3951
  */
3024
- public static reportingControllerGetPortfolioTrends(
3025
- data: ReportingControllerGetPortfolioTrendsData
3026
- ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
3952
+ public static dashboardControllerGetExpenses(
3953
+ data: DashboardControllerGetExpensesData
3954
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3027
3955
  return __request(OpenAPI, {
3028
3956
  method: 'GET',
3029
- url: '/api/v1/{region}/reporting/portfolio/trends',
3957
+ url: '/api/v1/{region}/dashboard/expenses',
3030
3958
  path: {
3031
3959
  region: data.region
3032
3960
  },
3033
3961
  query: {
3962
+ groupBy: data.groupBy,
3034
3963
  period: data.period,
3035
- granularity: data.granularity
3964
+ flow: data.flow
3036
3965
  },
3037
3966
  errors: {
3967
+ 400: 'Invalid groupBy or period',
3038
3968
  401: 'User not authenticated'
3039
3969
  }
3040
3970
  });
3041
3971
  }
3972
+ }
3042
3973
 
3974
+ export class InvestmentService {
3043
3975
  /**
3044
- * Generate portfolio snapshot
3045
- *
3046
- * Manually generate a portfolio snapshot for a specific date.
3047
- *
3048
- * **Multi-currency Support:**
3049
- * - Fetches balances grouped by currency
3050
- * - Uses user's baseCurrency setting for conversion
3051
- * - Stores exchange rates and warnings
3052
- *
3053
- * **Use Cases:**
3054
- * - Testing snapshot generation
3055
- * - Force regeneration after data correction
3056
- * - Initial setup for new users
3057
- *
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).
3058
3978
  * @param data The data for the request.
3059
3979
  * @param data.region Region code for tenant context
3060
- * @param data.requestBody Optional date (defaults to today)
3061
- * @returns GenerateSnapshotResponse Snapshot generated 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
3062
3984
  * @throws ApiError
3063
3985
  */
3064
- public static reportingControllerGenerateSnapshot(
3065
- data: ReportingControllerGenerateSnapshotData
3066
- ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
3986
+ public static holdingPnlControllerGetHoldingPnl(
3987
+ data: HoldingPnlControllerGetHoldingPnlData
3988
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3067
3989
  return __request(OpenAPI, {
3068
- method: 'POST',
3069
- url: '/api/v1/{region}/reporting/snapshots/generate',
3990
+ method: 'GET',
3991
+ url: '/api/v1/{region}/investment/holdings/pnl',
3070
3992
  path: {
3071
3993
  region: data.region
3072
3994
  },
3073
- body: data.requestBody,
3074
- mediaType: 'application/json',
3075
- errors: {
3076
- 400: 'Invalid date format',
3077
- 401: 'User not authenticated'
3078
- }
3079
- });
3080
- }
3081
-
3082
- /**
3083
- * Backfill portfolio snapshots
3084
- *
3085
- * Generate snapshots for a date range (historical data backfill).
3086
- *
3087
- * **Multi-currency Support:**
3088
- * - Each snapshot includes multi-currency data
3089
- * - Uses exchange rates available at generation time
3090
- * - Warnings stored for missing exchange rates
3091
- *
3092
- * **Best Practices:**
3093
- * - Use for initial setup after account configuration
3094
- * - Run during low-traffic periods for large date ranges
3095
- * - Existing snapshots are skipped (not regenerated)
3096
- *
3097
- * @param data The data for the request.
3098
- * @param data.region Region code for tenant context
3099
- * @param data.requestBody
3100
- * @returns BackfillSnapshotsResponse Backfill completed successfully
3101
- * @throws ApiError
3102
- */
3103
- public static reportingControllerBackfillSnapshots(
3104
- data: ReportingControllerBackfillSnapshotsData
3105
- ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
3106
- return __request(OpenAPI, {
3107
- method: 'POST',
3108
- url: '/api/v1/{region}/reporting/snapshots/backfill',
3109
- path: {
3110
- region: data.region
3995
+ query: {
3996
+ asOf: data.asOf,
3997
+ accountId: data.accountId,
3998
+ method: data.method
3111
3999
  },
3112
- body: data.requestBody,
3113
- mediaType: 'application/json',
3114
4000
  errors: {
3115
- 400: 'Invalid date format or range',
3116
- 401: 'User not authenticated',
3117
- 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'
3118
4003
  }
3119
4004
  });
3120
4005
  }
@@ -3143,7 +4028,7 @@ export class AuthService {
3143
4028
  * Anonymous login with access token
3144
4029
  * @param data The data for the request.
3145
4030
  * @param data.requestBody
3146
- * @returns unknown Login successful
4031
+ * @returns AnonymousLoginResponseDto Login successful
3147
4032
  * @throws ApiError
3148
4033
  */
3149
4034
  public static authControllerAccessTokenLogin(
@@ -3161,6 +4046,38 @@ export class AuthService {
3161
4046
  }
3162
4047
  }
3163
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
+
3164
4081
  export class DefaultService {
3165
4082
  /**
3166
4083
  * @returns unknown
@@ -3330,3 +4247,53 @@ export class InfoService {
3330
4247
  });
3331
4248
  }
3332
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
+ }