@firela/api-types 0.0.0-canary.32edff08 → 0.0.0-canary.344d1cb5

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,48 @@ import type {
95
99
  CommodityControllerGetOrCreateResponse,
96
100
  CommodityControllerBulkCreateData,
97
101
  CommodityControllerBulkCreateResponse,
102
+ ReportingControllerGetPortfolioTrendsData,
103
+ ReportingControllerGetPortfolioTrendsResponse,
104
+ ReportingControllerGetCashFlowTrendsData,
105
+ ReportingControllerGetCashFlowTrendsResponse,
106
+ ReportingControllerGenerateSnapshotData,
107
+ ReportingControllerGenerateSnapshotResponse,
108
+ ReportingControllerBackfillSnapshotsData,
109
+ ReportingControllerBackfillSnapshotsResponse,
110
+ PriceControllerCreateData,
111
+ PriceControllerCreateResponse,
112
+ PriceControllerFindAllData,
113
+ PriceControllerFindAllResponse,
114
+ PriceControllerFindOneData,
115
+ PriceControllerFindOneResponse,
116
+ PriceControllerUpdateData,
117
+ PriceControllerUpdateResponse,
118
+ PriceControllerDeleteData,
119
+ PriceControllerDeleteResponse,
120
+ PriceControllerBulkCreateData,
121
+ PriceControllerBulkCreateResponse,
122
+ UserControllerDeleteOwnUserData,
123
+ UserControllerDeleteOwnUserResponse,
124
+ UserControllerGetUserData,
125
+ UserControllerGetUserResponse,
126
+ UserControllerSignupUserData,
127
+ UserControllerSignupUserResponse,
128
+ UserControllerDeleteUserData,
129
+ UserControllerDeleteUserResponse,
130
+ UserControllerGetUserInfoData,
131
+ UserControllerGetUserInfoResponse,
132
+ UserControllerUpdateUserSettingData,
133
+ UserControllerUpdateUserSettingResponse,
134
+ UserControllerGetAllUserSettingsByPageData,
135
+ UserControllerGetAllUserSettingsByPageResponse,
136
+ UserControllerGetAssetLiabilitySummaryResponse,
137
+ PropertyControllerGetAllResponse,
138
+ PropertyControllerGetByKeyData,
139
+ PropertyControllerGetByKeyResponse,
140
+ PropertyControllerUpdateData,
141
+ PropertyControllerUpdateResponse,
142
+ PropertyControllerDeleteData,
143
+ PropertyControllerDeleteResponse,
98
144
  RecurringRuleControllerCreateData,
99
145
  RecurringRuleControllerCreateResponse,
100
146
  RecurringRuleControllerFindAllData,
@@ -147,28 +193,30 @@ import type {
147
193
  TransactionRuleControllerDeleteResponse,
148
194
  TransactionRuleControllerTestData,
149
195
  TransactionRuleControllerTestResponse,
150
- UserControllerDeleteOwnUserData,
151
- UserControllerDeleteOwnUserResponse,
152
- UserControllerGetUserData,
153
- UserControllerGetUserResponse,
154
- UserControllerSignupUserData,
155
- UserControllerSignupUserResponse,
156
- UserControllerDeleteUserData,
157
- UserControllerDeleteUserResponse,
158
- UserControllerGetUserInfoData,
159
- UserControllerGetUserInfoResponse,
160
- UserControllerUpdateUserSettingData,
161
- UserControllerUpdateUserSettingResponse,
162
- UserControllerGetAllUserSettingsByPageData,
163
- UserControllerGetAllUserSettingsByPageResponse,
164
- UserControllerGetAssetLiabilitySummaryResponse,
165
- PropertyControllerGetAllResponse,
166
- PropertyControllerGetByKeyData,
167
- PropertyControllerGetByKeyResponse,
168
- PropertyControllerUpdateData,
169
- PropertyControllerUpdateResponse,
170
- PropertyControllerDeleteData,
171
- PropertyControllerDeleteResponse,
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,60 @@ 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
+ PlatformControllerGetPlatformStandardsData,
267
+ PlatformControllerGetPlatformStandardsResponse,
268
+ PlatformControllerUpdateData,
269
+ PlatformControllerUpdateResponse,
270
+ PlatformControllerDeleteData,
271
+ PlatformControllerDeleteResponse,
209
272
  DashboardControllerGetNetWorthData,
210
273
  DashboardControllerGetNetWorthResponse,
211
274
  DashboardControllerGetAccountsData,
212
275
  DashboardControllerGetAccountsResponse,
213
276
  DashboardControllerGetCashFlowData,
214
277
  DashboardControllerGetCashFlowResponse,
215
- ReportingControllerGetPortfolioTrendsData,
216
- ReportingControllerGetPortfolioTrendsResponse,
217
- ReportingControllerGenerateSnapshotData,
218
- ReportingControllerGenerateSnapshotResponse,
219
- ReportingControllerBackfillSnapshotsData,
220
- ReportingControllerBackfillSnapshotsResponse,
278
+ DashboardControllerGetExpensesData,
279
+ DashboardControllerGetExpensesResponse,
280
+ HoldingPnlControllerGetHoldingPnlData,
281
+ HoldingPnlControllerGetHoldingPnlResponse,
221
282
  ApiKeysControllerCreateApiKeyResponse,
222
283
  AuthControllerAccessTokenLoginData,
223
284
  AuthControllerAccessTokenLoginResponse,
285
+ ParserContributionControllerCreateData,
286
+ ParserContributionControllerCreateResponse,
224
287
  CacheControllerFlushCacheResponse,
225
288
  ExchangeRateControllerGetExchangeRateData,
226
289
  ExchangeRateControllerGetExchangeRateResponse,
@@ -232,7 +295,11 @@ import type {
232
295
  HealthControllerResetCircuitBreakerData,
233
296
  HealthControllerResetCircuitBreakerResponse,
234
297
  HealthControllerGetMetricsResponse,
235
- InfoControllerGetInfoResponse
298
+ InfoControllerGetInfoResponse,
299
+ SymbolControllerSearchData,
300
+ SymbolControllerSearchResponse,
301
+ SymbolControllerGetQuoteData,
302
+ SymbolControllerGetQuoteResponse
236
303
  } from './types.gen';
237
304
 
238
305
  export class BeanAccountsService {
@@ -270,7 +337,7 @@ export class BeanAccountsService {
270
337
  * @param data.type Filter by account type
271
338
  * @param data.status Filter by status
272
339
  * @param data.isCustom Filter by custom (user-created) accounts only
273
- * @param data.search Search term for path or i18nKey
340
+ * @param data.search Search term matched against account path and user-set display name (case-insensitive)
274
341
  * @param data.limit Maximum number of results
275
342
  * @param data.offset Number of results to skip
276
343
  * @returns AccountListResponseDto Accounts retrieved successfully
@@ -351,7 +418,7 @@ export class BeanAccountsService {
351
418
 
352
419
  /**
353
420
  * Delete account
354
- * Deletes an account (only if no transactions)
421
+ * Deletes an account (only if no active transactions; voided/superseded residual postings are cleaned up)
355
422
  * @param data The data for the request.
356
423
  * @param data.id Account UUID
357
424
  * @param data.region Region code for tenant context
@@ -370,7 +437,7 @@ export class BeanAccountsService {
370
437
  },
371
438
  errors: {
372
439
  404: 'Account not found',
373
- 409: 'Account has transactions and cannot be deleted'
440
+ 409: 'Account has active transactions and cannot be deleted'
374
441
  }
375
442
  });
376
443
  }
@@ -432,16 +499,45 @@ export class BeanAccountsService {
432
499
  }
433
500
  });
434
501
  }
502
+
503
+ /**
504
+ * Post an opening-balance transaction
505
+ * 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.
506
+ * @param data The data for the request.
507
+ * @param data.id Account UUID
508
+ * @param data.region Region code for tenant context
509
+ * @param data.requestBody
510
+ * @returns OpeningBalanceResultDto Opening-balance transaction created
511
+ * @throws ApiError
512
+ */
513
+ public static accountControllerAddOpeningBalance(
514
+ data: AccountControllerAddOpeningBalanceData
515
+ ): CancelablePromise<AccountControllerAddOpeningBalanceResponse> {
516
+ return __request(OpenAPI, {
517
+ method: 'POST',
518
+ url: '/api/v1/{region}/bean/accounts/{id}/opening-balance',
519
+ path: {
520
+ id: data.id,
521
+ region: data.region
522
+ },
523
+ body: data.requestBody,
524
+ mediaType: 'application/json',
525
+ errors: {
526
+ 404: 'Account not found',
527
+ 409: 'An opening balance already exists for this account'
528
+ }
529
+ });
530
+ }
435
531
  }
436
532
 
437
533
  export class BeanAccountStandardsService {
438
534
  /**
439
535
  * Get account templates
440
- * Returns predefined account templates for a region. Supports filtering by account type and search term.
536
+ * Returns predefined account templates for a region. Supports filtering by account type and search term. Not-yet-open region codes return the universal-only catalog (#759).
441
537
  * @param data The data for the request.
442
- * @param data.region Region code (cn, us, de)
538
+ * @param data.region Region code (any ISO alpha-2; not-yet-open codes return the universal-only catalog)
443
539
  * @param data.type Filter by account type
444
- * @param data.search Search term for path or description
540
+ * @param data.search Search term for path, description, aliases, or localized display name
445
541
  * @returns AccountStandardListResponseDto Account templates retrieved successfully
446
542
  * @throws ApiError
447
543
  */
@@ -463,9 +559,9 @@ export class BeanAccountStandardsService {
463
559
 
464
560
  /**
465
561
  * Get template metadata for an account path
466
- * Returns extendable status and root type for a template path.
562
+ * Returns root type for a template path.
467
563
  * @param data The data for the request.
468
- * @param data.region Region code for tenant context
564
+ * @param data.region Region code for tenant context. Not-yet-open codes degrade to the universal-only catalog (#759)
469
565
  * @param data.path Account path to check
470
566
  * @returns TemplateMetadataResponseDto Template metadata retrieved successfully
471
567
  * @throws ApiError
@@ -487,9 +583,9 @@ export class BeanAccountStandardsService {
487
583
 
488
584
  /**
489
585
  * Get available regions with hierarchy
490
- * Returns supported regions with inheritance metadata
586
+ * Returns the full region catalog (every ISO 3166-1 entry) with an 'open' flag and inheritance metadata (#759)
491
587
  * @param data The data for the request.
492
- * @param data.region Region code for tenant context
588
+ * @param data.region Region code for tenant context. Not-yet-open codes degrade to the universal-only catalog (#759)
493
589
  * @returns RegionsMetadataResponseDto Regions metadata retrieved successfully
494
590
  * @throws ApiError
495
591
  */
@@ -546,9 +642,11 @@ export class BeanTransactionsService {
546
642
  * @param data.offset Number of items to skip (default: 0)
547
643
  * @param data.dateFrom Filter by start date (inclusive), format: YYYY-MM-DD
548
644
  * @param data.dateTo Filter by end date (inclusive), format: YYYY-MM-DD
549
- * @param data.status Filter by transaction status
645
+ * @param data.status Filter by transaction status: single value, comma-separated multi-value (e.g. VOIDED,SUPERSEDED), or ALL to include audit rows. Defaults to ACTIVE-only (ADR-0128; previously unfiltered — breaking change).
550
646
  * @param data.search Search in narration and payee fields (max 200 chars)
551
647
  * @param data.accountId Filter by account ID (transactions with postings to this account)
648
+ * @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).
649
+ * @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
650
  * @returns TransactionListResponseDto Transaction list
553
651
  * @throws ApiError
554
652
  */
@@ -568,7 +666,9 @@ export class BeanTransactionsService {
568
666
  dateTo: data.dateTo,
569
667
  status: data.status,
570
668
  search: data.search,
571
- accountId: data.accountId
669
+ accountId: data.accountId,
670
+ category: data.category,
671
+ flow: data.flow
572
672
  },
573
673
  errors: {
574
674
  400: 'Validation failed',
@@ -605,6 +705,36 @@ export class BeanTransactionsService {
605
705
  });
606
706
  }
607
707
 
708
+ /**
709
+ * Correct (supersede) a transaction
710
+ * Atomically voids the original (SUPERSEDED) and creates a replacement through the full validation pipeline.
711
+ * @param data The data for the request.
712
+ * @param data.id Original transaction ID to correct
713
+ * @param data.region Region code for tenant context
714
+ * @param data.requestBody
715
+ * @returns TransactionDetailDto Corrected transaction created
716
+ * @throws ApiError
717
+ */
718
+ public static transactionControllerCorrect(
719
+ data: TransactionControllerCorrectData
720
+ ): CancelablePromise<TransactionControllerCorrectResponse> {
721
+ return __request(OpenAPI, {
722
+ method: 'POST',
723
+ url: '/api/v1/{region}/bean/transactions/{id}/correct',
724
+ path: {
725
+ id: data.id,
726
+ region: data.region
727
+ },
728
+ body: data.requestBody,
729
+ mediaType: 'application/json',
730
+ errors: {
731
+ 404: 'Original transaction not found',
732
+ 409: 'Original no longer ACTIVE (concurrent modification)',
733
+ 422: 'Pipeline validation failed (does not balance, invalid accounts)'
734
+ }
735
+ });
736
+ }
737
+
608
738
  /**
609
739
  * Suggest transaction tags
610
740
  * Returns distinct tags from the user ACTIVE transactions, sorted by usage, for autocomplete. Optional q performs a case-insensitive prefix match.
@@ -726,7 +856,7 @@ export class BeanBalancesService {
726
856
  * Query account balance
727
857
  * Calculate account balance at a specific date for a single currency
728
858
  * @param data The data for the request.
729
- * @param data.account Account name (e.g., "Assets:Bank:Checking")
859
+ * @param data.account Account name (e.g., "Assets:Checking")
730
860
  * @param data.region Region code for tenant context
731
861
  * @param data.date Date to calculate balance at (ISO 8601 format)
732
862
  * @param data.currency Currency to query (e.g., "USD", "CNY")
@@ -1251,7 +1381,7 @@ export class AdminPayeeProfilesService {
1251
1381
  * Removes verification status by setting verifiedAt to null.
1252
1382
  * @param data The data for the request.
1253
1383
  * @param data.id Payee profile ID (UUID)
1254
- * @returns PayeeProfileResponseDto Payee profile unverified successfully
1384
+ * @returns void Payee profile unverified successfully
1255
1385
  * @throws ApiError
1256
1386
  */
1257
1387
  public static payeeProfileAdminControllerUnverify(
@@ -1447,442 +1577,1021 @@ export class BeanCommoditiesService {
1447
1577
  }
1448
1578
  }
1449
1579
 
1450
- export class RecurringRulesService {
1580
+ export class ReportingService {
1451
1581
  /**
1452
- * Create a new recurring rule
1453
- * Creates a new recurring transaction rule for the authenticated user
1582
+ * Get portfolio value trends
1583
+ *
1584
+ * Returns time series data of portfolio net worth.
1585
+ *
1586
+ * **Multi-currency Support:**
1587
+ * - `series[].byCurrency` - Currency breakdown for each data point
1588
+ * - `byCurrency` - Separate time series grouped by currency
1589
+ * - `warnings` - Exchange rate warnings if conversion failed
1590
+ *
1591
+ * **Parameters:**
1592
+ * - `period`: Time period (1m, 3m, 6m, 1y)
1593
+ * - `granularity`: Data granularity (day, week, month)
1594
+ *
1454
1595
  * @param data The data for the request.
1455
1596
  * @param data.region Region code for tenant context
1456
- * @param data.requestBody
1457
- * @returns RecurringRuleResponseDto Rule created successfully
1597
+ * @param data.period Time period
1598
+ * @param data.granularity Data granularity
1599
+ * @returns PortfolioTrendsResponseDto Trends retrieved successfully
1458
1600
  * @throws ApiError
1459
1601
  */
1460
- public static recurringRuleControllerCreate(
1461
- data: RecurringRuleControllerCreateData
1462
- ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1602
+ public static reportingControllerGetPortfolioTrends(
1603
+ data: ReportingControllerGetPortfolioTrendsData
1604
+ ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
1463
1605
  return __request(OpenAPI, {
1464
- method: 'POST',
1465
- url: '/api/v1/{region}/bean/recurring-rules',
1606
+ method: 'GET',
1607
+ url: '/api/v1/{region}/reporting/portfolio/trends',
1466
1608
  path: {
1467
1609
  region: data.region
1468
1610
  },
1469
- body: data.requestBody,
1470
- mediaType: 'application/json',
1611
+ query: {
1612
+ period: data.period,
1613
+ granularity: data.granularity
1614
+ },
1471
1615
  errors: {
1472
- 400: 'Invalid input data (e.g., autoCreate without accounts)',
1473
- 409: 'Rule with same name already exists'
1616
+ 401: 'User not authenticated'
1474
1617
  }
1475
1618
  });
1476
1619
  }
1477
1620
 
1478
1621
  /**
1479
- * List recurring rules
1480
- * Returns all recurring rules for the authenticated user with optional filtering
1622
+ * Get cash-flow trends
1623
+ *
1624
+ * Monthly income / expense / netSavings over a fixed N-month window
1625
+ * (current month + N−1 prior). Missing months are zero-filled (flow metric).
1626
+ *
1627
+ * **Parameters:**
1628
+ * - `period`: 1m | 3m | 6m | 1y (default 6m)
1629
+ * - `granularity`: accepted for API symmetry; v1 returns month buckets
1630
+ *
1481
1631
  * @param data The data for the request.
1482
1632
  * @param data.region Region code for tenant context
1483
- * @param data.isActive Filter by active status
1484
- * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
1485
- * @param data.hasAutoCreate Filter by autoCreate enabled
1486
- * @returns RecurringRuleResponseDto Rules retrieved successfully
1633
+ * @param data.period Time period
1634
+ * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
1635
+ * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
1487
1636
  * @throws ApiError
1488
1637
  */
1489
- public static recurringRuleControllerFindAll(
1490
- data: RecurringRuleControllerFindAllData
1491
- ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1638
+ public static reportingControllerGetCashFlowTrends(
1639
+ data: ReportingControllerGetCashFlowTrendsData
1640
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
1492
1641
  return __request(OpenAPI, {
1493
1642
  method: 'GET',
1494
- url: '/api/v1/{region}/bean/recurring-rules',
1643
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
1495
1644
  path: {
1496
1645
  region: data.region
1497
1646
  },
1498
1647
  query: {
1499
- isActive: data.isActive,
1500
- frequency: data.frequency,
1501
- hasAutoCreate: data.hasAutoCreate
1648
+ period: data.period,
1649
+ granularity: data.granularity
1650
+ },
1651
+ errors: {
1652
+ 401: 'User not authenticated'
1502
1653
  }
1503
1654
  });
1504
1655
  }
1505
1656
 
1506
1657
  /**
1507
- * Create recurring rule from transaction
1508
- * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1658
+ * Generate portfolio snapshot
1659
+ *
1660
+ * Manually generate a portfolio snapshot for a specific date.
1661
+ *
1662
+ * **Multi-currency Support:**
1663
+ * - Fetches balances grouped by currency
1664
+ * - Uses user's baseCurrency setting for conversion
1665
+ * - Stores exchange rates and warnings
1666
+ *
1667
+ * **Use Cases:**
1668
+ * - Testing snapshot generation
1669
+ * - Force regeneration after data correction
1670
+ * - Initial setup for new users
1671
+ *
1509
1672
  * @param data The data for the request.
1510
- * @param data.transactionId Source transaction ID
1511
1673
  * @param data.region Region code for tenant context
1512
- * @param data.requestBody
1513
- * @returns RecurringRuleResponseDto Rule created successfully
1674
+ * @param data.requestBody Optional date (defaults to today)
1675
+ * @returns GenerateSnapshotResponse Snapshot generated successfully
1514
1676
  * @throws ApiError
1515
1677
  */
1516
- public static recurringRuleControllerCreateFromTransaction(
1517
- data: RecurringRuleControllerCreateFromTransactionData
1518
- ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1678
+ public static reportingControllerGenerateSnapshot(
1679
+ data: ReportingControllerGenerateSnapshotData
1680
+ ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
1519
1681
  return __request(OpenAPI, {
1520
1682
  method: 'POST',
1521
- url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1683
+ url: '/api/v1/{region}/reporting/snapshots/generate',
1522
1684
  path: {
1523
- transactionId: data.transactionId,
1524
1685
  region: data.region
1525
1686
  },
1526
1687
  body: data.requestBody,
1527
1688
  mediaType: 'application/json',
1528
1689
  errors: {
1529
- 404: 'Transaction not found',
1530
- 409: 'Rule with same name already exists or transaction already linked'
1690
+ 400: 'Invalid date format',
1691
+ 401: 'User not authenticated'
1531
1692
  }
1532
1693
  });
1533
1694
  }
1534
1695
 
1535
1696
  /**
1536
- * Get recurring rule by ID
1537
- * Returns a specific recurring rule with its details
1697
+ * Backfill portfolio snapshots
1698
+ *
1699
+ * Generate snapshots for a date range (historical data backfill).
1700
+ *
1701
+ * **Multi-currency Support:**
1702
+ * - Each snapshot includes multi-currency data
1703
+ * - Uses exchange rates available at generation time
1704
+ * - Warnings stored for missing exchange rates
1705
+ *
1706
+ * **Best Practices:**
1707
+ * - Use for initial setup after account configuration
1708
+ * - Run during low-traffic periods for large date ranges
1709
+ * - Existing snapshots are skipped (not regenerated)
1710
+ *
1538
1711
  * @param data The data for the request.
1539
- * @param data.id Rule ID
1540
1712
  * @param data.region Region code for tenant context
1541
- * @returns RecurringRuleResponseDto Rule retrieved successfully
1713
+ * @param data.requestBody
1714
+ * @returns BackfillSnapshotsResponse Backfill completed successfully
1542
1715
  * @throws ApiError
1543
1716
  */
1544
- public static recurringRuleControllerFindOne(
1545
- data: RecurringRuleControllerFindOneData
1546
- ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1717
+ public static reportingControllerBackfillSnapshots(
1718
+ data: ReportingControllerBackfillSnapshotsData
1719
+ ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
1547
1720
  return __request(OpenAPI, {
1548
- method: 'GET',
1549
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1721
+ method: 'POST',
1722
+ url: '/api/v1/{region}/reporting/snapshots/backfill',
1550
1723
  path: {
1551
- id: data.id,
1552
1724
  region: data.region
1553
1725
  },
1726
+ body: data.requestBody,
1727
+ mediaType: 'application/json',
1554
1728
  errors: {
1555
- 404: 'Rule not found'
1729
+ 400: 'Invalid date format or range',
1730
+ 401: 'User not authenticated',
1731
+ 409: 'Backfill already in progress for this user'
1556
1732
  }
1557
1733
  });
1558
1734
  }
1735
+ }
1559
1736
 
1737
+ export class BeanPricesService {
1560
1738
  /**
1561
- * Update recurring rule
1562
- * Updates an existing recurring rule
1739
+ * Create a new price
1740
+ * Creates a new price entry for the authenticated user
1563
1741
  * @param data The data for the request.
1564
- * @param data.id Rule ID
1565
1742
  * @param data.region Region code for tenant context
1566
1743
  * @param data.requestBody
1567
- * @returns RecurringRuleResponseDto Rule updated successfully
1744
+ * @returns PriceResponseDto Price created successfully
1568
1745
  * @throws ApiError
1569
1746
  */
1570
- public static recurringRuleControllerUpdate(
1571
- data: RecurringRuleControllerUpdateData
1572
- ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1747
+ public static priceControllerCreate(
1748
+ data: PriceControllerCreateData
1749
+ ): CancelablePromise<PriceControllerCreateResponse> {
1573
1750
  return __request(OpenAPI, {
1574
- method: 'PATCH',
1575
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1751
+ method: 'POST',
1752
+ url: '/api/v1/{region}/bean/prices',
1576
1753
  path: {
1577
- id: data.id,
1578
1754
  region: data.region
1579
1755
  },
1580
1756
  body: data.requestBody,
1581
1757
  mediaType: 'application/json',
1582
1758
  errors: {
1583
- 400: 'Invalid input data',
1584
- 404: 'Rule not found'
1759
+ 404: 'Currency or quoteCurrency commodity not found',
1760
+ 409: 'Price already exists for this currency pair and date'
1585
1761
  }
1586
1762
  });
1587
1763
  }
1588
1764
 
1589
1765
  /**
1590
- * Delete recurring rule
1591
- * Soft deletes a recurring rule (sets isActive to false)
1766
+ * List user prices
1767
+ * Returns all price entries for the authenticated user with optional filtering
1592
1768
  * @param data The data for the request.
1593
- * @param data.id Rule ID
1594
1769
  * @param data.region Region code for tenant context
1595
- * @returns void Rule deleted successfully
1770
+ * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
1771
+ * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
1772
+ * @param data.dateFrom Filter prices from this date (ISO 8601 format)
1773
+ * @param data.dateTo Filter prices to this date (ISO 8601 format)
1774
+ * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
1775
+ * @param data.page Page number for pagination (default: 1)
1776
+ * @param data.limit Number of items per page (default: 20, max: 100)
1777
+ * @returns PriceListResponseDto Prices retrieved successfully
1596
1778
  * @throws ApiError
1597
1779
  */
1598
- public static recurringRuleControllerDelete(
1599
- data: RecurringRuleControllerDeleteData
1600
- ): CancelablePromise<RecurringRuleControllerDeleteResponse> {
1780
+ public static priceControllerFindAll(
1781
+ data: PriceControllerFindAllData
1782
+ ): CancelablePromise<PriceControllerFindAllResponse> {
1601
1783
  return __request(OpenAPI, {
1602
- method: 'DELETE',
1603
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1784
+ method: 'GET',
1785
+ url: '/api/v1/{region}/bean/prices',
1604
1786
  path: {
1605
- id: data.id,
1606
1787
  region: data.region
1607
1788
  },
1608
- errors: {
1609
- 404: 'Rule not found'
1789
+ query: {
1790
+ currency: data.currency,
1791
+ quoteCurrency: data.quoteCurrency,
1792
+ dateFrom: data.dateFrom,
1793
+ dateTo: data.dateTo,
1794
+ search: data.search,
1795
+ page: data.page,
1796
+ limit: data.limit
1610
1797
  }
1611
1798
  });
1612
1799
  }
1613
1800
 
1614
1801
  /**
1615
- * Get rule with statistics
1616
- * Returns a rule with pending/overdue counts and next expected date
1802
+ * Get price by ID
1803
+ * Returns a single price entry by its ID
1617
1804
  * @param data The data for the request.
1618
- * @param data.id Rule ID
1805
+ * @param data.id Price ID
1619
1806
  * @param data.region Region code for tenant context
1620
- * @returns RecurringRuleWithStatsResponseDto Rule with stats retrieved successfully
1807
+ * @returns PriceResponseDto Price retrieved successfully
1621
1808
  * @throws ApiError
1622
1809
  */
1623
- public static recurringRuleControllerGetWithStats(
1624
- data: RecurringRuleControllerGetWithStatsData
1625
- ): CancelablePromise<RecurringRuleControllerGetWithStatsResponse> {
1810
+ public static priceControllerFindOne(
1811
+ data: PriceControllerFindOneData
1812
+ ): CancelablePromise<PriceControllerFindOneResponse> {
1626
1813
  return __request(OpenAPI, {
1627
1814
  method: 'GET',
1628
- url: '/api/v1/{region}/bean/recurring-rules/{id}/stats',
1815
+ url: '/api/v1/{region}/bean/prices/{id}',
1629
1816
  path: {
1630
1817
  id: data.id,
1631
1818
  region: data.region
1632
1819
  },
1633
1820
  errors: {
1634
- 404: 'Rule not found'
1821
+ 404: 'Price not found'
1635
1822
  }
1636
1823
  });
1637
1824
  }
1638
- }
1639
1825
 
1640
- export class ExpectedTransactionsService {
1641
1826
  /**
1642
- * List expected transactions
1643
- * Returns expected transactions for the authenticated user with optional filtering
1827
+ * Update a price
1828
+ * Updates an existing price entry
1644
1829
  * @param data The data for the request.
1830
+ * @param data.id Price ID
1645
1831
  * @param data.region Region code for tenant context
1646
- * @param data.ruleId Filter by recurring rule ID
1647
- * @param data.status Filter by status (PENDING, COMPLETED, SKIPPED)
1648
- * @param data.fromDate Filter by date range start (YYYY-MM-DD)
1649
- * @param data.toDate Filter by date range end (YYYY-MM-DD)
1650
- * @returns ExpectedTransactionListResponseDto Expected transactions retrieved successfully
1832
+ * @param data.requestBody
1833
+ * @returns PriceResponseDto Price updated successfully
1651
1834
  * @throws ApiError
1652
1835
  */
1653
- public static expectedTransactionControllerFindAll(
1654
- data: ExpectedTransactionControllerFindAllData
1655
- ): CancelablePromise<ExpectedTransactionControllerFindAllResponse> {
1836
+ public static priceControllerUpdate(
1837
+ data: PriceControllerUpdateData
1838
+ ): CancelablePromise<PriceControllerUpdateResponse> {
1656
1839
  return __request(OpenAPI, {
1657
- method: 'GET',
1658
- url: '/api/v1/{region}/bean/expected-transactions',
1840
+ method: 'PUT',
1841
+ url: '/api/v1/{region}/bean/prices/{id}',
1659
1842
  path: {
1843
+ id: data.id,
1660
1844
  region: data.region
1661
1845
  },
1662
- query: {
1663
- ruleId: data.ruleId,
1664
- status: data.status,
1665
- fromDate: data.fromDate,
1666
- toDate: data.toDate
1846
+ body: data.requestBody,
1847
+ mediaType: 'application/json',
1848
+ errors: {
1849
+ 404: 'Price not found',
1850
+ 409: 'Updated price conflicts with existing price'
1667
1851
  }
1668
1852
  });
1669
1853
  }
1670
1854
 
1671
1855
  /**
1672
- * List overdue expected transactions
1673
- * Returns all overdue expected transactions (PENDING past tolerance)
1856
+ * Delete a price
1857
+ * Deletes a price entry (hard delete)
1674
1858
  * @param data The data for the request.
1859
+ * @param data.id Price ID
1675
1860
  * @param data.region Region code for tenant context
1676
- * @returns ExpectedTransactionListResponseDto Overdue transactions retrieved successfully
1861
+ * @returns void Price deleted successfully
1677
1862
  * @throws ApiError
1678
1863
  */
1679
- public static expectedTransactionControllerFindOverdue(
1680
- data: ExpectedTransactionControllerFindOverdueData
1681
- ): CancelablePromise<ExpectedTransactionControllerFindOverdueResponse> {
1864
+ public static priceControllerDelete(
1865
+ data: PriceControllerDeleteData
1866
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1682
1867
  return __request(OpenAPI, {
1683
- method: 'GET',
1684
- url: '/api/v1/{region}/bean/expected-transactions/overdue',
1868
+ method: 'DELETE',
1869
+ url: '/api/v1/{region}/bean/prices/{id}',
1685
1870
  path: {
1871
+ id: data.id,
1686
1872
  region: data.region
1873
+ },
1874
+ errors: {
1875
+ 404: 'Price not found'
1687
1876
  }
1688
1877
  });
1689
1878
  }
1690
1879
 
1691
1880
  /**
1692
- * Get expected transaction by ID
1693
- * Returns a specific expected transaction with rule details
1881
+ * Bulk create prices
1882
+ * Creates multiple price entries at once (skips duplicates)
1694
1883
  * @param data The data for the request.
1695
- * @param data.id Expected transaction ID
1696
1884
  * @param data.region Region code for tenant context
1697
- * @returns ExpectedTransactionResponseDto Expected transaction retrieved successfully
1885
+ * @param data.requestBody
1886
+ * @returns PriceResponseDto Prices created successfully
1698
1887
  * @throws ApiError
1699
1888
  */
1700
- public static expectedTransactionControllerFindOne(
1701
- data: ExpectedTransactionControllerFindOneData
1702
- ): CancelablePromise<ExpectedTransactionControllerFindOneResponse> {
1889
+ public static priceControllerBulkCreate(
1890
+ data: PriceControllerBulkCreateData
1891
+ ): CancelablePromise<PriceControllerBulkCreateResponse> {
1703
1892
  return __request(OpenAPI, {
1704
- method: 'GET',
1705
- url: '/api/v1/{region}/bean/expected-transactions/{id}',
1893
+ method: 'POST',
1894
+ url: '/api/v1/{region}/bean/prices/bulk',
1706
1895
  path: {
1707
- id: data.id,
1708
1896
  region: data.region
1709
1897
  },
1710
- errors: {
1711
- 404: 'Expected transaction not found'
1712
- }
1898
+ body: data.requestBody,
1899
+ mediaType: 'application/json'
1713
1900
  });
1714
1901
  }
1902
+ }
1715
1903
 
1904
+ export class UsersService {
1716
1905
  /**
1717
- * Skip expected transaction
1718
- * Marks an expected transaction as skipped (PENDING -> SKIPPED)
1906
+ * Delete own user account
1719
1907
  * @param data The data for the request.
1720
- * @param data.id Expected transaction ID
1721
- * @param data.region Region code for tenant context
1722
- * @returns ExpectedTransactionResponseDto Expected transaction skipped successfully
1908
+ * @param data.requestBody
1909
+ * @returns void User deleted successfully
1723
1910
  * @throws ApiError
1724
1911
  */
1725
- public static expectedTransactionControllerSkip(
1726
- data: ExpectedTransactionControllerSkipData
1727
- ): CancelablePromise<ExpectedTransactionControllerSkipResponse> {
1912
+ public static userControllerDeleteOwnUser(
1913
+ data: UserControllerDeleteOwnUserData
1914
+ ): CancelablePromise<UserControllerDeleteOwnUserResponse> {
1728
1915
  return __request(OpenAPI, {
1729
- method: 'POST',
1730
- url: '/api/v1/{region}/bean/expected-transactions/{id}/skip',
1731
- path: {
1732
- id: data.id,
1733
- region: data.region
1734
- },
1916
+ method: 'DELETE',
1917
+ url: '/api/v1/users',
1918
+ body: data.requestBody,
1919
+ mediaType: 'application/json',
1735
1920
  errors: {
1736
- 400: 'Cannot skip - not in PENDING status',
1737
- 404: 'Expected transaction not found'
1921
+ 403: 'Invalid access token'
1738
1922
  }
1739
1923
  });
1740
1924
  }
1741
1925
 
1742
1926
  /**
1743
- * Undo skip
1744
- * Reverses a skip operation (SKIPPED -> PENDING)
1927
+ * Get current authenticated user
1745
1928
  * @param data The data for the request.
1746
- * @param data.id Expected transaction ID
1747
- * @param data.region Region code for tenant context
1748
- * @returns ExpectedTransactionResponseDto Skip undone successfully
1929
+ * @param data.acceptLanguage
1930
+ * @returns UserResponseDto User retrieved successfully
1749
1931
  * @throws ApiError
1750
1932
  */
1751
- public static expectedTransactionControllerUndoSkip(
1752
- data: ExpectedTransactionControllerUndoSkipData
1753
- ): CancelablePromise<ExpectedTransactionControllerUndoSkipResponse> {
1933
+ public static userControllerGetUser(
1934
+ data: UserControllerGetUserData
1935
+ ): CancelablePromise<UserControllerGetUserResponse> {
1754
1936
  return __request(OpenAPI, {
1755
- method: 'DELETE',
1756
- url: '/api/v1/{region}/bean/expected-transactions/{id}/skip',
1757
- path: {
1758
- id: data.id,
1759
- region: data.region
1760
- },
1761
- errors: {
1762
- 400: 'Cannot undo - not in SKIPPED status',
1763
- 404: 'Expected transaction not found'
1937
+ method: 'GET',
1938
+ url: '/api/v1/users',
1939
+ headers: {
1940
+ 'accept-language': data.acceptLanguage
1764
1941
  }
1765
1942
  });
1766
1943
  }
1767
1944
 
1768
1945
  /**
1769
- * Confirm transaction match
1770
- * Manually matches an expected transaction with an actual transaction
1946
+ * Sign up new user
1947
+ * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
1771
1948
  * @param data The data for the request.
1772
- * @param data.id Expected transaction ID
1773
- * @param data.region Region code for tenant context
1774
1949
  * @param data.requestBody
1775
- * @returns unknown Match confirmed successfully
1950
+ * @returns SignupResponseDto User created successfully
1776
1951
  * @throws ApiError
1777
1952
  */
1778
- public static expectedTransactionControllerConfirmMatch(
1779
- data: ExpectedTransactionControllerConfirmMatchData
1780
- ): CancelablePromise<ExpectedTransactionControllerConfirmMatchResponse> {
1953
+ public static userControllerSignupUser(
1954
+ data: UserControllerSignupUserData
1955
+ ): CancelablePromise<UserControllerSignupUserResponse> {
1781
1956
  return __request(OpenAPI, {
1782
1957
  method: 'POST',
1783
- url: '/api/v1/{region}/bean/expected-transactions/{id}/match',
1784
- path: {
1785
- id: data.id,
1786
- region: data.region
1787
- },
1958
+ url: '/api/v1/users',
1788
1959
  body: data.requestBody,
1789
1960
  mediaType: 'application/json',
1790
1961
  errors: {
1791
- 400: 'Cannot match - not in PENDING status',
1792
- 404: 'Expected or actual transaction not found',
1793
- 409: 'Actual transaction already matched to another rule'
1962
+ 400: 'Invalid Turnstile token (when Turnstile is enabled)',
1963
+ 403: 'User signup is disabled'
1794
1964
  }
1795
1965
  });
1796
1966
  }
1797
1967
 
1798
1968
  /**
1799
- * Unmatch transaction
1800
- * Removes the match between expected and actual transaction (COMPLETED -> PENDING)
1969
+ * Delete user by ID (admin only)
1801
1970
  * @param data The data for the request.
1802
- * @param data.id Expected transaction ID
1803
- * @param data.region Region code for tenant context
1804
- * @returns unknown Match removed successfully
1971
+ * @param data.id User ID to delete
1972
+ * @returns void User deleted successfully
1805
1973
  * @throws ApiError
1806
1974
  */
1807
- public static expectedTransactionControllerUnmatch(
1808
- data: ExpectedTransactionControllerUnmatchData
1809
- ): CancelablePromise<ExpectedTransactionControllerUnmatchResponse> {
1975
+ public static userControllerDeleteUser(
1976
+ data: UserControllerDeleteUserData
1977
+ ): CancelablePromise<UserControllerDeleteUserResponse> {
1810
1978
  return __request(OpenAPI, {
1811
1979
  method: 'DELETE',
1812
- url: '/api/v1/{region}/bean/expected-transactions/{id}/match',
1980
+ url: '/api/v1/users/{id}',
1813
1981
  path: {
1814
- id: data.id,
1815
- region: data.region
1982
+ id: data.id
1816
1983
  },
1817
1984
  errors: {
1818
- 400: 'Cannot unmatch - not in COMPLETED status',
1819
- 404: 'Expected transaction not found'
1985
+ 403: 'Cannot delete own account or insufficient permissions'
1820
1986
  }
1821
1987
  });
1822
1988
  }
1823
1989
 
1824
1990
  /**
1825
- * Enter Now
1826
- * Creates an actual transaction for an expected transaction (YNAB-style Enter Now)
1991
+ * Get user info by user ID
1827
1992
  * @param data The data for the request.
1828
- * @param data.id Expected transaction ID
1829
- * @param data.region Region code for tenant context
1830
- * @param data.requestBody
1831
- * @returns unknown Transaction created successfully
1993
+ * @param data.id User ID
1994
+ * @returns unknown User info retrieved successfully
1832
1995
  * @throws ApiError
1833
1996
  */
1834
- public static expectedTransactionControllerEnterNow(
1835
- data: ExpectedTransactionControllerEnterNowData
1836
- ): CancelablePromise<ExpectedTransactionControllerEnterNowResponse> {
1997
+ public static userControllerGetUserInfo(
1998
+ data: UserControllerGetUserInfoData
1999
+ ): CancelablePromise<UserControllerGetUserInfoResponse> {
1837
2000
  return __request(OpenAPI, {
1838
- method: 'POST',
1839
- url: '/api/v1/{region}/bean/expected-transactions/{id}/enter',
2001
+ method: 'GET',
2002
+ url: '/api/v1/users/{id}/info',
1840
2003
  path: {
1841
- id: data.id,
1842
- region: data.region
2004
+ id: data.id
1843
2005
  },
1844
- body: data.requestBody,
1845
- mediaType: 'application/json',
1846
2006
  errors: {
1847
- 400: 'Cannot enter - not in PENDING status or missing accounts',
1848
- 404: 'Expected transaction or accounts not found'
2007
+ 403: 'Cannot access other user info without admin permission'
1849
2008
  }
1850
2009
  });
1851
2010
  }
1852
- }
1853
2011
 
1854
- export class RecurringForecastService {
1855
2012
  /**
1856
- * Get cash flow forecast
1857
- * Returns predicted outflows for the next N months based on active recurring rules
2013
+ * Update user settings
1858
2014
  * @param data The data for the request.
1859
- * @param data.region Region code for tenant context
1860
- * @param data.months Number of months to forecast (1-12, default 3)
1861
- * @returns ForecastResponseDto Forecast retrieved successfully
2015
+ * @param data.requestBody
2016
+ * @returns unknown Settings updated successfully
1862
2017
  * @throws ApiError
1863
2018
  */
1864
- public static forecastControllerGetForecast(
1865
- data: ForecastControllerGetForecastData
1866
- ): CancelablePromise<ForecastControllerGetForecastResponse> {
2019
+ public static userControllerUpdateUserSetting(
2020
+ data: UserControllerUpdateUserSettingData
2021
+ ): CancelablePromise<UserControllerUpdateUserSettingResponse> {
1867
2022
  return __request(OpenAPI, {
1868
- method: 'GET',
1869
- url: '/api/v1/{region}/bean/recurring/forecast',
1870
- path: {
1871
- region: data.region
1872
- },
1873
- query: {
1874
- months: data.months
2023
+ method: 'PUT',
2024
+ url: '/api/v1/users/setting',
2025
+ body: data.requestBody,
2026
+ mediaType: 'application/json',
2027
+ errors: {
2028
+ 403: 'Insufficient permissions'
1875
2029
  }
1876
2030
  });
1877
2031
  }
1878
- }
1879
2032
 
1880
- export class BeanTransactionRulesService {
1881
2033
  /**
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.
2034
+ * Get all user settings paginated (admin only)
1884
2035
  * @param data The data for the request.
1885
- * @param data.region Region code for tenant context
2036
+ * @param data.pageNo Page number
2037
+ * @param data.pageSize Page size
2038
+ * @returns unknown Settings list retrieved successfully
2039
+ * @throws ApiError
2040
+ */
2041
+ public static userControllerGetAllUserSettingsByPage(
2042
+ data: UserControllerGetAllUserSettingsByPageData
2043
+ ): CancelablePromise<UserControllerGetAllUserSettingsByPageResponse> {
2044
+ return __request(OpenAPI, {
2045
+ method: 'GET',
2046
+ url: '/api/v1/users/settings-by-page',
2047
+ query: {
2048
+ pageNo: data.pageNo,
2049
+ pageSize: data.pageSize
2050
+ }
2051
+ });
2052
+ }
2053
+
2054
+ /**
2055
+ * Get asset and liability summary for current user
2056
+ * @returns unknown Summary retrieved successfully
2057
+ * @throws ApiError
2058
+ */
2059
+ public static userControllerGetAssetLiabilitySummary(): CancelablePromise<UserControllerGetAssetLiabilitySummaryResponse> {
2060
+ return __request(OpenAPI, {
2061
+ method: 'GET',
2062
+ url: '/api/v1/users/asset-liability-summary'
2063
+ });
2064
+ }
2065
+ }
2066
+
2067
+ export class PropertiesService {
2068
+ /**
2069
+ * Get all system properties
2070
+ * @returns unknown Properties retrieved successfully
2071
+ * @throws ApiError
2072
+ */
2073
+ public static propertyControllerGetAll(): CancelablePromise<PropertyControllerGetAllResponse> {
2074
+ return __request(OpenAPI, {
2075
+ method: 'GET',
2076
+ url: '/api/v1/admin/properties',
2077
+ errors: {
2078
+ 401: 'Unauthorized',
2079
+ 403: 'Forbidden - insufficient permissions'
2080
+ }
2081
+ });
2082
+ }
2083
+
2084
+ /**
2085
+ * Get property by key
2086
+ * @param data The data for the request.
2087
+ * @param data.key Property key
2088
+ * @returns unknown Property retrieved successfully
2089
+ * @throws ApiError
2090
+ */
2091
+ public static propertyControllerGetByKey(
2092
+ data: PropertyControllerGetByKeyData
2093
+ ): CancelablePromise<PropertyControllerGetByKeyResponse> {
2094
+ return __request(OpenAPI, {
2095
+ method: 'GET',
2096
+ url: '/api/v1/admin/properties/{key}',
2097
+ path: {
2098
+ key: data.key
2099
+ },
2100
+ errors: {
2101
+ 401: 'Unauthorized',
2102
+ 403: 'Forbidden - insufficient permissions',
2103
+ 404: 'Property not found'
2104
+ }
2105
+ });
2106
+ }
2107
+
2108
+ /**
2109
+ * Update a system property
2110
+ * @param data The data for the request.
2111
+ * @param data.key Property key
2112
+ * @param data.requestBody
2113
+ * @returns unknown Property updated successfully
2114
+ * @throws ApiError
2115
+ */
2116
+ public static propertyControllerUpdate(
2117
+ data: PropertyControllerUpdateData
2118
+ ): CancelablePromise<PropertyControllerUpdateResponse> {
2119
+ return __request(OpenAPI, {
2120
+ method: 'PUT',
2121
+ url: '/api/v1/admin/properties/{key}',
2122
+ path: {
2123
+ key: data.key
2124
+ },
2125
+ body: data.requestBody,
2126
+ mediaType: 'application/json',
2127
+ errors: {
2128
+ 401: 'Unauthorized',
2129
+ 403: 'Forbidden - insufficient permissions'
2130
+ }
2131
+ });
2132
+ }
2133
+
2134
+ /**
2135
+ * Delete a system property
2136
+ * @param data The data for the request.
2137
+ * @param data.key Property key
2138
+ * @returns void Property deleted successfully
2139
+ * @throws ApiError
2140
+ */
2141
+ public static propertyControllerDelete(
2142
+ data: PropertyControllerDeleteData
2143
+ ): CancelablePromise<PropertyControllerDeleteResponse> {
2144
+ return __request(OpenAPI, {
2145
+ method: 'DELETE',
2146
+ url: '/api/v1/admin/properties/{key}',
2147
+ path: {
2148
+ key: data.key
2149
+ },
2150
+ errors: {
2151
+ 401: 'Unauthorized',
2152
+ 403: 'Forbidden - insufficient permissions',
2153
+ 404: 'Property not found'
2154
+ }
2155
+ });
2156
+ }
2157
+ }
2158
+
2159
+ export class RecurringRulesService {
2160
+ /**
2161
+ * Create a new recurring rule
2162
+ * Creates a new recurring transaction rule for the authenticated user
2163
+ * @param data The data for the request.
2164
+ * @param data.region Region code for tenant context
2165
+ * @param data.requestBody
2166
+ * @returns RecurringRuleResponseDto Rule created successfully
2167
+ * @throws ApiError
2168
+ */
2169
+ public static recurringRuleControllerCreate(
2170
+ data: RecurringRuleControllerCreateData
2171
+ ): CancelablePromise<RecurringRuleControllerCreateResponse> {
2172
+ return __request(OpenAPI, {
2173
+ method: 'POST',
2174
+ url: '/api/v1/{region}/bean/recurring-rules',
2175
+ path: {
2176
+ region: data.region
2177
+ },
2178
+ body: data.requestBody,
2179
+ mediaType: 'application/json',
2180
+ errors: {
2181
+ 400: 'Invalid input data (e.g., autoCreate without accounts)',
2182
+ 409: 'Rule with same name already exists'
2183
+ }
2184
+ });
2185
+ }
2186
+
2187
+ /**
2188
+ * List recurring rules
2189
+ * Returns all recurring rules for the authenticated user with optional filtering
2190
+ * @param data The data for the request.
2191
+ * @param data.region Region code for tenant context
2192
+ * @param data.isActive Filter by active status
2193
+ * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
2194
+ * @param data.hasAutoCreate Filter by autoCreate enabled
2195
+ * @returns RecurringRuleResponseDto Rules retrieved successfully
2196
+ * @throws ApiError
2197
+ */
2198
+ public static recurringRuleControllerFindAll(
2199
+ data: RecurringRuleControllerFindAllData
2200
+ ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
2201
+ return __request(OpenAPI, {
2202
+ method: 'GET',
2203
+ url: '/api/v1/{region}/bean/recurring-rules',
2204
+ path: {
2205
+ region: data.region
2206
+ },
2207
+ query: {
2208
+ isActive: data.isActive,
2209
+ frequency: data.frequency,
2210
+ hasAutoCreate: data.hasAutoCreate
2211
+ }
2212
+ });
2213
+ }
2214
+
2215
+ /**
2216
+ * Create recurring rule from transaction
2217
+ * Auto-creates a recurring rule using transaction data. User only confirms frequency.
2218
+ * @param data The data for the request.
2219
+ * @param data.transactionId Source transaction ID
2220
+ * @param data.region Region code for tenant context
2221
+ * @param data.requestBody
2222
+ * @returns RecurringRuleResponseDto Rule created successfully
2223
+ * @throws ApiError
2224
+ */
2225
+ public static recurringRuleControllerCreateFromTransaction(
2226
+ data: RecurringRuleControllerCreateFromTransactionData
2227
+ ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
2228
+ return __request(OpenAPI, {
2229
+ method: 'POST',
2230
+ url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
2231
+ path: {
2232
+ transactionId: data.transactionId,
2233
+ region: data.region
2234
+ },
2235
+ body: data.requestBody,
2236
+ mediaType: 'application/json',
2237
+ errors: {
2238
+ 404: 'Transaction not found',
2239
+ 409: 'Rule with same name already exists or transaction already linked'
2240
+ }
2241
+ });
2242
+ }
2243
+
2244
+ /**
2245
+ * Get recurring rule by ID
2246
+ * Returns a specific recurring rule with its details
2247
+ * @param data The data for the request.
2248
+ * @param data.id Rule ID
2249
+ * @param data.region Region code for tenant context
2250
+ * @returns RecurringRuleResponseDto Rule retrieved successfully
2251
+ * @throws ApiError
2252
+ */
2253
+ public static recurringRuleControllerFindOne(
2254
+ data: RecurringRuleControllerFindOneData
2255
+ ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
2256
+ return __request(OpenAPI, {
2257
+ method: 'GET',
2258
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
2259
+ path: {
2260
+ id: data.id,
2261
+ region: data.region
2262
+ },
2263
+ errors: {
2264
+ 404: 'Rule not found'
2265
+ }
2266
+ });
2267
+ }
2268
+
2269
+ /**
2270
+ * Update recurring rule
2271
+ * Updates an existing recurring rule
2272
+ * @param data The data for the request.
2273
+ * @param data.id Rule ID
2274
+ * @param data.region Region code for tenant context
2275
+ * @param data.requestBody
2276
+ * @returns RecurringRuleResponseDto Rule updated successfully
2277
+ * @throws ApiError
2278
+ */
2279
+ public static recurringRuleControllerUpdate(
2280
+ data: RecurringRuleControllerUpdateData
2281
+ ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
2282
+ return __request(OpenAPI, {
2283
+ method: 'PATCH',
2284
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
2285
+ path: {
2286
+ id: data.id,
2287
+ region: data.region
2288
+ },
2289
+ body: data.requestBody,
2290
+ mediaType: 'application/json',
2291
+ errors: {
2292
+ 400: 'Invalid input data',
2293
+ 404: 'Rule not found'
2294
+ }
2295
+ });
2296
+ }
2297
+
2298
+ /**
2299
+ * Delete recurring rule
2300
+ * Soft deletes a recurring rule (sets isActive to false)
2301
+ * @param data The data for the request.
2302
+ * @param data.id Rule ID
2303
+ * @param data.region Region code for tenant context
2304
+ * @returns void Rule deleted successfully
2305
+ * @throws ApiError
2306
+ */
2307
+ public static recurringRuleControllerDelete(
2308
+ data: RecurringRuleControllerDeleteData
2309
+ ): CancelablePromise<RecurringRuleControllerDeleteResponse> {
2310
+ return __request(OpenAPI, {
2311
+ method: 'DELETE',
2312
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
2313
+ path: {
2314
+ id: data.id,
2315
+ region: data.region
2316
+ },
2317
+ errors: {
2318
+ 404: 'Rule not found'
2319
+ }
2320
+ });
2321
+ }
2322
+
2323
+ /**
2324
+ * Get rule with statistics
2325
+ * Returns a rule with pending/overdue counts and next expected date
2326
+ * @param data The data for the request.
2327
+ * @param data.id Rule ID
2328
+ * @param data.region Region code for tenant context
2329
+ * @returns RecurringRuleWithStatsResponseDto Rule with stats retrieved successfully
2330
+ * @throws ApiError
2331
+ */
2332
+ public static recurringRuleControllerGetWithStats(
2333
+ data: RecurringRuleControllerGetWithStatsData
2334
+ ): CancelablePromise<RecurringRuleControllerGetWithStatsResponse> {
2335
+ return __request(OpenAPI, {
2336
+ method: 'GET',
2337
+ url: '/api/v1/{region}/bean/recurring-rules/{id}/stats',
2338
+ path: {
2339
+ id: data.id,
2340
+ region: data.region
2341
+ },
2342
+ errors: {
2343
+ 404: 'Rule not found'
2344
+ }
2345
+ });
2346
+ }
2347
+ }
2348
+
2349
+ export class ExpectedTransactionsService {
2350
+ /**
2351
+ * List expected transactions
2352
+ * Returns expected transactions for the authenticated user with optional filtering
2353
+ * @param data The data for the request.
2354
+ * @param data.region Region code for tenant context
2355
+ * @param data.ruleId Filter by recurring rule ID
2356
+ * @param data.status Filter by status (PENDING, COMPLETED, SKIPPED)
2357
+ * @param data.fromDate Filter by date range start (YYYY-MM-DD)
2358
+ * @param data.toDate Filter by date range end (YYYY-MM-DD)
2359
+ * @returns ExpectedTransactionListResponseDto Expected transactions retrieved successfully
2360
+ * @throws ApiError
2361
+ */
2362
+ public static expectedTransactionControllerFindAll(
2363
+ data: ExpectedTransactionControllerFindAllData
2364
+ ): CancelablePromise<ExpectedTransactionControllerFindAllResponse> {
2365
+ return __request(OpenAPI, {
2366
+ method: 'GET',
2367
+ url: '/api/v1/{region}/bean/expected-transactions',
2368
+ path: {
2369
+ region: data.region
2370
+ },
2371
+ query: {
2372
+ ruleId: data.ruleId,
2373
+ status: data.status,
2374
+ fromDate: data.fromDate,
2375
+ toDate: data.toDate
2376
+ }
2377
+ });
2378
+ }
2379
+
2380
+ /**
2381
+ * List overdue expected transactions
2382
+ * Returns all overdue expected transactions (PENDING past tolerance)
2383
+ * @param data The data for the request.
2384
+ * @param data.region Region code for tenant context
2385
+ * @returns ExpectedTransactionListResponseDto Overdue transactions retrieved successfully
2386
+ * @throws ApiError
2387
+ */
2388
+ public static expectedTransactionControllerFindOverdue(
2389
+ data: ExpectedTransactionControllerFindOverdueData
2390
+ ): CancelablePromise<ExpectedTransactionControllerFindOverdueResponse> {
2391
+ return __request(OpenAPI, {
2392
+ method: 'GET',
2393
+ url: '/api/v1/{region}/bean/expected-transactions/overdue',
2394
+ path: {
2395
+ region: data.region
2396
+ }
2397
+ });
2398
+ }
2399
+
2400
+ /**
2401
+ * Get expected transaction by ID
2402
+ * Returns a specific expected transaction with rule details
2403
+ * @param data The data for the request.
2404
+ * @param data.id Expected transaction ID
2405
+ * @param data.region Region code for tenant context
2406
+ * @returns ExpectedTransactionResponseDto Expected transaction retrieved successfully
2407
+ * @throws ApiError
2408
+ */
2409
+ public static expectedTransactionControllerFindOne(
2410
+ data: ExpectedTransactionControllerFindOneData
2411
+ ): CancelablePromise<ExpectedTransactionControllerFindOneResponse> {
2412
+ return __request(OpenAPI, {
2413
+ method: 'GET',
2414
+ url: '/api/v1/{region}/bean/expected-transactions/{id}',
2415
+ path: {
2416
+ id: data.id,
2417
+ region: data.region
2418
+ },
2419
+ errors: {
2420
+ 404: 'Expected transaction not found'
2421
+ }
2422
+ });
2423
+ }
2424
+
2425
+ /**
2426
+ * Skip expected transaction
2427
+ * Marks an expected transaction as skipped (PENDING -> SKIPPED)
2428
+ * @param data The data for the request.
2429
+ * @param data.id Expected transaction ID
2430
+ * @param data.region Region code for tenant context
2431
+ * @returns ExpectedTransactionResponseDto Expected transaction skipped successfully
2432
+ * @throws ApiError
2433
+ */
2434
+ public static expectedTransactionControllerSkip(
2435
+ data: ExpectedTransactionControllerSkipData
2436
+ ): CancelablePromise<ExpectedTransactionControllerSkipResponse> {
2437
+ return __request(OpenAPI, {
2438
+ method: 'POST',
2439
+ url: '/api/v1/{region}/bean/expected-transactions/{id}/skip',
2440
+ path: {
2441
+ id: data.id,
2442
+ region: data.region
2443
+ },
2444
+ errors: {
2445
+ 400: 'Cannot skip - not in PENDING status',
2446
+ 404: 'Expected transaction not found'
2447
+ }
2448
+ });
2449
+ }
2450
+
2451
+ /**
2452
+ * Undo skip
2453
+ * Reverses a skip operation (SKIPPED -> PENDING)
2454
+ * @param data The data for the request.
2455
+ * @param data.id Expected transaction ID
2456
+ * @param data.region Region code for tenant context
2457
+ * @returns void Skip undone successfully
2458
+ * @throws ApiError
2459
+ */
2460
+ public static expectedTransactionControllerUndoSkip(
2461
+ data: ExpectedTransactionControllerUndoSkipData
2462
+ ): CancelablePromise<ExpectedTransactionControllerUndoSkipResponse> {
2463
+ return __request(OpenAPI, {
2464
+ method: 'DELETE',
2465
+ url: '/api/v1/{region}/bean/expected-transactions/{id}/skip',
2466
+ path: {
2467
+ id: data.id,
2468
+ region: data.region
2469
+ },
2470
+ errors: {
2471
+ 400: 'Cannot undo - not in SKIPPED status',
2472
+ 404: 'Expected transaction not found'
2473
+ }
2474
+ });
2475
+ }
2476
+
2477
+ /**
2478
+ * Confirm transaction match
2479
+ * Manually matches an expected transaction with an actual transaction
2480
+ * @param data The data for the request.
2481
+ * @param data.id Expected transaction ID
2482
+ * @param data.region Region code for tenant context
2483
+ * @param data.requestBody
2484
+ * @returns unknown Match confirmed successfully
2485
+ * @throws ApiError
2486
+ */
2487
+ public static expectedTransactionControllerConfirmMatch(
2488
+ data: ExpectedTransactionControllerConfirmMatchData
2489
+ ): CancelablePromise<ExpectedTransactionControllerConfirmMatchResponse> {
2490
+ return __request(OpenAPI, {
2491
+ method: 'POST',
2492
+ url: '/api/v1/{region}/bean/expected-transactions/{id}/match',
2493
+ path: {
2494
+ id: data.id,
2495
+ region: data.region
2496
+ },
2497
+ body: data.requestBody,
2498
+ mediaType: 'application/json',
2499
+ errors: {
2500
+ 400: 'Cannot match - not in PENDING status',
2501
+ 404: 'Expected or actual transaction not found',
2502
+ 409: 'Actual transaction already matched to another rule'
2503
+ }
2504
+ });
2505
+ }
2506
+
2507
+ /**
2508
+ * Unmatch transaction
2509
+ * Removes the match between expected and actual transaction (COMPLETED -> PENDING)
2510
+ * @param data The data for the request.
2511
+ * @param data.id Expected transaction ID
2512
+ * @param data.region Region code for tenant context
2513
+ * @returns void Match removed successfully
2514
+ * @throws ApiError
2515
+ */
2516
+ public static expectedTransactionControllerUnmatch(
2517
+ data: ExpectedTransactionControllerUnmatchData
2518
+ ): CancelablePromise<ExpectedTransactionControllerUnmatchResponse> {
2519
+ return __request(OpenAPI, {
2520
+ method: 'DELETE',
2521
+ url: '/api/v1/{region}/bean/expected-transactions/{id}/match',
2522
+ path: {
2523
+ id: data.id,
2524
+ region: data.region
2525
+ },
2526
+ errors: {
2527
+ 400: 'Cannot unmatch - not in COMPLETED status',
2528
+ 404: 'Expected transaction not found'
2529
+ }
2530
+ });
2531
+ }
2532
+
2533
+ /**
2534
+ * Enter Now
2535
+ * Creates an actual transaction for an expected transaction (YNAB-style Enter Now)
2536
+ * @param data The data for the request.
2537
+ * @param data.id Expected transaction ID
2538
+ * @param data.region Region code for tenant context
2539
+ * @param data.requestBody
2540
+ * @returns unknown Transaction created successfully
2541
+ * @throws ApiError
2542
+ */
2543
+ public static expectedTransactionControllerEnterNow(
2544
+ data: ExpectedTransactionControllerEnterNowData
2545
+ ): CancelablePromise<ExpectedTransactionControllerEnterNowResponse> {
2546
+ return __request(OpenAPI, {
2547
+ method: 'POST',
2548
+ url: '/api/v1/{region}/bean/expected-transactions/{id}/enter',
2549
+ path: {
2550
+ id: data.id,
2551
+ region: data.region
2552
+ },
2553
+ body: data.requestBody,
2554
+ mediaType: 'application/json',
2555
+ errors: {
2556
+ 400: 'Cannot enter - not in PENDING status or missing accounts',
2557
+ 404: 'Expected transaction or accounts not found'
2558
+ }
2559
+ });
2560
+ }
2561
+ }
2562
+
2563
+ export class RecurringForecastService {
2564
+ /**
2565
+ * Get cash flow forecast
2566
+ * Returns predicted outflows for the next N months based on active recurring rules
2567
+ * @param data The data for the request.
2568
+ * @param data.region Region code for tenant context
2569
+ * @param data.months Number of months to forecast (1-12, default 3)
2570
+ * @returns ForecastResponseDto Forecast retrieved successfully
2571
+ * @throws ApiError
2572
+ */
2573
+ public static forecastControllerGetForecast(
2574
+ data: ForecastControllerGetForecastData
2575
+ ): CancelablePromise<ForecastControllerGetForecastResponse> {
2576
+ return __request(OpenAPI, {
2577
+ method: 'GET',
2578
+ url: '/api/v1/{region}/bean/recurring/forecast',
2579
+ path: {
2580
+ region: data.region
2581
+ },
2582
+ query: {
2583
+ months: data.months
2584
+ }
2585
+ });
2586
+ }
2587
+ }
2588
+
2589
+ export class BeanTransactionRulesService {
2590
+ /**
2591
+ * Create a new transaction rule (or upsert if upsertByPayee=true)
2592
+ * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2593
+ * @param data The data for the request.
2594
+ * @param data.region Region code for tenant context
1886
2595
  * @param data.requestBody
1887
2596
  * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
1888
2597
  * @throws ApiError
@@ -2155,256 +2864,337 @@ export class BeanTransactionRulesService {
2155
2864
  }
2156
2865
  }
2157
2866
 
2158
- export class UsersService {
2159
- /**
2160
- * Delete own user account
2161
- * @param data The data for the request.
2162
- * @param data.requestBody
2163
- * @returns void User deleted successfully
2164
- * @throws ApiError
2165
- */
2166
- public static userControllerDeleteOwnUser(
2167
- data: UserControllerDeleteOwnUserData
2168
- ): CancelablePromise<UserControllerDeleteOwnUserResponse> {
2169
- return __request(OpenAPI, {
2170
- method: 'DELETE',
2171
- url: '/api/v1/users',
2172
- body: data.requestBody,
2173
- mediaType: 'application/json',
2174
- errors: {
2175
- 403: 'Invalid access token'
2176
- }
2177
- });
2178
- }
2179
-
2867
+ export class BeanCategoryCatalogService {
2180
2868
  /**
2181
- * Get current authenticated user
2869
+ * List category catalog for a region
2870
+ * Returns the region-scoped category slugs (expense/income/investment/banking/transfer/payment) for the NLP result picker, each with the categoryAccount paths the region-enabled system rules map it to (#816). CN-exclusive payment instruments (huabei/baitiao) appear only under /cn.
2182
2871
  * @param data The data for the request.
2183
- * @param data.acceptLanguage
2184
- * @returns unknown User retrieved successfully
2872
+ * @param data.region Region code for tenant context
2873
+ * @param data.scenario Filter by scenario
2874
+ * @param data.routeBearing Filter by routeBearing (entity-router route() consumes it)
2875
+ * @returns CategoryCatalogListResponseDto Category catalog retrieved successfully
2185
2876
  * @throws ApiError
2186
2877
  */
2187
- public static userControllerGetUser(
2188
- data: UserControllerGetUserData
2189
- ): CancelablePromise<UserControllerGetUserResponse> {
2878
+ public static categoryCatalogControllerList(
2879
+ data: CategoryCatalogControllerListData
2880
+ ): CancelablePromise<CategoryCatalogControllerListResponse> {
2190
2881
  return __request(OpenAPI, {
2191
2882
  method: 'GET',
2192
- url: '/api/v1/users',
2193
- headers: {
2194
- 'accept-language': data.acceptLanguage
2883
+ url: '/api/v1/{region}/bean/categories',
2884
+ path: {
2885
+ region: data.region
2886
+ },
2887
+ query: {
2888
+ scenario: data.scenario,
2889
+ routeBearing: data.routeBearing
2195
2890
  }
2196
2891
  });
2197
2892
  }
2893
+ }
2198
2894
 
2895
+ export class LifeEventsService {
2199
2896
  /**
2200
- * Sign up new user
2201
- * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
2897
+ * Create a new life event
2898
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2202
2899
  * @param data The data for the request.
2900
+ * @param data.region Region code for tenant context (decorative for life events)
2203
2901
  * @param data.requestBody
2204
- * @returns unknown User created successfully
2902
+ * @returns EventResponseDto Life event created successfully
2205
2903
  * @throws ApiError
2206
2904
  */
2207
- public static userControllerSignupUser(
2208
- data: UserControllerSignupUserData
2209
- ): CancelablePromise<UserControllerSignupUserResponse> {
2905
+ public static eventControllerCreate(
2906
+ data: EventControllerCreateData
2907
+ ): CancelablePromise<EventControllerCreateResponse> {
2210
2908
  return __request(OpenAPI, {
2211
2909
  method: 'POST',
2212
- url: '/api/v1/users',
2910
+ url: '/api/v1/{region}/bean/events',
2911
+ path: {
2912
+ region: data.region
2913
+ },
2213
2914
  body: data.requestBody,
2214
2915
  mediaType: 'application/json',
2215
2916
  errors: {
2216
- 400: 'Invalid Turnstile token (when Turnstile is enabled)',
2217
- 403: 'User signup is disabled'
2917
+ 409: 'Life event already exists for this (userId, type, date) combination'
2218
2918
  }
2219
2919
  });
2220
2920
  }
2221
2921
 
2222
2922
  /**
2223
- * Delete user by ID (admin only)
2923
+ * List user life events
2924
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2224
2925
  * @param data The data for the request.
2225
- * @param data.id User ID to delete
2226
- * @returns void User deleted successfully
2926
+ * @param data.region Region code for tenant context (decorative for life events)
2927
+ * @param data.type Filter by life event type (exact match)
2928
+ * @param data.q Search term for description (case-insensitive partial match)
2929
+ * @param data.from Filter life events from this date (ISO 8601 format)
2930
+ * @param data.to Filter life events to this date (ISO 8601 format)
2931
+ * @param data.page Page number for pagination (default: 1)
2932
+ * @param data.limit Number of items per page (default: 20, max: 100)
2933
+ * @returns EventListResponseDto Life events retrieved successfully
2227
2934
  * @throws ApiError
2228
2935
  */
2229
- public static userControllerDeleteUser(
2230
- data: UserControllerDeleteUserData
2231
- ): CancelablePromise<UserControllerDeleteUserResponse> {
2936
+ public static eventControllerFindAll(
2937
+ data: EventControllerFindAllData
2938
+ ): CancelablePromise<EventControllerFindAllResponse> {
2232
2939
  return __request(OpenAPI, {
2233
- method: 'DELETE',
2234
- url: '/api/v1/users/{id}',
2940
+ method: 'GET',
2941
+ url: '/api/v1/{region}/bean/events',
2235
2942
  path: {
2236
- id: data.id
2943
+ region: data.region
2237
2944
  },
2238
- errors: {
2239
- 403: 'Cannot delete own account or insufficient permissions'
2945
+ query: {
2946
+ type: data.type,
2947
+ q: data.q,
2948
+ from: data.from,
2949
+ to: data.to,
2950
+ page: data.page,
2951
+ limit: data.limit
2240
2952
  }
2241
2953
  });
2242
2954
  }
2243
2955
 
2244
2956
  /**
2245
- * Get user info by user ID
2957
+ * Get life event by ID
2958
+ * Returns a single life event by its ID. Returns ETag header.
2246
2959
  * @param data The data for the request.
2247
- * @param data.id User ID
2248
- * @returns unknown User info retrieved successfully
2960
+ * @param data.id Life event ID
2961
+ * @param data.region Region code for tenant context (decorative for life events)
2962
+ * @returns EventResponseDto Life event retrieved successfully
2249
2963
  * @throws ApiError
2250
2964
  */
2251
- public static userControllerGetUserInfo(
2252
- data: UserControllerGetUserInfoData
2253
- ): CancelablePromise<UserControllerGetUserInfoResponse> {
2965
+ public static eventControllerFindOne(
2966
+ data: EventControllerFindOneData
2967
+ ): CancelablePromise<EventControllerFindOneResponse> {
2254
2968
  return __request(OpenAPI, {
2255
2969
  method: 'GET',
2256
- url: '/api/v1/users/{id}/info',
2970
+ url: '/api/v1/{region}/bean/events/{id}',
2257
2971
  path: {
2258
- id: data.id
2972
+ id: data.id,
2973
+ region: data.region
2259
2974
  },
2260
2975
  errors: {
2261
- 403: 'Cannot access other user info without admin permission'
2976
+ 404: 'Life event not found'
2262
2977
  }
2263
2978
  });
2264
2979
  }
2265
2980
 
2266
2981
  /**
2267
- * Update user settings
2982
+ * Update a life event
2983
+ * Updates an existing life event. If If-Match header is provided, performs optimistic concurrency check; mismatched updatedAt returns 412.
2268
2984
  * @param data The data for the request.
2985
+ * @param data.id Life event ID
2986
+ * @param data.region Region code for tenant context (decorative for life events)
2269
2987
  * @param data.requestBody
2270
- * @returns unknown Settings updated successfully
2988
+ * @returns EventResponseDto Life event updated successfully
2271
2989
  * @throws ApiError
2272
2990
  */
2273
- public static userControllerUpdateUserSetting(
2274
- data: UserControllerUpdateUserSettingData
2275
- ): CancelablePromise<UserControllerUpdateUserSettingResponse> {
2991
+ public static eventControllerUpdate(
2992
+ data: EventControllerUpdateData
2993
+ ): CancelablePromise<EventControllerUpdateResponse> {
2276
2994
  return __request(OpenAPI, {
2277
2995
  method: 'PUT',
2278
- url: '/api/v1/users/setting',
2996
+ url: '/api/v1/{region}/bean/events/{id}',
2997
+ path: {
2998
+ id: data.id,
2999
+ region: data.region
3000
+ },
2279
3001
  body: data.requestBody,
2280
3002
  mediaType: 'application/json',
2281
3003
  errors: {
2282
- 403: 'Insufficient permissions'
3004
+ 400: 'If-Match header is not a valid ISO 8601 date',
3005
+ 404: 'Life event not found',
3006
+ 409: 'Updated event conflicts with an existing (userId, type, date) combination',
3007
+ 412: 'If-Match precondition failed (updatedAt mismatch)'
2283
3008
  }
2284
3009
  });
2285
3010
  }
2286
3011
 
2287
3012
  /**
2288
- * Get all user settings paginated (admin only)
3013
+ * Delete a life event
3014
+ * Deletes a life event entry (hard delete). Returns 204.
2289
3015
  * @param data The data for the request.
2290
- * @param data.pageNo Page number
2291
- * @param data.pageSize Page size
2292
- * @returns unknown Settings list retrieved successfully
3016
+ * @param data.id Life event ID
3017
+ * @param data.region Region code for tenant context (decorative for life events)
3018
+ * @returns void Life event deleted successfully
2293
3019
  * @throws ApiError
2294
3020
  */
2295
- public static userControllerGetAllUserSettingsByPage(
2296
- data: UserControllerGetAllUserSettingsByPageData
2297
- ): CancelablePromise<UserControllerGetAllUserSettingsByPageResponse> {
3021
+ public static eventControllerDelete(
3022
+ data: EventControllerDeleteData
3023
+ ): CancelablePromise<EventControllerDeleteResponse> {
3024
+ return __request(OpenAPI, {
3025
+ method: 'DELETE',
3026
+ url: '/api/v1/{region}/bean/events/{id}',
3027
+ path: {
3028
+ id: data.id,
3029
+ region: data.region
3030
+ },
3031
+ errors: {
3032
+ 404: 'Life event not found'
3033
+ }
3034
+ });
3035
+ }
3036
+
3037
+ /**
3038
+ * Slice time-series by a life event (Phase 79)
3039
+ * Returns aggregated time-series for postings matching accountPattern within the half-open date range of the given life event.
3040
+ * @param data The data for the request.
3041
+ * @param data.id Life event ID
3042
+ * @param data.accountPattern
3043
+ * @param data.granularity
3044
+ * @param data.region Region code for tenant context (decorative for life events)
3045
+ * @returns unknown Time-series sliced by the life event range
3046
+ * @throws ApiError
3047
+ */
3048
+ public static eventControllerGetSlice(
3049
+ data: EventControllerGetSliceData
3050
+ ): CancelablePromise<EventControllerGetSliceResponse> {
2298
3051
  return __request(OpenAPI, {
2299
3052
  method: 'GET',
2300
- url: '/api/v1/users/settings-by-page',
3053
+ url: '/api/v1/{region}/bean/events/{id}/slice',
3054
+ path: {
3055
+ id: data.id,
3056
+ region: data.region
3057
+ },
2301
3058
  query: {
2302
- pageNo: data.pageNo,
2303
- pageSize: data.pageSize
3059
+ accountPattern: data.accountPattern,
3060
+ granularity: data.granularity
3061
+ },
3062
+ errors: {
3063
+ 400: 'accountPattern query param is empty',
3064
+ 404: 'Life event not found'
2304
3065
  }
2305
3066
  });
2306
3067
  }
3068
+ }
2307
3069
 
3070
+ export class OnboardingService {
2308
3071
  /**
2309
- * Get asset and liability summary for current user
2310
- * @returns unknown Summary retrieved successfully
3072
+ * Bootstrap core accounts + register asset accounts with opening balances (ADR-0113)
3073
+ * @param data The data for the request.
3074
+ * @param data.region Region code for tenant context. Not-yet-open codes are accepted: the universal catalog backs onboarding regardless of region (#759)
3075
+ * @param data.requestBody
3076
+ * @returns unknown Onboarding bootstrap result.
2311
3077
  * @throws ApiError
2312
3078
  */
2313
- public static userControllerGetAssetLiabilitySummary(): CancelablePromise<UserControllerGetAssetLiabilitySummaryResponse> {
3079
+ public static onboardingControllerBootstrap(
3080
+ data: OnboardingControllerBootstrapData
3081
+ ): CancelablePromise<OnboardingControllerBootstrapResponse> {
2314
3082
  return __request(OpenAPI, {
2315
- method: 'GET',
2316
- url: '/api/v1/users/asset-liability-summary'
3083
+ method: 'POST',
3084
+ url: '/api/v1/{region}/bean/onboarding',
3085
+ path: {
3086
+ region: data.region
3087
+ },
3088
+ body: data.requestBody,
3089
+ mediaType: 'application/json',
3090
+ errors: {
3091
+ 422: 'Invalid region/account path/duplicate paths.'
3092
+ }
2317
3093
  });
2318
3094
  }
2319
3095
  }
2320
3096
 
2321
- export class PropertiesService {
3097
+ export class BalanceReconciliationService {
2322
3098
  /**
2323
- * Get all system properties
2324
- * @returns unknown Properties retrieved successfully
3099
+ * Preview reconciliation (book vs actual)
3100
+ * Computes book balance, diff, Beancount-inferred tolerance, and suggested action without persisting.
3101
+ * @param data The data for the request.
3102
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3103
+ * @param data.requestBody
3104
+ * @returns ReconciliationComputeResultDto Reconciliation preview
2325
3105
  * @throws ApiError
2326
3106
  */
2327
- public static propertyControllerGetAll(): CancelablePromise<PropertyControllerGetAllResponse> {
3107
+ public static reconciliationControllerCompute(
3108
+ data: ReconciliationControllerComputeData
3109
+ ): CancelablePromise<ReconciliationControllerComputeResponse> {
2328
3110
  return __request(OpenAPI, {
2329
- method: 'GET',
2330
- url: '/api/v1/admin/properties',
3111
+ method: 'POST',
3112
+ url: '/api/v1/{region}/bean/reconciliations',
3113
+ path: {
3114
+ region: data.region
3115
+ },
3116
+ body: data.requestBody,
3117
+ mediaType: 'application/json',
2331
3118
  errors: {
2332
- 401: 'Unauthorized',
2333
- 403: 'Forbidden - insufficient permissions'
3119
+ 404: 'Account not found'
2334
3120
  }
2335
3121
  });
2336
3122
  }
2337
3123
 
2338
3124
  /**
2339
- * Get property by key
3125
+ * Record a balance assertion
3126
+ * Persists the reconciliation as a BeanBalance assertion (amount = actual, diffAmount = book − actual). Re-reconciling the same day/currency upserts.
2340
3127
  * @param data The data for the request.
2341
- * @param data.key Property key
2342
- * @returns unknown Property retrieved successfully
3128
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3129
+ * @param data.requestBody
3130
+ * @returns ReconciliationRecordDto Balance assertion recorded
2343
3131
  * @throws ApiError
2344
3132
  */
2345
- public static propertyControllerGetByKey(
2346
- data: PropertyControllerGetByKeyData
2347
- ): CancelablePromise<PropertyControllerGetByKeyResponse> {
3133
+ public static reconciliationControllerAssert(
3134
+ data: ReconciliationControllerAssertData
3135
+ ): CancelablePromise<ReconciliationControllerAssertResponse> {
2348
3136
  return __request(OpenAPI, {
2349
- method: 'GET',
2350
- url: '/api/v1/admin/properties/{key}',
3137
+ method: 'POST',
3138
+ url: '/api/v1/{region}/bean/reconciliations/assert',
2351
3139
  path: {
2352
- key: data.key
3140
+ region: data.region
2353
3141
  },
3142
+ body: data.requestBody,
3143
+ mediaType: 'application/json',
2354
3144
  errors: {
2355
- 401: 'Unauthorized',
2356
- 403: 'Forbidden - insufficient permissions',
2357
- 404: 'Property not found'
3145
+ 404: 'Account not found'
2358
3146
  }
2359
3147
  });
2360
3148
  }
2361
3149
 
2362
3150
  /**
2363
- * Update a system property
3151
+ * Generate a pad adjusting entry
3152
+ * 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.
2364
3153
  * @param data The data for the request.
2365
- * @param data.key Property key
3154
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2366
3155
  * @param data.requestBody
2367
- * @returns unknown Property updated successfully
3156
+ * @returns PadResultDto Pad adjusting entry generated
2368
3157
  * @throws ApiError
2369
3158
  */
2370
- public static propertyControllerUpdate(
2371
- data: PropertyControllerUpdateData
2372
- ): CancelablePromise<PropertyControllerUpdateResponse> {
3159
+ public static reconciliationControllerPad(
3160
+ data: ReconciliationControllerPadData
3161
+ ): CancelablePromise<ReconciliationControllerPadResponse> {
2373
3162
  return __request(OpenAPI, {
2374
- method: 'PUT',
2375
- url: '/api/v1/admin/properties/{key}',
3163
+ method: 'POST',
3164
+ url: '/api/v1/{region}/bean/reconciliations/pad',
2376
3165
  path: {
2377
- key: data.key
3166
+ region: data.region
2378
3167
  },
2379
3168
  body: data.requestBody,
2380
3169
  mediaType: 'application/json',
2381
3170
  errors: {
2382
- 401: 'Unauthorized',
2383
- 403: 'Forbidden - insufficient permissions'
3171
+ 400: 'Book already within tolerance — no pad needed',
3172
+ 404: 'Account not found'
2384
3173
  }
2385
3174
  });
2386
3175
  }
2387
3176
 
2388
3177
  /**
2389
- * Delete a system property
3178
+ * List reconciliation history for an account
3179
+ * Returns recorded balance assertions (most recent first). The latest drives the account-detail "Last <date>" badge.
2390
3180
  * @param data The data for the request.
2391
- * @param data.key Property key
2392
- * @returns void Property deleted successfully
3181
+ * @param data.accountId BeanAccount id
3182
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3183
+ * @returns ReconciliationRecordDto Reconciliation history
2393
3184
  * @throws ApiError
2394
3185
  */
2395
- public static propertyControllerDelete(
2396
- data: PropertyControllerDeleteData
2397
- ): CancelablePromise<PropertyControllerDeleteResponse> {
3186
+ public static reconciliationControllerHistory(
3187
+ data: ReconciliationControllerHistoryData
3188
+ ): CancelablePromise<ReconciliationControllerHistoryResponse> {
2398
3189
  return __request(OpenAPI, {
2399
- method: 'DELETE',
2400
- url: '/api/v1/admin/properties/{key}',
3190
+ method: 'GET',
3191
+ url: '/api/v1/{region}/bean/accounts/{accountId}/reconciliations',
2401
3192
  path: {
2402
- key: data.key
3193
+ accountId: data.accountId,
3194
+ region: data.region
2403
3195
  },
2404
3196
  errors: {
2405
- 401: 'Unauthorized',
2406
- 403: 'Forbidden - insufficient permissions',
2407
- 404: 'Property not found'
3197
+ 404: 'Account not found'
2408
3198
  }
2409
3199
  });
2410
3200
  }
@@ -2414,7 +3204,7 @@ export class BeanExportService {
2414
3204
  /**
2415
3205
  * Export Beancount ledger as ZIP
2416
3206
  * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
2417
- * @returns unknown
3207
+ * @returns binary ZIP archive (application/zip) streamed as an attachment
2418
3208
  * @throws ApiError
2419
3209
  */
2420
3210
  public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
@@ -2502,412 +3292,587 @@ export class BeanImportService {
2502
3292
  formData: data.formData,
2503
3293
  mediaType: 'multipart/form-data',
2504
3294
  errors: {
2505
- 400: 'Bad request - invalid file or no file uploaded'
3295
+ 400: 'Bad request - invalid file or no file uploaded'
3296
+ }
3297
+ });
3298
+ }
3299
+
3300
+ /**
3301
+ * Get importer configuration
3302
+ * Returns the current configuration for the specified importer. Creates default configuration if none exists.
3303
+ * @param data The data for the request.
3304
+ * @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
3305
+ * @param data.region Region code for tenant context
3306
+ * @returns ImporterConfigDto Configuration retrieved successfully
3307
+ * @throws ApiError
3308
+ */
3309
+ public static importerConfigControllerGetConfig(
3310
+ data: ImporterConfigControllerGetConfigData
3311
+ ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
3312
+ return __request(OpenAPI, {
3313
+ method: 'GET',
3314
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
3315
+ path: {
3316
+ importerId: data.importerId,
3317
+ region: data.region
3318
+ },
3319
+ errors: {
3320
+ 400: 'Invalid input - Unsupported importer',
3321
+ 401: 'Unauthorized - Authentication required'
3322
+ }
3323
+ });
3324
+ }
3325
+
3326
+ /**
3327
+ * Update importer configuration
3328
+ * Updates the configuration for the specified importer. Partial updates are supported.
3329
+ * @param data The data for the request.
3330
+ * @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
3331
+ * @param data.region Region code for tenant context
3332
+ * @param data.requestBody Partial configuration update. Only provided fields will be updated.
3333
+ * @returns ImporterConfigDto Configuration updated successfully
3334
+ * @throws ApiError
3335
+ */
3336
+ public static importerConfigControllerUpdateConfig(
3337
+ data: ImporterConfigControllerUpdateConfigData
3338
+ ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
3339
+ return __request(OpenAPI, {
3340
+ method: 'PUT',
3341
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
3342
+ path: {
3343
+ importerId: data.importerId,
3344
+ region: data.region
3345
+ },
3346
+ body: data.requestBody,
3347
+ mediaType: 'application/json',
3348
+ errors: {
3349
+ 400: 'Invalid input - Validation failed',
3350
+ 404: 'Configuration not found'
3351
+ }
3352
+ });
3353
+ }
3354
+
3355
+ /**
3356
+ * Reset configuration to default
3357
+ * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
3358
+ * @param data The data for the request.
3359
+ * @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
3360
+ * @param data.region Region code for tenant context
3361
+ * @returns ImporterConfigDto Configuration reset successfully
3362
+ * @throws ApiError
3363
+ */
3364
+ public static importerConfigControllerResetConfig(
3365
+ data: ImporterConfigControllerResetConfigData
3366
+ ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
3367
+ return __request(OpenAPI, {
3368
+ method: 'POST',
3369
+ url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
3370
+ path: {
3371
+ importerId: data.importerId,
3372
+ region: data.region
3373
+ },
3374
+ errors: {
3375
+ 400: 'Invalid input - Unsupported importer'
3376
+ }
3377
+ });
3378
+ }
3379
+ }
3380
+
3381
+ export class ProviderSyncService {
3382
+ /**
3383
+ * Sync transactions from financial data provider
3384
+ *
3385
+ * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
3386
+ *
3387
+ * **Supported Providers:**
3388
+ * - **plaid**: Plaid API (US, Canada, Europe)
3389
+ * - **teller**: Teller API (US)
3390
+ * - **truelayer**: TrueLayer Open Banking (UK, Europe)
3391
+ * - **gocardless**: GoCardless Bank Account Data (Europe)
3392
+ * - **simplefin**: SimpleFIN (Self-hosted)
3393
+ * - **yodlee**: Yodlee (Global)
3394
+ * - **beancount-direct**: Beancount format transactions
3395
+ * - **parsed-bill**: Client-side parsed bill transactions
3396
+ *
3397
+ * **Processing Flow:**
3398
+ * 1. Transform raw data via provider adapter
3399
+ * 2. Validate transaction format
3400
+ * 3. Deduplicate using originalId
3401
+ * 4. Classify using rule engine
3402
+ * 5. Route low-confidence to Review Center
3403
+ * 6. Persist validated transactions
3404
+ *
3405
+ * @param data The data for the request.
3406
+ * @param data.providerName Provider name
3407
+ * @param data.region Region code for tenant context
3408
+ * @param data.requestBody
3409
+ * @returns ProviderSyncResponseDto Sync completed successfully
3410
+ * @throws ApiError
3411
+ */
3412
+ public static providerSyncControllerSync(
3413
+ data: ProviderSyncControllerSyncData
3414
+ ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3415
+ return __request(OpenAPI, {
3416
+ method: 'POST',
3417
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3418
+ path: {
3419
+ providerName: data.providerName,
3420
+ region: data.region
3421
+ },
3422
+ body: data.requestBody,
3423
+ mediaType: 'application/json',
3424
+ errors: {
3425
+ 400: 'Invalid request data',
3426
+ 401: 'Missing or invalid authentication',
3427
+ 404: 'Provider not supported'
3428
+ }
3429
+ });
3430
+ }
3431
+
3432
+ /**
3433
+ * Get supported providers
3434
+ * Returns a list of all providers supported by the sync endpoint.
3435
+ * @param data The data for the request.
3436
+ * @param data.region Region code for tenant context
3437
+ * @returns SupportedProvidersResponseDto List of supported providers
3438
+ * @throws ApiError
3439
+ */
3440
+ public static providerSyncControllerGetSupportedProviders(
3441
+ data: ProviderSyncControllerGetSupportedProvidersData
3442
+ ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3443
+ return __request(OpenAPI, {
3444
+ method: 'GET',
3445
+ url: '/api/v1/{region}/bean/import/provider/supported',
3446
+ path: {
3447
+ region: data.region
3448
+ },
3449
+ errors: {
3450
+ 401: 'Missing or invalid authentication'
3451
+ }
3452
+ });
3453
+ }
3454
+
3455
+ /**
3456
+ * Check if provider is supported
3457
+ * Returns whether a specific provider is supported.
3458
+ * @param data The data for the request.
3459
+ * @param data.providerName Provider name to check
3460
+ * @param data.region Region code for tenant context
3461
+ * @returns unknown Provider support status
3462
+ * @throws ApiError
3463
+ */
3464
+ public static providerSyncControllerIsProviderSupported(
3465
+ data: ProviderSyncControllerIsProviderSupportedData
3466
+ ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3467
+ return __request(OpenAPI, {
3468
+ method: 'GET',
3469
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
3470
+ path: {
3471
+ providerName: data.providerName,
3472
+ region: data.region
3473
+ },
3474
+ errors: {
3475
+ 401: 'Missing or invalid authentication'
2506
3476
  }
2507
3477
  });
2508
3478
  }
3479
+ }
2509
3480
 
3481
+ export class ExternalAccountLinksService {
2510
3482
  /**
2511
- * Get importer configuration
2512
- * Returns the current configuration for the specified importer. Creates default configuration if none exists.
3483
+ * Create an external account → BeanAccount mapping (ADR-0113)
2513
3484
  * @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
2515
3485
  * @param data.region Region code for tenant context
2516
- * @returns ImporterConfigDto Configuration retrieved successfully
3486
+ * @param data.requestBody
3487
+ * @returns ExternalAccountLinkResponseDto Link created.
2517
3488
  * @throws ApiError
2518
3489
  */
2519
- public static importerConfigControllerGetConfig(
2520
- data: ImporterConfigControllerGetConfigData
2521
- ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
3490
+ public static externalAccountLinkControllerCreate(
3491
+ data: ExternalAccountLinkControllerCreateData
3492
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
2522
3493
  return __request(OpenAPI, {
2523
- method: 'GET',
2524
- url: '/api/v1/{region}/bean/import/config/{importerId}',
3494
+ method: 'POST',
3495
+ url: '/api/v1/{region}/bean/external-account-links',
2525
3496
  path: {
2526
- importerId: data.importerId,
2527
3497
  region: data.region
2528
3498
  },
3499
+ body: data.requestBody,
3500
+ mediaType: 'application/json',
2529
3501
  errors: {
2530
- 400: 'Invalid input - Unsupported importer',
2531
- 401: 'Unauthorized - Authentication required'
3502
+ 422: 'beanAccountId not owned, or an active link already exists.'
2532
3503
  }
2533
3504
  });
2534
3505
  }
2535
3506
 
2536
3507
  /**
2537
- * Update importer configuration
2538
- * Updates the configuration for the specified importer. Partial updates are supported.
3508
+ * List the user's active external account links
2539
3509
  * @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
3510
+ * @param data.provider
2541
3511
  * @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
3512
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
2544
3513
  * @throws ApiError
2545
3514
  */
2546
- public static importerConfigControllerUpdateConfig(
2547
- data: ImporterConfigControllerUpdateConfigData
2548
- ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
3515
+ public static externalAccountLinkControllerFindAll(
3516
+ data: ExternalAccountLinkControllerFindAllData
3517
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
2549
3518
  return __request(OpenAPI, {
2550
- method: 'PUT',
2551
- url: '/api/v1/{region}/bean/import/config/{importerId}',
3519
+ method: 'GET',
3520
+ url: '/api/v1/{region}/bean/external-account-links',
2552
3521
  path: {
2553
- importerId: data.importerId,
2554
3522
  region: data.region
2555
3523
  },
2556
- body: data.requestBody,
2557
- mediaType: 'application/json',
2558
- errors: {
2559
- 400: 'Invalid input - Validation failed',
2560
- 404: 'Configuration not found'
3524
+ query: {
3525
+ provider: data.provider
2561
3526
  }
2562
3527
  });
2563
3528
  }
2564
3529
 
2565
3530
  /**
2566
- * Reset configuration to default
2567
- * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
3531
+ * Get a single external account link
2568
3532
  * @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
3533
+ * @param data.id
2570
3534
  * @param data.region Region code for tenant context
2571
- * @returns ImporterConfigDto Configuration reset successfully
3535
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
2572
3536
  * @throws ApiError
2573
3537
  */
2574
- public static importerConfigControllerResetConfig(
2575
- data: ImporterConfigControllerResetConfigData
2576
- ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
3538
+ public static externalAccountLinkControllerFindOne(
3539
+ data: ExternalAccountLinkControllerFindOneData
3540
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
2577
3541
  return __request(OpenAPI, {
2578
- method: 'POST',
2579
- url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
3542
+ method: 'GET',
3543
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
2580
3544
  path: {
2581
- importerId: data.importerId,
3545
+ id: data.id,
2582
3546
  region: data.region
2583
3547
  },
2584
3548
  errors: {
2585
- 400: 'Invalid input - Unsupported importer'
3549
+ 422: 'Link not found or not owned by the user.'
2586
3550
  }
2587
3551
  });
2588
3552
  }
2589
- }
2590
3553
 
2591
- export class BeanPlatformsService {
2592
3554
  /**
2593
- * Get all platforms with statistics
2594
- * @returns unknown List of platforms with binding and account counts
3555
+ * Soft-delete (disconnect) an external account link
3556
+ * @param data The data for the request.
3557
+ * @param data.id
3558
+ * @param data.region Region code for tenant context
3559
+ * @returns void Link soft-deleted; historical transactions are unaffected.
2595
3560
  * @throws ApiError
2596
3561
  */
2597
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
3562
+ public static externalAccountLinkControllerRemove(
3563
+ data: ExternalAccountLinkControllerRemoveData
3564
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
2598
3565
  return __request(OpenAPI, {
2599
- method: 'GET',
2600
- url: '/api/v1/bean/platforms'
3566
+ method: 'DELETE',
3567
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3568
+ path: {
3569
+ id: data.id,
3570
+ region: data.region
3571
+ }
2601
3572
  });
2602
3573
  }
3574
+ }
2603
3575
 
3576
+ export class ImportTelemetryService {
2604
3577
  /**
2605
- * Create a new platform
3578
+ * Receive anonymous parser failure telemetry
2606
3579
  * @param data The data for the request.
3580
+ * @param data.region Region code for tenant context
2607
3581
  * @param data.requestBody
2608
- * @returns unknown Platform created successfully
3582
+ * @returns unknown Telemetry report received
2609
3583
  * @throws ApiError
2610
3584
  */
2611
- public static platformControllerCreate(
2612
- data: PlatformControllerCreateData
2613
- ): CancelablePromise<PlatformControllerCreateResponse> {
3585
+ public static telemetryControllerReportTelemetry(
3586
+ data: TelemetryControllerReportTelemetryData
3587
+ ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
2614
3588
  return __request(OpenAPI, {
2615
3589
  method: 'POST',
2616
- url: '/api/v1/bean/platforms',
3590
+ url: '/api/v1/{region}/bean/import/parser-telemetry',
3591
+ path: {
3592
+ region: data.region
3593
+ },
2617
3594
  body: data.requestBody,
2618
3595
  mediaType: 'application/json',
2619
3596
  errors: {
2620
- 409: 'Platform already exists'
3597
+ 401: 'Unauthorized'
2621
3598
  }
2622
3599
  });
2623
3600
  }
2624
3601
 
2625
3602
  /**
2626
- * Get platform list for current user
2627
- * @returns unknown List of platforms with user binding status
3603
+ * Receive anonymous zero-hit coverage miss report
3604
+ * @param data The data for the request.
3605
+ * @param data.region Region code for tenant context
3606
+ * @param data.requestBody
3607
+ * @returns unknown Coverage miss report received
2628
3608
  * @throws ApiError
2629
3609
  */
2630
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3610
+ public static telemetryControllerReportCoverageMiss(
3611
+ data: TelemetryControllerReportCoverageMissData
3612
+ ): CancelablePromise<TelemetryControllerReportCoverageMissResponse> {
2631
3613
  return __request(OpenAPI, {
2632
- method: 'GET',
2633
- url: '/api/v1/bean/platforms/list'
3614
+ method: 'POST',
3615
+ url: '/api/v1/{region}/bean/import/parser-coverage-miss',
3616
+ path: {
3617
+ region: data.region
3618
+ },
3619
+ body: data.requestBody,
3620
+ mediaType: 'application/json',
3621
+ errors: {
3622
+ 401: 'Unauthorized'
3623
+ }
2634
3624
  });
2635
3625
  }
2636
3626
 
2637
3627
  /**
2638
- * Match platforms by name or alias
3628
+ * Coverage metrics (uncovered format aggregation)
2639
3629
  * @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
3630
+ * @param data.region Region code for tenant context
3631
+ * @param data.topN Top-N uncovered formats (default 10)
3632
+ * @returns unknown Coverage metrics
2643
3633
  * @throws ApiError
2644
3634
  */
2645
- public static platformControllerMatchPlatforms(
2646
- data: PlatformControllerMatchPlatformsData
2647
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3635
+ public static telemetryControllerGetCoverageMetrics(
3636
+ data: TelemetryControllerGetCoverageMetricsData
3637
+ ): CancelablePromise<TelemetryControllerGetCoverageMetricsResponse> {
2648
3638
  return __request(OpenAPI, {
2649
3639
  method: 'GET',
2650
- url: '/api/v1/bean/platforms/match',
2651
- query: {
2652
- q: data.q,
3640
+ url: '/api/v1/{region}/bean/import/parser-coverage-metrics',
3641
+ path: {
2653
3642
  region: data.region
3643
+ },
3644
+ query: {
3645
+ topN: data.topN
2654
3646
  }
2655
3647
  });
2656
3648
  }
3649
+ }
2657
3650
 
3651
+ export class BeanNlpService {
2658
3652
  /**
2659
- * Update a platform
3653
+ * Process natural language input
3654
+ * 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
3655
  * @param data The data for the request.
2661
- * @param data.id Platform ID
2662
- * @param data.requestBody
2663
- * @returns unknown Platform updated successfully
3656
+ * @param data.region Region code for tenant context
3657
+ * @param data.requestBody Natural language transaction input with optional session ID
3658
+ * @returns NlpResponseDto NLP processing result - either created transaction or asking for more info
2664
3659
  * @throws ApiError
2665
3660
  */
2666
- public static platformControllerUpdate(
2667
- data: PlatformControllerUpdateData
2668
- ): CancelablePromise<PlatformControllerUpdateResponse> {
3661
+ public static nlpControllerProcessNaturalLanguage(
3662
+ data: NlpControllerProcessNaturalLanguageData
3663
+ ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
2669
3664
  return __request(OpenAPI, {
2670
- method: 'PUT',
2671
- url: '/api/v1/bean/platforms/{id}',
3665
+ method: 'POST',
3666
+ url: '/api/v1/{region}/bean/nlp/process',
2672
3667
  path: {
2673
- id: data.id
3668
+ region: data.region
2674
3669
  },
2675
3670
  body: data.requestBody,
2676
3671
  mediaType: 'application/json',
2677
3672
  errors: {
2678
- 404: 'Platform not found'
3673
+ 400: 'Invalid input',
3674
+ 401: 'Unauthorized'
2679
3675
  }
2680
3676
  });
2681
3677
  }
2682
3678
 
2683
3679
  /**
2684
- * Delete a platform
3680
+ * Clear dialogue session
3681
+ * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
2685
3682
  * @param data The data for the request.
2686
- * @param data.id Platform ID
2687
- * @returns void Platform deleted successfully
3683
+ * @param data.region Region code for tenant context
3684
+ * @param data.sessionId Specific session ID to clear (defaults to user session)
3685
+ * @returns void Session cleared successfully
2688
3686
  * @throws ApiError
2689
3687
  */
2690
- public static platformControllerDelete(
2691
- data: PlatformControllerDeleteData
2692
- ): CancelablePromise<PlatformControllerDeleteResponse> {
3688
+ public static nlpControllerClearSession(
3689
+ data: NlpControllerClearSessionData
3690
+ ): CancelablePromise<NlpControllerClearSessionResponse> {
2693
3691
  return __request(OpenAPI, {
2694
3692
  method: 'DELETE',
2695
- url: '/api/v1/bean/platforms/{id}',
3693
+ url: '/api/v1/{region}/bean/nlp/session',
2696
3694
  path: {
2697
- id: data.id
3695
+ region: data.region
3696
+ },
3697
+ query: {
3698
+ sessionId: data.sessionId
2698
3699
  },
2699
3700
  errors: {
2700
- 404: 'Platform not found'
3701
+ 401: 'Unauthorized'
2701
3702
  }
2702
3703
  });
2703
3704
  }
2704
- }
2705
3705
 
2706
- export class ProviderSyncService {
2707
3706
  /**
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
- *
3707
+ * Get current session state
3708
+ * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
2730
3709
  * @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
3710
+ * @param data.region Region code for tenant context
3711
+ * @param data.sessionId Specific session ID to get (defaults to user session)
3712
+ * @returns unknown Current session state (or null if no active session)
2735
3713
  * @throws ApiError
2736
3714
  */
2737
- public static providerSyncControllerSync(
2738
- data: ProviderSyncControllerSyncData
2739
- ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3715
+ public static nlpControllerGetSession(
3716
+ data: NlpControllerGetSessionData
3717
+ ): CancelablePromise<NlpControllerGetSessionResponse> {
2740
3718
  return __request(OpenAPI, {
2741
- method: 'POST',
2742
- url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3719
+ method: 'GET',
3720
+ url: '/api/v1/{region}/bean/nlp/session',
2743
3721
  path: {
2744
- providerName: data.providerName,
2745
3722
  region: data.region
2746
3723
  },
2747
- body: data.requestBody,
2748
- mediaType: 'application/json',
3724
+ query: {
3725
+ sessionId: data.sessionId
3726
+ },
2749
3727
  errors: {
2750
- 400: 'Invalid request data',
2751
- 401: 'Missing or invalid authentication',
2752
- 404: 'Provider not supported'
3728
+ 401: 'Unauthorized'
2753
3729
  }
2754
3730
  });
2755
3731
  }
3732
+ }
2756
3733
 
3734
+ export class BeanPlatformsService {
2757
3735
  /**
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
3736
+ * Get all platforms with statistics
3737
+ * @returns unknown List of platforms with binding and account counts
2763
3738
  * @throws ApiError
2764
3739
  */
2765
- public static providerSyncControllerGetSupportedProviders(
2766
- data: ProviderSyncControllerGetSupportedProvidersData
2767
- ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3740
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2768
3741
  return __request(OpenAPI, {
2769
3742
  method: 'GET',
2770
- url: '/api/v1/{region}/bean/import/provider/supported',
2771
- path: {
2772
- region: data.region
2773
- },
3743
+ url: '/api/v1/bean/platforms'
3744
+ });
3745
+ }
3746
+
3747
+ /**
3748
+ * Create a new platform
3749
+ * @param data The data for the request.
3750
+ * @param data.requestBody
3751
+ * @returns unknown Platform created successfully
3752
+ * @throws ApiError
3753
+ */
3754
+ public static platformControllerCreate(
3755
+ data: PlatformControllerCreateData
3756
+ ): CancelablePromise<PlatformControllerCreateResponse> {
3757
+ return __request(OpenAPI, {
3758
+ method: 'POST',
3759
+ url: '/api/v1/bean/platforms',
3760
+ body: data.requestBody,
3761
+ mediaType: 'application/json',
2774
3762
  errors: {
2775
- 401: 'Missing or invalid authentication'
3763
+ 409: 'Platform already exists'
2776
3764
  }
2777
3765
  });
2778
3766
  }
2779
3767
 
2780
3768
  /**
2781
- * Check if provider is supported
2782
- * Returns whether a specific provider is supported.
3769
+ * Get platform list for current user
2783
3770
  * @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
3771
+ * @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").
3772
+ * @returns PlatformListItemDto List of platforms with user binding status
2787
3773
  * @throws ApiError
2788
3774
  */
2789
- public static providerSyncControllerIsProviderSupported(
2790
- data: ProviderSyncControllerIsProviderSupportedData
2791
- ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3775
+ public static platformControllerGetPlatformList(
3776
+ data: PlatformControllerGetPlatformListData = {}
3777
+ ): CancelablePromise<PlatformControllerGetPlatformListResponse> {
2792
3778
  return __request(OpenAPI, {
2793
3779
  method: 'GET',
2794
- url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
2795
- path: {
2796
- providerName: data.providerName,
3780
+ url: '/api/v1/bean/platforms/list',
3781
+ query: {
2797
3782
  region: data.region
2798
- },
2799
- errors: {
2800
- 401: 'Missing or invalid authentication'
2801
3783
  }
2802
3784
  });
2803
3785
  }
2804
- }
2805
3786
 
2806
- export class ImportTelemetryService {
2807
3787
  /**
2808
- * Receive anonymous parser failure telemetry
3788
+ * Match platforms by name or alias
2809
3789
  * @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
3790
+ * @param data.q Search query — Chinese name, English name, or abbreviation
3791
+ * @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").
3792
+ * @returns PlatformMatchResponseDto Matching platforms with overall match type and truncation flag
2813
3793
  * @throws ApiError
2814
3794
  */
2815
- public static telemetryControllerReportTelemetry(
2816
- data: TelemetryControllerReportTelemetryData
2817
- ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
3795
+ public static platformControllerMatchPlatforms(
3796
+ data: PlatformControllerMatchPlatformsData
3797
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
2818
3798
  return __request(OpenAPI, {
2819
- method: 'POST',
2820
- url: '/api/v1/{region}/bean/import/parser-telemetry',
2821
- path: {
3799
+ method: 'GET',
3800
+ url: '/api/v1/bean/platforms/match',
3801
+ query: {
3802
+ q: data.q,
2822
3803
  region: data.region
2823
- },
2824
- body: data.requestBody,
2825
- mediaType: 'application/json',
2826
- errors: {
2827
- 401: 'Unauthorized'
2828
3804
  }
2829
3805
  });
2830
3806
  }
2831
- }
2832
3807
 
2833
- export class BeanNlpService {
2834
3808
  /**
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"
3809
+ * Get the region and candidate account standards for a platform
2837
3810
  * @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
3811
+ * @param data.id Platform ID (from a match result)
3812
+ * @param data.region Region code (ISO 3166-1 alpha-2, case-insensitive). Required for global platforms (countryCode null) — resolved as their template region; ignored when the platform has its own countryCode.
3813
+ * @param data.type Filter templates by account type (path first segment)
3814
+ * @returns PlatformStandardsResponseDto Resolved region plus the merged account-standard catalog of that region (groupable by productCategory client-side)
2841
3815
  * @throws ApiError
2842
3816
  */
2843
- public static nlpControllerProcessNaturalLanguage(
2844
- data: NlpControllerProcessNaturalLanguageData
2845
- ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
3817
+ public static platformControllerGetPlatformStandards(
3818
+ data: PlatformControllerGetPlatformStandardsData
3819
+ ): CancelablePromise<PlatformControllerGetPlatformStandardsResponse> {
2846
3820
  return __request(OpenAPI, {
2847
- method: 'POST',
2848
- url: '/api/v1/{region}/bean/nlp/process',
3821
+ method: 'GET',
3822
+ url: '/api/v1/bean/platforms/{id}/standards',
2849
3823
  path: {
2850
- region: data.region
3824
+ id: data.id
2851
3825
  },
2852
- body: data.requestBody,
2853
- mediaType: 'application/json',
2854
- errors: {
2855
- 400: 'Invalid input',
2856
- 401: 'Unauthorized'
3826
+ query: {
3827
+ region: data.region,
3828
+ type: data.type
2857
3829
  }
2858
3830
  });
2859
3831
  }
2860
3832
 
2861
3833
  /**
2862
- * Clear dialogue session
2863
- * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
3834
+ * Update a platform
2864
3835
  * @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
3836
+ * @param data.id Platform ID
3837
+ * @param data.requestBody
3838
+ * @returns unknown Platform updated successfully
2868
3839
  * @throws ApiError
2869
3840
  */
2870
- public static nlpControllerClearSession(
2871
- data: NlpControllerClearSessionData
2872
- ): CancelablePromise<NlpControllerClearSessionResponse> {
3841
+ public static platformControllerUpdate(
3842
+ data: PlatformControllerUpdateData
3843
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
2873
3844
  return __request(OpenAPI, {
2874
- method: 'DELETE',
2875
- url: '/api/v1/{region}/bean/nlp/session',
3845
+ method: 'PUT',
3846
+ url: '/api/v1/bean/platforms/{id}',
2876
3847
  path: {
2877
- region: data.region
2878
- },
2879
- query: {
2880
- sessionId: data.sessionId
3848
+ id: data.id
2881
3849
  },
3850
+ body: data.requestBody,
3851
+ mediaType: 'application/json',
2882
3852
  errors: {
2883
- 401: 'Unauthorized'
3853
+ 404: 'Platform not found'
2884
3854
  }
2885
3855
  });
2886
3856
  }
2887
3857
 
2888
3858
  /**
2889
- * Get current session state
2890
- * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
3859
+ * Delete a platform
2891
3860
  * @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)
3861
+ * @param data.id Platform ID
3862
+ * @returns void Platform deleted successfully
2895
3863
  * @throws ApiError
2896
3864
  */
2897
- public static nlpControllerGetSession(
2898
- data: NlpControllerGetSessionData
2899
- ): CancelablePromise<NlpControllerGetSessionResponse> {
3865
+ public static platformControllerDelete(
3866
+ data: PlatformControllerDeleteData
3867
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
2900
3868
  return __request(OpenAPI, {
2901
- method: 'GET',
2902
- url: '/api/v1/{region}/bean/nlp/session',
3869
+ method: 'DELETE',
3870
+ url: '/api/v1/bean/platforms/{id}',
2903
3871
  path: {
2904
- region: data.region
2905
- },
2906
- query: {
2907
- sessionId: data.sessionId
3872
+ id: data.id
2908
3873
  },
2909
3874
  errors: {
2910
- 401: 'Unauthorized'
3875
+ 404: 'Platform not found'
2911
3876
  }
2912
3877
  });
2913
3878
  }
@@ -2948,6 +3913,7 @@ export class DashboardService {
2948
3913
  * @param data.region Region code for tenant context
2949
3914
  * @param data.groupBy Grouping strategy
2950
3915
  * @param data.date Date for balance calculation (ISO 8601 format)
3916
+ * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
2951
3917
  * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
2952
3918
  * @throws ApiError
2953
3919
  */
@@ -2962,7 +3928,8 @@ export class DashboardService {
2962
3928
  },
2963
3929
  query: {
2964
3930
  groupBy: data.groupBy,
2965
- date: data.date
3931
+ date: data.date,
3932
+ accountId: data.accountId
2966
3933
  },
2967
3934
  errors: {
2968
3935
  401: 'User not authenticated'
@@ -2997,124 +3964,69 @@ export class DashboardService {
2997
3964
  }
2998
3965
  });
2999
3966
  }
3000
- }
3001
3967
 
3002
- export class ReportingService {
3003
3968
  /**
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
- *
3969
+ * Get expenses/income grouped by functional category
3970
+ * 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
3971
  * @param data The data for the request.
3018
3972
  * @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
3973
+ * @param data.groupBy Grouping strategy
3974
+ * @param data.period Time window (1m = current calendar month)
3975
+ * @param data.flow Account root to aggregate (expense → ^Expenses:, income → ^Income:)
3976
+ * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3022
3977
  * @throws ApiError
3023
3978
  */
3024
- public static reportingControllerGetPortfolioTrends(
3025
- data: ReportingControllerGetPortfolioTrendsData
3026
- ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
3979
+ public static dashboardControllerGetExpenses(
3980
+ data: DashboardControllerGetExpensesData
3981
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3027
3982
  return __request(OpenAPI, {
3028
3983
  method: 'GET',
3029
- url: '/api/v1/{region}/reporting/portfolio/trends',
3984
+ url: '/api/v1/{region}/dashboard/expenses',
3030
3985
  path: {
3031
3986
  region: data.region
3032
3987
  },
3033
3988
  query: {
3989
+ groupBy: data.groupBy,
3034
3990
  period: data.period,
3035
- granularity: data.granularity
3991
+ flow: data.flow
3036
3992
  },
3037
3993
  errors: {
3994
+ 400: 'Invalid groupBy or period',
3038
3995
  401: 'User not authenticated'
3039
3996
  }
3040
3997
  });
3041
3998
  }
3999
+ }
3042
4000
 
4001
+ export class InvestmentService {
3043
4002
  /**
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
- *
4003
+ * Get per-holding unrealized + realized P&L
4004
+ * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3058
4005
  * @param data The data for the request.
3059
4006
  * @param data.region Region code for tenant context
3060
- * @param data.requestBody Optional date (defaults to today)
3061
- * @returns GenerateSnapshotResponse Snapshot generated successfully
4007
+ * @param data.asOf As-of date (ISO 8601), defaults to today
4008
+ * @param data.accountId Scope to a single account
4009
+ * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
4010
+ * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3062
4011
  * @throws ApiError
3063
4012
  */
3064
- public static reportingControllerGenerateSnapshot(
3065
- data: ReportingControllerGenerateSnapshotData
3066
- ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
4013
+ public static holdingPnlControllerGetHoldingPnl(
4014
+ data: HoldingPnlControllerGetHoldingPnlData
4015
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3067
4016
  return __request(OpenAPI, {
3068
- method: 'POST',
3069
- url: '/api/v1/{region}/reporting/snapshots/generate',
4017
+ method: 'GET',
4018
+ url: '/api/v1/{region}/investment/holdings/pnl',
3070
4019
  path: {
3071
4020
  region: data.region
3072
4021
  },
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
4022
+ query: {
4023
+ asOf: data.asOf,
4024
+ accountId: data.accountId,
4025
+ method: data.method
3111
4026
  },
3112
- body: data.requestBody,
3113
- mediaType: 'application/json',
3114
4027
  errors: {
3115
- 400: 'Invalid date format or range',
3116
- 401: 'User not authenticated',
3117
- 409: 'Backfill already in progress for this user'
4028
+ 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
4029
+ 401: 'User not authenticated'
3118
4030
  }
3119
4031
  });
3120
4032
  }
@@ -3143,7 +4055,7 @@ export class AuthService {
3143
4055
  * Anonymous login with access token
3144
4056
  * @param data The data for the request.
3145
4057
  * @param data.requestBody
3146
- * @returns unknown Login successful
4058
+ * @returns AnonymousLoginResponseDto Login successful
3147
4059
  * @throws ApiError
3148
4060
  */
3149
4061
  public static authControllerAccessTokenLogin(
@@ -3161,15 +4073,52 @@ export class AuthService {
3161
4073
  }
3162
4074
  }
3163
4075
 
3164
- export class DefaultService {
4076
+ export class CommunityService {
4077
+ /**
4078
+ * Relay a sanitized parser-contribution payload
4079
+ * 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).
4080
+ * @param data The data for the request.
4081
+ * @param data.region Region code for tenant context (routing only; the institution region rides in the payload meta)
4082
+ * @param data.requestBody
4083
+ * @returns ParserContributionRelayResponseDto Issue created by the bot
4084
+ * @throws ApiError
4085
+ */
4086
+ public static parserContributionControllerCreate(
4087
+ data: ParserContributionControllerCreateData
4088
+ ): CancelablePromise<ParserContributionControllerCreateResponse> {
4089
+ return __request(OpenAPI, {
4090
+ method: 'POST',
4091
+ url: '/api/v1/{region}/community/parser-contributions',
4092
+ path: {
4093
+ region: data.region
4094
+ },
4095
+ body: data.requestBody,
4096
+ mediaType: 'application/json',
4097
+ errors: {
4098
+ 401: 'Unauthorized',
4099
+ 422: 'Validation failed (institution slug, empty samples, row/cell size limits)',
4100
+ 429: 'Rate limited (5 submissions per user per hour)',
4101
+ 501: 'Relay not configured on this deployment — clients fall back to the clipboard flow',
4102
+ 502: 'GitHub bot failure (upstream), safe to retry'
4103
+ }
4104
+ });
4105
+ }
4106
+ }
4107
+
4108
+ export class AdminCacheService {
3165
4109
  /**
3166
- * @returns unknown
4110
+ * Flush entire cache (L1 + L2)
4111
+ * Clears ALL cache entries across ALL namespaces and users. Use only for emergency cache corruption recovery, maintenance-window refresh, or development resets.
4112
+ * @returns unknown Cache flushed successfully
3167
4113
  * @throws ApiError
3168
4114
  */
3169
4115
  public static cacheControllerFlushCache(): CancelablePromise<CacheControllerFlushCacheResponse> {
3170
4116
  return __request(OpenAPI, {
3171
4117
  method: 'POST',
3172
- url: '/api/v1/cache/flush'
4118
+ url: '/api/v1/cache/flush',
4119
+ errors: {
4120
+ 403: 'Admin access required'
4121
+ }
3173
4122
  });
3174
4123
  }
3175
4124
  }
@@ -3330,3 +4279,53 @@ export class InfoService {
3330
4279
  });
3331
4280
  }
3332
4281
  }
4282
+
4283
+ export class MarketDataService {
4284
+ /**
4285
+ * Search market symbols by name or code
4286
+ * Ranked search over the openbb catalog. Empty `q` returns [].
4287
+ * @param data The data for the request.
4288
+ * @param data.q Search term — matched against symbol and instrument name. Empty string returns [].
4289
+ * @param data.limit Maximum number of results (clamped 1..50)
4290
+ * @param data.exchange Filter by exchange code (e.g. US, HK, SS, SZ)
4291
+ * @param data.assetType Filter by OpenBB asset_type (e.g. stock, etf)
4292
+ * @returns SymbolSearchResultDto Ranked search results
4293
+ * @throws ApiError
4294
+ */
4295
+ public static symbolControllerSearch(
4296
+ data: SymbolControllerSearchData
4297
+ ): CancelablePromise<SymbolControllerSearchResponse> {
4298
+ return __request(OpenAPI, {
4299
+ method: 'GET',
4300
+ url: '/api/v1/market/symbols/search',
4301
+ query: {
4302
+ q: data.q,
4303
+ limit: data.limit,
4304
+ exchange: data.exchange,
4305
+ assetType: data.assetType
4306
+ }
4307
+ });
4308
+ }
4309
+
4310
+ /**
4311
+ * Get a market symbol quote
4312
+ * @param data The data for the request.
4313
+ * @param data.symbol
4314
+ * @returns SymbolQuoteDto Symbol quote
4315
+ * @throws ApiError
4316
+ */
4317
+ public static symbolControllerGetQuote(
4318
+ data: SymbolControllerGetQuoteData
4319
+ ): CancelablePromise<SymbolControllerGetQuoteResponse> {
4320
+ return __request(OpenAPI, {
4321
+ method: 'GET',
4322
+ url: '/api/v1/market/symbols/{symbol}/quote',
4323
+ path: {
4324
+ symbol: data.symbol
4325
+ },
4326
+ errors: {
4327
+ 404: 'Symbol not found in the openbb catalog'
4328
+ }
4329
+ });
4330
+ }
4331
+ }