@firela/api-types 0.0.0-canary.8cbdced0 → 0.0.0-canary.97006feb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,8 @@ import type {
17
17
  AccountControllerCloseResponse,
18
18
  AccountControllerReopenData,
19
19
  AccountControllerReopenResponse,
20
+ AccountControllerAddOpeningBalanceData,
21
+ AccountControllerAddOpeningBalanceResponse,
20
22
  AccountStandardsControllerGetTemplatesData,
21
23
  AccountStandardsControllerGetTemplatesResponse,
22
24
  AccountStandardsControllerGetTemplateMetadataData,
@@ -97,6 +99,18 @@ import type {
97
99
  CommodityControllerGetOrCreateResponse,
98
100
  CommodityControllerBulkCreateData,
99
101
  CommodityControllerBulkCreateResponse,
102
+ PriceControllerCreateData,
103
+ PriceControllerCreateResponse,
104
+ PriceControllerFindAllData,
105
+ PriceControllerFindAllResponse,
106
+ PriceControllerFindOneData,
107
+ PriceControllerFindOneResponse,
108
+ PriceControllerUpdateData,
109
+ PriceControllerUpdateResponse,
110
+ PriceControllerDeleteData,
111
+ PriceControllerDeleteResponse,
112
+ PriceControllerBulkCreateData,
113
+ PriceControllerBulkCreateResponse,
100
114
  RecurringRuleControllerCreateData,
101
115
  RecurringRuleControllerCreateResponse,
102
116
  RecurringRuleControllerFindAllData,
@@ -129,26 +143,14 @@ import type {
129
143
  ExpectedTransactionControllerEnterNowResponse,
130
144
  ForecastControllerGetForecastData,
131
145
  ForecastControllerGetForecastResponse,
132
- TransactionRuleControllerCreateData,
133
- TransactionRuleControllerCreateResponse,
134
- TransactionRuleControllerListData,
135
- TransactionRuleControllerListResponse,
136
- TransactionRuleControllerValidateData,
137
- TransactionRuleControllerValidateResponse,
138
- TransactionRuleControllerBulkCreateData,
139
- TransactionRuleControllerBulkCreateResponse,
140
- TransactionRuleControllerExportData,
141
- TransactionRuleControllerExportResponse,
142
- TransactionRuleControllerGetStatisticsData,
143
- TransactionRuleControllerGetStatisticsResponse,
144
- TransactionRuleControllerGetDetailData,
145
- TransactionRuleControllerGetDetailResponse,
146
- TransactionRuleControllerUpdateData,
147
- TransactionRuleControllerUpdateResponse,
148
- TransactionRuleControllerDeleteData,
149
- TransactionRuleControllerDeleteResponse,
150
- TransactionRuleControllerTestData,
151
- TransactionRuleControllerTestResponse,
146
+ ReportingControllerGetPortfolioTrendsData,
147
+ ReportingControllerGetPortfolioTrendsResponse,
148
+ ReportingControllerGetCashFlowTrendsData,
149
+ ReportingControllerGetCashFlowTrendsResponse,
150
+ ReportingControllerGenerateSnapshotData,
151
+ ReportingControllerGenerateSnapshotResponse,
152
+ ReportingControllerBackfillSnapshotsData,
153
+ ReportingControllerBackfillSnapshotsResponse,
152
154
  UserControllerDeleteOwnUserData,
153
155
  UserControllerDeleteOwnUserResponse,
154
156
  UserControllerGetUserData,
@@ -171,6 +173,48 @@ import type {
171
173
  PropertyControllerUpdateResponse,
172
174
  PropertyControllerDeleteData,
173
175
  PropertyControllerDeleteResponse,
176
+ TransactionRuleControllerCreateData,
177
+ TransactionRuleControllerCreateResponse,
178
+ TransactionRuleControllerListData,
179
+ TransactionRuleControllerListResponse,
180
+ TransactionRuleControllerValidateData,
181
+ TransactionRuleControllerValidateResponse,
182
+ TransactionRuleControllerBulkCreateData,
183
+ TransactionRuleControllerBulkCreateResponse,
184
+ TransactionRuleControllerExportData,
185
+ TransactionRuleControllerExportResponse,
186
+ TransactionRuleControllerGetStatisticsData,
187
+ TransactionRuleControllerGetStatisticsResponse,
188
+ TransactionRuleControllerGetDetailData,
189
+ TransactionRuleControllerGetDetailResponse,
190
+ TransactionRuleControllerUpdateData,
191
+ TransactionRuleControllerUpdateResponse,
192
+ TransactionRuleControllerDeleteData,
193
+ TransactionRuleControllerDeleteResponse,
194
+ TransactionRuleControllerTestData,
195
+ TransactionRuleControllerTestResponse,
196
+ EventControllerCreateData,
197
+ EventControllerCreateResponse,
198
+ EventControllerFindAllData,
199
+ EventControllerFindAllResponse,
200
+ EventControllerFindOneData,
201
+ EventControllerFindOneResponse,
202
+ EventControllerUpdateData,
203
+ EventControllerUpdateResponse,
204
+ EventControllerDeleteData,
205
+ EventControllerDeleteResponse,
206
+ EventControllerGetSliceData,
207
+ EventControllerGetSliceResponse,
208
+ OnboardingControllerBootstrapData,
209
+ OnboardingControllerBootstrapResponse,
210
+ ReconciliationControllerComputeData,
211
+ ReconciliationControllerComputeResponse,
212
+ ReconciliationControllerAssertData,
213
+ ReconciliationControllerAssertResponse,
214
+ ReconciliationControllerPadData,
215
+ ReconciliationControllerPadResponse,
216
+ ReconciliationControllerHistoryData,
217
+ ReconciliationControllerHistoryResponse,
174
218
  ExportControllerExportBeancountResponse,
175
219
  FileImportControllerImportFileData,
176
220
  FileImportControllerImportFileResponse,
@@ -184,22 +228,20 @@ import type {
184
228
  ImporterConfigControllerUpdateConfigResponse,
185
229
  ImporterConfigControllerResetConfigData,
186
230
  ImporterConfigControllerResetConfigResponse,
187
- PlatformControllerFindAllResponse,
188
- PlatformControllerCreateData,
189
- PlatformControllerCreateResponse,
190
- PlatformControllerGetPlatformListResponse,
191
- PlatformControllerMatchPlatformsData,
192
- PlatformControllerMatchPlatformsResponse,
193
- PlatformControllerUpdateData,
194
- PlatformControllerUpdateResponse,
195
- PlatformControllerDeleteData,
196
- PlatformControllerDeleteResponse,
197
231
  ProviderSyncControllerSyncData,
198
232
  ProviderSyncControllerSyncResponse,
199
233
  ProviderSyncControllerGetSupportedProvidersData,
200
234
  ProviderSyncControllerGetSupportedProvidersResponse,
201
235
  ProviderSyncControllerIsProviderSupportedData,
202
236
  ProviderSyncControllerIsProviderSupportedResponse,
237
+ ExternalAccountLinkControllerCreateData,
238
+ ExternalAccountLinkControllerCreateResponse,
239
+ ExternalAccountLinkControllerFindAllData,
240
+ ExternalAccountLinkControllerFindAllResponse,
241
+ ExternalAccountLinkControllerFindOneData,
242
+ ExternalAccountLinkControllerFindOneResponse,
243
+ ExternalAccountLinkControllerRemoveData,
244
+ ExternalAccountLinkControllerRemoveResponse,
203
245
  TelemetryControllerReportTelemetryData,
204
246
  TelemetryControllerReportTelemetryResponse,
205
247
  TelemetryControllerReportCoverageMissData,
@@ -212,32 +254,26 @@ import type {
212
254
  NlpControllerClearSessionResponse,
213
255
  NlpControllerGetSessionData,
214
256
  NlpControllerGetSessionResponse,
257
+ PlatformControllerFindAllResponse,
258
+ PlatformControllerCreateData,
259
+ PlatformControllerCreateResponse,
260
+ PlatformControllerGetPlatformListResponse,
261
+ PlatformControllerMatchPlatformsData,
262
+ PlatformControllerMatchPlatformsResponse,
263
+ PlatformControllerUpdateData,
264
+ PlatformControllerUpdateResponse,
265
+ PlatformControllerDeleteData,
266
+ PlatformControllerDeleteResponse,
215
267
  DashboardControllerGetNetWorthData,
216
268
  DashboardControllerGetNetWorthResponse,
217
269
  DashboardControllerGetAccountsData,
218
270
  DashboardControllerGetAccountsResponse,
219
271
  DashboardControllerGetCashFlowData,
220
272
  DashboardControllerGetCashFlowResponse,
273
+ DashboardControllerGetExpensesData,
274
+ DashboardControllerGetExpensesResponse,
221
275
  HoldingPnlControllerGetHoldingPnlData,
222
276
  HoldingPnlControllerGetHoldingPnlResponse,
223
- PriceControllerCreateData,
224
- PriceControllerCreateResponse,
225
- PriceControllerFindAllData,
226
- PriceControllerFindAllResponse,
227
- PriceControllerFindOneData,
228
- PriceControllerFindOneResponse,
229
- PriceControllerUpdateData,
230
- PriceControllerUpdateResponse,
231
- PriceControllerDeleteData,
232
- PriceControllerDeleteResponse,
233
- PriceControllerBulkCreateData,
234
- PriceControllerBulkCreateResponse,
235
- ReportingControllerGetPortfolioTrendsData,
236
- ReportingControllerGetPortfolioTrendsResponse,
237
- ReportingControllerGenerateSnapshotData,
238
- ReportingControllerGenerateSnapshotResponse,
239
- ReportingControllerBackfillSnapshotsData,
240
- ReportingControllerBackfillSnapshotsResponse,
241
277
  ApiKeysControllerCreateApiKeyResponse,
242
278
  AuthControllerAccessTokenLoginData,
243
279
  AuthControllerAccessTokenLoginResponse,
@@ -257,10 +293,12 @@ import type {
257
293
 
258
294
  export class BeanAccountsService {
259
295
  /**
296
+ * Create a new account
297
+ * Creates a new account (Beancount Open directive)
260
298
  * @param data The data for the request.
261
299
  * @param data.region Region code for tenant context
262
300
  * @param data.requestBody
263
- * @returns unknown
301
+ * @returns AccountResponseDto Account created successfully
264
302
  * @throws ApiError
265
303
  */
266
304
  public static accountControllerCreate(
@@ -273,7 +311,10 @@ export class BeanAccountsService {
273
311
  region: data.region
274
312
  },
275
313
  body: data.requestBody,
276
- mediaType: 'application/json'
314
+ mediaType: 'application/json',
315
+ errors: {
316
+ 409: 'Account already exists'
317
+ }
277
318
  });
278
319
  }
279
320
 
@@ -285,7 +326,7 @@ export class BeanAccountsService {
285
326
  * @param data.type Filter by account type
286
327
  * @param data.status Filter by status
287
328
  * @param data.isCustom Filter by custom (user-created) accounts only
288
- * @param data.search Search term for path or i18nKey
329
+ * @param data.search Search term for account path
289
330
  * @param data.limit Maximum number of results
290
331
  * @param data.offset Number of results to skip
291
332
  * @returns AccountListResponseDto Accounts retrieved successfully
@@ -337,11 +378,13 @@ export class BeanAccountsService {
337
378
  }
338
379
 
339
380
  /**
381
+ * Update account
382
+ * Updates account metadata (path cannot be changed)
340
383
  * @param data The data for the request.
341
- * @param data.id
384
+ * @param data.id Account UUID
342
385
  * @param data.region Region code for tenant context
343
386
  * @param data.requestBody
344
- * @returns unknown
387
+ * @returns AccountResponseDto Account updated successfully
345
388
  * @throws ApiError
346
389
  */
347
390
  public static accountControllerUpdate(
@@ -355,15 +398,20 @@ export class BeanAccountsService {
355
398
  region: data.region
356
399
  },
357
400
  body: data.requestBody,
358
- mediaType: 'application/json'
401
+ mediaType: 'application/json',
402
+ errors: {
403
+ 404: 'Account not found'
404
+ }
359
405
  });
360
406
  }
361
407
 
362
408
  /**
409
+ * Delete account
410
+ * Deletes an account (only if no transactions)
363
411
  * @param data The data for the request.
364
- * @param data.id
412
+ * @param data.id Account UUID
365
413
  * @param data.region Region code for tenant context
366
- * @returns unknown
414
+ * @returns void Account deleted successfully
367
415
  * @throws ApiError
368
416
  */
369
417
  public static accountControllerDelete(
@@ -375,16 +423,22 @@ export class BeanAccountsService {
375
423
  path: {
376
424
  id: data.id,
377
425
  region: data.region
426
+ },
427
+ errors: {
428
+ 404: 'Account not found',
429
+ 409: 'Account has transactions and cannot be deleted'
378
430
  }
379
431
  });
380
432
  }
381
433
 
382
434
  /**
435
+ * Close account
436
+ * Closes an account (Beancount Close directive)
383
437
  * @param data The data for the request.
384
- * @param data.id
438
+ * @param data.id Account UUID
385
439
  * @param data.region Region code for tenant context
386
440
  * @param data.requestBody
387
- * @returns unknown
441
+ * @returns AccountResponseDto Account closed successfully
388
442
  * @throws ApiError
389
443
  */
390
444
  public static accountControllerClose(
@@ -398,16 +452,22 @@ export class BeanAccountsService {
398
452
  region: data.region
399
453
  },
400
454
  body: data.requestBody,
401
- mediaType: 'application/json'
455
+ mediaType: 'application/json',
456
+ errors: {
457
+ 400: 'Account is already closed',
458
+ 404: 'Account not found'
459
+ }
402
460
  });
403
461
  }
404
462
 
405
463
  /**
464
+ * Reopen account
465
+ * Reopens a previously closed account
406
466
  * @param data The data for the request.
407
- * @param data.id
467
+ * @param data.id Account UUID
408
468
  * @param data.region Region code for tenant context
409
469
  * @param data.requestBody
410
- * @returns unknown
470
+ * @returns AccountResponseDto Account reopened successfully
411
471
  * @throws ApiError
412
472
  */
413
473
  public static accountControllerReopen(
@@ -421,7 +481,40 @@ export class BeanAccountsService {
421
481
  region: data.region
422
482
  },
423
483
  body: data.requestBody,
424
- mediaType: 'application/json'
484
+ mediaType: 'application/json',
485
+ errors: {
486
+ 400: 'Account is not closed',
487
+ 404: 'Account not found'
488
+ }
489
+ });
490
+ }
491
+
492
+ /**
493
+ * Post an opening-balance transaction
494
+ * 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.
495
+ * @param data The data for the request.
496
+ * @param data.id Account UUID
497
+ * @param data.region Region code for tenant context
498
+ * @param data.requestBody
499
+ * @returns OpeningBalanceResultDto Opening-balance transaction created
500
+ * @throws ApiError
501
+ */
502
+ public static accountControllerAddOpeningBalance(
503
+ data: AccountControllerAddOpeningBalanceData
504
+ ): CancelablePromise<AccountControllerAddOpeningBalanceResponse> {
505
+ return __request(OpenAPI, {
506
+ method: 'POST',
507
+ url: '/api/v1/{region}/bean/accounts/{id}/opening-balance',
508
+ path: {
509
+ id: data.id,
510
+ region: data.region
511
+ },
512
+ body: data.requestBody,
513
+ mediaType: 'application/json',
514
+ errors: {
515
+ 404: 'Account not found',
516
+ 409: 'An opening balance already exists for this account'
517
+ }
425
518
  });
426
519
  }
427
520
  }
@@ -455,7 +548,7 @@ export class BeanAccountStandardsService {
455
548
 
456
549
  /**
457
550
  * Get template metadata for an account path
458
- * Returns extendable status and root type for a template path.
551
+ * Returns root type for a template path.
459
552
  * @param data The data for the request.
460
553
  * @param data.region Region code for tenant context
461
554
  * @param data.path Account path to check
@@ -541,6 +634,7 @@ export class BeanTransactionsService {
541
634
  * @param data.status Filter by transaction status
542
635
  * @param data.search Search in narration and payee fields (max 200 chars)
543
636
  * @param data.accountId Filter by account ID (transactions with postings to this account)
637
+ * @param data.category Filter by ADR-0075 functional category (Group segment); matches any posting to an Expenses/Income account whose derived Group segment equals this value
544
638
  * @returns TransactionListResponseDto Transaction list
545
639
  * @throws ApiError
546
640
  */
@@ -560,7 +654,8 @@ export class BeanTransactionsService {
560
654
  dateTo: data.dateTo,
561
655
  status: data.status,
562
656
  search: data.search,
563
- accountId: data.accountId
657
+ accountId: data.accountId,
658
+ category: data.category
564
659
  },
565
660
  errors: {
566
661
  400: 'Validation failed',
@@ -748,7 +843,7 @@ export class BeanBalancesService {
748
843
  * Query account balance
749
844
  * Calculate account balance at a specific date for a single currency
750
845
  * @param data The data for the request.
751
- * @param data.account Account name (e.g., "Assets:Bank:Checking")
846
+ * @param data.account Account name (e.g., "Assets:Checking")
752
847
  * @param data.region Region code for tenant context
753
848
  * @param data.date Date to calculate balance at (ISO 8601 format)
754
849
  * @param data.currency Currency to query (e.g., "USD", "CNY")
@@ -1469,112 +1564,279 @@ export class BeanCommoditiesService {
1469
1564
  }
1470
1565
  }
1471
1566
 
1472
- export class RecurringRulesService {
1567
+ export class BeanPricesService {
1473
1568
  /**
1474
- * Create a new recurring rule
1475
- * Creates a new recurring transaction rule for the authenticated user
1569
+ * Create a new price
1570
+ * Creates a new price entry for the authenticated user
1476
1571
  * @param data The data for the request.
1477
1572
  * @param data.region Region code for tenant context
1478
1573
  * @param data.requestBody
1479
- * @returns RecurringRuleResponseDto Rule created successfully
1574
+ * @returns PriceResponseDto Price created successfully
1480
1575
  * @throws ApiError
1481
1576
  */
1482
- public static recurringRuleControllerCreate(
1483
- data: RecurringRuleControllerCreateData
1484
- ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1577
+ public static priceControllerCreate(
1578
+ data: PriceControllerCreateData
1579
+ ): CancelablePromise<PriceControllerCreateResponse> {
1485
1580
  return __request(OpenAPI, {
1486
1581
  method: 'POST',
1487
- url: '/api/v1/{region}/bean/recurring-rules',
1582
+ url: '/api/v1/{region}/bean/prices',
1488
1583
  path: {
1489
1584
  region: data.region
1490
1585
  },
1491
1586
  body: data.requestBody,
1492
1587
  mediaType: 'application/json',
1493
1588
  errors: {
1494
- 400: 'Invalid input data (e.g., autoCreate without accounts)',
1495
- 409: 'Rule with same name already exists'
1589
+ 404: 'Currency or quoteCurrency commodity not found',
1590
+ 409: 'Price already exists for this currency pair and date'
1496
1591
  }
1497
1592
  });
1498
1593
  }
1499
1594
 
1500
1595
  /**
1501
- * List recurring rules
1502
- * Returns all recurring rules for the authenticated user with optional filtering
1596
+ * List user prices
1597
+ * Returns all price entries for the authenticated user with optional filtering
1503
1598
  * @param data The data for the request.
1504
1599
  * @param data.region Region code for tenant context
1505
- * @param data.isActive Filter by active status
1506
- * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
1507
- * @param data.hasAutoCreate Filter by autoCreate enabled
1508
- * @returns RecurringRuleResponseDto Rules retrieved successfully
1600
+ * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
1601
+ * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
1602
+ * @param data.dateFrom Filter prices from this date (ISO 8601 format)
1603
+ * @param data.dateTo Filter prices to this date (ISO 8601 format)
1604
+ * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
1605
+ * @param data.page Page number for pagination (default: 1)
1606
+ * @param data.limit Number of items per page (default: 20, max: 100)
1607
+ * @returns PriceListResponseDto Prices retrieved successfully
1509
1608
  * @throws ApiError
1510
1609
  */
1511
- public static recurringRuleControllerFindAll(
1512
- data: RecurringRuleControllerFindAllData
1513
- ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1610
+ public static priceControllerFindAll(
1611
+ data: PriceControllerFindAllData
1612
+ ): CancelablePromise<PriceControllerFindAllResponse> {
1514
1613
  return __request(OpenAPI, {
1515
1614
  method: 'GET',
1516
- url: '/api/v1/{region}/bean/recurring-rules',
1615
+ url: '/api/v1/{region}/bean/prices',
1517
1616
  path: {
1518
1617
  region: data.region
1519
1618
  },
1520
1619
  query: {
1521
- isActive: data.isActive,
1522
- frequency: data.frequency,
1523
- hasAutoCreate: data.hasAutoCreate
1620
+ currency: data.currency,
1621
+ quoteCurrency: data.quoteCurrency,
1622
+ dateFrom: data.dateFrom,
1623
+ dateTo: data.dateTo,
1624
+ search: data.search,
1625
+ page: data.page,
1626
+ limit: data.limit
1524
1627
  }
1525
1628
  });
1526
1629
  }
1527
1630
 
1528
1631
  /**
1529
- * Create recurring rule from transaction
1530
- * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1632
+ * Get price by ID
1633
+ * Returns a single price entry by its ID
1531
1634
  * @param data The data for the request.
1532
- * @param data.transactionId Source transaction ID
1635
+ * @param data.id Price ID
1533
1636
  * @param data.region Region code for tenant context
1534
- * @param data.requestBody
1535
- * @returns RecurringRuleResponseDto Rule created successfully
1637
+ * @returns PriceResponseDto Price retrieved successfully
1536
1638
  * @throws ApiError
1537
1639
  */
1538
- public static recurringRuleControllerCreateFromTransaction(
1539
- data: RecurringRuleControllerCreateFromTransactionData
1540
- ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1640
+ public static priceControllerFindOne(
1641
+ data: PriceControllerFindOneData
1642
+ ): CancelablePromise<PriceControllerFindOneResponse> {
1541
1643
  return __request(OpenAPI, {
1542
- method: 'POST',
1543
- url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1644
+ method: 'GET',
1645
+ url: '/api/v1/{region}/bean/prices/{id}',
1544
1646
  path: {
1545
- transactionId: data.transactionId,
1647
+ id: data.id,
1546
1648
  region: data.region
1547
1649
  },
1548
- body: data.requestBody,
1549
- mediaType: 'application/json',
1550
1650
  errors: {
1551
- 404: 'Transaction not found',
1552
- 409: 'Rule with same name already exists or transaction already linked'
1651
+ 404: 'Price not found'
1553
1652
  }
1554
1653
  });
1555
1654
  }
1556
1655
 
1557
1656
  /**
1558
- * Get recurring rule by ID
1559
- * Returns a specific recurring rule with its details
1657
+ * Update a price
1658
+ * Updates an existing price entry
1560
1659
  * @param data The data for the request.
1561
- * @param data.id Rule ID
1660
+ * @param data.id Price ID
1562
1661
  * @param data.region Region code for tenant context
1563
- * @returns RecurringRuleResponseDto Rule retrieved successfully
1662
+ * @param data.requestBody
1663
+ * @returns PriceResponseDto Price updated successfully
1564
1664
  * @throws ApiError
1565
1665
  */
1566
- public static recurringRuleControllerFindOne(
1567
- data: RecurringRuleControllerFindOneData
1568
- ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1666
+ public static priceControllerUpdate(
1667
+ data: PriceControllerUpdateData
1668
+ ): CancelablePromise<PriceControllerUpdateResponse> {
1569
1669
  return __request(OpenAPI, {
1570
- method: 'GET',
1571
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1670
+ method: 'PUT',
1671
+ url: '/api/v1/{region}/bean/prices/{id}',
1572
1672
  path: {
1573
1673
  id: data.id,
1574
1674
  region: data.region
1575
1675
  },
1676
+ body: data.requestBody,
1677
+ mediaType: 'application/json',
1576
1678
  errors: {
1577
- 404: 'Rule not found'
1679
+ 404: 'Price not found',
1680
+ 409: 'Updated price conflicts with existing price'
1681
+ }
1682
+ });
1683
+ }
1684
+
1685
+ /**
1686
+ * Delete a price
1687
+ * Deletes a price entry (hard delete)
1688
+ * @param data The data for the request.
1689
+ * @param data.id Price ID
1690
+ * @param data.region Region code for tenant context
1691
+ * @returns void Price deleted successfully
1692
+ * @throws ApiError
1693
+ */
1694
+ public static priceControllerDelete(
1695
+ data: PriceControllerDeleteData
1696
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1697
+ return __request(OpenAPI, {
1698
+ method: 'DELETE',
1699
+ url: '/api/v1/{region}/bean/prices/{id}',
1700
+ path: {
1701
+ id: data.id,
1702
+ region: data.region
1703
+ },
1704
+ errors: {
1705
+ 404: 'Price not found'
1706
+ }
1707
+ });
1708
+ }
1709
+
1710
+ /**
1711
+ * Bulk create prices
1712
+ * Creates multiple price entries at once (skips duplicates)
1713
+ * @param data The data for the request.
1714
+ * @param data.region Region code for tenant context
1715
+ * @param data.requestBody
1716
+ * @returns PriceResponseDto Prices created successfully
1717
+ * @throws ApiError
1718
+ */
1719
+ public static priceControllerBulkCreate(
1720
+ data: PriceControllerBulkCreateData
1721
+ ): CancelablePromise<PriceControllerBulkCreateResponse> {
1722
+ return __request(OpenAPI, {
1723
+ method: 'POST',
1724
+ url: '/api/v1/{region}/bean/prices/bulk',
1725
+ path: {
1726
+ region: data.region
1727
+ },
1728
+ body: data.requestBody,
1729
+ mediaType: 'application/json'
1730
+ });
1731
+ }
1732
+ }
1733
+
1734
+ export class RecurringRulesService {
1735
+ /**
1736
+ * Create a new recurring rule
1737
+ * Creates a new recurring transaction rule for the authenticated user
1738
+ * @param data The data for the request.
1739
+ * @param data.region Region code for tenant context
1740
+ * @param data.requestBody
1741
+ * @returns RecurringRuleResponseDto Rule created successfully
1742
+ * @throws ApiError
1743
+ */
1744
+ public static recurringRuleControllerCreate(
1745
+ data: RecurringRuleControllerCreateData
1746
+ ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1747
+ return __request(OpenAPI, {
1748
+ method: 'POST',
1749
+ url: '/api/v1/{region}/bean/recurring-rules',
1750
+ path: {
1751
+ region: data.region
1752
+ },
1753
+ body: data.requestBody,
1754
+ mediaType: 'application/json',
1755
+ errors: {
1756
+ 400: 'Invalid input data (e.g., autoCreate without accounts)',
1757
+ 409: 'Rule with same name already exists'
1758
+ }
1759
+ });
1760
+ }
1761
+
1762
+ /**
1763
+ * List recurring rules
1764
+ * Returns all recurring rules for the authenticated user with optional filtering
1765
+ * @param data The data for the request.
1766
+ * @param data.region Region code for tenant context
1767
+ * @param data.isActive Filter by active status
1768
+ * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
1769
+ * @param data.hasAutoCreate Filter by autoCreate enabled
1770
+ * @returns RecurringRuleResponseDto Rules retrieved successfully
1771
+ * @throws ApiError
1772
+ */
1773
+ public static recurringRuleControllerFindAll(
1774
+ data: RecurringRuleControllerFindAllData
1775
+ ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1776
+ return __request(OpenAPI, {
1777
+ method: 'GET',
1778
+ url: '/api/v1/{region}/bean/recurring-rules',
1779
+ path: {
1780
+ region: data.region
1781
+ },
1782
+ query: {
1783
+ isActive: data.isActive,
1784
+ frequency: data.frequency,
1785
+ hasAutoCreate: data.hasAutoCreate
1786
+ }
1787
+ });
1788
+ }
1789
+
1790
+ /**
1791
+ * Create recurring rule from transaction
1792
+ * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1793
+ * @param data The data for the request.
1794
+ * @param data.transactionId Source transaction ID
1795
+ * @param data.region Region code for tenant context
1796
+ * @param data.requestBody
1797
+ * @returns RecurringRuleResponseDto Rule created successfully
1798
+ * @throws ApiError
1799
+ */
1800
+ public static recurringRuleControllerCreateFromTransaction(
1801
+ data: RecurringRuleControllerCreateFromTransactionData
1802
+ ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1803
+ return __request(OpenAPI, {
1804
+ method: 'POST',
1805
+ url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1806
+ path: {
1807
+ transactionId: data.transactionId,
1808
+ region: data.region
1809
+ },
1810
+ body: data.requestBody,
1811
+ mediaType: 'application/json',
1812
+ errors: {
1813
+ 404: 'Transaction not found',
1814
+ 409: 'Rule with same name already exists or transaction already linked'
1815
+ }
1816
+ });
1817
+ }
1818
+
1819
+ /**
1820
+ * Get recurring rule by ID
1821
+ * Returns a specific recurring rule with its details
1822
+ * @param data The data for the request.
1823
+ * @param data.id Rule ID
1824
+ * @param data.region Region code for tenant context
1825
+ * @returns RecurringRuleResponseDto Rule retrieved successfully
1826
+ * @throws ApiError
1827
+ */
1828
+ public static recurringRuleControllerFindOne(
1829
+ data: RecurringRuleControllerFindOneData
1830
+ ): CancelablePromise<RecurringRuleControllerFindOneResponse> {
1831
+ return __request(OpenAPI, {
1832
+ method: 'GET',
1833
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
1834
+ path: {
1835
+ id: data.id,
1836
+ region: data.region
1837
+ },
1838
+ errors: {
1839
+ 404: 'Rule not found'
1578
1840
  }
1579
1841
  });
1580
1842
  }
@@ -1899,279 +2161,158 @@ export class RecurringForecastService {
1899
2161
  }
1900
2162
  }
1901
2163
 
1902
- export class BeanTransactionRulesService {
2164
+ export class ReportingService {
1903
2165
  /**
1904
- * Create a new transaction rule (or upsert if upsertByPayee=true)
1905
- * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2166
+ * Get portfolio value trends
2167
+ *
2168
+ * Returns time series data of portfolio net worth.
2169
+ *
2170
+ * **Multi-currency Support:**
2171
+ * - `series[].byCurrency` - Currency breakdown for each data point
2172
+ * - `byCurrency` - Separate time series grouped by currency
2173
+ * - `warnings` - Exchange rate warnings if conversion failed
2174
+ *
2175
+ * **Parameters:**
2176
+ * - `period`: Time period (1m, 3m, 6m, 1y)
2177
+ * - `granularity`: Data granularity (day, week, month)
2178
+ *
1906
2179
  * @param data The data for the request.
1907
2180
  * @param data.region Region code for tenant context
1908
- * @param data.requestBody
1909
- * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2181
+ * @param data.period Time period
2182
+ * @param data.granularity Data granularity
2183
+ * @returns PortfolioTrendsResponseDto Trends retrieved successfully
1910
2184
  * @throws ApiError
1911
2185
  */
1912
- public static transactionRuleControllerCreate(
1913
- data: TransactionRuleControllerCreateData
1914
- ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2186
+ public static reportingControllerGetPortfolioTrends(
2187
+ data: ReportingControllerGetPortfolioTrendsData
2188
+ ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
1915
2189
  return __request(OpenAPI, {
1916
- method: 'POST',
1917
- url: '/api/v1/{region}/bean/transaction-rules',
2190
+ method: 'GET',
2191
+ url: '/api/v1/{region}/reporting/portfolio/trends',
1918
2192
  path: {
1919
2193
  region: data.region
1920
2194
  },
1921
- body: data.requestBody,
1922
- mediaType: 'application/json',
2195
+ query: {
2196
+ period: data.period,
2197
+ granularity: data.granularity
2198
+ },
1923
2199
  errors: {
1924
- 400: 'Validation failed',
1925
- 401: 'Unauthorized',
1926
- 409: 'Resource conflict - another process is updating this rule'
2200
+ 401: 'User not authenticated'
1927
2201
  }
1928
2202
  });
1929
2203
  }
1930
2204
 
1931
2205
  /**
1932
- * Get all transaction rules for user
2206
+ * Get cash-flow trends
2207
+ *
2208
+ * Monthly income / expense / netSavings over a fixed N-month window
2209
+ * (current month + N−1 prior). Missing months are zero-filled (flow metric).
2210
+ *
2211
+ * **Parameters:**
2212
+ * - `period`: 1m | 3m | 6m | 1y (default 6m)
2213
+ * - `granularity`: accepted for API symmetry; v1 returns month buckets
2214
+ *
1933
2215
  * @param data The data for the request.
1934
2216
  * @param data.region Region code for tenant context
1935
- * @param data.limit Max results per page (default: 20, max: 100)
1936
- * @param data.offset Pagination offset (default: 0)
1937
- * @param data.enabled Filter by enabled status
1938
- * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
1939
- * @param data.autoApplyEnabled Filter by auto-apply status
1940
- * @returns TransactionRuleListResponseDto List of rules
2217
+ * @param data.period Time period
2218
+ * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
2219
+ * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
1941
2220
  * @throws ApiError
1942
2221
  */
1943
- public static transactionRuleControllerList(
1944
- data: TransactionRuleControllerListData
1945
- ): CancelablePromise<TransactionRuleControllerListResponse> {
2222
+ public static reportingControllerGetCashFlowTrends(
2223
+ data: ReportingControllerGetCashFlowTrendsData
2224
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
1946
2225
  return __request(OpenAPI, {
1947
2226
  method: 'GET',
1948
- url: '/api/v1/{region}/bean/transaction-rules',
2227
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
1949
2228
  path: {
1950
2229
  region: data.region
1951
2230
  },
1952
2231
  query: {
1953
- limit: data.limit,
1954
- offset: data.offset,
1955
- enabled: data.enabled,
1956
- learningSource: data.learningSource,
1957
- autoApplyEnabled: data.autoApplyEnabled
2232
+ period: data.period,
2233
+ granularity: data.granularity
1958
2234
  },
1959
2235
  errors: {
1960
- 401: 'Unauthorized'
2236
+ 401: 'User not authenticated'
1961
2237
  }
1962
2238
  });
1963
2239
  }
1964
2240
 
1965
2241
  /**
1966
- * Validate transaction rule configuration
2242
+ * Generate portfolio snapshot
2243
+ *
2244
+ * Manually generate a portfolio snapshot for a specific date.
2245
+ *
2246
+ * **Multi-currency Support:**
2247
+ * - Fetches balances grouped by currency
2248
+ * - Uses user's baseCurrency setting for conversion
2249
+ * - Stores exchange rates and warnings
2250
+ *
2251
+ * **Use Cases:**
2252
+ * - Testing snapshot generation
2253
+ * - Force regeneration after data correction
2254
+ * - Initial setup for new users
2255
+ *
1967
2256
  * @param data The data for the request.
1968
2257
  * @param data.region Region code for tenant context
1969
- * @param data.requestBody
1970
- * @returns ValidateRuleResponseDto Validation result
2258
+ * @param data.requestBody Optional date (defaults to today)
2259
+ * @returns GenerateSnapshotResponse Snapshot generated successfully
1971
2260
  * @throws ApiError
1972
2261
  */
1973
- public static transactionRuleControllerValidate(
1974
- data: TransactionRuleControllerValidateData
1975
- ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2262
+ public static reportingControllerGenerateSnapshot(
2263
+ data: ReportingControllerGenerateSnapshotData
2264
+ ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
1976
2265
  return __request(OpenAPI, {
1977
2266
  method: 'POST',
1978
- url: '/api/v1/{region}/bean/transaction-rules/validate',
2267
+ url: '/api/v1/{region}/reporting/snapshots/generate',
1979
2268
  path: {
1980
2269
  region: data.region
1981
2270
  },
1982
2271
  body: data.requestBody,
1983
2272
  mediaType: 'application/json',
1984
2273
  errors: {
1985
- 400: 'Validation failed',
1986
- 401: 'Unauthorized'
1987
- }
1988
- });
1989
- }
1990
-
1991
- /**
1992
- * Bulk create transaction rules
1993
- * @param data The data for the request.
1994
- * @param data.region Region code for tenant context
1995
- * @param data.requestBody
1996
- * @returns BulkCreateRulesResponseDto Bulk create completed
1997
- * @throws ApiError
1998
- */
1999
- public static transactionRuleControllerBulkCreate(
2000
- data: TransactionRuleControllerBulkCreateData
2001
- ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2002
- return __request(OpenAPI, {
2003
- method: 'POST',
2004
- url: '/api/v1/{region}/bean/transaction-rules/bulk',
2005
- path: {
2006
- region: data.region
2007
- },
2008
- body: data.requestBody,
2009
- mediaType: 'application/json',
2010
- errors: {
2011
- 400: 'Invalid bulk create data',
2012
- 401: 'Unauthorized'
2013
- }
2014
- });
2015
- }
2016
-
2017
- /**
2018
- * Export transaction rules
2019
- * @param data The data for the request.
2020
- * @param data.format Export format (currently only JSON supported)
2021
- * @param data.region Region code for tenant context
2022
- * @returns ExportRulesResponseDto Exported rules
2023
- * @throws ApiError
2024
- */
2025
- public static transactionRuleControllerExport(
2026
- data: TransactionRuleControllerExportData
2027
- ): CancelablePromise<TransactionRuleControllerExportResponse> {
2028
- return __request(OpenAPI, {
2029
- method: 'GET',
2030
- url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2031
- path: {
2032
- format: data.format,
2033
- region: data.region
2034
- },
2035
- errors: {
2036
- 400: 'Unsupported format',
2037
- 401: 'Unauthorized'
2038
- }
2039
- });
2040
- }
2041
-
2042
- /**
2043
- * Get transaction rule statistics
2044
- * @param data The data for the request.
2045
- * @param data.period Statistics time period
2046
- * @param data.region Region code for tenant context
2047
- * @returns RuleStatisticsResponseDto Rule statistics
2048
- * @throws ApiError
2049
- */
2050
- public static transactionRuleControllerGetStatistics(
2051
- data: TransactionRuleControllerGetStatisticsData
2052
- ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2053
- return __request(OpenAPI, {
2054
- method: 'GET',
2055
- url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2056
- path: {
2057
- period: data.period,
2058
- region: data.region
2059
- },
2060
- errors: {
2061
- 401: 'Unauthorized'
2062
- }
2063
- });
2064
- }
2065
-
2066
- /**
2067
- * Get transaction rule detail
2068
- * @param data The data for the request.
2069
- * @param data.ruleId Rule ID
2070
- * @param data.region Region code for tenant context
2071
- * @returns TransactionRuleResponseDto Rule details
2072
- * @throws ApiError
2073
- */
2074
- public static transactionRuleControllerGetDetail(
2075
- data: TransactionRuleControllerGetDetailData
2076
- ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2077
- return __request(OpenAPI, {
2078
- method: 'GET',
2079
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2080
- path: {
2081
- ruleId: data.ruleId,
2082
- region: data.region
2083
- },
2084
- errors: {
2085
- 401: 'Unauthorized',
2086
- 403: 'Forbidden - not owner of rule',
2087
- 404: 'Rule not found'
2088
- }
2089
- });
2090
- }
2091
-
2092
- /**
2093
- * Update a transaction rule
2094
- * @param data The data for the request.
2095
- * @param data.ruleId Rule ID to update
2096
- * @param data.region Region code for tenant context
2097
- * @param data.requestBody
2098
- * @returns TransactionRuleResponseDto Rule updated successfully
2099
- * @throws ApiError
2100
- */
2101
- public static transactionRuleControllerUpdate(
2102
- data: TransactionRuleControllerUpdateData
2103
- ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2104
- return __request(OpenAPI, {
2105
- method: 'PUT',
2106
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2107
- path: {
2108
- ruleId: data.ruleId,
2109
- region: data.region
2110
- },
2111
- body: data.requestBody,
2112
- mediaType: 'application/json',
2113
- errors: {
2114
- 400: 'Validation failed',
2115
- 401: 'Unauthorized',
2116
- 403: 'Forbidden - not owner of rule',
2117
- 404: 'Rule not found',
2118
- 409: 'Resource conflict - rule is being modified by another process'
2119
- }
2120
- });
2121
- }
2122
-
2123
- /**
2124
- * Delete a transaction rule
2125
- * @param data The data for the request.
2126
- * @param data.ruleId Rule ID to delete
2127
- * @param data.region Region code for tenant context
2128
- * @returns void Rule deleted successfully
2129
- * @throws ApiError
2130
- */
2131
- public static transactionRuleControllerDelete(
2132
- data: TransactionRuleControllerDeleteData
2133
- ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2134
- return __request(OpenAPI, {
2135
- method: 'DELETE',
2136
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2137
- path: {
2138
- ruleId: data.ruleId,
2139
- region: data.region
2140
- },
2141
- errors: {
2142
- 401: 'Unauthorized',
2143
- 403: 'Forbidden - not owner of rule',
2144
- 404: 'Rule not found',
2145
- 409: 'Resource conflict - rule is being modified by another process'
2274
+ 400: 'Invalid date format',
2275
+ 401: 'User not authenticated'
2146
2276
  }
2147
2277
  });
2148
2278
  }
2149
2279
 
2150
2280
  /**
2151
- * Test rule matching
2281
+ * Backfill portfolio snapshots
2282
+ *
2283
+ * Generate snapshots for a date range (historical data backfill).
2284
+ *
2285
+ * **Multi-currency Support:**
2286
+ * - Each snapshot includes multi-currency data
2287
+ * - Uses exchange rates available at generation time
2288
+ * - Warnings stored for missing exchange rates
2289
+ *
2290
+ * **Best Practices:**
2291
+ * - Use for initial setup after account configuration
2292
+ * - Run during low-traffic periods for large date ranges
2293
+ * - Existing snapshots are skipped (not regenerated)
2294
+ *
2152
2295
  * @param data The data for the request.
2153
- * @param data.ruleId Rule ID to test
2154
2296
  * @param data.region Region code for tenant context
2155
2297
  * @param data.requestBody
2156
- * @returns TestRuleResponseDto Test result
2298
+ * @returns BackfillSnapshotsResponse Backfill completed successfully
2157
2299
  * @throws ApiError
2158
2300
  */
2159
- public static transactionRuleControllerTest(
2160
- data: TransactionRuleControllerTestData
2161
- ): CancelablePromise<TransactionRuleControllerTestResponse> {
2301
+ public static reportingControllerBackfillSnapshots(
2302
+ data: ReportingControllerBackfillSnapshotsData
2303
+ ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
2162
2304
  return __request(OpenAPI, {
2163
2305
  method: 'POST',
2164
- url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2306
+ url: '/api/v1/{region}/reporting/snapshots/backfill',
2165
2307
  path: {
2166
- ruleId: data.ruleId,
2167
2308
  region: data.region
2168
2309
  },
2169
2310
  body: data.requestBody,
2170
2311
  mediaType: 'application/json',
2171
2312
  errors: {
2172
- 401: 'Unauthorized',
2173
- 403: 'Forbidden - not owner of rule',
2174
- 404: 'Rule not found'
2313
+ 400: 'Invalid date format or range',
2314
+ 401: 'User not authenticated',
2315
+ 409: 'Backfill already in progress for this user'
2175
2316
  }
2176
2317
  });
2177
2318
  }
@@ -2223,7 +2364,7 @@ export class UsersService {
2223
2364
  * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
2224
2365
  * @param data The data for the request.
2225
2366
  * @param data.requestBody
2226
- * @returns unknown User created successfully
2367
+ * @returns SignupResponseDto User created successfully
2227
2368
  * @throws ApiError
2228
2369
  */
2229
2370
  public static userControllerSignupUser(
@@ -2432,921 +2573,1387 @@ export class PropertiesService {
2432
2573
  }
2433
2574
  }
2434
2575
 
2435
- export class BeanExportService {
2436
- /**
2437
- * Export Beancount ledger as ZIP
2438
- * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
2439
- * @returns unknown
2440
- * @throws ApiError
2441
- */
2442
- public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
2443
- return __request(OpenAPI, {
2444
- method: 'GET',
2445
- url: '/api/v1/{region}/bean/export/beancount'
2446
- });
2447
- }
2448
- }
2449
-
2450
- export class BeanImportService {
2576
+ export class BeanTransactionRulesService {
2451
2577
  /**
2452
- * Import a bill file
2453
- * Upload and process a bill file (CSV, PDF, OFX, etc.). The system automatically identifies the file type, extracts transactions, validates them, and stores only validated transactions to the database. Maximum file size: 50MB. Only 1 import per user at a time (concurrent imports rejected with 429).
2578
+ * Create a new transaction rule (or upsert if upsertByPayee=true)
2579
+ * Creates a new rule. If upsertByPayee=true, updates existing rule matching payeeKeywords[0] instead of creating duplicate.
2454
2580
  * @param data The data for the request.
2455
2581
  * @param data.region Region code for tenant context
2456
- * @param data.formData Bill file to import
2457
- * @returns ImportResultDto File imported successfully
2582
+ * @param data.requestBody
2583
+ * @returns TransactionRuleResponseDto Rule updated successfully (upsert mode)
2458
2584
  * @throws ApiError
2459
2585
  */
2460
- public static fileImportControllerImportFile(
2461
- data: FileImportControllerImportFileData
2462
- ): CancelablePromise<FileImportControllerImportFileResponse> {
2586
+ public static transactionRuleControllerCreate(
2587
+ data: TransactionRuleControllerCreateData
2588
+ ): CancelablePromise<TransactionRuleControllerCreateResponse> {
2463
2589
  return __request(OpenAPI, {
2464
2590
  method: 'POST',
2465
- url: '/api/v1/{region}/bean/import/file',
2591
+ url: '/api/v1/{region}/bean/transaction-rules',
2466
2592
  path: {
2467
2593
  region: data.region
2468
2594
  },
2469
- formData: data.formData,
2470
- mediaType: 'multipart/form-data',
2595
+ body: data.requestBody,
2596
+ mediaType: 'application/json',
2471
2597
  errors: {
2472
- 400: 'Bad request - file-format-unsupported or file-import-failed',
2473
- 413: 'Payload too large - file exceeds 50MB limit',
2474
- 429: 'Too many requests - user already has import in progress',
2475
- 500: 'Internal server error - DATABASE_ERROR'
2598
+ 400: 'Validation failed',
2599
+ 401: 'Unauthorized',
2600
+ 409: 'Resource conflict - another process is updating this rule'
2476
2601
  }
2477
2602
  });
2478
2603
  }
2479
2604
 
2480
2605
  /**
2481
- * Identify file type
2482
- * Upload a file to check if it can be processed by any registered importer. Does not perform actual import - useful for pre-validation. Uses user-specific importer configuration.
2606
+ * Get all transaction rules for user
2483
2607
  * @param data The data for the request.
2484
2608
  * @param data.region Region code for tenant context
2485
- * @param data.formData File to identify
2486
- * @returns IdentifyResultDto File identification result
2609
+ * @param data.limit Max results per page (default: 20, max: 100)
2610
+ * @param data.offset Pagination offset (default: 0)
2611
+ * @param data.enabled Filter by enabled status
2612
+ * @param data.learningSource Filter by learning source. Omit this parameter or pass empty string to get manually created rules (learningSource is null in database).
2613
+ * @param data.autoApplyEnabled Filter by auto-apply status
2614
+ * @returns TransactionRuleListResponseDto List of rules
2487
2615
  * @throws ApiError
2488
2616
  */
2489
- public static fileImportControllerIdentifyFile(
2490
- data: FileImportControllerIdentifyFileData
2491
- ): CancelablePromise<FileImportControllerIdentifyFileResponse> {
2617
+ public static transactionRuleControllerList(
2618
+ data: TransactionRuleControllerListData
2619
+ ): CancelablePromise<TransactionRuleControllerListResponse> {
2492
2620
  return __request(OpenAPI, {
2493
- method: 'POST',
2494
- url: '/api/v1/{region}/bean/import/identify',
2621
+ method: 'GET',
2622
+ url: '/api/v1/{region}/bean/transaction-rules',
2495
2623
  path: {
2496
2624
  region: data.region
2497
2625
  },
2498
- formData: data.formData,
2499
- mediaType: 'multipart/form-data',
2626
+ query: {
2627
+ limit: data.limit,
2628
+ offset: data.offset,
2629
+ enabled: data.enabled,
2630
+ learningSource: data.learningSource,
2631
+ autoApplyEnabled: data.autoApplyEnabled
2632
+ },
2500
2633
  errors: {
2501
- 400: 'Bad request - No file uploaded'
2634
+ 401: 'Unauthorized'
2502
2635
  }
2503
2636
  });
2504
2637
  }
2505
2638
 
2506
2639
  /**
2640
+ * Validate transaction rule configuration
2507
2641
  * @param data The data for the request.
2508
2642
  * @param data.region Region code for tenant context
2509
- * @returns unknown
2643
+ * @param data.requestBody
2644
+ * @returns ValidateRuleResponseDto Validation result
2510
2645
  * @throws ApiError
2511
2646
  */
2512
- public static fileImportControllerImportBeancount(
2513
- data: FileImportControllerImportBeancountData
2514
- ): CancelablePromise<FileImportControllerImportBeancountResponse> {
2647
+ public static transactionRuleControllerValidate(
2648
+ data: TransactionRuleControllerValidateData
2649
+ ): CancelablePromise<TransactionRuleControllerValidateResponse> {
2515
2650
  return __request(OpenAPI, {
2516
2651
  method: 'POST',
2517
- url: '/api/v1/{region}/bean/import/beancount',
2652
+ url: '/api/v1/{region}/bean/transaction-rules/validate',
2518
2653
  path: {
2519
2654
  region: data.region
2655
+ },
2656
+ body: data.requestBody,
2657
+ mediaType: 'application/json',
2658
+ errors: {
2659
+ 400: 'Validation failed',
2660
+ 401: 'Unauthorized'
2520
2661
  }
2521
2662
  });
2522
2663
  }
2523
2664
 
2524
2665
  /**
2525
- * Get importer configuration
2526
- * Returns the current configuration for the specified importer. Creates default configuration if none exists.
2666
+ * Bulk create transaction rules
2527
2667
  * @param data The data for the request.
2528
- * @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
2529
2668
  * @param data.region Region code for tenant context
2530
- * @returns ImporterConfigDto Configuration retrieved successfully
2669
+ * @param data.requestBody
2670
+ * @returns BulkCreateRulesResponseDto Bulk create completed
2531
2671
  * @throws ApiError
2532
2672
  */
2533
- public static importerConfigControllerGetConfig(
2534
- data: ImporterConfigControllerGetConfigData
2535
- ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
2673
+ public static transactionRuleControllerBulkCreate(
2674
+ data: TransactionRuleControllerBulkCreateData
2675
+ ): CancelablePromise<TransactionRuleControllerBulkCreateResponse> {
2536
2676
  return __request(OpenAPI, {
2537
- method: 'GET',
2538
- url: '/api/v1/{region}/bean/import/config/{importerId}',
2677
+ method: 'POST',
2678
+ url: '/api/v1/{region}/bean/transaction-rules/bulk',
2539
2679
  path: {
2540
- importerId: data.importerId,
2541
2680
  region: data.region
2542
2681
  },
2682
+ body: data.requestBody,
2683
+ mediaType: 'application/json',
2543
2684
  errors: {
2544
- 400: 'Invalid input - Unsupported importer',
2545
- 401: 'Unauthorized - Authentication required'
2685
+ 400: 'Invalid bulk create data',
2686
+ 401: 'Unauthorized'
2546
2687
  }
2547
2688
  });
2548
2689
  }
2549
2690
 
2550
2691
  /**
2551
- * Update importer configuration
2552
- * Updates the configuration for the specified importer. Partial updates are supported.
2692
+ * Export transaction rules
2553
2693
  * @param data The data for the request.
2554
- * @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
2694
+ * @param data.format Export format (currently only JSON supported)
2555
2695
  * @param data.region Region code for tenant context
2556
- * @param data.requestBody Partial configuration update. Only provided fields will be updated.
2557
- * @returns ImporterConfigDto Configuration updated successfully
2696
+ * @returns ExportRulesResponseDto Exported rules
2558
2697
  * @throws ApiError
2559
2698
  */
2560
- public static importerConfigControllerUpdateConfig(
2561
- data: ImporterConfigControllerUpdateConfigData
2562
- ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
2699
+ public static transactionRuleControllerExport(
2700
+ data: TransactionRuleControllerExportData
2701
+ ): CancelablePromise<TransactionRuleControllerExportResponse> {
2563
2702
  return __request(OpenAPI, {
2564
- method: 'PUT',
2565
- url: '/api/v1/{region}/bean/import/config/{importerId}',
2703
+ method: 'GET',
2704
+ url: '/api/v1/{region}/bean/transaction-rules/export/{format}',
2566
2705
  path: {
2567
- importerId: data.importerId,
2706
+ format: data.format,
2568
2707
  region: data.region
2569
2708
  },
2570
- body: data.requestBody,
2571
- mediaType: 'application/json',
2572
2709
  errors: {
2573
- 400: 'Invalid input - Validation failed',
2574
- 404: 'Configuration not found'
2710
+ 400: 'Unsupported format',
2711
+ 401: 'Unauthorized'
2575
2712
  }
2576
2713
  });
2577
2714
  }
2578
2715
 
2579
2716
  /**
2580
- * Reset configuration to default
2581
- * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
2717
+ * Get transaction rule statistics
2582
2718
  * @param data The data for the request.
2583
- * @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
2719
+ * @param data.period Statistics time period
2584
2720
  * @param data.region Region code for tenant context
2585
- * @returns ImporterConfigDto Configuration reset successfully
2721
+ * @returns RuleStatisticsResponseDto Rule statistics
2586
2722
  * @throws ApiError
2587
2723
  */
2588
- public static importerConfigControllerResetConfig(
2589
- data: ImporterConfigControllerResetConfigData
2590
- ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
2724
+ public static transactionRuleControllerGetStatistics(
2725
+ data: TransactionRuleControllerGetStatisticsData
2726
+ ): CancelablePromise<TransactionRuleControllerGetStatisticsResponse> {
2591
2727
  return __request(OpenAPI, {
2592
- method: 'POST',
2593
- url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
2728
+ method: 'GET',
2729
+ url: '/api/v1/{region}/bean/transaction-rules/statistics/{period}',
2594
2730
  path: {
2595
- importerId: data.importerId,
2731
+ period: data.period,
2596
2732
  region: data.region
2597
2733
  },
2598
2734
  errors: {
2599
- 400: 'Invalid input - Unsupported importer'
2735
+ 401: 'Unauthorized'
2600
2736
  }
2601
2737
  });
2602
2738
  }
2603
- }
2604
2739
 
2605
- export class BeanPlatformsService {
2606
2740
  /**
2607
- * Get all platforms with statistics
2608
- * @returns unknown List of platforms with binding and account counts
2741
+ * Get transaction rule detail
2742
+ * @param data The data for the request.
2743
+ * @param data.ruleId Rule ID
2744
+ * @param data.region Region code for tenant context
2745
+ * @returns TransactionRuleResponseDto Rule details
2609
2746
  * @throws ApiError
2610
2747
  */
2611
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2748
+ public static transactionRuleControllerGetDetail(
2749
+ data: TransactionRuleControllerGetDetailData
2750
+ ): CancelablePromise<TransactionRuleControllerGetDetailResponse> {
2612
2751
  return __request(OpenAPI, {
2613
2752
  method: 'GET',
2614
- url: '/api/v1/bean/platforms'
2753
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2754
+ path: {
2755
+ ruleId: data.ruleId,
2756
+ region: data.region
2757
+ },
2758
+ errors: {
2759
+ 401: 'Unauthorized',
2760
+ 403: 'Forbidden - not owner of rule',
2761
+ 404: 'Rule not found'
2762
+ }
2615
2763
  });
2616
2764
  }
2617
2765
 
2618
2766
  /**
2619
- * Create a new platform
2767
+ * Update a transaction rule
2620
2768
  * @param data The data for the request.
2769
+ * @param data.ruleId Rule ID to update
2770
+ * @param data.region Region code for tenant context
2621
2771
  * @param data.requestBody
2622
- * @returns unknown Platform created successfully
2772
+ * @returns TransactionRuleResponseDto Rule updated successfully
2623
2773
  * @throws ApiError
2624
2774
  */
2625
- public static platformControllerCreate(
2626
- data: PlatformControllerCreateData
2627
- ): CancelablePromise<PlatformControllerCreateResponse> {
2775
+ public static transactionRuleControllerUpdate(
2776
+ data: TransactionRuleControllerUpdateData
2777
+ ): CancelablePromise<TransactionRuleControllerUpdateResponse> {
2628
2778
  return __request(OpenAPI, {
2629
- method: 'POST',
2630
- url: '/api/v1/bean/platforms',
2779
+ method: 'PUT',
2780
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2781
+ path: {
2782
+ ruleId: data.ruleId,
2783
+ region: data.region
2784
+ },
2631
2785
  body: data.requestBody,
2632
2786
  mediaType: 'application/json',
2633
2787
  errors: {
2634
- 409: 'Platform already exists'
2788
+ 400: 'Validation failed',
2789
+ 401: 'Unauthorized',
2790
+ 403: 'Forbidden - not owner of rule',
2791
+ 404: 'Rule not found',
2792
+ 409: 'Resource conflict - rule is being modified by another process'
2635
2793
  }
2636
2794
  });
2637
2795
  }
2638
2796
 
2639
2797
  /**
2640
- * Get platform list for current user
2641
- * @returns unknown List of platforms with user binding status
2798
+ * Delete a transaction rule
2799
+ * @param data The data for the request.
2800
+ * @param data.ruleId Rule ID to delete
2801
+ * @param data.region Region code for tenant context
2802
+ * @returns void Rule deleted successfully
2642
2803
  * @throws ApiError
2643
2804
  */
2644
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
2805
+ public static transactionRuleControllerDelete(
2806
+ data: TransactionRuleControllerDeleteData
2807
+ ): CancelablePromise<TransactionRuleControllerDeleteResponse> {
2645
2808
  return __request(OpenAPI, {
2646
- method: 'GET',
2647
- url: '/api/v1/bean/platforms/list'
2809
+ method: 'DELETE',
2810
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}',
2811
+ path: {
2812
+ ruleId: data.ruleId,
2813
+ region: data.region
2814
+ },
2815
+ errors: {
2816
+ 401: 'Unauthorized',
2817
+ 403: 'Forbidden - not owner of rule',
2818
+ 404: 'Rule not found',
2819
+ 409: 'Resource conflict - rule is being modified by another process'
2820
+ }
2648
2821
  });
2649
2822
  }
2650
2823
 
2651
2824
  /**
2652
- * Match platforms by name or alias
2825
+ * Test rule matching
2653
2826
  * @param data The data for the request.
2654
- * @param data.q Search query — Chinese name, English name, or abbreviation
2655
- * @param data.region Region code for category override lookup
2656
- * @returns unknown List of matching platforms with suggested segment names
2827
+ * @param data.ruleId Rule ID to test
2828
+ * @param data.region Region code for tenant context
2829
+ * @param data.requestBody
2830
+ * @returns TestRuleResponseDto Test result
2657
2831
  * @throws ApiError
2658
2832
  */
2659
- public static platformControllerMatchPlatforms(
2660
- data: PlatformControllerMatchPlatformsData
2661
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
2833
+ public static transactionRuleControllerTest(
2834
+ data: TransactionRuleControllerTestData
2835
+ ): CancelablePromise<TransactionRuleControllerTestResponse> {
2662
2836
  return __request(OpenAPI, {
2663
- method: 'GET',
2664
- url: '/api/v1/bean/platforms/match',
2665
- query: {
2666
- q: data.q,
2837
+ method: 'POST',
2838
+ url: '/api/v1/{region}/bean/transaction-rules/{ruleId}/test',
2839
+ path: {
2840
+ ruleId: data.ruleId,
2667
2841
  region: data.region
2842
+ },
2843
+ body: data.requestBody,
2844
+ mediaType: 'application/json',
2845
+ errors: {
2846
+ 401: 'Unauthorized',
2847
+ 403: 'Forbidden - not owner of rule',
2848
+ 404: 'Rule not found'
2668
2849
  }
2669
2850
  });
2670
2851
  }
2852
+ }
2671
2853
 
2854
+ export class LifeEventsService {
2672
2855
  /**
2673
- * Update a platform
2856
+ * Create a new life event
2857
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2674
2858
  * @param data The data for the request.
2675
- * @param data.id Platform ID
2859
+ * @param data.region Region code for tenant context (decorative for life events)
2676
2860
  * @param data.requestBody
2677
- * @returns unknown Platform updated successfully
2861
+ * @returns EventResponseDto Life event created successfully
2678
2862
  * @throws ApiError
2679
2863
  */
2680
- public static platformControllerUpdate(
2681
- data: PlatformControllerUpdateData
2682
- ): CancelablePromise<PlatformControllerUpdateResponse> {
2864
+ public static eventControllerCreate(
2865
+ data: EventControllerCreateData
2866
+ ): CancelablePromise<EventControllerCreateResponse> {
2683
2867
  return __request(OpenAPI, {
2684
- method: 'PUT',
2685
- url: '/api/v1/bean/platforms/{id}',
2868
+ method: 'POST',
2869
+ url: '/api/v1/{region}/bean/events',
2686
2870
  path: {
2687
- id: data.id
2871
+ region: data.region
2688
2872
  },
2689
2873
  body: data.requestBody,
2690
2874
  mediaType: 'application/json',
2691
2875
  errors: {
2692
- 404: 'Platform not found'
2876
+ 409: 'Life event already exists for this (userId, type, date) combination'
2693
2877
  }
2694
2878
  });
2695
2879
  }
2696
2880
 
2697
2881
  /**
2698
- * Delete a platform
2882
+ * List user life events
2883
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2699
2884
  * @param data The data for the request.
2700
- * @param data.id Platform ID
2701
- * @returns void Platform deleted successfully
2885
+ * @param data.region Region code for tenant context (decorative for life events)
2886
+ * @param data.type Filter by life event type (exact match)
2887
+ * @param data.q Search term for description (case-insensitive partial match)
2888
+ * @param data.from Filter life events from this date (ISO 8601 format)
2889
+ * @param data.to Filter life events to this date (ISO 8601 format)
2890
+ * @param data.page Page number for pagination (default: 1)
2891
+ * @param data.limit Number of items per page (default: 20, max: 100)
2892
+ * @returns EventListResponseDto Life events retrieved successfully
2702
2893
  * @throws ApiError
2703
2894
  */
2704
- public static platformControllerDelete(
2705
- data: PlatformControllerDeleteData
2706
- ): CancelablePromise<PlatformControllerDeleteResponse> {
2895
+ public static eventControllerFindAll(
2896
+ data: EventControllerFindAllData
2897
+ ): CancelablePromise<EventControllerFindAllResponse> {
2707
2898
  return __request(OpenAPI, {
2708
- method: 'DELETE',
2709
- url: '/api/v1/bean/platforms/{id}',
2899
+ method: 'GET',
2900
+ url: '/api/v1/{region}/bean/events',
2710
2901
  path: {
2711
- id: data.id
2902
+ region: data.region
2712
2903
  },
2713
- errors: {
2714
- 404: 'Platform not found'
2904
+ query: {
2905
+ type: data.type,
2906
+ q: data.q,
2907
+ from: data.from,
2908
+ to: data.to,
2909
+ page: data.page,
2910
+ limit: data.limit
2715
2911
  }
2716
2912
  });
2717
2913
  }
2718
- }
2719
2914
 
2720
- export class ProviderSyncService {
2721
2915
  /**
2916
+ * Get life event by ID
2917
+ * Returns a single life event by its ID. Returns ETag header.
2722
2918
  * @param data The data for the request.
2723
- * @param data.providerName
2724
- * @param data.region Region code for tenant context
2725
- * @param data.requestBody
2726
- * @returns unknown
2919
+ * @param data.id Life event ID
2920
+ * @param data.region Region code for tenant context (decorative for life events)
2921
+ * @returns EventResponseDto Life event retrieved successfully
2727
2922
  * @throws ApiError
2728
2923
  */
2729
- public static providerSyncControllerSync(
2730
- data: ProviderSyncControllerSyncData
2731
- ): CancelablePromise<ProviderSyncControllerSyncResponse> {
2924
+ public static eventControllerFindOne(
2925
+ data: EventControllerFindOneData
2926
+ ): CancelablePromise<EventControllerFindOneResponse> {
2732
2927
  return __request(OpenAPI, {
2733
- method: 'POST',
2734
- url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
2928
+ method: 'GET',
2929
+ url: '/api/v1/{region}/bean/events/{id}',
2735
2930
  path: {
2736
- providerName: data.providerName,
2931
+ id: data.id,
2737
2932
  region: data.region
2738
2933
  },
2739
- body: data.requestBody,
2740
- mediaType: 'application/json'
2934
+ errors: {
2935
+ 404: 'Life event not found'
2936
+ }
2741
2937
  });
2742
2938
  }
2743
2939
 
2744
2940
  /**
2745
- * Get supported providers
2746
- * Returns a list of all providers supported by the sync endpoint.
2941
+ * Update a life event
2942
+ * Updates an existing life event. If If-Match header is provided, performs optimistic concurrency check; mismatched updatedAt returns 412.
2747
2943
  * @param data The data for the request.
2748
- * @param data.region Region code for tenant context
2749
- * @returns SupportedProvidersResponseDto List of supported providers
2944
+ * @param data.id Life event ID
2945
+ * @param data.region Region code for tenant context (decorative for life events)
2946
+ * @param data.requestBody
2947
+ * @returns EventResponseDto Life event updated successfully
2750
2948
  * @throws ApiError
2751
2949
  */
2752
- public static providerSyncControllerGetSupportedProviders(
2753
- data: ProviderSyncControllerGetSupportedProvidersData
2754
- ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
2950
+ public static eventControllerUpdate(
2951
+ data: EventControllerUpdateData
2952
+ ): CancelablePromise<EventControllerUpdateResponse> {
2755
2953
  return __request(OpenAPI, {
2756
- method: 'GET',
2757
- url: '/api/v1/{region}/bean/import/provider/supported',
2954
+ method: 'PUT',
2955
+ url: '/api/v1/{region}/bean/events/{id}',
2758
2956
  path: {
2957
+ id: data.id,
2759
2958
  region: data.region
2760
2959
  },
2960
+ body: data.requestBody,
2961
+ mediaType: 'application/json',
2761
2962
  errors: {
2762
- 401: 'Missing or invalid authentication'
2963
+ 400: 'If-Match header is not a valid ISO 8601 date',
2964
+ 404: 'Life event not found',
2965
+ 409: 'Updated event conflicts with an existing (userId, type, date) combination',
2966
+ 412: 'If-Match precondition failed (updatedAt mismatch)'
2763
2967
  }
2764
2968
  });
2765
2969
  }
2766
2970
 
2767
2971
  /**
2768
- * Check if provider is supported
2769
- * Returns whether a specific provider is supported.
2972
+ * Delete a life event
2973
+ * Deletes a life event entry (hard delete). Returns 204.
2770
2974
  * @param data The data for the request.
2771
- * @param data.providerName Provider name to check
2772
- * @param data.region Region code for tenant context
2773
- * @returns unknown Provider support status
2975
+ * @param data.id Life event ID
2976
+ * @param data.region Region code for tenant context (decorative for life events)
2977
+ * @returns void Life event deleted successfully
2774
2978
  * @throws ApiError
2775
2979
  */
2776
- public static providerSyncControllerIsProviderSupported(
2777
- data: ProviderSyncControllerIsProviderSupportedData
2778
- ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
2980
+ public static eventControllerDelete(
2981
+ data: EventControllerDeleteData
2982
+ ): CancelablePromise<EventControllerDeleteResponse> {
2779
2983
  return __request(OpenAPI, {
2780
- method: 'GET',
2781
- url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
2984
+ method: 'DELETE',
2985
+ url: '/api/v1/{region}/bean/events/{id}',
2782
2986
  path: {
2783
- providerName: data.providerName,
2987
+ id: data.id,
2784
2988
  region: data.region
2785
2989
  },
2786
2990
  errors: {
2787
- 401: 'Missing or invalid authentication'
2991
+ 404: 'Life event not found'
2788
2992
  }
2789
2993
  });
2790
2994
  }
2791
- }
2792
2995
 
2793
- export class ImportTelemetryService {
2794
2996
  /**
2795
- * Receive anonymous parser failure telemetry
2997
+ * Slice time-series by a life event (Phase 79)
2998
+ * Returns aggregated time-series for postings matching accountPattern within the half-open date range of the given life event.
2796
2999
  * @param data The data for the request.
2797
- * @param data.region Region code for tenant context
2798
- * @param data.requestBody
2799
- * @returns unknown Telemetry report received
3000
+ * @param data.id Life event ID
3001
+ * @param data.accountPattern
3002
+ * @param data.granularity
3003
+ * @param data.region Region code for tenant context (decorative for life events)
3004
+ * @returns unknown Time-series sliced by the life event range
2800
3005
  * @throws ApiError
2801
3006
  */
2802
- public static telemetryControllerReportTelemetry(
2803
- data: TelemetryControllerReportTelemetryData
2804
- ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
3007
+ public static eventControllerGetSlice(
3008
+ data: EventControllerGetSliceData
3009
+ ): CancelablePromise<EventControllerGetSliceResponse> {
2805
3010
  return __request(OpenAPI, {
2806
- method: 'POST',
2807
- url: '/api/v1/{region}/bean/import/parser-telemetry',
3011
+ method: 'GET',
3012
+ url: '/api/v1/{region}/bean/events/{id}/slice',
2808
3013
  path: {
3014
+ id: data.id,
2809
3015
  region: data.region
2810
3016
  },
2811
- body: data.requestBody,
2812
- mediaType: 'application/json',
3017
+ query: {
3018
+ accountPattern: data.accountPattern,
3019
+ granularity: data.granularity
3020
+ },
2813
3021
  errors: {
2814
- 401: 'Unauthorized'
3022
+ 400: 'accountPattern query param is empty',
3023
+ 404: 'Life event not found'
2815
3024
  }
2816
3025
  });
2817
3026
  }
3027
+ }
2818
3028
 
3029
+ export class OnboardingService {
2819
3030
  /**
2820
- * Receive anonymous zero-hit coverage miss report
3031
+ * Bootstrap core accounts + register asset accounts with opening balances (ADR-0113)
2821
3032
  * @param data The data for the request.
2822
3033
  * @param data.region Region code for tenant context
2823
3034
  * @param data.requestBody
2824
- * @returns unknown Coverage miss report received
3035
+ * @returns unknown Onboarding bootstrap result.
2825
3036
  * @throws ApiError
2826
3037
  */
2827
- public static telemetryControllerReportCoverageMiss(
2828
- data: TelemetryControllerReportCoverageMissData
2829
- ): CancelablePromise<TelemetryControllerReportCoverageMissResponse> {
3038
+ public static onboardingControllerBootstrap(
3039
+ data: OnboardingControllerBootstrapData
3040
+ ): CancelablePromise<OnboardingControllerBootstrapResponse> {
2830
3041
  return __request(OpenAPI, {
2831
3042
  method: 'POST',
2832
- url: '/api/v1/{region}/bean/import/parser-coverage-miss',
3043
+ url: '/api/v1/{region}/bean/onboarding',
2833
3044
  path: {
2834
3045
  region: data.region
2835
3046
  },
2836
3047
  body: data.requestBody,
2837
3048
  mediaType: 'application/json',
2838
3049
  errors: {
2839
- 401: 'Unauthorized'
3050
+ 422: 'Invalid region/account path/duplicate paths.'
2840
3051
  }
2841
3052
  });
2842
3053
  }
3054
+ }
2843
3055
 
3056
+ export class BalanceReconciliationService {
2844
3057
  /**
2845
- * Coverage metrics (uncovered format aggregation)
3058
+ * Preview reconciliation (book vs actual)
3059
+ * Computes book balance, diff, Beancount-inferred tolerance, and suggested action without persisting.
2846
3060
  * @param data The data for the request.
2847
- * @param data.region Region code for tenant context
2848
- * @param data.topN Top-N uncovered formats (default 10)
2849
- * @returns unknown Coverage metrics
3061
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3062
+ * @param data.requestBody
3063
+ * @returns ReconciliationComputeResultDto Reconciliation preview
2850
3064
  * @throws ApiError
2851
3065
  */
2852
- public static telemetryControllerGetCoverageMetrics(
2853
- data: TelemetryControllerGetCoverageMetricsData
2854
- ): CancelablePromise<TelemetryControllerGetCoverageMetricsResponse> {
3066
+ public static reconciliationControllerCompute(
3067
+ data: ReconciliationControllerComputeData
3068
+ ): CancelablePromise<ReconciliationControllerComputeResponse> {
2855
3069
  return __request(OpenAPI, {
2856
- method: 'GET',
2857
- url: '/api/v1/{region}/bean/import/parser-coverage-metrics',
3070
+ method: 'POST',
3071
+ url: '/api/v1/{region}/bean/reconciliations',
2858
3072
  path: {
2859
3073
  region: data.region
2860
3074
  },
2861
- query: {
2862
- topN: data.topN
3075
+ body: data.requestBody,
3076
+ mediaType: 'application/json',
3077
+ errors: {
3078
+ 404: 'Account not found'
2863
3079
  }
2864
3080
  });
2865
3081
  }
2866
- }
2867
3082
 
2868
- export class BeanNlpService {
2869
3083
  /**
3084
+ * Record a balance assertion
3085
+ * Persists the reconciliation as a BeanBalance assertion (amount = actual, diffAmount = book − actual). Re-reconciling the same day/currency upserts.
2870
3086
  * @param data The data for the request.
2871
- * @param data.region Region code for tenant context
3087
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2872
3088
  * @param data.requestBody
2873
- * @returns unknown
3089
+ * @returns ReconciliationRecordDto Balance assertion recorded
2874
3090
  * @throws ApiError
2875
3091
  */
2876
- public static nlpControllerProcessNaturalLanguage(
2877
- data: NlpControllerProcessNaturalLanguageData
2878
- ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
3092
+ public static reconciliationControllerAssert(
3093
+ data: ReconciliationControllerAssertData
3094
+ ): CancelablePromise<ReconciliationControllerAssertResponse> {
2879
3095
  return __request(OpenAPI, {
2880
3096
  method: 'POST',
2881
- url: '/api/v1/{region}/bean/nlp/process',
3097
+ url: '/api/v1/{region}/bean/reconciliations/assert',
2882
3098
  path: {
2883
3099
  region: data.region
2884
3100
  },
2885
3101
  body: data.requestBody,
2886
- mediaType: 'application/json'
3102
+ mediaType: 'application/json',
3103
+ errors: {
3104
+ 404: 'Account not found'
3105
+ }
2887
3106
  });
2888
3107
  }
2889
3108
 
2890
3109
  /**
2891
- * Clear dialogue session
2892
- * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
3110
+ * Generate a pad adjusting entry
3111
+ * 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.
2893
3112
  * @param data The data for the request.
2894
- * @param data.region Region code for tenant context
2895
- * @param data.sessionId Specific session ID to clear (defaults to user session)
2896
- * @returns void Session cleared successfully
3113
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3114
+ * @param data.requestBody
3115
+ * @returns PadResultDto Pad adjusting entry generated
2897
3116
  * @throws ApiError
2898
3117
  */
2899
- public static nlpControllerClearSession(
2900
- data: NlpControllerClearSessionData
2901
- ): CancelablePromise<NlpControllerClearSessionResponse> {
3118
+ public static reconciliationControllerPad(
3119
+ data: ReconciliationControllerPadData
3120
+ ): CancelablePromise<ReconciliationControllerPadResponse> {
2902
3121
  return __request(OpenAPI, {
2903
- method: 'DELETE',
2904
- url: '/api/v1/{region}/bean/nlp/session',
3122
+ method: 'POST',
3123
+ url: '/api/v1/{region}/bean/reconciliations/pad',
2905
3124
  path: {
2906
3125
  region: data.region
2907
3126
  },
2908
- query: {
2909
- sessionId: data.sessionId
2910
- },
3127
+ body: data.requestBody,
3128
+ mediaType: 'application/json',
2911
3129
  errors: {
2912
- 401: 'Unauthorized'
3130
+ 400: 'Book already within tolerance — no pad needed',
3131
+ 404: 'Account not found'
2913
3132
  }
2914
3133
  });
2915
3134
  }
2916
3135
 
2917
3136
  /**
2918
- * Get current session state
2919
- * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
3137
+ * List reconciliation history for an account
3138
+ * Returns recorded balance assertions (most recent first). The latest drives the account-detail "Last <date>" badge.
2920
3139
  * @param data The data for the request.
2921
- * @param data.region Region code for tenant context
2922
- * @param data.sessionId Specific session ID to get (defaults to user session)
2923
- * @returns unknown Current session state (or null if no active session)
3140
+ * @param data.accountId BeanAccount id
3141
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3142
+ * @returns ReconciliationRecordDto Reconciliation history
2924
3143
  * @throws ApiError
2925
3144
  */
2926
- public static nlpControllerGetSession(
2927
- data: NlpControllerGetSessionData
2928
- ): CancelablePromise<NlpControllerGetSessionResponse> {
3145
+ public static reconciliationControllerHistory(
3146
+ data: ReconciliationControllerHistoryData
3147
+ ): CancelablePromise<ReconciliationControllerHistoryResponse> {
2929
3148
  return __request(OpenAPI, {
2930
3149
  method: 'GET',
2931
- url: '/api/v1/{region}/bean/nlp/session',
3150
+ url: '/api/v1/{region}/bean/accounts/{accountId}/reconciliations',
2932
3151
  path: {
3152
+ accountId: data.accountId,
2933
3153
  region: data.region
2934
3154
  },
2935
- query: {
2936
- sessionId: data.sessionId
2937
- },
2938
3155
  errors: {
2939
- 401: 'Unauthorized'
3156
+ 404: 'Account not found'
2940
3157
  }
2941
3158
  });
2942
3159
  }
2943
3160
  }
2944
3161
 
2945
- export class DashboardService {
3162
+ export class BeanExportService {
2946
3163
  /**
2947
- * Get net worth overview
2948
- * Returns total net worth with breakdown of assets and liabilities
3164
+ * Export Beancount ledger as ZIP
3165
+ * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
3166
+ * @returns unknown
3167
+ * @throws ApiError
3168
+ */
3169
+ public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
3170
+ return __request(OpenAPI, {
3171
+ method: 'GET',
3172
+ url: '/api/v1/{region}/bean/export/beancount'
3173
+ });
3174
+ }
3175
+ }
3176
+
3177
+ export class BeanImportService {
3178
+ /**
3179
+ * Import a bill file
3180
+ * Upload and process a bill file (CSV, PDF, OFX, etc.). The system automatically identifies the file type, extracts transactions, validates them, and stores only validated transactions to the database. Maximum file size: 50MB. Only 1 import per user at a time (concurrent imports rejected with 429).
2949
3181
  * @param data The data for the request.
2950
3182
  * @param data.region Region code for tenant context
2951
- * @param data.date Date for balance calculation (ISO 8601 format)
2952
- * @returns NetWorthResponseDto Net worth retrieved successfully
3183
+ * @param data.formData Bill file to import
3184
+ * @returns ImportResultDto File imported successfully
2953
3185
  * @throws ApiError
2954
3186
  */
2955
- public static dashboardControllerGetNetWorth(
2956
- data: DashboardControllerGetNetWorthData
2957
- ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3187
+ public static fileImportControllerImportFile(
3188
+ data: FileImportControllerImportFileData
3189
+ ): CancelablePromise<FileImportControllerImportFileResponse> {
2958
3190
  return __request(OpenAPI, {
2959
- method: 'GET',
2960
- url: '/api/v1/{region}/dashboard/net-worth',
3191
+ method: 'POST',
3192
+ url: '/api/v1/{region}/bean/import/file',
2961
3193
  path: {
2962
3194
  region: data.region
2963
3195
  },
2964
- query: {
2965
- date: data.date
2966
- },
3196
+ formData: data.formData,
3197
+ mediaType: 'multipart/form-data',
2967
3198
  errors: {
2968
- 401: 'User not authenticated'
3199
+ 400: 'Bad request - file-format-unsupported or file-import-failed',
3200
+ 413: 'Payload too large - file exceeds 50MB limit',
3201
+ 429: 'Too many requests - user already has import in progress',
3202
+ 500: 'Internal server error - DATABASE_ERROR'
2969
3203
  }
2970
3204
  });
2971
3205
  }
2972
3206
 
2973
3207
  /**
2974
- * Get accounts grouped by platform
2975
- * Returns accounts with balances grouped by financial platform
3208
+ * Identify file type
3209
+ * Upload a file to check if it can be processed by any registered importer. Does not perform actual import - useful for pre-validation. Uses user-specific importer configuration.
2976
3210
  * @param data The data for the request.
2977
3211
  * @param data.region Region code for tenant context
2978
- * @param data.groupBy Grouping strategy
2979
- * @param data.date Date for balance calculation (ISO 8601 format)
2980
- * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
2981
- * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
3212
+ * @param data.formData File to identify
3213
+ * @returns IdentifyResultDto File identification result
2982
3214
  * @throws ApiError
2983
3215
  */
2984
- public static dashboardControllerGetAccounts(
2985
- data: DashboardControllerGetAccountsData
2986
- ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3216
+ public static fileImportControllerIdentifyFile(
3217
+ data: FileImportControllerIdentifyFileData
3218
+ ): CancelablePromise<FileImportControllerIdentifyFileResponse> {
2987
3219
  return __request(OpenAPI, {
2988
- method: 'GET',
2989
- url: '/api/v1/{region}/dashboard/accounts',
3220
+ method: 'POST',
3221
+ url: '/api/v1/{region}/bean/import/identify',
2990
3222
  path: {
2991
3223
  region: data.region
2992
3224
  },
2993
- query: {
2994
- groupBy: data.groupBy,
2995
- date: data.date,
2996
- accountId: data.accountId
2997
- },
3225
+ formData: data.formData,
3226
+ mediaType: 'multipart/form-data',
2998
3227
  errors: {
2999
- 401: 'User not authenticated'
3228
+ 400: 'Bad request - No file uploaded'
3000
3229
  }
3001
3230
  });
3002
3231
  }
3003
3232
 
3004
3233
  /**
3005
- * Get cash flow summary
3006
- * Returns income, expenses, and savings for a monthly period
3234
+ * Import a Beancount file in community format
3235
+ * Upload a .beancount file to import. The system parses community-format paths, converts to internal format using category metadata, auto-creates accounts, and imports transactions with deduplication. Maximum file size: 50MB. Only 1 import per user at a time.
3007
3236
  * @param data The data for the request.
3008
- * @param data.period Period in YYYY-MM format
3009
3237
  * @param data.region Region code for tenant context
3010
- * @returns CashFlowResponseDto Cash flow retrieved successfully
3238
+ * @param data.formData Beancount file to import
3239
+ * @returns unknown Beancount file imported successfully
3011
3240
  * @throws ApiError
3012
3241
  */
3013
- public static dashboardControllerGetCashFlow(
3014
- data: DashboardControllerGetCashFlowData
3015
- ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3242
+ public static fileImportControllerImportBeancount(
3243
+ data: FileImportControllerImportBeancountData
3244
+ ): CancelablePromise<FileImportControllerImportBeancountResponse> {
3016
3245
  return __request(OpenAPI, {
3017
- method: 'GET',
3018
- url: '/api/v1/{region}/dashboard/cash-flow',
3246
+ method: 'POST',
3247
+ url: '/api/v1/{region}/bean/import/beancount',
3019
3248
  path: {
3020
3249
  region: data.region
3021
3250
  },
3022
- query: {
3023
- period: data.period
3024
- },
3251
+ formData: data.formData,
3252
+ mediaType: 'multipart/form-data',
3025
3253
  errors: {
3026
- 400: 'Invalid period format',
3027
- 401: 'User not authenticated'
3254
+ 400: 'Bad request - invalid file or no file uploaded'
3028
3255
  }
3029
3256
  });
3030
3257
  }
3031
- }
3032
3258
 
3033
- export class InvestmentService {
3034
3259
  /**
3035
- * Get per-holding unrealized + realized P&L
3036
- * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3260
+ * Get importer configuration
3261
+ * Returns the current configuration for the specified importer. Creates default configuration if none exists.
3037
3262
  * @param data The data for the request.
3263
+ * @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
3038
3264
  * @param data.region Region code for tenant context
3039
- * @param data.asOf As-of date (ISO 8601), defaults to today
3040
- * @param data.accountId Scope to a single account
3041
- * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
3042
- * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3265
+ * @returns ImporterConfigDto Configuration retrieved successfully
3043
3266
  * @throws ApiError
3044
3267
  */
3045
- public static holdingPnlControllerGetHoldingPnl(
3046
- data: HoldingPnlControllerGetHoldingPnlData
3047
- ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3268
+ public static importerConfigControllerGetConfig(
3269
+ data: ImporterConfigControllerGetConfigData
3270
+ ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
3048
3271
  return __request(OpenAPI, {
3049
3272
  method: 'GET',
3050
- url: '/api/v1/{region}/investment/holdings/pnl',
3273
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
3051
3274
  path: {
3275
+ importerId: data.importerId,
3052
3276
  region: data.region
3053
3277
  },
3054
- query: {
3055
- asOf: data.asOf,
3056
- accountId: data.accountId,
3057
- method: data.method
3058
- },
3059
3278
  errors: {
3060
- 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3061
- 401: 'User not authenticated'
3279
+ 400: 'Invalid input - Unsupported importer',
3280
+ 401: 'Unauthorized - Authentication required'
3062
3281
  }
3063
3282
  });
3064
3283
  }
3065
- }
3066
3284
 
3067
- export class BeanPricesService {
3068
3285
  /**
3069
- * Create a new price
3070
- * Creates a new price entry for the authenticated user
3286
+ * Update importer configuration
3287
+ * Updates the configuration for the specified importer. Partial updates are supported.
3071
3288
  * @param data The data for the request.
3289
+ * @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
3072
3290
  * @param data.region Region code for tenant context
3073
- * @param data.requestBody
3074
- * @returns PriceResponseDto Price created successfully
3291
+ * @param data.requestBody Partial configuration update. Only provided fields will be updated.
3292
+ * @returns ImporterConfigDto Configuration updated successfully
3075
3293
  * @throws ApiError
3076
3294
  */
3077
- public static priceControllerCreate(
3078
- data: PriceControllerCreateData
3079
- ): CancelablePromise<PriceControllerCreateResponse> {
3295
+ public static importerConfigControllerUpdateConfig(
3296
+ data: ImporterConfigControllerUpdateConfigData
3297
+ ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
3080
3298
  return __request(OpenAPI, {
3081
- method: 'POST',
3082
- url: '/api/v1/{region}/bean/prices',
3299
+ method: 'PUT',
3300
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
3083
3301
  path: {
3302
+ importerId: data.importerId,
3084
3303
  region: data.region
3085
3304
  },
3086
3305
  body: data.requestBody,
3087
3306
  mediaType: 'application/json',
3088
3307
  errors: {
3089
- 404: 'Currency or quoteCurrency commodity not found',
3090
- 409: 'Price already exists for this currency pair and date'
3308
+ 400: 'Invalid input - Validation failed',
3309
+ 404: 'Configuration not found'
3091
3310
  }
3092
3311
  });
3093
3312
  }
3094
3313
 
3095
3314
  /**
3096
- * List user prices
3097
- * Returns all price entries for the authenticated user with optional filtering
3315
+ * Reset configuration to default
3316
+ * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
3098
3317
  * @param data The data for the request.
3318
+ * @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
3099
3319
  * @param data.region Region code for tenant context
3100
- * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
3101
- * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
3102
- * @param data.dateFrom Filter prices from this date (ISO 8601 format)
3103
- * @param data.dateTo Filter prices to this date (ISO 8601 format)
3104
- * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
3105
- * @param data.page Page number for pagination (default: 1)
3106
- * @param data.limit Number of items per page (default: 20, max: 100)
3107
- * @returns PriceListResponseDto Prices retrieved successfully
3320
+ * @returns ImporterConfigDto Configuration reset successfully
3108
3321
  * @throws ApiError
3109
3322
  */
3110
- public static priceControllerFindAll(
3111
- data: PriceControllerFindAllData
3112
- ): CancelablePromise<PriceControllerFindAllResponse> {
3323
+ public static importerConfigControllerResetConfig(
3324
+ data: ImporterConfigControllerResetConfigData
3325
+ ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
3113
3326
  return __request(OpenAPI, {
3114
- method: 'GET',
3115
- url: '/api/v1/{region}/bean/prices',
3327
+ method: 'POST',
3328
+ url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
3116
3329
  path: {
3330
+ importerId: data.importerId,
3117
3331
  region: data.region
3118
3332
  },
3119
- query: {
3120
- currency: data.currency,
3121
- quoteCurrency: data.quoteCurrency,
3122
- dateFrom: data.dateFrom,
3123
- dateTo: data.dateTo,
3124
- search: data.search,
3125
- page: data.page,
3126
- limit: data.limit
3333
+ errors: {
3334
+ 400: 'Invalid input - Unsupported importer'
3127
3335
  }
3128
3336
  });
3129
3337
  }
3338
+ }
3130
3339
 
3340
+ export class ProviderSyncService {
3131
3341
  /**
3132
- * Get price by ID
3133
- * Returns a single price entry by its ID
3342
+ * Sync transactions from financial data provider
3343
+ *
3344
+ * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
3345
+ *
3346
+ * **Supported Providers:**
3347
+ * - **plaid**: Plaid API (US, Canada, Europe)
3348
+ * - **teller**: Teller API (US)
3349
+ * - **truelayer**: TrueLayer Open Banking (UK, Europe)
3350
+ * - **gocardless**: GoCardless Bank Account Data (Europe)
3351
+ * - **simplefin**: SimpleFIN (Self-hosted)
3352
+ * - **yodlee**: Yodlee (Global)
3353
+ * - **beancount-direct**: Beancount format transactions
3354
+ * - **parsed-bill**: Client-side parsed bill transactions
3355
+ *
3356
+ * **Processing Flow:**
3357
+ * 1. Transform raw data via provider adapter
3358
+ * 2. Validate transaction format
3359
+ * 3. Deduplicate using originalId
3360
+ * 4. Classify using rule engine
3361
+ * 5. Route low-confidence to Review Center
3362
+ * 6. Persist validated transactions
3363
+ *
3134
3364
  * @param data The data for the request.
3135
- * @param data.id Price ID
3365
+ * @param data.providerName Provider name
3136
3366
  * @param data.region Region code for tenant context
3137
- * @returns PriceResponseDto Price retrieved successfully
3367
+ * @param data.requestBody
3368
+ * @returns ProviderSyncResponseDto Sync completed successfully
3138
3369
  * @throws ApiError
3139
3370
  */
3140
- public static priceControllerFindOne(
3141
- data: PriceControllerFindOneData
3142
- ): CancelablePromise<PriceControllerFindOneResponse> {
3371
+ public static providerSyncControllerSync(
3372
+ data: ProviderSyncControllerSyncData
3373
+ ): CancelablePromise<ProviderSyncControllerSyncResponse> {
3143
3374
  return __request(OpenAPI, {
3144
- method: 'GET',
3145
- url: '/api/v1/{region}/bean/prices/{id}',
3375
+ method: 'POST',
3376
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/sync',
3146
3377
  path: {
3147
- id: data.id,
3378
+ providerName: data.providerName,
3148
3379
  region: data.region
3149
3380
  },
3381
+ body: data.requestBody,
3382
+ mediaType: 'application/json',
3150
3383
  errors: {
3151
- 404: 'Price not found'
3384
+ 400: 'Invalid request data',
3385
+ 401: 'Missing or invalid authentication',
3386
+ 404: 'Provider not supported'
3152
3387
  }
3153
3388
  });
3154
3389
  }
3155
3390
 
3156
3391
  /**
3157
- * Update a price
3158
- * Updates an existing price entry
3392
+ * Get supported providers
3393
+ * Returns a list of all providers supported by the sync endpoint.
3159
3394
  * @param data The data for the request.
3160
- * @param data.id Price ID
3161
3395
  * @param data.region Region code for tenant context
3162
- * @param data.requestBody
3163
- * @returns PriceResponseDto Price updated successfully
3396
+ * @returns SupportedProvidersResponseDto List of supported providers
3164
3397
  * @throws ApiError
3165
3398
  */
3166
- public static priceControllerUpdate(
3167
- data: PriceControllerUpdateData
3168
- ): CancelablePromise<PriceControllerUpdateResponse> {
3399
+ public static providerSyncControllerGetSupportedProviders(
3400
+ data: ProviderSyncControllerGetSupportedProvidersData
3401
+ ): CancelablePromise<ProviderSyncControllerGetSupportedProvidersResponse> {
3169
3402
  return __request(OpenAPI, {
3170
- method: 'PUT',
3171
- url: '/api/v1/{region}/bean/prices/{id}',
3403
+ method: 'GET',
3404
+ url: '/api/v1/{region}/bean/import/provider/supported',
3172
3405
  path: {
3173
- id: data.id,
3174
3406
  region: data.region
3175
3407
  },
3176
- body: data.requestBody,
3177
- mediaType: 'application/json',
3178
3408
  errors: {
3179
- 404: 'Price not found',
3180
- 409: 'Updated price conflicts with existing price'
3409
+ 401: 'Missing or invalid authentication'
3181
3410
  }
3182
3411
  });
3183
3412
  }
3184
3413
 
3185
3414
  /**
3186
- * Delete a price
3187
- * Deletes a price entry (hard delete)
3415
+ * Check if provider is supported
3416
+ * Returns whether a specific provider is supported.
3188
3417
  * @param data The data for the request.
3189
- * @param data.id Price ID
3418
+ * @param data.providerName Provider name to check
3190
3419
  * @param data.region Region code for tenant context
3191
- * @returns void Price deleted successfully
3420
+ * @returns unknown Provider support status
3192
3421
  * @throws ApiError
3193
3422
  */
3194
- public static priceControllerDelete(
3195
- data: PriceControllerDeleteData
3196
- ): CancelablePromise<PriceControllerDeleteResponse> {
3423
+ public static providerSyncControllerIsProviderSupported(
3424
+ data: ProviderSyncControllerIsProviderSupportedData
3425
+ ): CancelablePromise<ProviderSyncControllerIsProviderSupportedResponse> {
3197
3426
  return __request(OpenAPI, {
3198
- method: 'DELETE',
3199
- url: '/api/v1/{region}/bean/prices/{id}',
3427
+ method: 'GET',
3428
+ url: '/api/v1/{region}/bean/import/provider/{providerName}/supported',
3200
3429
  path: {
3201
- id: data.id,
3430
+ providerName: data.providerName,
3202
3431
  region: data.region
3203
3432
  },
3204
3433
  errors: {
3205
- 404: 'Price not found'
3434
+ 401: 'Missing or invalid authentication'
3206
3435
  }
3207
3436
  });
3208
3437
  }
3438
+ }
3209
3439
 
3440
+ export class ExternalAccountLinksService {
3210
3441
  /**
3211
- * Bulk create prices
3212
- * Creates multiple price entries at once (skips duplicates)
3442
+ * Create an external account → BeanAccount mapping (ADR-0113)
3213
3443
  * @param data The data for the request.
3214
3444
  * @param data.region Region code for tenant context
3215
3445
  * @param data.requestBody
3216
- * @returns PriceResponseDto Prices created successfully
3446
+ * @returns ExternalAccountLinkResponseDto Link created.
3217
3447
  * @throws ApiError
3218
3448
  */
3219
- public static priceControllerBulkCreate(
3220
- data: PriceControllerBulkCreateData
3221
- ): CancelablePromise<PriceControllerBulkCreateResponse> {
3449
+ public static externalAccountLinkControllerCreate(
3450
+ data: ExternalAccountLinkControllerCreateData
3451
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
3222
3452
  return __request(OpenAPI, {
3223
3453
  method: 'POST',
3224
- url: '/api/v1/{region}/bean/prices/bulk',
3454
+ url: '/api/v1/{region}/bean/external-account-links',
3225
3455
  path: {
3226
3456
  region: data.region
3227
3457
  },
3228
3458
  body: data.requestBody,
3229
- mediaType: 'application/json'
3459
+ mediaType: 'application/json',
3460
+ errors: {
3461
+ 422: 'beanAccountId not owned, or an active link already exists.'
3462
+ }
3230
3463
  });
3231
3464
  }
3232
- }
3233
3465
 
3234
- export class ReportingService {
3235
3466
  /**
3236
- * Get portfolio value trends
3237
- *
3238
- * Returns time series data of portfolio net worth.
3239
- *
3240
- * **Multi-currency Support:**
3241
- * - `series[].byCurrency` - Currency breakdown for each data point
3242
- * - `byCurrency` - Separate time series grouped by currency
3243
- * - `warnings` - Exchange rate warnings if conversion failed
3244
- *
3245
- * **Parameters:**
3246
- * - `period`: Time period (1m, 3m, 6m, 1y)
3247
- * - `granularity`: Data granularity (day, week, month)
3248
- *
3467
+ * List the user's active external account links
3249
3468
  * @param data The data for the request.
3469
+ * @param data.provider
3250
3470
  * @param data.region Region code for tenant context
3251
- * @param data.period Time period
3252
- * @param data.granularity Data granularity
3253
- * @returns PortfolioTrendsResponseDto Trends retrieved successfully
3471
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
3254
3472
  * @throws ApiError
3255
3473
  */
3256
- public static reportingControllerGetPortfolioTrends(
3257
- data: ReportingControllerGetPortfolioTrendsData
3258
- ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
3474
+ public static externalAccountLinkControllerFindAll(
3475
+ data: ExternalAccountLinkControllerFindAllData
3476
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
3259
3477
  return __request(OpenAPI, {
3260
3478
  method: 'GET',
3261
- url: '/api/v1/{region}/reporting/portfolio/trends',
3479
+ url: '/api/v1/{region}/bean/external-account-links',
3262
3480
  path: {
3263
3481
  region: data.region
3264
3482
  },
3265
3483
  query: {
3266
- period: data.period,
3267
- granularity: data.granularity
3484
+ provider: data.provider
3485
+ }
3486
+ });
3487
+ }
3488
+
3489
+ /**
3490
+ * Get a single external account link
3491
+ * @param data The data for the request.
3492
+ * @param data.id
3493
+ * @param data.region Region code for tenant context
3494
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
3495
+ * @throws ApiError
3496
+ */
3497
+ public static externalAccountLinkControllerFindOne(
3498
+ data: ExternalAccountLinkControllerFindOneData
3499
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
3500
+ return __request(OpenAPI, {
3501
+ method: 'GET',
3502
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3503
+ path: {
3504
+ id: data.id,
3505
+ region: data.region
3268
3506
  },
3269
3507
  errors: {
3270
- 401: 'User not authenticated'
3508
+ 422: 'Link not found or not owned by the user.'
3271
3509
  }
3272
3510
  });
3273
3511
  }
3274
3512
 
3275
3513
  /**
3276
- * Generate portfolio snapshot
3277
- *
3278
- * Manually generate a portfolio snapshot for a specific date.
3279
- *
3280
- * **Multi-currency Support:**
3281
- * - Fetches balances grouped by currency
3282
- * - Uses user's baseCurrency setting for conversion
3283
- * - Stores exchange rates and warnings
3284
- *
3285
- * **Use Cases:**
3286
- * - Testing snapshot generation
3287
- * - Force regeneration after data correction
3288
- * - Initial setup for new users
3289
- *
3514
+ * Soft-delete (disconnect) an external account link
3290
3515
  * @param data The data for the request.
3516
+ * @param data.id
3291
3517
  * @param data.region Region code for tenant context
3292
- * @param data.requestBody Optional date (defaults to today)
3293
- * @returns GenerateSnapshotResponse Snapshot generated successfully
3518
+ * @returns void Link soft-deleted; historical transactions are unaffected.
3294
3519
  * @throws ApiError
3295
3520
  */
3296
- public static reportingControllerGenerateSnapshot(
3297
- data: ReportingControllerGenerateSnapshotData
3298
- ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
3521
+ public static externalAccountLinkControllerRemove(
3522
+ data: ExternalAccountLinkControllerRemoveData
3523
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
3524
+ return __request(OpenAPI, {
3525
+ method: 'DELETE',
3526
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3527
+ path: {
3528
+ id: data.id,
3529
+ region: data.region
3530
+ }
3531
+ });
3532
+ }
3533
+ }
3534
+
3535
+ export class ImportTelemetryService {
3536
+ /**
3537
+ * Receive anonymous parser failure telemetry
3538
+ * @param data The data for the request.
3539
+ * @param data.region Region code for tenant context
3540
+ * @param data.requestBody
3541
+ * @returns unknown Telemetry report received
3542
+ * @throws ApiError
3543
+ */
3544
+ public static telemetryControllerReportTelemetry(
3545
+ data: TelemetryControllerReportTelemetryData
3546
+ ): CancelablePromise<TelemetryControllerReportTelemetryResponse> {
3299
3547
  return __request(OpenAPI, {
3300
3548
  method: 'POST',
3301
- url: '/api/v1/{region}/reporting/snapshots/generate',
3549
+ url: '/api/v1/{region}/bean/import/parser-telemetry',
3302
3550
  path: {
3303
3551
  region: data.region
3304
3552
  },
3305
3553
  body: data.requestBody,
3306
3554
  mediaType: 'application/json',
3307
3555
  errors: {
3308
- 400: 'Invalid date format',
3309
- 401: 'User not authenticated'
3556
+ 401: 'Unauthorized'
3310
3557
  }
3311
3558
  });
3312
3559
  }
3313
3560
 
3314
3561
  /**
3315
- * Backfill portfolio snapshots
3316
- *
3317
- * Generate snapshots for a date range (historical data backfill).
3318
- *
3319
- * **Multi-currency Support:**
3320
- * - Each snapshot includes multi-currency data
3321
- * - Uses exchange rates available at generation time
3322
- * - Warnings stored for missing exchange rates
3323
- *
3324
- * **Best Practices:**
3325
- * - Use for initial setup after account configuration
3326
- * - Run during low-traffic periods for large date ranges
3327
- * - Existing snapshots are skipped (not regenerated)
3328
- *
3562
+ * Receive anonymous zero-hit coverage miss report
3329
3563
  * @param data The data for the request.
3330
3564
  * @param data.region Region code for tenant context
3331
3565
  * @param data.requestBody
3332
- * @returns BackfillSnapshotsResponse Backfill completed successfully
3566
+ * @returns unknown Coverage miss report received
3333
3567
  * @throws ApiError
3334
3568
  */
3335
- public static reportingControllerBackfillSnapshots(
3336
- data: ReportingControllerBackfillSnapshotsData
3337
- ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
3569
+ public static telemetryControllerReportCoverageMiss(
3570
+ data: TelemetryControllerReportCoverageMissData
3571
+ ): CancelablePromise<TelemetryControllerReportCoverageMissResponse> {
3338
3572
  return __request(OpenAPI, {
3339
3573
  method: 'POST',
3340
- url: '/api/v1/{region}/reporting/snapshots/backfill',
3574
+ url: '/api/v1/{region}/bean/import/parser-coverage-miss',
3341
3575
  path: {
3342
3576
  region: data.region
3343
3577
  },
3344
3578
  body: data.requestBody,
3345
3579
  mediaType: 'application/json',
3346
3580
  errors: {
3347
- 400: 'Invalid date format or range',
3348
- 401: 'User not authenticated',
3349
- 409: 'Backfill already in progress for this user'
3581
+ 401: 'Unauthorized'
3582
+ }
3583
+ });
3584
+ }
3585
+
3586
+ /**
3587
+ * Coverage metrics (uncovered format aggregation)
3588
+ * @param data The data for the request.
3589
+ * @param data.region Region code for tenant context
3590
+ * @param data.topN Top-N uncovered formats (default 10)
3591
+ * @returns unknown Coverage metrics
3592
+ * @throws ApiError
3593
+ */
3594
+ public static telemetryControllerGetCoverageMetrics(
3595
+ data: TelemetryControllerGetCoverageMetricsData
3596
+ ): CancelablePromise<TelemetryControllerGetCoverageMetricsResponse> {
3597
+ return __request(OpenAPI, {
3598
+ method: 'GET',
3599
+ url: '/api/v1/{region}/bean/import/parser-coverage-metrics',
3600
+ path: {
3601
+ region: data.region
3602
+ },
3603
+ query: {
3604
+ topN: data.topN
3605
+ }
3606
+ });
3607
+ }
3608
+ }
3609
+
3610
+ export class BeanNlpService {
3611
+ /**
3612
+ * Process natural language input
3613
+ * 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"
3614
+ * @param data The data for the request.
3615
+ * @param data.region Region code for tenant context
3616
+ * @param data.requestBody Natural language transaction input with optional session ID
3617
+ * @returns NlpResponseDto NLP processing result - either created transaction or asking for more info
3618
+ * @throws ApiError
3619
+ */
3620
+ public static nlpControllerProcessNaturalLanguage(
3621
+ data: NlpControllerProcessNaturalLanguageData
3622
+ ): CancelablePromise<NlpControllerProcessNaturalLanguageResponse> {
3623
+ return __request(OpenAPI, {
3624
+ method: 'POST',
3625
+ url: '/api/v1/{region}/bean/nlp/process',
3626
+ path: {
3627
+ region: data.region
3628
+ },
3629
+ body: data.requestBody,
3630
+ mediaType: 'application/json',
3631
+ errors: {
3632
+ 400: 'Invalid input',
3633
+ 401: 'Unauthorized'
3634
+ }
3635
+ });
3636
+ }
3637
+
3638
+ /**
3639
+ * Clear dialogue session
3640
+ * Clear the current NLP dialogue session. Use this to cancel an ongoing multi-turn dialogue.
3641
+ * @param data The data for the request.
3642
+ * @param data.region Region code for tenant context
3643
+ * @param data.sessionId Specific session ID to clear (defaults to user session)
3644
+ * @returns void Session cleared successfully
3645
+ * @throws ApiError
3646
+ */
3647
+ public static nlpControllerClearSession(
3648
+ data: NlpControllerClearSessionData
3649
+ ): CancelablePromise<NlpControllerClearSessionResponse> {
3650
+ return __request(OpenAPI, {
3651
+ method: 'DELETE',
3652
+ url: '/api/v1/{region}/bean/nlp/session',
3653
+ path: {
3654
+ region: data.region
3655
+ },
3656
+ query: {
3657
+ sessionId: data.sessionId
3658
+ },
3659
+ errors: {
3660
+ 401: 'Unauthorized'
3661
+ }
3662
+ });
3663
+ }
3664
+
3665
+ /**
3666
+ * Get current session state
3667
+ * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
3668
+ * @param data The data for the request.
3669
+ * @param data.region Region code for tenant context
3670
+ * @param data.sessionId Specific session ID to get (defaults to user session)
3671
+ * @returns unknown Current session state (or null if no active session)
3672
+ * @throws ApiError
3673
+ */
3674
+ public static nlpControllerGetSession(
3675
+ data: NlpControllerGetSessionData
3676
+ ): CancelablePromise<NlpControllerGetSessionResponse> {
3677
+ return __request(OpenAPI, {
3678
+ method: 'GET',
3679
+ url: '/api/v1/{region}/bean/nlp/session',
3680
+ path: {
3681
+ region: data.region
3682
+ },
3683
+ query: {
3684
+ sessionId: data.sessionId
3685
+ },
3686
+ errors: {
3687
+ 401: 'Unauthorized'
3688
+ }
3689
+ });
3690
+ }
3691
+ }
3692
+
3693
+ export class BeanPlatformsService {
3694
+ /**
3695
+ * Get all platforms with statistics
3696
+ * @returns unknown List of platforms with binding and account counts
3697
+ * @throws ApiError
3698
+ */
3699
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
3700
+ return __request(OpenAPI, {
3701
+ method: 'GET',
3702
+ url: '/api/v1/bean/platforms'
3703
+ });
3704
+ }
3705
+
3706
+ /**
3707
+ * Create a new platform
3708
+ * @param data The data for the request.
3709
+ * @param data.requestBody
3710
+ * @returns unknown Platform created successfully
3711
+ * @throws ApiError
3712
+ */
3713
+ public static platformControllerCreate(
3714
+ data: PlatformControllerCreateData
3715
+ ): CancelablePromise<PlatformControllerCreateResponse> {
3716
+ return __request(OpenAPI, {
3717
+ method: 'POST',
3718
+ url: '/api/v1/bean/platforms',
3719
+ body: data.requestBody,
3720
+ mediaType: 'application/json',
3721
+ errors: {
3722
+ 409: 'Platform already exists'
3723
+ }
3724
+ });
3725
+ }
3726
+
3727
+ /**
3728
+ * Get platform list for current user
3729
+ * @returns PlatformListItemDto List of platforms with user binding status
3730
+ * @throws ApiError
3731
+ */
3732
+ public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3733
+ return __request(OpenAPI, {
3734
+ method: 'GET',
3735
+ url: '/api/v1/bean/platforms/list'
3736
+ });
3737
+ }
3738
+
3739
+ /**
3740
+ * Match platforms by name or alias
3741
+ * @param data The data for the request.
3742
+ * @param data.q Search query — Chinese name, English name, or abbreviation
3743
+ * @param data.region Region code for category override lookup
3744
+ * @returns PlatformMatchResponseDto Matching platforms with overall match type and truncation flag
3745
+ * @throws ApiError
3746
+ */
3747
+ public static platformControllerMatchPlatforms(
3748
+ data: PlatformControllerMatchPlatformsData
3749
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3750
+ return __request(OpenAPI, {
3751
+ method: 'GET',
3752
+ url: '/api/v1/bean/platforms/match',
3753
+ query: {
3754
+ q: data.q,
3755
+ region: data.region
3756
+ }
3757
+ });
3758
+ }
3759
+
3760
+ /**
3761
+ * Update a platform
3762
+ * @param data The data for the request.
3763
+ * @param data.id Platform ID
3764
+ * @param data.requestBody
3765
+ * @returns unknown Platform updated successfully
3766
+ * @throws ApiError
3767
+ */
3768
+ public static platformControllerUpdate(
3769
+ data: PlatformControllerUpdateData
3770
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
3771
+ return __request(OpenAPI, {
3772
+ method: 'PUT',
3773
+ url: '/api/v1/bean/platforms/{id}',
3774
+ path: {
3775
+ id: data.id
3776
+ },
3777
+ body: data.requestBody,
3778
+ mediaType: 'application/json',
3779
+ errors: {
3780
+ 404: 'Platform not found'
3781
+ }
3782
+ });
3783
+ }
3784
+
3785
+ /**
3786
+ * Delete a platform
3787
+ * @param data The data for the request.
3788
+ * @param data.id Platform ID
3789
+ * @returns void Platform deleted successfully
3790
+ * @throws ApiError
3791
+ */
3792
+ public static platformControllerDelete(
3793
+ data: PlatformControllerDeleteData
3794
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
3795
+ return __request(OpenAPI, {
3796
+ method: 'DELETE',
3797
+ url: '/api/v1/bean/platforms/{id}',
3798
+ path: {
3799
+ id: data.id
3800
+ },
3801
+ errors: {
3802
+ 404: 'Platform not found'
3803
+ }
3804
+ });
3805
+ }
3806
+ }
3807
+
3808
+ export class DashboardService {
3809
+ /**
3810
+ * Get net worth overview
3811
+ * Returns total net worth with breakdown of assets and liabilities
3812
+ * @param data The data for the request.
3813
+ * @param data.region Region code for tenant context
3814
+ * @param data.date Date for balance calculation (ISO 8601 format)
3815
+ * @returns NetWorthResponseDto Net worth retrieved successfully
3816
+ * @throws ApiError
3817
+ */
3818
+ public static dashboardControllerGetNetWorth(
3819
+ data: DashboardControllerGetNetWorthData
3820
+ ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3821
+ return __request(OpenAPI, {
3822
+ method: 'GET',
3823
+ url: '/api/v1/{region}/dashboard/net-worth',
3824
+ path: {
3825
+ region: data.region
3826
+ },
3827
+ query: {
3828
+ date: data.date
3829
+ },
3830
+ errors: {
3831
+ 401: 'User not authenticated'
3832
+ }
3833
+ });
3834
+ }
3835
+
3836
+ /**
3837
+ * Get accounts grouped by platform
3838
+ * Returns accounts with balances grouped by financial platform
3839
+ * @param data The data for the request.
3840
+ * @param data.region Region code for tenant context
3841
+ * @param data.groupBy Grouping strategy
3842
+ * @param data.date Date for balance calculation (ISO 8601 format)
3843
+ * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
3844
+ * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
3845
+ * @throws ApiError
3846
+ */
3847
+ public static dashboardControllerGetAccounts(
3848
+ data: DashboardControllerGetAccountsData
3849
+ ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3850
+ return __request(OpenAPI, {
3851
+ method: 'GET',
3852
+ url: '/api/v1/{region}/dashboard/accounts',
3853
+ path: {
3854
+ region: data.region
3855
+ },
3856
+ query: {
3857
+ groupBy: data.groupBy,
3858
+ date: data.date,
3859
+ accountId: data.accountId
3860
+ },
3861
+ errors: {
3862
+ 401: 'User not authenticated'
3863
+ }
3864
+ });
3865
+ }
3866
+
3867
+ /**
3868
+ * Get cash flow summary
3869
+ * Returns income, expenses, and savings for a monthly period
3870
+ * @param data The data for the request.
3871
+ * @param data.period Period in YYYY-MM format
3872
+ * @param data.region Region code for tenant context
3873
+ * @returns CashFlowResponseDto Cash flow retrieved successfully
3874
+ * @throws ApiError
3875
+ */
3876
+ public static dashboardControllerGetCashFlow(
3877
+ data: DashboardControllerGetCashFlowData
3878
+ ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3879
+ return __request(OpenAPI, {
3880
+ method: 'GET',
3881
+ url: '/api/v1/{region}/dashboard/cash-flow',
3882
+ path: {
3883
+ region: data.region
3884
+ },
3885
+ query: {
3886
+ period: data.period
3887
+ },
3888
+ errors: {
3889
+ 400: 'Invalid period format',
3890
+ 401: 'User not authenticated'
3891
+ }
3892
+ });
3893
+ }
3894
+
3895
+ /**
3896
+ * Get expenses/income grouped by functional category
3897
+ * 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)
3898
+ * @param data The data for the request.
3899
+ * @param data.region Region code for tenant context
3900
+ * @param data.groupBy Grouping strategy
3901
+ * @param data.period Time window (1m = current calendar month)
3902
+ * @param data.flow Account root to aggregate (expense → ^Expenses:, income → ^Income:)
3903
+ * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3904
+ * @throws ApiError
3905
+ */
3906
+ public static dashboardControllerGetExpenses(
3907
+ data: DashboardControllerGetExpensesData
3908
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3909
+ return __request(OpenAPI, {
3910
+ method: 'GET',
3911
+ url: '/api/v1/{region}/dashboard/expenses',
3912
+ path: {
3913
+ region: data.region
3914
+ },
3915
+ query: {
3916
+ groupBy: data.groupBy,
3917
+ period: data.period,
3918
+ flow: data.flow
3919
+ },
3920
+ errors: {
3921
+ 400: 'Invalid groupBy or period',
3922
+ 401: 'User not authenticated'
3923
+ }
3924
+ });
3925
+ }
3926
+ }
3927
+
3928
+ export class InvestmentService {
3929
+ /**
3930
+ * Get per-holding unrealized + realized P&L
3931
+ * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3932
+ * @param data The data for the request.
3933
+ * @param data.region Region code for tenant context
3934
+ * @param data.asOf As-of date (ISO 8601), defaults to today
3935
+ * @param data.accountId Scope to a single account
3936
+ * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
3937
+ * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3938
+ * @throws ApiError
3939
+ */
3940
+ public static holdingPnlControllerGetHoldingPnl(
3941
+ data: HoldingPnlControllerGetHoldingPnlData
3942
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3943
+ return __request(OpenAPI, {
3944
+ method: 'GET',
3945
+ url: '/api/v1/{region}/investment/holdings/pnl',
3946
+ path: {
3947
+ region: data.region
3948
+ },
3949
+ query: {
3950
+ asOf: data.asOf,
3951
+ accountId: data.accountId,
3952
+ method: data.method
3953
+ },
3954
+ errors: {
3955
+ 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3956
+ 401: 'User not authenticated'
3350
3957
  }
3351
3958
  });
3352
3959
  }
@@ -3375,7 +3982,7 @@ export class AuthService {
3375
3982
  * Anonymous login with access token
3376
3983
  * @param data The data for the request.
3377
3984
  * @param data.requestBody
3378
- * @returns unknown Login successful
3985
+ * @returns AnonymousLoginResponseDto Login successful
3379
3986
  * @throws ApiError
3380
3987
  */
3381
3988
  public static authControllerAccessTokenLogin(