@firela/api-types 0.0.0-canary.6feee68d → 0.0.0-canary.70d4c0d2

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,10 @@ import type {
29
31
  TransactionControllerListResponse,
30
32
  TransactionControllerCreateBatchData,
31
33
  TransactionControllerCreateBatchResponse,
34
+ TransactionControllerCorrectData,
35
+ TransactionControllerCorrectResponse,
36
+ TransactionControllerSuggestTagsData,
37
+ TransactionControllerSuggestTagsResponse,
32
38
  TransactionControllerGetDetailData,
33
39
  TransactionControllerGetDetailResponse,
34
40
  TransactionControllerUpdateData,
@@ -93,6 +99,48 @@ import type {
93
99
  CommodityControllerGetOrCreateResponse,
94
100
  CommodityControllerBulkCreateData,
95
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,
96
144
  RecurringRuleControllerCreateData,
97
145
  RecurringRuleControllerCreateResponse,
98
146
  RecurringRuleControllerFindAllData,
@@ -145,28 +193,30 @@ import type {
145
193
  TransactionRuleControllerDeleteResponse,
146
194
  TransactionRuleControllerTestData,
147
195
  TransactionRuleControllerTestResponse,
148
- UserControllerDeleteOwnUserData,
149
- UserControllerDeleteOwnUserResponse,
150
- UserControllerGetUserData,
151
- UserControllerGetUserResponse,
152
- UserControllerSignupUserData,
153
- UserControllerSignupUserResponse,
154
- UserControllerDeleteUserData,
155
- UserControllerDeleteUserResponse,
156
- UserControllerGetUserInfoData,
157
- UserControllerGetUserInfoResponse,
158
- UserControllerUpdateUserSettingData,
159
- UserControllerUpdateUserSettingResponse,
160
- UserControllerGetAllUserSettingsByPageData,
161
- UserControllerGetAllUserSettingsByPageResponse,
162
- UserControllerGetAssetLiabilitySummaryResponse,
163
- PropertyControllerGetAllResponse,
164
- PropertyControllerGetByKeyData,
165
- PropertyControllerGetByKeyResponse,
166
- PropertyControllerUpdateData,
167
- PropertyControllerUpdateResponse,
168
- PropertyControllerDeleteData,
169
- 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,
170
220
  ExportControllerExportBeancountResponse,
171
221
  FileImportControllerImportFileData,
172
222
  FileImportControllerImportFileResponse,
@@ -180,45 +230,60 @@ import type {
180
230
  ImporterConfigControllerUpdateConfigResponse,
181
231
  ImporterConfigControllerResetConfigData,
182
232
  ImporterConfigControllerResetConfigResponse,
183
- PlatformControllerFindAllResponse,
184
- PlatformControllerCreateData,
185
- PlatformControllerCreateResponse,
186
- PlatformControllerGetPlatformListResponse,
187
- PlatformControllerMatchPlatformsData,
188
- PlatformControllerMatchPlatformsResponse,
189
- PlatformControllerUpdateData,
190
- PlatformControllerUpdateResponse,
191
- PlatformControllerDeleteData,
192
- PlatformControllerDeleteResponse,
193
233
  ProviderSyncControllerSyncData,
194
234
  ProviderSyncControllerSyncResponse,
195
235
  ProviderSyncControllerGetSupportedProvidersData,
196
236
  ProviderSyncControllerGetSupportedProvidersResponse,
197
237
  ProviderSyncControllerIsProviderSupportedData,
198
238
  ProviderSyncControllerIsProviderSupportedResponse,
239
+ ExternalAccountLinkControllerCreateData,
240
+ ExternalAccountLinkControllerCreateResponse,
241
+ ExternalAccountLinkControllerFindAllData,
242
+ ExternalAccountLinkControllerFindAllResponse,
243
+ ExternalAccountLinkControllerFindOneData,
244
+ ExternalAccountLinkControllerFindOneResponse,
245
+ ExternalAccountLinkControllerRemoveData,
246
+ ExternalAccountLinkControllerRemoveResponse,
199
247
  TelemetryControllerReportTelemetryData,
200
248
  TelemetryControllerReportTelemetryResponse,
249
+ TelemetryControllerReportCoverageMissData,
250
+ TelemetryControllerReportCoverageMissResponse,
251
+ TelemetryControllerGetCoverageMetricsData,
252
+ TelemetryControllerGetCoverageMetricsResponse,
201
253
  NlpControllerProcessNaturalLanguageData,
202
254
  NlpControllerProcessNaturalLanguageResponse,
203
255
  NlpControllerClearSessionData,
204
256
  NlpControllerClearSessionResponse,
205
257
  NlpControllerGetSessionData,
206
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,
207
272
  DashboardControllerGetNetWorthData,
208
273
  DashboardControllerGetNetWorthResponse,
209
274
  DashboardControllerGetAccountsData,
210
275
  DashboardControllerGetAccountsResponse,
211
276
  DashboardControllerGetCashFlowData,
212
277
  DashboardControllerGetCashFlowResponse,
213
- ReportingControllerGetPortfolioTrendsData,
214
- ReportingControllerGetPortfolioTrendsResponse,
215
- ReportingControllerGenerateSnapshotData,
216
- ReportingControllerGenerateSnapshotResponse,
217
- ReportingControllerBackfillSnapshotsData,
218
- ReportingControllerBackfillSnapshotsResponse,
278
+ DashboardControllerGetExpensesData,
279
+ DashboardControllerGetExpensesResponse,
280
+ HoldingPnlControllerGetHoldingPnlData,
281
+ HoldingPnlControllerGetHoldingPnlResponse,
219
282
  ApiKeysControllerCreateApiKeyResponse,
220
283
  AuthControllerAccessTokenLoginData,
221
284
  AuthControllerAccessTokenLoginResponse,
285
+ ParserContributionControllerCreateData,
286
+ ParserContributionControllerCreateResponse,
222
287
  CacheControllerFlushCacheResponse,
223
288
  ExchangeRateControllerGetExchangeRateData,
224
289
  ExchangeRateControllerGetExchangeRateResponse,
@@ -230,7 +295,11 @@ import type {
230
295
  HealthControllerResetCircuitBreakerData,
231
296
  HealthControllerResetCircuitBreakerResponse,
232
297
  HealthControllerGetMetricsResponse,
233
- InfoControllerGetInfoResponse
298
+ InfoControllerGetInfoResponse,
299
+ SymbolControllerSearchData,
300
+ SymbolControllerSearchResponse,
301
+ SymbolControllerGetQuoteData,
302
+ SymbolControllerGetQuoteResponse
234
303
  } from './types.gen';
235
304
 
236
305
  export class BeanAccountsService {
@@ -268,7 +337,7 @@ export class BeanAccountsService {
268
337
  * @param data.type Filter by account type
269
338
  * @param data.status Filter by status
270
339
  * @param data.isCustom Filter by custom (user-created) accounts only
271
- * @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)
272
341
  * @param data.limit Maximum number of results
273
342
  * @param data.offset Number of results to skip
274
343
  * @returns AccountListResponseDto Accounts retrieved successfully
@@ -349,7 +418,7 @@ export class BeanAccountsService {
349
418
 
350
419
  /**
351
420
  * Delete account
352
- * Deletes an account (only if no transactions)
421
+ * Deletes an account (only if no active transactions; voided/superseded residual postings are cleaned up)
353
422
  * @param data The data for the request.
354
423
  * @param data.id Account UUID
355
424
  * @param data.region Region code for tenant context
@@ -368,7 +437,7 @@ export class BeanAccountsService {
368
437
  },
369
438
  errors: {
370
439
  404: 'Account not found',
371
- 409: 'Account has transactions and cannot be deleted'
440
+ 409: 'Account has active transactions and cannot be deleted'
372
441
  }
373
442
  });
374
443
  }
@@ -430,16 +499,45 @@ export class BeanAccountsService {
430
499
  }
431
500
  });
432
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
+ }
433
531
  }
434
532
 
435
533
  export class BeanAccountStandardsService {
436
534
  /**
437
535
  * Get account templates
438
- * 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).
439
537
  * @param data The data for the request.
440
- * @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)
441
539
  * @param data.type Filter by account type
442
- * @param data.search Search term for path or description
540
+ * @param data.search Search term for path, description, aliases, or localized display name
443
541
  * @returns AccountStandardListResponseDto Account templates retrieved successfully
444
542
  * @throws ApiError
445
543
  */
@@ -461,9 +559,9 @@ export class BeanAccountStandardsService {
461
559
 
462
560
  /**
463
561
  * Get template metadata for an account path
464
- * Returns extendable status and root type for a template path.
562
+ * Returns root type for a template path.
465
563
  * @param data The data for the request.
466
- * @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)
467
565
  * @param data.path Account path to check
468
566
  * @returns TemplateMetadataResponseDto Template metadata retrieved successfully
469
567
  * @throws ApiError
@@ -485,9 +583,9 @@ export class BeanAccountStandardsService {
485
583
 
486
584
  /**
487
585
  * Get available regions with hierarchy
488
- * 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)
489
587
  * @param data The data for the request.
490
- * @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)
491
589
  * @returns RegionsMetadataResponseDto Regions metadata retrieved successfully
492
590
  * @throws ApiError
493
591
  */
@@ -544,9 +642,11 @@ export class BeanTransactionsService {
544
642
  * @param data.offset Number of items to skip (default: 0)
545
643
  * @param data.dateFrom Filter by start date (inclusive), format: YYYY-MM-DD
546
644
  * @param data.dateTo Filter by end date (inclusive), format: YYYY-MM-DD
547
- * @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).
548
646
  * @param data.search Search in narration and payee fields (max 200 chars)
549
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.
550
650
  * @returns TransactionListResponseDto Transaction list
551
651
  * @throws ApiError
552
652
  */
@@ -566,7 +666,9 @@ export class BeanTransactionsService {
566
666
  dateTo: data.dateTo,
567
667
  status: data.status,
568
668
  search: data.search,
569
- accountId: data.accountId
669
+ accountId: data.accountId,
670
+ category: data.category,
671
+ flow: data.flow
570
672
  },
571
673
  errors: {
572
674
  400: 'Validation failed',
@@ -603,6 +705,68 @@ export class BeanTransactionsService {
603
705
  });
604
706
  }
605
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
+
738
+ /**
739
+ * Suggest transaction tags
740
+ * Returns distinct tags from the user ACTIVE transactions, sorted by usage, for autocomplete. Optional q performs a case-insensitive prefix match.
741
+ * @param data The data for the request.
742
+ * @param data.region Region code for tenant context
743
+ * @param data.q Prefix match, case-insensitive (max 50 chars)
744
+ * @param data.sort usage (default) or name
745
+ * @param data.limit Max suggestions (1-100, default 10)
746
+ * @returns TagSuggestionsResponseDto Tag suggestions
747
+ * @throws ApiError
748
+ */
749
+ public static transactionControllerSuggestTags(
750
+ data: TransactionControllerSuggestTagsData
751
+ ): CancelablePromise<TransactionControllerSuggestTagsResponse> {
752
+ return __request(OpenAPI, {
753
+ method: 'GET',
754
+ url: '/api/v1/{region}/bean/transactions/tags',
755
+ path: {
756
+ region: data.region
757
+ },
758
+ query: {
759
+ q: data.q,
760
+ sort: data.sort,
761
+ limit: data.limit
762
+ },
763
+ errors: {
764
+ 400: 'Validation failed',
765
+ 401: 'Authentication required'
766
+ }
767
+ });
768
+ }
769
+
606
770
  /**
607
771
  * Get transaction detail
608
772
  * Returns transaction details including all postings
@@ -692,7 +856,7 @@ export class BeanBalancesService {
692
856
  * Query account balance
693
857
  * Calculate account balance at a specific date for a single currency
694
858
  * @param data The data for the request.
695
- * @param data.account Account name (e.g., "Assets:Bank:Checking")
859
+ * @param data.account Account name (e.g., "Assets:Checking")
696
860
  * @param data.region Region code for tenant context
697
861
  * @param data.date Date to calculate balance at (ISO 8601 format)
698
862
  * @param data.currency Currency to query (e.g., "USD", "CNY")
@@ -1217,7 +1381,7 @@ export class AdminPayeeProfilesService {
1217
1381
  * Removes verification status by setting verifiedAt to null.
1218
1382
  * @param data The data for the request.
1219
1383
  * @param data.id Payee profile ID (UUID)
1220
- * @returns PayeeProfileResponseDto Payee profile unverified successfully
1384
+ * @returns void Payee profile unverified successfully
1221
1385
  * @throws ApiError
1222
1386
  */
1223
1387
  public static payeeProfileAdminControllerUnverify(
@@ -1413,424 +1577,1003 @@ export class BeanCommoditiesService {
1413
1577
  }
1414
1578
  }
1415
1579
 
1416
- export class RecurringRulesService {
1580
+ export class ReportingService {
1417
1581
  /**
1418
- * Create a new recurring rule
1419
- * 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
+ *
1420
1595
  * @param data The data for the request.
1421
1596
  * @param data.region Region code for tenant context
1422
- * @param data.requestBody
1423
- * @returns RecurringRuleResponseDto Rule created successfully
1597
+ * @param data.period Time period
1598
+ * @param data.granularity Data granularity
1599
+ * @returns PortfolioTrendsResponseDto Trends retrieved successfully
1424
1600
  * @throws ApiError
1425
1601
  */
1426
- public static recurringRuleControllerCreate(
1427
- data: RecurringRuleControllerCreateData
1428
- ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1602
+ public static reportingControllerGetPortfolioTrends(
1603
+ data: ReportingControllerGetPortfolioTrendsData
1604
+ ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
1429
1605
  return __request(OpenAPI, {
1430
- method: 'POST',
1431
- url: '/api/v1/{region}/bean/recurring-rules',
1606
+ method: 'GET',
1607
+ url: '/api/v1/{region}/reporting/portfolio/trends',
1432
1608
  path: {
1433
1609
  region: data.region
1434
1610
  },
1435
- body: data.requestBody,
1436
- mediaType: 'application/json',
1611
+ query: {
1612
+ period: data.period,
1613
+ granularity: data.granularity
1614
+ },
1437
1615
  errors: {
1438
- 400: 'Invalid input data (e.g., autoCreate without accounts)',
1439
- 409: 'Rule with same name already exists'
1616
+ 401: 'User not authenticated'
1440
1617
  }
1441
1618
  });
1442
1619
  }
1443
1620
 
1444
1621
  /**
1445
- * List recurring rules
1446
- * 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
+ *
1447
1631
  * @param data The data for the request.
1448
1632
  * @param data.region Region code for tenant context
1449
- * @param data.isActive Filter by active status
1450
- * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
1451
- * @param data.hasAutoCreate Filter by autoCreate enabled
1452
- * @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
1453
1636
  * @throws ApiError
1454
1637
  */
1455
- public static recurringRuleControllerFindAll(
1456
- data: RecurringRuleControllerFindAllData
1457
- ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1638
+ public static reportingControllerGetCashFlowTrends(
1639
+ data: ReportingControllerGetCashFlowTrendsData
1640
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
1458
1641
  return __request(OpenAPI, {
1459
1642
  method: 'GET',
1460
- url: '/api/v1/{region}/bean/recurring-rules',
1643
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
1461
1644
  path: {
1462
1645
  region: data.region
1463
1646
  },
1464
1647
  query: {
1465
- isActive: data.isActive,
1466
- frequency: data.frequency,
1467
- hasAutoCreate: data.hasAutoCreate
1648
+ period: data.period,
1649
+ granularity: data.granularity
1650
+ },
1651
+ errors: {
1652
+ 401: 'User not authenticated'
1468
1653
  }
1469
1654
  });
1470
1655
  }
1471
1656
 
1472
1657
  /**
1473
- * Create recurring rule from transaction
1474
- * 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
+ *
1475
1672
  * @param data The data for the request.
1476
- * @param data.transactionId Source transaction ID
1477
1673
  * @param data.region Region code for tenant context
1478
- * @param data.requestBody
1479
- * @returns RecurringRuleResponseDto Rule created successfully
1674
+ * @param data.requestBody Optional date (defaults to today)
1675
+ * @returns GenerateSnapshotResponse Snapshot generated successfully
1480
1676
  * @throws ApiError
1481
1677
  */
1482
- public static recurringRuleControllerCreateFromTransaction(
1483
- data: RecurringRuleControllerCreateFromTransactionData
1484
- ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1678
+ public static reportingControllerGenerateSnapshot(
1679
+ data: ReportingControllerGenerateSnapshotData
1680
+ ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
1485
1681
  return __request(OpenAPI, {
1486
1682
  method: 'POST',
1487
- url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1683
+ url: '/api/v1/{region}/reporting/snapshots/generate',
1488
1684
  path: {
1489
- transactionId: data.transactionId,
1490
1685
  region: data.region
1491
1686
  },
1492
1687
  body: data.requestBody,
1493
1688
  mediaType: 'application/json',
1494
1689
  errors: {
1495
- 404: 'Transaction not found',
1496
- 409: 'Rule with same name already exists or transaction already linked'
1690
+ 400: 'Invalid date format',
1691
+ 401: 'User not authenticated'
1497
1692
  }
1498
1693
  });
1499
1694
  }
1500
1695
 
1501
1696
  /**
1502
- * Get recurring rule by ID
1503
- * 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
+ *
1504
1711
  * @param data The data for the request.
1505
- * @param data.id Rule ID
1506
1712
  * @param data.region Region code for tenant context
1507
- * @returns RecurringRuleResponseDto Rule retrieved successfully
1713
+ * @param data.requestBody
1714
+ * @returns BackfillSnapshotsResponse Backfill completed successfully
1508
1715
  * @throws ApiError
1509
1716
  */
1510
- public static recurringRuleControllerFindOne(
1511
- data: RecurringRuleControllerFindOneData
1512
- ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1717
+ public static reportingControllerBackfillSnapshots(
1718
+ data: ReportingControllerBackfillSnapshotsData
1719
+ ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
1513
1720
  return __request(OpenAPI, {
1514
- method: 'GET',
1515
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1721
+ method: 'POST',
1722
+ url: '/api/v1/{region}/reporting/snapshots/backfill',
1516
1723
  path: {
1517
- id: data.id,
1518
1724
  region: data.region
1519
1725
  },
1726
+ body: data.requestBody,
1727
+ mediaType: 'application/json',
1520
1728
  errors: {
1521
- 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'
1522
1732
  }
1523
1733
  });
1524
1734
  }
1735
+ }
1525
1736
 
1737
+ export class BeanPricesService {
1526
1738
  /**
1527
- * Update recurring rule
1528
- * Updates an existing recurring rule
1739
+ * Create a new price
1740
+ * Creates a new price entry for the authenticated user
1529
1741
  * @param data The data for the request.
1530
- * @param data.id Rule ID
1531
1742
  * @param data.region Region code for tenant context
1532
1743
  * @param data.requestBody
1533
- * @returns RecurringRuleResponseDto Rule updated successfully
1744
+ * @returns PriceResponseDto Price created successfully
1534
1745
  * @throws ApiError
1535
1746
  */
1536
- public static recurringRuleControllerUpdate(
1537
- data: RecurringRuleControllerUpdateData
1538
- ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1747
+ public static priceControllerCreate(
1748
+ data: PriceControllerCreateData
1749
+ ): CancelablePromise<PriceControllerCreateResponse> {
1539
1750
  return __request(OpenAPI, {
1540
- method: 'PATCH',
1541
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1751
+ method: 'POST',
1752
+ url: '/api/v1/{region}/bean/prices',
1542
1753
  path: {
1543
- id: data.id,
1544
1754
  region: data.region
1545
1755
  },
1546
1756
  body: data.requestBody,
1547
1757
  mediaType: 'application/json',
1548
1758
  errors: {
1549
- 400: 'Invalid input data',
1550
- 404: 'Rule not found'
1759
+ 404: 'Currency or quoteCurrency commodity not found',
1760
+ 409: 'Price already exists for this currency pair and date'
1551
1761
  }
1552
1762
  });
1553
1763
  }
1554
1764
 
1555
1765
  /**
1556
- * Delete recurring rule
1557
- * 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
1558
1768
  * @param data The data for the request.
1559
- * @param data.id Rule ID
1560
1769
  * @param data.region Region code for tenant context
1561
- * @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
1562
1778
  * @throws ApiError
1563
1779
  */
1564
- public static recurringRuleControllerDelete(
1565
- data: RecurringRuleControllerDeleteData
1566
- ): CancelablePromise<RecurringRuleControllerDeleteResponse> {
1780
+ public static priceControllerFindAll(
1781
+ data: PriceControllerFindAllData
1782
+ ): CancelablePromise<PriceControllerFindAllResponse> {
1567
1783
  return __request(OpenAPI, {
1568
- method: 'DELETE',
1569
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1784
+ method: 'GET',
1785
+ url: '/api/v1/{region}/bean/prices',
1570
1786
  path: {
1571
- id: data.id,
1572
1787
  region: data.region
1573
1788
  },
1574
- errors: {
1575
- 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
1576
1797
  }
1577
1798
  });
1578
1799
  }
1579
1800
 
1580
1801
  /**
1581
- * Get rule with statistics
1582
- * 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
1583
1804
  * @param data The data for the request.
1584
- * @param data.id Rule ID
1805
+ * @param data.id Price ID
1585
1806
  * @param data.region Region code for tenant context
1586
- * @returns RecurringRuleWithStatsResponseDto Rule with stats retrieved successfully
1807
+ * @returns PriceResponseDto Price retrieved successfully
1587
1808
  * @throws ApiError
1588
1809
  */
1589
- public static recurringRuleControllerGetWithStats(
1590
- data: RecurringRuleControllerGetWithStatsData
1591
- ): CancelablePromise<RecurringRuleControllerGetWithStatsResponse> {
1810
+ public static priceControllerFindOne(
1811
+ data: PriceControllerFindOneData
1812
+ ): CancelablePromise<PriceControllerFindOneResponse> {
1592
1813
  return __request(OpenAPI, {
1593
1814
  method: 'GET',
1594
- url: '/api/v1/{region}/bean/recurring-rules/{id}/stats',
1815
+ url: '/api/v1/{region}/bean/prices/{id}',
1595
1816
  path: {
1596
1817
  id: data.id,
1597
1818
  region: data.region
1598
1819
  },
1599
1820
  errors: {
1600
- 404: 'Rule not found'
1821
+ 404: 'Price not found'
1601
1822
  }
1602
1823
  });
1603
1824
  }
1604
- }
1605
1825
 
1606
- export class ExpectedTransactionsService {
1607
1826
  /**
1608
- * List expected transactions
1609
- * Returns expected transactions for the authenticated user with optional filtering
1827
+ * Update a price
1828
+ * Updates an existing price entry
1610
1829
  * @param data The data for the request.
1830
+ * @param data.id Price ID
1611
1831
  * @param data.region Region code for tenant context
1612
- * @param data.ruleId Filter by recurring rule ID
1613
- * @param data.status Filter by status (PENDING, COMPLETED, SKIPPED)
1614
- * @param data.fromDate Filter by date range start (YYYY-MM-DD)
1615
- * @param data.toDate Filter by date range end (YYYY-MM-DD)
1616
- * @returns ExpectedTransactionListResponseDto Expected transactions retrieved successfully
1832
+ * @param data.requestBody
1833
+ * @returns PriceResponseDto Price updated successfully
1617
1834
  * @throws ApiError
1618
1835
  */
1619
- public static expectedTransactionControllerFindAll(
1620
- data: ExpectedTransactionControllerFindAllData
1621
- ): CancelablePromise<ExpectedTransactionControllerFindAllResponse> {
1836
+ public static priceControllerUpdate(
1837
+ data: PriceControllerUpdateData
1838
+ ): CancelablePromise<PriceControllerUpdateResponse> {
1622
1839
  return __request(OpenAPI, {
1623
- method: 'GET',
1624
- url: '/api/v1/{region}/bean/expected-transactions',
1840
+ method: 'PUT',
1841
+ url: '/api/v1/{region}/bean/prices/{id}',
1625
1842
  path: {
1843
+ id: data.id,
1626
1844
  region: data.region
1627
1845
  },
1628
- query: {
1629
- ruleId: data.ruleId,
1630
- status: data.status,
1631
- fromDate: data.fromDate,
1632
- 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'
1633
1851
  }
1634
1852
  });
1635
1853
  }
1636
1854
 
1637
1855
  /**
1638
- * List overdue expected transactions
1639
- * Returns all overdue expected transactions (PENDING past tolerance)
1856
+ * Delete a price
1857
+ * Deletes a price entry (hard delete)
1640
1858
  * @param data The data for the request.
1859
+ * @param data.id Price ID
1641
1860
  * @param data.region Region code for tenant context
1642
- * @returns ExpectedTransactionListResponseDto Overdue transactions retrieved successfully
1861
+ * @returns void Price deleted successfully
1643
1862
  * @throws ApiError
1644
1863
  */
1645
- public static expectedTransactionControllerFindOverdue(
1646
- data: ExpectedTransactionControllerFindOverdueData
1647
- ): CancelablePromise<ExpectedTransactionControllerFindOverdueResponse> {
1864
+ public static priceControllerDelete(
1865
+ data: PriceControllerDeleteData
1866
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1648
1867
  return __request(OpenAPI, {
1649
- method: 'GET',
1650
- url: '/api/v1/{region}/bean/expected-transactions/overdue',
1868
+ method: 'DELETE',
1869
+ url: '/api/v1/{region}/bean/prices/{id}',
1651
1870
  path: {
1871
+ id: data.id,
1652
1872
  region: data.region
1873
+ },
1874
+ errors: {
1875
+ 404: 'Price not found'
1653
1876
  }
1654
1877
  });
1655
1878
  }
1656
1879
 
1657
1880
  /**
1658
- * Get expected transaction by ID
1659
- * Returns a specific expected transaction with rule details
1881
+ * Bulk create prices
1882
+ * Creates multiple price entries at once (skips duplicates)
1660
1883
  * @param data The data for the request.
1661
- * @param data.id Expected transaction ID
1662
1884
  * @param data.region Region code for tenant context
1663
- * @returns ExpectedTransactionResponseDto Expected transaction retrieved successfully
1885
+ * @param data.requestBody
1886
+ * @returns PriceResponseDto Prices created successfully
1664
1887
  * @throws ApiError
1665
1888
  */
1666
- public static expectedTransactionControllerFindOne(
1667
- data: ExpectedTransactionControllerFindOneData
1668
- ): CancelablePromise<ExpectedTransactionControllerFindOneResponse> {
1889
+ public static priceControllerBulkCreate(
1890
+ data: PriceControllerBulkCreateData
1891
+ ): CancelablePromise<PriceControllerBulkCreateResponse> {
1669
1892
  return __request(OpenAPI, {
1670
- method: 'GET',
1671
- url: '/api/v1/{region}/bean/expected-transactions/{id}',
1893
+ method: 'POST',
1894
+ url: '/api/v1/{region}/bean/prices/bulk',
1672
1895
  path: {
1673
- id: data.id,
1674
1896
  region: data.region
1675
1897
  },
1676
- errors: {
1677
- 404: 'Expected transaction not found'
1678
- }
1898
+ body: data.requestBody,
1899
+ mediaType: 'application/json'
1679
1900
  });
1680
1901
  }
1902
+ }
1681
1903
 
1904
+ export class UsersService {
1682
1905
  /**
1683
- * Skip expected transaction
1684
- * Marks an expected transaction as skipped (PENDING -> SKIPPED)
1906
+ * Delete own user account
1685
1907
  * @param data The data for the request.
1686
- * @param data.id Expected transaction ID
1687
- * @param data.region Region code for tenant context
1688
- * @returns ExpectedTransactionResponseDto Expected transaction skipped successfully
1908
+ * @param data.requestBody
1909
+ * @returns void User deleted successfully
1689
1910
  * @throws ApiError
1690
1911
  */
1691
- public static expectedTransactionControllerSkip(
1692
- data: ExpectedTransactionControllerSkipData
1693
- ): CancelablePromise<ExpectedTransactionControllerSkipResponse> {
1912
+ public static userControllerDeleteOwnUser(
1913
+ data: UserControllerDeleteOwnUserData
1914
+ ): CancelablePromise<UserControllerDeleteOwnUserResponse> {
1694
1915
  return __request(OpenAPI, {
1695
- method: 'POST',
1696
- url: '/api/v1/{region}/bean/expected-transactions/{id}/skip',
1697
- path: {
1698
- id: data.id,
1699
- region: data.region
1700
- },
1916
+ method: 'DELETE',
1917
+ url: '/api/v1/users',
1918
+ body: data.requestBody,
1919
+ mediaType: 'application/json',
1701
1920
  errors: {
1702
- 400: 'Cannot skip - not in PENDING status',
1703
- 404: 'Expected transaction not found'
1921
+ 403: 'Invalid access token'
1704
1922
  }
1705
1923
  });
1706
1924
  }
1707
1925
 
1708
1926
  /**
1709
- * Undo skip
1710
- * Reverses a skip operation (SKIPPED -> PENDING)
1927
+ * Get current authenticated user
1711
1928
  * @param data The data for the request.
1712
- * @param data.id Expected transaction ID
1713
- * @param data.region Region code for tenant context
1714
- * @returns ExpectedTransactionResponseDto Skip undone successfully
1929
+ * @param data.acceptLanguage
1930
+ * @returns UserResponseDto User retrieved successfully
1715
1931
  * @throws ApiError
1716
1932
  */
1717
- public static expectedTransactionControllerUndoSkip(
1718
- data: ExpectedTransactionControllerUndoSkipData
1719
- ): CancelablePromise<ExpectedTransactionControllerUndoSkipResponse> {
1933
+ public static userControllerGetUser(
1934
+ data: UserControllerGetUserData
1935
+ ): CancelablePromise<UserControllerGetUserResponse> {
1720
1936
  return __request(OpenAPI, {
1721
- method: 'DELETE',
1722
- url: '/api/v1/{region}/bean/expected-transactions/{id}/skip',
1723
- path: {
1724
- id: data.id,
1725
- region: data.region
1726
- },
1727
- errors: {
1728
- 400: 'Cannot undo - not in SKIPPED status',
1729
- 404: 'Expected transaction not found'
1937
+ method: 'GET',
1938
+ url: '/api/v1/users',
1939
+ headers: {
1940
+ 'accept-language': data.acceptLanguage
1730
1941
  }
1731
1942
  });
1732
1943
  }
1733
1944
 
1734
1945
  /**
1735
- * Confirm transaction match
1736
- * 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).
1737
1948
  * @param data The data for the request.
1738
- * @param data.id Expected transaction ID
1739
- * @param data.region Region code for tenant context
1740
1949
  * @param data.requestBody
1741
- * @returns unknown Match confirmed successfully
1950
+ * @returns SignupResponseDto User created successfully
1742
1951
  * @throws ApiError
1743
1952
  */
1744
- public static expectedTransactionControllerConfirmMatch(
1745
- data: ExpectedTransactionControllerConfirmMatchData
1746
- ): CancelablePromise<ExpectedTransactionControllerConfirmMatchResponse> {
1953
+ public static userControllerSignupUser(
1954
+ data: UserControllerSignupUserData
1955
+ ): CancelablePromise<UserControllerSignupUserResponse> {
1747
1956
  return __request(OpenAPI, {
1748
1957
  method: 'POST',
1749
- url: '/api/v1/{region}/bean/expected-transactions/{id}/match',
1750
- path: {
1751
- id: data.id,
1752
- region: data.region
1753
- },
1958
+ url: '/api/v1/users',
1754
1959
  body: data.requestBody,
1755
1960
  mediaType: 'application/json',
1756
1961
  errors: {
1757
- 400: 'Cannot match - not in PENDING status',
1758
- 404: 'Expected or actual transaction not found',
1759
- 409: 'Actual transaction already matched to another rule'
1962
+ 400: 'Invalid Turnstile token (when Turnstile is enabled)',
1963
+ 403: 'User signup is disabled'
1760
1964
  }
1761
1965
  });
1762
1966
  }
1763
1967
 
1764
1968
  /**
1765
- * Unmatch transaction
1766
- * Removes the match between expected and actual transaction (COMPLETED -> PENDING)
1969
+ * Delete user by ID (admin only)
1767
1970
  * @param data The data for the request.
1768
- * @param data.id Expected transaction ID
1769
- * @param data.region Region code for tenant context
1770
- * @returns unknown Match removed successfully
1971
+ * @param data.id User ID to delete
1972
+ * @returns void User deleted successfully
1771
1973
  * @throws ApiError
1772
1974
  */
1773
- public static expectedTransactionControllerUnmatch(
1774
- data: ExpectedTransactionControllerUnmatchData
1775
- ): CancelablePromise<ExpectedTransactionControllerUnmatchResponse> {
1975
+ public static userControllerDeleteUser(
1976
+ data: UserControllerDeleteUserData
1977
+ ): CancelablePromise<UserControllerDeleteUserResponse> {
1776
1978
  return __request(OpenAPI, {
1777
1979
  method: 'DELETE',
1778
- url: '/api/v1/{region}/bean/expected-transactions/{id}/match',
1980
+ url: '/api/v1/users/{id}',
1779
1981
  path: {
1780
- id: data.id,
1781
- region: data.region
1982
+ id: data.id
1782
1983
  },
1783
1984
  errors: {
1784
- 400: 'Cannot unmatch - not in COMPLETED status',
1785
- 404: 'Expected transaction not found'
1985
+ 403: 'Cannot delete own account or insufficient permissions'
1786
1986
  }
1787
1987
  });
1788
1988
  }
1789
1989
 
1790
1990
  /**
1791
- * Enter Now
1792
- * Creates an actual transaction for an expected transaction (YNAB-style Enter Now)
1991
+ * Get user info by user ID
1793
1992
  * @param data The data for the request.
1794
- * @param data.id Expected transaction ID
1795
- * @param data.region Region code for tenant context
1796
- * @param data.requestBody
1797
- * @returns unknown Transaction created successfully
1993
+ * @param data.id User ID
1994
+ * @returns unknown User info retrieved successfully
1798
1995
  * @throws ApiError
1799
1996
  */
1800
- public static expectedTransactionControllerEnterNow(
1801
- data: ExpectedTransactionControllerEnterNowData
1802
- ): CancelablePromise<ExpectedTransactionControllerEnterNowResponse> {
1997
+ public static userControllerGetUserInfo(
1998
+ data: UserControllerGetUserInfoData
1999
+ ): CancelablePromise<UserControllerGetUserInfoResponse> {
1803
2000
  return __request(OpenAPI, {
1804
- method: 'POST',
1805
- url: '/api/v1/{region}/bean/expected-transactions/{id}/enter',
2001
+ method: 'GET',
2002
+ url: '/api/v1/users/{id}/info',
1806
2003
  path: {
1807
- id: data.id,
1808
- region: data.region
2004
+ id: data.id
1809
2005
  },
1810
- body: data.requestBody,
1811
- mediaType: 'application/json',
1812
2006
  errors: {
1813
- 400: 'Cannot enter - not in PENDING status or missing accounts',
1814
- 404: 'Expected transaction or accounts not found'
2007
+ 403: 'Cannot access other user info without admin permission'
1815
2008
  }
1816
2009
  });
1817
2010
  }
1818
- }
1819
2011
 
1820
- export class RecurringForecastService {
1821
2012
  /**
1822
- * Get cash flow forecast
1823
- * Returns predicted outflows for the next N months based on active recurring rules
2013
+ * Update user settings
1824
2014
  * @param data The data for the request.
1825
- * @param data.region Region code for tenant context
1826
- * @param data.months Number of months to forecast (1-12, default 3)
1827
- * @returns ForecastResponseDto Forecast retrieved successfully
2015
+ * @param data.requestBody
2016
+ * @returns unknown Settings updated successfully
1828
2017
  * @throws ApiError
1829
2018
  */
1830
- public static forecastControllerGetForecast(
1831
- data: ForecastControllerGetForecastData
1832
- ): CancelablePromise<ForecastControllerGetForecastResponse> {
1833
- return __request(OpenAPI, {
2019
+ public static userControllerUpdateUserSetting(
2020
+ data: UserControllerUpdateUserSettingData
2021
+ ): CancelablePromise<UserControllerUpdateUserSettingResponse> {
2022
+ return __request(OpenAPI, {
2023
+ method: 'PUT',
2024
+ url: '/api/v1/users/setting',
2025
+ body: data.requestBody,
2026
+ mediaType: 'application/json',
2027
+ errors: {
2028
+ 403: 'Insufficient permissions'
2029
+ }
2030
+ });
2031
+ }
2032
+
2033
+ /**
2034
+ * Get all user settings paginated (admin only)
2035
+ * @param data The data for the request.
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, {
1834
2577
  method: 'GET',
1835
2578
  url: '/api/v1/{region}/bean/recurring/forecast',
1836
2579
  path: {
@@ -2121,256 +2864,337 @@ export class BeanTransactionRulesService {
2121
2864
  }
2122
2865
  }
2123
2866
 
2124
- export class UsersService {
2125
- /**
2126
- * Delete own user account
2127
- * @param data The data for the request.
2128
- * @param data.requestBody
2129
- * @returns void User deleted successfully
2130
- * @throws ApiError
2131
- */
2132
- public static userControllerDeleteOwnUser(
2133
- data: UserControllerDeleteOwnUserData
2134
- ): CancelablePromise<UserControllerDeleteOwnUserResponse> {
2135
- return __request(OpenAPI, {
2136
- method: 'DELETE',
2137
- url: '/api/v1/users',
2138
- body: data.requestBody,
2139
- mediaType: 'application/json',
2140
- errors: {
2141
- 403: 'Invalid access token'
2142
- }
2143
- });
2144
- }
2145
-
2867
+ export class BeanCategoryCatalogService {
2146
2868
  /**
2147
- * 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.
2148
2871
  * @param data The data for the request.
2149
- * @param data.acceptLanguage
2150
- * @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
2151
2876
  * @throws ApiError
2152
2877
  */
2153
- public static userControllerGetUser(
2154
- data: UserControllerGetUserData
2155
- ): CancelablePromise<UserControllerGetUserResponse> {
2878
+ public static categoryCatalogControllerList(
2879
+ data: CategoryCatalogControllerListData
2880
+ ): CancelablePromise<CategoryCatalogControllerListResponse> {
2156
2881
  return __request(OpenAPI, {
2157
2882
  method: 'GET',
2158
- url: '/api/v1/users',
2159
- headers: {
2160
- '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
2161
2890
  }
2162
2891
  });
2163
2892
  }
2893
+ }
2164
2894
 
2895
+ export class LifeEventsService {
2165
2896
  /**
2166
- * Sign up new user
2167
- * 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.
2168
2899
  * @param data The data for the request.
2900
+ * @param data.region Region code for tenant context (decorative for life events)
2169
2901
  * @param data.requestBody
2170
- * @returns unknown User created successfully
2902
+ * @returns EventResponseDto Life event created successfully
2171
2903
  * @throws ApiError
2172
2904
  */
2173
- public static userControllerSignupUser(
2174
- data: UserControllerSignupUserData
2175
- ): CancelablePromise<UserControllerSignupUserResponse> {
2905
+ public static eventControllerCreate(
2906
+ data: EventControllerCreateData
2907
+ ): CancelablePromise<EventControllerCreateResponse> {
2176
2908
  return __request(OpenAPI, {
2177
2909
  method: 'POST',
2178
- url: '/api/v1/users',
2910
+ url: '/api/v1/{region}/bean/events',
2911
+ path: {
2912
+ region: data.region
2913
+ },
2179
2914
  body: data.requestBody,
2180
2915
  mediaType: 'application/json',
2181
2916
  errors: {
2182
- 400: 'Invalid Turnstile token (when Turnstile is enabled)',
2183
- 403: 'User signup is disabled'
2917
+ 409: 'Life event already exists for this (userId, type, date) combination'
2184
2918
  }
2185
2919
  });
2186
2920
  }
2187
2921
 
2188
2922
  /**
2189
- * 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.
2190
2925
  * @param data The data for the request.
2191
- * @param data.id User ID to delete
2192
- * @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
2193
2934
  * @throws ApiError
2194
2935
  */
2195
- public static userControllerDeleteUser(
2196
- data: UserControllerDeleteUserData
2197
- ): CancelablePromise<UserControllerDeleteUserResponse> {
2936
+ public static eventControllerFindAll(
2937
+ data: EventControllerFindAllData
2938
+ ): CancelablePromise<EventControllerFindAllResponse> {
2198
2939
  return __request(OpenAPI, {
2199
- method: 'DELETE',
2200
- url: '/api/v1/users/{id}',
2940
+ method: 'GET',
2941
+ url: '/api/v1/{region}/bean/events',
2201
2942
  path: {
2202
- id: data.id
2943
+ region: data.region
2203
2944
  },
2204
- errors: {
2205
- 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
2206
2952
  }
2207
2953
  });
2208
2954
  }
2209
2955
 
2210
2956
  /**
2211
- * Get user info by user ID
2957
+ * Get life event by ID
2958
+ * Returns a single life event by its ID. Returns ETag header.
2212
2959
  * @param data The data for the request.
2213
- * @param data.id User ID
2214
- * @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
2215
2963
  * @throws ApiError
2216
2964
  */
2217
- public static userControllerGetUserInfo(
2218
- data: UserControllerGetUserInfoData
2219
- ): CancelablePromise<UserControllerGetUserInfoResponse> {
2965
+ public static eventControllerFindOne(
2966
+ data: EventControllerFindOneData
2967
+ ): CancelablePromise<EventControllerFindOneResponse> {
2220
2968
  return __request(OpenAPI, {
2221
2969
  method: 'GET',
2222
- url: '/api/v1/users/{id}/info',
2970
+ url: '/api/v1/{region}/bean/events/{id}',
2223
2971
  path: {
2224
- id: data.id
2972
+ id: data.id,
2973
+ region: data.region
2225
2974
  },
2226
2975
  errors: {
2227
- 403: 'Cannot access other user info without admin permission'
2976
+ 404: 'Life event not found'
2228
2977
  }
2229
2978
  });
2230
2979
  }
2231
2980
 
2232
2981
  /**
2233
- * 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.
2234
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)
2235
2987
  * @param data.requestBody
2236
- * @returns unknown Settings updated successfully
2988
+ * @returns EventResponseDto Life event updated successfully
2237
2989
  * @throws ApiError
2238
2990
  */
2239
- public static userControllerUpdateUserSetting(
2240
- data: UserControllerUpdateUserSettingData
2241
- ): CancelablePromise<UserControllerUpdateUserSettingResponse> {
2991
+ public static eventControllerUpdate(
2992
+ data: EventControllerUpdateData
2993
+ ): CancelablePromise<EventControllerUpdateResponse> {
2242
2994
  return __request(OpenAPI, {
2243
2995
  method: 'PUT',
2244
- url: '/api/v1/users/setting',
2996
+ url: '/api/v1/{region}/bean/events/{id}',
2997
+ path: {
2998
+ id: data.id,
2999
+ region: data.region
3000
+ },
2245
3001
  body: data.requestBody,
2246
3002
  mediaType: 'application/json',
2247
3003
  errors: {
2248
- 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)'
2249
3008
  }
2250
3009
  });
2251
3010
  }
2252
3011
 
2253
3012
  /**
2254
- * Get all user settings paginated (admin only)
3013
+ * Delete a life event
3014
+ * Deletes a life event entry (hard delete). Returns 204.
2255
3015
  * @param data The data for the request.
2256
- * @param data.pageNo Page number
2257
- * @param data.pageSize Page size
2258
- * @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
2259
3019
  * @throws ApiError
2260
3020
  */
2261
- public static userControllerGetAllUserSettingsByPage(
2262
- data: UserControllerGetAllUserSettingsByPageData
2263
- ): 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> {
2264
3051
  return __request(OpenAPI, {
2265
3052
  method: 'GET',
2266
- 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
+ },
2267
3058
  query: {
2268
- pageNo: data.pageNo,
2269
- 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'
2270
3065
  }
2271
3066
  });
2272
3067
  }
3068
+ }
2273
3069
 
3070
+ export class OnboardingService {
2274
3071
  /**
2275
- * Get asset and liability summary for current user
2276
- * @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.
2277
3077
  * @throws ApiError
2278
3078
  */
2279
- public static userControllerGetAssetLiabilitySummary(): CancelablePromise<UserControllerGetAssetLiabilitySummaryResponse> {
3079
+ public static onboardingControllerBootstrap(
3080
+ data: OnboardingControllerBootstrapData
3081
+ ): CancelablePromise<OnboardingControllerBootstrapResponse> {
2280
3082
  return __request(OpenAPI, {
2281
- method: 'GET',
2282
- 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
+ }
2283
3093
  });
2284
3094
  }
2285
3095
  }
2286
3096
 
2287
- export class PropertiesService {
3097
+ export class BalanceReconciliationService {
2288
3098
  /**
2289
- * Get all system properties
2290
- * @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
2291
3105
  * @throws ApiError
2292
3106
  */
2293
- public static propertyControllerGetAll(): CancelablePromise<PropertyControllerGetAllResponse> {
3107
+ public static reconciliationControllerCompute(
3108
+ data: ReconciliationControllerComputeData
3109
+ ): CancelablePromise<ReconciliationControllerComputeResponse> {
2294
3110
  return __request(OpenAPI, {
2295
- method: 'GET',
2296
- 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',
2297
3118
  errors: {
2298
- 401: 'Unauthorized',
2299
- 403: 'Forbidden - insufficient permissions'
3119
+ 404: 'Account not found'
2300
3120
  }
2301
3121
  });
2302
3122
  }
2303
3123
 
2304
3124
  /**
2305
- * 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.
2306
3127
  * @param data The data for the request.
2307
- * @param data.key Property key
2308
- * @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
2309
3131
  * @throws ApiError
2310
3132
  */
2311
- public static propertyControllerGetByKey(
2312
- data: PropertyControllerGetByKeyData
2313
- ): CancelablePromise<PropertyControllerGetByKeyResponse> {
3133
+ public static reconciliationControllerAssert(
3134
+ data: ReconciliationControllerAssertData
3135
+ ): CancelablePromise<ReconciliationControllerAssertResponse> {
2314
3136
  return __request(OpenAPI, {
2315
- method: 'GET',
2316
- url: '/api/v1/admin/properties/{key}',
3137
+ method: 'POST',
3138
+ url: '/api/v1/{region}/bean/reconciliations/assert',
2317
3139
  path: {
2318
- key: data.key
3140
+ region: data.region
2319
3141
  },
3142
+ body: data.requestBody,
3143
+ mediaType: 'application/json',
2320
3144
  errors: {
2321
- 401: 'Unauthorized',
2322
- 403: 'Forbidden - insufficient permissions',
2323
- 404: 'Property not found'
3145
+ 404: 'Account not found'
2324
3146
  }
2325
3147
  });
2326
3148
  }
2327
3149
 
2328
3150
  /**
2329
- * 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.
2330
3153
  * @param data The data for the request.
2331
- * @param data.key Property key
3154
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2332
3155
  * @param data.requestBody
2333
- * @returns unknown Property updated successfully
3156
+ * @returns PadResultDto Pad adjusting entry generated
2334
3157
  * @throws ApiError
2335
3158
  */
2336
- public static propertyControllerUpdate(
2337
- data: PropertyControllerUpdateData
2338
- ): CancelablePromise<PropertyControllerUpdateResponse> {
3159
+ public static reconciliationControllerPad(
3160
+ data: ReconciliationControllerPadData
3161
+ ): CancelablePromise<ReconciliationControllerPadResponse> {
2339
3162
  return __request(OpenAPI, {
2340
- method: 'PUT',
2341
- url: '/api/v1/admin/properties/{key}',
3163
+ method: 'POST',
3164
+ url: '/api/v1/{region}/bean/reconciliations/pad',
2342
3165
  path: {
2343
- key: data.key
3166
+ region: data.region
2344
3167
  },
2345
3168
  body: data.requestBody,
2346
3169
  mediaType: 'application/json',
2347
3170
  errors: {
2348
- 401: 'Unauthorized',
2349
- 403: 'Forbidden - insufficient permissions'
3171
+ 400: 'Book already within tolerance — no pad needed',
3172
+ 404: 'Account not found'
2350
3173
  }
2351
3174
  });
2352
3175
  }
2353
3176
 
2354
3177
  /**
2355
- * 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.
2356
3180
  * @param data The data for the request.
2357
- * @param data.key Property key
2358
- * @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
2359
3184
  * @throws ApiError
2360
3185
  */
2361
- public static propertyControllerDelete(
2362
- data: PropertyControllerDeleteData
2363
- ): CancelablePromise<PropertyControllerDeleteResponse> {
3186
+ public static reconciliationControllerHistory(
3187
+ data: ReconciliationControllerHistoryData
3188
+ ): CancelablePromise<ReconciliationControllerHistoryResponse> {
2364
3189
  return __request(OpenAPI, {
2365
- method: 'DELETE',
2366
- url: '/api/v1/admin/properties/{key}',
3190
+ method: 'GET',
3191
+ url: '/api/v1/{region}/bean/accounts/{accountId}/reconciliations',
2367
3192
  path: {
2368
- key: data.key
3193
+ accountId: data.accountId,
3194
+ region: data.region
2369
3195
  },
2370
3196
  errors: {
2371
- 401: 'Unauthorized',
2372
- 403: 'Forbidden - insufficient permissions',
2373
- 404: 'Property not found'
3197
+ 404: 'Account not found'
2374
3198
  }
2375
3199
  });
2376
3200
  }
@@ -2380,7 +3204,7 @@ export class BeanExportService {
2380
3204
  /**
2381
3205
  * Export Beancount ledger as ZIP
2382
3206
  * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
2383
- * @returns unknown
3207
+ * @returns binary ZIP archive (application/zip) streamed as an attachment
2384
3208
  * @throws ApiError
2385
3209
  */
2386
3210
  public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
@@ -2468,412 +3292,587 @@ export class BeanImportService {
2468
3292
  formData: data.formData,
2469
3293
  mediaType: 'multipart/form-data',
2470
3294
  errors: {
2471
- 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'
2472
3476
  }
2473
3477
  });
2474
3478
  }
3479
+ }
2475
3480
 
3481
+ export class ExternalAccountLinksService {
2476
3482
  /**
2477
- * Get importer configuration
2478
- * Returns the current configuration for the specified importer. Creates default configuration if none exists.
3483
+ * Create an external account → BeanAccount mapping (ADR-0113)
2479
3484
  * @param data The data for the request.
2480
- * @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
2481
3485
  * @param data.region Region code for tenant context
2482
- * @returns ImporterConfigDto Configuration retrieved successfully
3486
+ * @param data.requestBody
3487
+ * @returns ExternalAccountLinkResponseDto Link created.
2483
3488
  * @throws ApiError
2484
3489
  */
2485
- public static importerConfigControllerGetConfig(
2486
- data: ImporterConfigControllerGetConfigData
2487
- ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
3490
+ public static externalAccountLinkControllerCreate(
3491
+ data: ExternalAccountLinkControllerCreateData
3492
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
2488
3493
  return __request(OpenAPI, {
2489
- method: 'GET',
2490
- url: '/api/v1/{region}/bean/import/config/{importerId}',
3494
+ method: 'POST',
3495
+ url: '/api/v1/{region}/bean/external-account-links',
2491
3496
  path: {
2492
- importerId: data.importerId,
2493
3497
  region: data.region
2494
3498
  },
3499
+ body: data.requestBody,
3500
+ mediaType: 'application/json',
2495
3501
  errors: {
2496
- 400: 'Invalid input - Unsupported importer',
2497
- 401: 'Unauthorized - Authentication required'
3502
+ 422: 'beanAccountId not owned, or an active link already exists.'
2498
3503
  }
2499
3504
  });
2500
3505
  }
2501
3506
 
2502
3507
  /**
2503
- * Update importer configuration
2504
- * Updates the configuration for the specified importer. Partial updates are supported.
3508
+ * List the user's active external account links
2505
3509
  * @param data The data for the request.
2506
- * @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
2507
3511
  * @param data.region Region code for tenant context
2508
- * @param data.requestBody Partial configuration update. Only provided fields will be updated.
2509
- * @returns ImporterConfigDto Configuration updated successfully
3512
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
2510
3513
  * @throws ApiError
2511
3514
  */
2512
- public static importerConfigControllerUpdateConfig(
2513
- data: ImporterConfigControllerUpdateConfigData
2514
- ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
3515
+ public static externalAccountLinkControllerFindAll(
3516
+ data: ExternalAccountLinkControllerFindAllData
3517
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
2515
3518
  return __request(OpenAPI, {
2516
- method: 'PUT',
2517
- url: '/api/v1/{region}/bean/import/config/{importerId}',
3519
+ method: 'GET',
3520
+ url: '/api/v1/{region}/bean/external-account-links',
2518
3521
  path: {
2519
- importerId: data.importerId,
2520
3522
  region: data.region
2521
3523
  },
2522
- body: data.requestBody,
2523
- mediaType: 'application/json',
2524
- errors: {
2525
- 400: 'Invalid input - Validation failed',
2526
- 404: 'Configuration not found'
3524
+ query: {
3525
+ provider: data.provider
2527
3526
  }
2528
3527
  });
2529
3528
  }
2530
3529
 
2531
3530
  /**
2532
- * Reset configuration to default
2533
- * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
3531
+ * Get a single external account link
2534
3532
  * @param data The data for the request.
2535
- * @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
2536
3534
  * @param data.region Region code for tenant context
2537
- * @returns ImporterConfigDto Configuration reset successfully
3535
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
2538
3536
  * @throws ApiError
2539
3537
  */
2540
- public static importerConfigControllerResetConfig(
2541
- data: ImporterConfigControllerResetConfigData
2542
- ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
3538
+ public static externalAccountLinkControllerFindOne(
3539
+ data: ExternalAccountLinkControllerFindOneData
3540
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
2543
3541
  return __request(OpenAPI, {
2544
- method: 'POST',
2545
- url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
3542
+ method: 'GET',
3543
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
2546
3544
  path: {
2547
- importerId: data.importerId,
3545
+ id: data.id,
2548
3546
  region: data.region
2549
3547
  },
2550
3548
  errors: {
2551
- 400: 'Invalid input - Unsupported importer'
3549
+ 422: 'Link not found or not owned by the user.'
2552
3550
  }
2553
3551
  });
2554
3552
  }
2555
- }
2556
3553
 
2557
- export class BeanPlatformsService {
2558
3554
  /**
2559
- * Get all platforms with statistics
2560
- * @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.
2561
3560
  * @throws ApiError
2562
3561
  */
2563
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
3562
+ public static externalAccountLinkControllerRemove(
3563
+ data: ExternalAccountLinkControllerRemoveData
3564
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
2564
3565
  return __request(OpenAPI, {
2565
- method: 'GET',
2566
- 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
+ }
2567
3572
  });
2568
3573
  }
3574
+ }
2569
3575
 
3576
+ export class ImportTelemetryService {
2570
3577
  /**
2571
- * Create a new platform
3578
+ * Receive anonymous parser failure telemetry
2572
3579
  * @param data The data for the request.
3580
+ * @param data.region Region code for tenant context
2573
3581
  * @param data.requestBody
2574
- * @returns unknown Platform created successfully
3582
+ * @returns unknown Telemetry report received
2575
3583
  * @throws ApiError
2576
3584
  */
2577
- public static platformControllerCreate(
2578
- data: PlatformControllerCreateData
2579
- ): CancelablePromise<PlatformControllerCreateResponse> {
3585
+ public static telemetryControllerReportTelemetry(
3586
+ data: TelemetryControllerReportTelemetryData
3587
+ ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
2580
3588
  return __request(OpenAPI, {
2581
3589
  method: 'POST',
2582
- url: '/api/v1/bean/platforms',
3590
+ url: '/api/v1/{region}/bean/import/parser-telemetry',
3591
+ path: {
3592
+ region: data.region
3593
+ },
2583
3594
  body: data.requestBody,
2584
3595
  mediaType: 'application/json',
2585
3596
  errors: {
2586
- 409: 'Platform already exists'
3597
+ 401: 'Unauthorized'
2587
3598
  }
2588
3599
  });
2589
3600
  }
2590
3601
 
2591
3602
  /**
2592
- * Get platform list for current user
2593
- * @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
2594
3608
  * @throws ApiError
2595
3609
  */
2596
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3610
+ public static telemetryControllerReportCoverageMiss(
3611
+ data: TelemetryControllerReportCoverageMissData
3612
+ ): CancelablePromise<TelemetryControllerReportCoverageMissResponse> {
2597
3613
  return __request(OpenAPI, {
2598
- method: 'GET',
2599
- 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
+ }
2600
3624
  });
2601
3625
  }
2602
3626
 
2603
3627
  /**
2604
- * Match platforms by name or alias
3628
+ * Coverage metrics (uncovered format aggregation)
2605
3629
  * @param data The data for the request.
2606
- * @param data.q Search query — Chinese name, English name, or abbreviation
2607
- * @param data.region Region code for category override lookup
2608
- * @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
2609
3633
  * @throws ApiError
2610
3634
  */
2611
- public static platformControllerMatchPlatforms(
2612
- data: PlatformControllerMatchPlatformsData
2613
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3635
+ public static telemetryControllerGetCoverageMetrics(
3636
+ data: TelemetryControllerGetCoverageMetricsData
3637
+ ): CancelablePromise<TelemetryControllerGetCoverageMetricsResponse> {
2614
3638
  return __request(OpenAPI, {
2615
3639
  method: 'GET',
2616
- url: '/api/v1/bean/platforms/match',
2617
- query: {
2618
- q: data.q,
3640
+ url: '/api/v1/{region}/bean/import/parser-coverage-metrics',
3641
+ path: {
2619
3642
  region: data.region
3643
+ },
3644
+ query: {
3645
+ topN: data.topN
2620
3646
  }
2621
3647
  });
2622
3648
  }
3649
+ }
2623
3650
 
3651
+ export class BeanNlpService {
2624
3652
  /**
2625
- * 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"
2626
3655
  * @param data The data for the request.
2627
- * @param data.id Platform ID
2628
- * @param data.requestBody
2629
- * @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
2630
3659
  * @throws ApiError
2631
3660
  */
2632
- public static platformControllerUpdate(
2633
- data: PlatformControllerUpdateData
2634
- ): CancelablePromise<PlatformControllerUpdateResponse> {
3661
+ public static nlpControllerProcessNaturalLanguage(
3662
+ data: NlpControllerProcessNaturalLanguageData
3663
+ ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
2635
3664
  return __request(OpenAPI, {
2636
- method: 'PUT',
2637
- url: '/api/v1/bean/platforms/{id}',
3665
+ method: 'POST',
3666
+ url: '/api/v1/{region}/bean/nlp/process',
2638
3667
  path: {
2639
- id: data.id
3668
+ region: data.region
2640
3669
  },
2641
3670
  body: data.requestBody,
2642
3671
  mediaType: 'application/json',
2643
3672
  errors: {
2644
- 404: 'Platform not found'
3673
+ 400: 'Invalid input',
3674
+ 401: 'Unauthorized'
2645
3675
  }
2646
3676
  });
2647
3677
  }
2648
3678
 
2649
3679
  /**
2650
- * Delete a platform
3680
+ * Clear dialogue session
3681
+ * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
2651
3682
  * @param data The data for the request.
2652
- * @param data.id Platform ID
2653
- * @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
2654
3686
  * @throws ApiError
2655
3687
  */
2656
- public static platformControllerDelete(
2657
- data: PlatformControllerDeleteData
2658
- ): CancelablePromise<PlatformControllerDeleteResponse> {
3688
+ public static nlpControllerClearSession(
3689
+ data: NlpControllerClearSessionData
3690
+ ): CancelablePromise<NlpControllerClearSessionResponse> {
2659
3691
  return __request(OpenAPI, {
2660
3692
  method: 'DELETE',
2661
- url: '/api/v1/bean/platforms/{id}',
3693
+ url: '/api/v1/{region}/bean/nlp/session',
2662
3694
  path: {
2663
- id: data.id
3695
+ region: data.region
3696
+ },
3697
+ query: {
3698
+ sessionId: data.sessionId
2664
3699
  },
2665
3700
  errors: {
2666
- 404: 'Platform not found'
3701
+ 401: 'Unauthorized'
2667
3702
  }
2668
3703
  });
2669
3704
  }
2670
- }
2671
3705
 
2672
- export class ProviderSyncService {
2673
3706
  /**
2674
- * Sync transactions from financial data provider
2675
- *
2676
- * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
2677
- *
2678
- * **Supported Providers:**
2679
- * - **plaid**: Plaid API (US, Canada, Europe)
2680
- * - **teller**: Teller API (US)
2681
- * - **truelayer**: TrueLayer Open Banking (UK, Europe)
2682
- * - **gocardless**: GoCardless Bank Account Data (Europe)
2683
- * - **simplefin**: SimpleFIN (Self-hosted)
2684
- * - **yodlee**: Yodlee (Global)
2685
- * - **beancount-direct**: Beancount format transactions
2686
- * - **parsed-bill**: Client-side parsed bill transactions
2687
- *
2688
- * **Processing Flow:**
2689
- * 1. Transform raw data via provider adapter
2690
- * 2. Validate transaction format
2691
- * 3. Deduplicate using originalId
2692
- * 4. Classify using rule engine
2693
- * 5. Route low-confidence to Review Center
2694
- * 6. Persist validated transactions
2695
- *
3707
+ * Get current session state
3708
+ * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
2696
3709
  * @param data The data for the request.
2697
- * @param data.providerName Provider name
2698
- * @param data.region Region code
2699
- * @param data.requestBody
2700
- * @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)
2701
3713
  * @throws ApiError
2702
3714
  */
2703
- public static providerSyncControllerSync(
2704
- data: ProviderSyncControllerSyncData
2705
- ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3715
+ public static nlpControllerGetSession(
3716
+ data: NlpControllerGetSessionData
3717
+ ): CancelablePromise<NlpControllerGetSessionResponse> {
2706
3718
  return __request(OpenAPI, {
2707
- method: 'POST',
2708
- url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3719
+ method: 'GET',
3720
+ url: '/api/v1/{region}/bean/nlp/session',
2709
3721
  path: {
2710
- providerName: data.providerName,
2711
3722
  region: data.region
2712
3723
  },
2713
- body: data.requestBody,
2714
- mediaType: 'application/json',
3724
+ query: {
3725
+ sessionId: data.sessionId
3726
+ },
2715
3727
  errors: {
2716
- 400: 'Invalid request data',
2717
- 401: 'Missing or invalid authentication',
2718
- 404: 'Provider not supported'
3728
+ 401: 'Unauthorized'
2719
3729
  }
2720
3730
  });
2721
3731
  }
3732
+ }
2722
3733
 
3734
+ export class BeanPlatformsService {
2723
3735
  /**
2724
- * Get supported providers
2725
- * Returns a list of all providers supported by the sync endpoint.
2726
- * @param data The data for the request.
2727
- * @param data.region Region code for tenant context
2728
- * @returns SupportedProvidersResponseDto List of supported providers
3736
+ * Get all platforms with statistics
3737
+ * @returns unknown List of platforms with binding and account counts
2729
3738
  * @throws ApiError
2730
3739
  */
2731
- public static providerSyncControllerGetSupportedProviders(
2732
- data: ProviderSyncControllerGetSupportedProvidersData
2733
- ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3740
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2734
3741
  return __request(OpenAPI, {
2735
3742
  method: 'GET',
2736
- url: '/api/v1/{region}/bean/import/provider/supported',
2737
- path: {
2738
- region: data.region
2739
- },
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',
2740
3762
  errors: {
2741
- 401: 'Missing or invalid authentication'
3763
+ 409: 'Platform already exists'
2742
3764
  }
2743
3765
  });
2744
3766
  }
2745
3767
 
2746
3768
  /**
2747
- * Check if provider is supported
2748
- * Returns whether a specific provider is supported.
3769
+ * Get platform list for current user
2749
3770
  * @param data The data for the request.
2750
- * @param data.providerName Provider name to check
2751
- * @param data.region Region code for tenant context
2752
- * @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
2753
3773
  * @throws ApiError
2754
3774
  */
2755
- public static providerSyncControllerIsProviderSupported(
2756
- data: ProviderSyncControllerIsProviderSupportedData
2757
- ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3775
+ public static platformControllerGetPlatformList(
3776
+ data: PlatformControllerGetPlatformListData = {}
3777
+ ): CancelablePromise<PlatformControllerGetPlatformListResponse> {
2758
3778
  return __request(OpenAPI, {
2759
3779
  method: 'GET',
2760
- url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
2761
- path: {
2762
- providerName: data.providerName,
3780
+ url: '/api/v1/bean/platforms/list',
3781
+ query: {
2763
3782
  region: data.region
2764
- },
2765
- errors: {
2766
- 401: 'Missing or invalid authentication'
2767
3783
  }
2768
3784
  });
2769
3785
  }
2770
- }
2771
3786
 
2772
- export class ImportTelemetryService {
2773
3787
  /**
2774
- * Receive anonymous parser failure telemetry
3788
+ * Match platforms by name or alias
2775
3789
  * @param data The data for the request.
2776
- * @param data.region Region code for tenant context
2777
- * @param data.requestBody
2778
- * @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
2779
3793
  * @throws ApiError
2780
3794
  */
2781
- public static telemetryControllerReportTelemetry(
2782
- data: TelemetryControllerReportTelemetryData
2783
- ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
3795
+ public static platformControllerMatchPlatforms(
3796
+ data: PlatformControllerMatchPlatformsData
3797
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
2784
3798
  return __request(OpenAPI, {
2785
- method: 'POST',
2786
- url: '/api/v1/{region}/bean/import/parser-telemetry',
2787
- path: {
3799
+ method: 'GET',
3800
+ url: '/api/v1/bean/platforms/match',
3801
+ query: {
3802
+ q: data.q,
2788
3803
  region: data.region
2789
- },
2790
- body: data.requestBody,
2791
- mediaType: 'application/json',
2792
- errors: {
2793
- 401: 'Unauthorized'
2794
3804
  }
2795
3805
  });
2796
3806
  }
2797
- }
2798
3807
 
2799
- export class BeanNlpService {
2800
3808
  /**
2801
- * Process natural language input
2802
- * 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
2803
3810
  * @param data The data for the request.
2804
- * @param data.region Region code for tenant context
2805
- * @param data.requestBody Natural language transaction input with optional session ID
2806
- * @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)
2807
3815
  * @throws ApiError
2808
3816
  */
2809
- public static nlpControllerProcessNaturalLanguage(
2810
- data: NlpControllerProcessNaturalLanguageData
2811
- ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
3817
+ public static platformControllerGetPlatformStandards(
3818
+ data: PlatformControllerGetPlatformStandardsData
3819
+ ): CancelablePromise<PlatformControllerGetPlatformStandardsResponse> {
2812
3820
  return __request(OpenAPI, {
2813
- method: 'POST',
2814
- url: '/api/v1/{region}/bean/nlp/process',
3821
+ method: 'GET',
3822
+ url: '/api/v1/bean/platforms/{id}/standards',
2815
3823
  path: {
2816
- region: data.region
3824
+ id: data.id
2817
3825
  },
2818
- body: data.requestBody,
2819
- mediaType: 'application/json',
2820
- errors: {
2821
- 400: 'Invalid input',
2822
- 401: 'Unauthorized'
3826
+ query: {
3827
+ region: data.region,
3828
+ type: data.type
2823
3829
  }
2824
3830
  });
2825
3831
  }
2826
3832
 
2827
3833
  /**
2828
- * Clear dialogue session
2829
- * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
3834
+ * Update a platform
2830
3835
  * @param data The data for the request.
2831
- * @param data.region Region code for tenant context
2832
- * @param data.sessionId Specific session ID to clear (defaults to user session)
2833
- * @returns void Session cleared successfully
3836
+ * @param data.id Platform ID
3837
+ * @param data.requestBody
3838
+ * @returns unknown Platform updated successfully
2834
3839
  * @throws ApiError
2835
3840
  */
2836
- public static nlpControllerClearSession(
2837
- data: NlpControllerClearSessionData
2838
- ): CancelablePromise<NlpControllerClearSessionResponse> {
3841
+ public static platformControllerUpdate(
3842
+ data: PlatformControllerUpdateData
3843
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
2839
3844
  return __request(OpenAPI, {
2840
- method: 'DELETE',
2841
- url: '/api/v1/{region}/bean/nlp/session',
3845
+ method: 'PUT',
3846
+ url: '/api/v1/bean/platforms/{id}',
2842
3847
  path: {
2843
- region: data.region
2844
- },
2845
- query: {
2846
- sessionId: data.sessionId
3848
+ id: data.id
2847
3849
  },
3850
+ body: data.requestBody,
3851
+ mediaType: 'application/json',
2848
3852
  errors: {
2849
- 401: 'Unauthorized'
3853
+ 404: 'Platform not found'
2850
3854
  }
2851
3855
  });
2852
3856
  }
2853
3857
 
2854
3858
  /**
2855
- * Get current session state
2856
- * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
3859
+ * Delete a platform
2857
3860
  * @param data The data for the request.
2858
- * @param data.region Region code for tenant context
2859
- * @param data.sessionId Specific session ID to get (defaults to user session)
2860
- * @returns unknown Current session state (or null if no active session)
3861
+ * @param data.id Platform ID
3862
+ * @returns void Platform deleted successfully
2861
3863
  * @throws ApiError
2862
3864
  */
2863
- public static nlpControllerGetSession(
2864
- data: NlpControllerGetSessionData
2865
- ): CancelablePromise<NlpControllerGetSessionResponse> {
3865
+ public static platformControllerDelete(
3866
+ data: PlatformControllerDeleteData
3867
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
2866
3868
  return __request(OpenAPI, {
2867
- method: 'GET',
2868
- url: '/api/v1/{region}/bean/nlp/session',
3869
+ method: 'DELETE',
3870
+ url: '/api/v1/bean/platforms/{id}',
2869
3871
  path: {
2870
- region: data.region
2871
- },
2872
- query: {
2873
- sessionId: data.sessionId
3872
+ id: data.id
2874
3873
  },
2875
3874
  errors: {
2876
- 401: 'Unauthorized'
3875
+ 404: 'Platform not found'
2877
3876
  }
2878
3877
  });
2879
3878
  }
@@ -2914,6 +3913,7 @@ export class DashboardService {
2914
3913
  * @param data.region Region code for tenant context
2915
3914
  * @param data.groupBy Grouping strategy
2916
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)
2917
3917
  * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
2918
3918
  * @throws ApiError
2919
3919
  */
@@ -2928,7 +3928,8 @@ export class DashboardService {
2928
3928
  },
2929
3929
  query: {
2930
3930
  groupBy: data.groupBy,
2931
- date: data.date
3931
+ date: data.date,
3932
+ accountId: data.accountId
2932
3933
  },
2933
3934
  errors: {
2934
3935
  401: 'User not authenticated'
@@ -2963,124 +3964,69 @@ export class DashboardService {
2963
3964
  }
2964
3965
  });
2965
3966
  }
2966
- }
2967
3967
 
2968
- export class ReportingService {
2969
3968
  /**
2970
- * Get portfolio value trends
2971
- *
2972
- * Returns time series data of portfolio net worth.
2973
- *
2974
- * **Multi-currency Support:**
2975
- * - `series[].byCurrency` - Currency breakdown for each data point
2976
- * - `byCurrency` - Separate time series grouped by currency
2977
- * - `warnings` - Exchange rate warnings if conversion failed
2978
- *
2979
- * **Parameters:**
2980
- * - `period`: Time period (1m, 3m, 6m, 1y)
2981
- * - `granularity`: Data granularity (day, week, month)
2982
- *
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)
2983
3971
  * @param data The data for the request.
2984
3972
  * @param data.region Region code for tenant context
2985
- * @param data.period Time period
2986
- * @param data.granularity Data granularity
2987
- * @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
2988
3977
  * @throws ApiError
2989
3978
  */
2990
- public static reportingControllerGetPortfolioTrends(
2991
- data: ReportingControllerGetPortfolioTrendsData
2992
- ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
3979
+ public static dashboardControllerGetExpenses(
3980
+ data: DashboardControllerGetExpensesData
3981
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
2993
3982
  return __request(OpenAPI, {
2994
3983
  method: 'GET',
2995
- url: '/api/v1/{region}/reporting/portfolio/trends',
3984
+ url: '/api/v1/{region}/dashboard/expenses',
2996
3985
  path: {
2997
3986
  region: data.region
2998
3987
  },
2999
3988
  query: {
3989
+ groupBy: data.groupBy,
3000
3990
  period: data.period,
3001
- granularity: data.granularity
3991
+ flow: data.flow
3002
3992
  },
3003
3993
  errors: {
3994
+ 400: 'Invalid groupBy or period',
3004
3995
  401: 'User not authenticated'
3005
3996
  }
3006
3997
  });
3007
3998
  }
3999
+ }
3008
4000
 
4001
+ export class InvestmentService {
3009
4002
  /**
3010
- * Generate portfolio snapshot
3011
- *
3012
- * Manually generate a portfolio snapshot for a specific date.
3013
- *
3014
- * **Multi-currency Support:**
3015
- * - Fetches balances grouped by currency
3016
- * - Uses user's baseCurrency setting for conversion
3017
- * - Stores exchange rates and warnings
3018
- *
3019
- * **Use Cases:**
3020
- * - Testing snapshot generation
3021
- * - Force regeneration after data correction
3022
- * - Initial setup for new users
3023
- *
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).
3024
4005
  * @param data The data for the request.
3025
4006
  * @param data.region Region code for tenant context
3026
- * @param data.requestBody Optional date (defaults to today)
3027
- * @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
3028
4011
  * @throws ApiError
3029
4012
  */
3030
- public static reportingControllerGenerateSnapshot(
3031
- data: ReportingControllerGenerateSnapshotData
3032
- ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
4013
+ public static holdingPnlControllerGetHoldingPnl(
4014
+ data: HoldingPnlControllerGetHoldingPnlData
4015
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3033
4016
  return __request(OpenAPI, {
3034
- method: 'POST',
3035
- url: '/api/v1/{region}/reporting/snapshots/generate',
4017
+ method: 'GET',
4018
+ url: '/api/v1/{region}/investment/holdings/pnl',
3036
4019
  path: {
3037
4020
  region: data.region
3038
4021
  },
3039
- body: data.requestBody,
3040
- mediaType: 'application/json',
3041
- errors: {
3042
- 400: 'Invalid date format',
3043
- 401: 'User not authenticated'
3044
- }
3045
- });
3046
- }
3047
-
3048
- /**
3049
- * Backfill portfolio snapshots
3050
- *
3051
- * Generate snapshots for a date range (historical data backfill).
3052
- *
3053
- * **Multi-currency Support:**
3054
- * - Each snapshot includes multi-currency data
3055
- * - Uses exchange rates available at generation time
3056
- * - Warnings stored for missing exchange rates
3057
- *
3058
- * **Best Practices:**
3059
- * - Use for initial setup after account configuration
3060
- * - Run during low-traffic periods for large date ranges
3061
- * - Existing snapshots are skipped (not regenerated)
3062
- *
3063
- * @param data The data for the request.
3064
- * @param data.region Region code for tenant context
3065
- * @param data.requestBody
3066
- * @returns BackfillSnapshotsResponse Backfill completed successfully
3067
- * @throws ApiError
3068
- */
3069
- public static reportingControllerBackfillSnapshots(
3070
- data: ReportingControllerBackfillSnapshotsData
3071
- ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
3072
- return __request(OpenAPI, {
3073
- method: 'POST',
3074
- url: '/api/v1/{region}/reporting/snapshots/backfill',
3075
- path: {
3076
- region: data.region
4022
+ query: {
4023
+ asOf: data.asOf,
4024
+ accountId: data.accountId,
4025
+ method: data.method
3077
4026
  },
3078
- body: data.requestBody,
3079
- mediaType: 'application/json',
3080
4027
  errors: {
3081
- 400: 'Invalid date format or range',
3082
- 401: 'User not authenticated',
3083
- 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'
3084
4030
  }
3085
4031
  });
3086
4032
  }
@@ -3109,7 +4055,7 @@ export class AuthService {
3109
4055
  * Anonymous login with access token
3110
4056
  * @param data The data for the request.
3111
4057
  * @param data.requestBody
3112
- * @returns unknown Login successful
4058
+ * @returns AnonymousLoginResponseDto Login successful
3113
4059
  * @throws ApiError
3114
4060
  */
3115
4061
  public static authControllerAccessTokenLogin(
@@ -3127,15 +4073,52 @@ export class AuthService {
3127
4073
  }
3128
4074
  }
3129
4075
 
3130
- 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 {
3131
4109
  /**
3132
- * @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
3133
4113
  * @throws ApiError
3134
4114
  */
3135
4115
  public static cacheControllerFlushCache(): CancelablePromise<CacheControllerFlushCacheResponse> {
3136
4116
  return __request(OpenAPI, {
3137
4117
  method: 'POST',
3138
- url: '/api/v1/cache/flush'
4118
+ url: '/api/v1/cache/flush',
4119
+ errors: {
4120
+ 403: 'Admin access required'
4121
+ }
3139
4122
  });
3140
4123
  }
3141
4124
  }
@@ -3296,3 +4279,53 @@ export class InfoService {
3296
4279
  });
3297
4280
  }
3298
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
+ }