@firela/api-types 0.0.0-canary.8cbdced0 → 0.0.0-canary.9256c41b

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,
@@ -171,6 +185,28 @@ import type {
171
185
  PropertyControllerUpdateResponse,
172
186
  PropertyControllerDeleteData,
173
187
  PropertyControllerDeleteResponse,
188
+ EventControllerCreateData,
189
+ EventControllerCreateResponse,
190
+ EventControllerFindAllData,
191
+ EventControllerFindAllResponse,
192
+ EventControllerFindOneData,
193
+ EventControllerFindOneResponse,
194
+ EventControllerUpdateData,
195
+ EventControllerUpdateResponse,
196
+ EventControllerDeleteData,
197
+ EventControllerDeleteResponse,
198
+ EventControllerGetSliceData,
199
+ EventControllerGetSliceResponse,
200
+ OnboardingControllerBootstrapData,
201
+ OnboardingControllerBootstrapResponse,
202
+ ReconciliationControllerComputeData,
203
+ ReconciliationControllerComputeResponse,
204
+ ReconciliationControllerAssertData,
205
+ ReconciliationControllerAssertResponse,
206
+ ReconciliationControllerPadData,
207
+ ReconciliationControllerPadResponse,
208
+ ReconciliationControllerHistoryData,
209
+ ReconciliationControllerHistoryResponse,
174
210
  ExportControllerExportBeancountResponse,
175
211
  FileImportControllerImportFileData,
176
212
  FileImportControllerImportFileResponse,
@@ -184,22 +220,20 @@ import type {
184
220
  ImporterConfigControllerUpdateConfigResponse,
185
221
  ImporterConfigControllerResetConfigData,
186
222
  ImporterConfigControllerResetConfigResponse,
187
- PlatformControllerFindAllResponse,
188
- PlatformControllerCreateData,
189
- PlatformControllerCreateResponse,
190
- PlatformControllerGetPlatformListResponse,
191
- PlatformControllerMatchPlatformsData,
192
- PlatformControllerMatchPlatformsResponse,
193
- PlatformControllerUpdateData,
194
- PlatformControllerUpdateResponse,
195
- PlatformControllerDeleteData,
196
- PlatformControllerDeleteResponse,
197
223
  ProviderSyncControllerSyncData,
198
224
  ProviderSyncControllerSyncResponse,
199
225
  ProviderSyncControllerGetSupportedProvidersData,
200
226
  ProviderSyncControllerGetSupportedProvidersResponse,
201
227
  ProviderSyncControllerIsProviderSupportedData,
202
228
  ProviderSyncControllerIsProviderSupportedResponse,
229
+ ExternalAccountLinkControllerCreateData,
230
+ ExternalAccountLinkControllerCreateResponse,
231
+ ExternalAccountLinkControllerFindAllData,
232
+ ExternalAccountLinkControllerFindAllResponse,
233
+ ExternalAccountLinkControllerFindOneData,
234
+ ExternalAccountLinkControllerFindOneResponse,
235
+ ExternalAccountLinkControllerRemoveData,
236
+ ExternalAccountLinkControllerRemoveResponse,
203
237
  TelemetryControllerReportTelemetryData,
204
238
  TelemetryControllerReportTelemetryResponse,
205
239
  TelemetryControllerReportCoverageMissData,
@@ -212,28 +246,30 @@ import type {
212
246
  NlpControllerClearSessionResponse,
213
247
  NlpControllerGetSessionData,
214
248
  NlpControllerGetSessionResponse,
249
+ PlatformControllerFindAllResponse,
250
+ PlatformControllerCreateData,
251
+ PlatformControllerCreateResponse,
252
+ PlatformControllerGetPlatformListResponse,
253
+ PlatformControllerMatchPlatformsData,
254
+ PlatformControllerMatchPlatformsResponse,
255
+ PlatformControllerUpdateData,
256
+ PlatformControllerUpdateResponse,
257
+ PlatformControllerDeleteData,
258
+ PlatformControllerDeleteResponse,
215
259
  DashboardControllerGetNetWorthData,
216
260
  DashboardControllerGetNetWorthResponse,
217
261
  DashboardControllerGetAccountsData,
218
262
  DashboardControllerGetAccountsResponse,
219
263
  DashboardControllerGetCashFlowData,
220
264
  DashboardControllerGetCashFlowResponse,
265
+ DashboardControllerGetExpensesData,
266
+ DashboardControllerGetExpensesResponse,
221
267
  HoldingPnlControllerGetHoldingPnlData,
222
268
  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
269
  ReportingControllerGetPortfolioTrendsData,
236
270
  ReportingControllerGetPortfolioTrendsResponse,
271
+ ReportingControllerGetCashFlowTrendsData,
272
+ ReportingControllerGetCashFlowTrendsResponse,
237
273
  ReportingControllerGenerateSnapshotData,
238
274
  ReportingControllerGenerateSnapshotResponse,
239
275
  ReportingControllerBackfillSnapshotsData,
@@ -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,173 +1564,340 @@ 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'
1578
1681
  }
1579
1682
  });
1580
1683
  }
1581
1684
 
1582
1685
  /**
1583
- * Update recurring rule
1584
- * Updates an existing recurring rule
1686
+ * Delete a price
1687
+ * Deletes a price entry (hard delete)
1585
1688
  * @param data The data for the request.
1586
- * @param data.id Rule ID
1689
+ * @param data.id Price ID
1587
1690
  * @param data.region Region code for tenant context
1588
- * @param data.requestBody
1589
- * @returns RecurringRuleResponseDto Rule updated successfully
1691
+ * @returns void Price deleted successfully
1590
1692
  * @throws ApiError
1591
1693
  */
1592
- public static recurringRuleControllerUpdate(
1593
- data: RecurringRuleControllerUpdateData
1594
- ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1694
+ public static priceControllerDelete(
1695
+ data: PriceControllerDeleteData
1696
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1595
1697
  return __request(OpenAPI, {
1596
- method: 'PATCH',
1597
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1698
+ method: 'DELETE',
1699
+ url: '/api/v1/{region}/bean/prices/{id}',
1598
1700
  path: {
1599
1701
  id: data.id,
1600
1702
  region: data.region
1601
1703
  },
1602
- body: data.requestBody,
1603
- mediaType: 'application/json',
1604
1704
  errors: {
1605
- 400: 'Invalid input data',
1606
- 404: 'Rule not found'
1705
+ 404: 'Price not found'
1607
1706
  }
1608
1707
  });
1609
1708
  }
1610
1709
 
1611
1710
  /**
1612
- * Delete recurring rule
1613
- * Soft deletes a recurring rule (sets isActive to false)
1711
+ * Bulk create prices
1712
+ * Creates multiple price entries at once (skips duplicates)
1614
1713
  * @param data The data for the request.
1615
- * @param data.id Rule ID
1616
1714
  * @param data.region Region code for tenant context
1617
- * @returns void Rule deleted successfully
1715
+ * @param data.requestBody
1716
+ * @returns PriceResponseDto Prices created successfully
1618
1717
  * @throws ApiError
1619
1718
  */
1620
- public static recurringRuleControllerDelete(
1621
- data: RecurringRuleControllerDeleteData
1622
- ): CancelablePromise<RecurringRuleControllerDeleteResponse> {
1719
+ public static priceControllerBulkCreate(
1720
+ data: PriceControllerBulkCreateData
1721
+ ): CancelablePromise<PriceControllerBulkCreateResponse> {
1623
1722
  return __request(OpenAPI, {
1624
- method: 'DELETE',
1625
- url: '/api/v1/{region}/bean/recurring-rules/{id}',
1723
+ method: 'POST',
1724
+ url: '/api/v1/{region}/bean/prices/bulk',
1626
1725
  path: {
1627
- id: data.id,
1628
1726
  region: data.region
1629
1727
  },
1630
- errors: {
1631
- 404: 'Rule not found'
1632
- }
1728
+ body: data.requestBody,
1729
+ mediaType: 'application/json'
1633
1730
  });
1634
1731
  }
1732
+ }
1635
1733
 
1734
+ export class RecurringRulesService {
1636
1735
  /**
1637
- * Get rule with statistics
1638
- * Returns a rule with pending/overdue counts and next expected date
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'
1840
+ }
1841
+ });
1842
+ }
1843
+
1844
+ /**
1845
+ * Update recurring rule
1846
+ * Updates an existing recurring rule
1847
+ * @param data The data for the request.
1848
+ * @param data.id Rule ID
1849
+ * @param data.region Region code for tenant context
1850
+ * @param data.requestBody
1851
+ * @returns RecurringRuleResponseDto Rule updated successfully
1852
+ * @throws ApiError
1853
+ */
1854
+ public static recurringRuleControllerUpdate(
1855
+ data: RecurringRuleControllerUpdateData
1856
+ ): CancelablePromise<RecurringRuleControllerUpdateResponse> {
1857
+ return __request(OpenAPI, {
1858
+ method: 'PATCH',
1859
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
1860
+ path: {
1861
+ id: data.id,
1862
+ region: data.region
1863
+ },
1864
+ body: data.requestBody,
1865
+ mediaType: 'application/json',
1866
+ errors: {
1867
+ 400: 'Invalid input data',
1868
+ 404: 'Rule not found'
1869
+ }
1870
+ });
1871
+ }
1872
+
1873
+ /**
1874
+ * Delete recurring rule
1875
+ * Soft deletes a recurring rule (sets isActive to false)
1876
+ * @param data The data for the request.
1877
+ * @param data.id Rule ID
1878
+ * @param data.region Region code for tenant context
1879
+ * @returns void Rule deleted successfully
1880
+ * @throws ApiError
1881
+ */
1882
+ public static recurringRuleControllerDelete(
1883
+ data: RecurringRuleControllerDeleteData
1884
+ ): CancelablePromise<RecurringRuleControllerDeleteResponse> {
1885
+ return __request(OpenAPI, {
1886
+ method: 'DELETE',
1887
+ url: '/api/v1/{region}/bean/recurring-rules/{id}',
1888
+ path: {
1889
+ id: data.id,
1890
+ region: data.region
1891
+ },
1892
+ errors: {
1893
+ 404: 'Rule not found'
1894
+ }
1895
+ });
1896
+ }
1897
+
1898
+ /**
1899
+ * Get rule with statistics
1900
+ * Returns a rule with pending/overdue counts and next expected date
1639
1901
  * @param data The data for the request.
1640
1902
  * @param data.id Rule ID
1641
1903
  * @param data.region Region code for tenant context
@@ -2223,7 +2485,7 @@ export class UsersService {
2223
2485
  * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
2224
2486
  * @param data The data for the request.
2225
2487
  * @param data.requestBody
2226
- * @returns unknown User created successfully
2488
+ * @returns SignupResponseDto User created successfully
2227
2489
  * @throws ApiError
2228
2490
  */
2229
2491
  public static userControllerSignupUser(
@@ -2432,286 +2694,487 @@ export class PropertiesService {
2432
2694
  }
2433
2695
  }
2434
2696
 
2435
- export class BeanExportService {
2697
+ export class LifeEventsService {
2436
2698
  /**
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
2699
+ * Create a new life event
2700
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2701
+ * @param data The data for the request.
2702
+ * @param data.region Region code for tenant context (decorative for life events)
2703
+ * @param data.requestBody
2704
+ * @returns EventResponseDto Life event created successfully
2440
2705
  * @throws ApiError
2441
2706
  */
2442
- public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
2707
+ public static eventControllerCreate(
2708
+ data: EventControllerCreateData
2709
+ ): CancelablePromise<EventControllerCreateResponse> {
2443
2710
  return __request(OpenAPI, {
2444
- method: 'GET',
2445
- url: '/api/v1/{region}/bean/export/beancount'
2711
+ method: 'POST',
2712
+ url: '/api/v1/{region}/bean/events',
2713
+ path: {
2714
+ region: data.region
2715
+ },
2716
+ body: data.requestBody,
2717
+ mediaType: 'application/json',
2718
+ errors: {
2719
+ 409: 'Life event already exists for this (userId, type, date) combination'
2720
+ }
2446
2721
  });
2447
2722
  }
2448
- }
2449
2723
 
2450
- export class BeanImportService {
2451
2724
  /**
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).
2725
+ * List user life events
2726
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2454
2727
  * @param data The data for the request.
2455
- * @param data.region Region code for tenant context
2456
- * @param data.formData Bill file to import
2457
- * @returns ImportResultDto File imported successfully
2728
+ * @param data.region Region code for tenant context (decorative for life events)
2729
+ * @param data.type Filter by life event type (exact match)
2730
+ * @param data.q Search term for description (case-insensitive partial match)
2731
+ * @param data.from Filter life events from this date (ISO 8601 format)
2732
+ * @param data.to Filter life events to this date (ISO 8601 format)
2733
+ * @param data.page Page number for pagination (default: 1)
2734
+ * @param data.limit Number of items per page (default: 20, max: 100)
2735
+ * @returns EventListResponseDto Life events retrieved successfully
2458
2736
  * @throws ApiError
2459
2737
  */
2460
- public static fileImportControllerImportFile(
2461
- data: FileImportControllerImportFileData
2462
- ): CancelablePromise<FileImportControllerImportFileResponse> {
2738
+ public static eventControllerFindAll(
2739
+ data: EventControllerFindAllData
2740
+ ): CancelablePromise<EventControllerFindAllResponse> {
2463
2741
  return __request(OpenAPI, {
2464
- method: 'POST',
2465
- url: '/api/v1/{region}/bean/import/file',
2742
+ method: 'GET',
2743
+ url: '/api/v1/{region}/bean/events',
2466
2744
  path: {
2467
2745
  region: data.region
2468
2746
  },
2469
- formData: data.formData,
2470
- mediaType: 'multipart/form-data',
2471
- 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'
2747
+ query: {
2748
+ type: data.type,
2749
+ q: data.q,
2750
+ from: data.from,
2751
+ to: data.to,
2752
+ page: data.page,
2753
+ limit: data.limit
2476
2754
  }
2477
2755
  });
2478
2756
  }
2479
2757
 
2480
2758
  /**
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.
2759
+ * Get life event by ID
2760
+ * Returns a single life event by its ID. Returns ETag header.
2483
2761
  * @param data The data for the request.
2484
- * @param data.region Region code for tenant context
2485
- * @param data.formData File to identify
2486
- * @returns IdentifyResultDto File identification result
2762
+ * @param data.id Life event ID
2763
+ * @param data.region Region code for tenant context (decorative for life events)
2764
+ * @returns EventResponseDto Life event retrieved successfully
2487
2765
  * @throws ApiError
2488
2766
  */
2489
- public static fileImportControllerIdentifyFile(
2490
- data: FileImportControllerIdentifyFileData
2491
- ): CancelablePromise<FileImportControllerIdentifyFileResponse> {
2767
+ public static eventControllerFindOne(
2768
+ data: EventControllerFindOneData
2769
+ ): CancelablePromise<EventControllerFindOneResponse> {
2492
2770
  return __request(OpenAPI, {
2493
- method: 'POST',
2494
- url: '/api/v1/{region}/bean/import/identify',
2771
+ method: 'GET',
2772
+ url: '/api/v1/{region}/bean/events/{id}',
2495
2773
  path: {
2774
+ id: data.id,
2496
2775
  region: data.region
2497
2776
  },
2498
- formData: data.formData,
2499
- mediaType: 'multipart/form-data',
2500
2777
  errors: {
2501
- 400: 'Bad request - No file uploaded'
2778
+ 404: 'Life event not found'
2502
2779
  }
2503
2780
  });
2504
2781
  }
2505
2782
 
2506
2783
  /**
2784
+ * Update a life event
2785
+ * Updates an existing life event. If If-Match header is provided, performs optimistic concurrency check; mismatched updatedAt returns 412.
2507
2786
  * @param data The data for the request.
2508
- * @param data.region Region code for tenant context
2509
- * @returns unknown
2787
+ * @param data.id Life event ID
2788
+ * @param data.region Region code for tenant context (decorative for life events)
2789
+ * @param data.requestBody
2790
+ * @returns EventResponseDto Life event updated successfully
2510
2791
  * @throws ApiError
2511
2792
  */
2512
- public static fileImportControllerImportBeancount(
2513
- data: FileImportControllerImportBeancountData
2514
- ): CancelablePromise<FileImportControllerImportBeancountResponse> {
2793
+ public static eventControllerUpdate(
2794
+ data: EventControllerUpdateData
2795
+ ): CancelablePromise<EventControllerUpdateResponse> {
2515
2796
  return __request(OpenAPI, {
2516
- method: 'POST',
2517
- url: '/api/v1/{region}/bean/import/beancount',
2797
+ method: 'PUT',
2798
+ url: '/api/v1/{region}/bean/events/{id}',
2518
2799
  path: {
2800
+ id: data.id,
2519
2801
  region: data.region
2802
+ },
2803
+ body: data.requestBody,
2804
+ mediaType: 'application/json',
2805
+ errors: {
2806
+ 400: 'If-Match header is not a valid ISO 8601 date',
2807
+ 404: 'Life event not found',
2808
+ 409: 'Updated event conflicts with an existing (userId, type, date) combination',
2809
+ 412: 'If-Match precondition failed (updatedAt mismatch)'
2520
2810
  }
2521
2811
  });
2522
2812
  }
2523
2813
 
2524
2814
  /**
2525
- * Get importer configuration
2526
- * Returns the current configuration for the specified importer. Creates default configuration if none exists.
2815
+ * Delete a life event
2816
+ * Deletes a life event entry (hard delete). Returns 204.
2527
2817
  * @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
- * @param data.region Region code for tenant context
2530
- * @returns ImporterConfigDto Configuration retrieved successfully
2818
+ * @param data.id Life event ID
2819
+ * @param data.region Region code for tenant context (decorative for life events)
2820
+ * @returns void Life event deleted successfully
2531
2821
  * @throws ApiError
2532
2822
  */
2533
- public static importerConfigControllerGetConfig(
2534
- data: ImporterConfigControllerGetConfigData
2535
- ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
2823
+ public static eventControllerDelete(
2824
+ data: EventControllerDeleteData
2825
+ ): CancelablePromise<EventControllerDeleteResponse> {
2536
2826
  return __request(OpenAPI, {
2537
- method: 'GET',
2538
- url: '/api/v1/{region}/bean/import/config/{importerId}',
2827
+ method: 'DELETE',
2828
+ url: '/api/v1/{region}/bean/events/{id}',
2539
2829
  path: {
2540
- importerId: data.importerId,
2830
+ id: data.id,
2541
2831
  region: data.region
2542
2832
  },
2543
2833
  errors: {
2544
- 400: 'Invalid input - Unsupported importer',
2545
- 401: 'Unauthorized - Authentication required'
2834
+ 404: 'Life event not found'
2546
2835
  }
2547
2836
  });
2548
2837
  }
2549
2838
 
2550
2839
  /**
2551
- * Update importer configuration
2552
- * Updates the configuration for the specified importer. Partial updates are supported.
2840
+ * Slice time-series by a life event (Phase 79)
2841
+ * Returns aggregated time-series for postings matching accountPattern within the half-open date range of the given life event.
2842
+ * @param data The data for the request.
2843
+ * @param data.id Life event ID
2844
+ * @param data.accountPattern
2845
+ * @param data.granularity
2846
+ * @param data.region Region code for tenant context (decorative for life events)
2847
+ * @returns unknown Time-series sliced by the life event range
2848
+ * @throws ApiError
2849
+ */
2850
+ public static eventControllerGetSlice(
2851
+ data: EventControllerGetSliceData
2852
+ ): CancelablePromise<EventControllerGetSliceResponse> {
2853
+ return __request(OpenAPI, {
2854
+ method: 'GET',
2855
+ url: '/api/v1/{region}/bean/events/{id}/slice',
2856
+ path: {
2857
+ id: data.id,
2858
+ region: data.region
2859
+ },
2860
+ query: {
2861
+ accountPattern: data.accountPattern,
2862
+ granularity: data.granularity
2863
+ },
2864
+ errors: {
2865
+ 400: 'accountPattern query param is empty',
2866
+ 404: 'Life event not found'
2867
+ }
2868
+ });
2869
+ }
2870
+ }
2871
+
2872
+ export class OnboardingService {
2873
+ /**
2874
+ * Bootstrap core accounts + register asset accounts with opening balances (ADR-0113)
2553
2875
  * @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
2555
2876
  * @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
2877
+ * @param data.requestBody
2878
+ * @returns unknown Onboarding bootstrap result.
2558
2879
  * @throws ApiError
2559
2880
  */
2560
- public static importerConfigControllerUpdateConfig(
2561
- data: ImporterConfigControllerUpdateConfigData
2562
- ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
2881
+ public static onboardingControllerBootstrap(
2882
+ data: OnboardingControllerBootstrapData
2883
+ ): CancelablePromise<OnboardingControllerBootstrapResponse> {
2563
2884
  return __request(OpenAPI, {
2564
- method: 'PUT',
2565
- url: '/api/v1/{region}/bean/import/config/{importerId}',
2885
+ method: 'POST',
2886
+ url: '/api/v1/{region}/bean/onboarding',
2566
2887
  path: {
2567
- importerId: data.importerId,
2568
2888
  region: data.region
2569
2889
  },
2570
2890
  body: data.requestBody,
2571
2891
  mediaType: 'application/json',
2572
2892
  errors: {
2573
- 400: 'Invalid input - Validation failed',
2574
- 404: 'Configuration not found'
2893
+ 422: 'Invalid region/account path/duplicate paths.'
2575
2894
  }
2576
2895
  });
2577
2896
  }
2897
+ }
2578
2898
 
2899
+ export class BalanceReconciliationService {
2579
2900
  /**
2580
- * Reset configuration to default
2581
- * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
2901
+ * Preview reconciliation (book vs actual)
2902
+ * Computes book balance, diff, Beancount-inferred tolerance, and suggested action without persisting.
2582
2903
  * @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
2584
- * @param data.region Region code for tenant context
2585
- * @returns ImporterConfigDto Configuration reset successfully
2904
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2905
+ * @param data.requestBody
2906
+ * @returns ReconciliationComputeResultDto Reconciliation preview
2586
2907
  * @throws ApiError
2587
2908
  */
2588
- public static importerConfigControllerResetConfig(
2589
- data: ImporterConfigControllerResetConfigData
2590
- ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
2909
+ public static reconciliationControllerCompute(
2910
+ data: ReconciliationControllerComputeData
2911
+ ): CancelablePromise<ReconciliationControllerComputeResponse> {
2591
2912
  return __request(OpenAPI, {
2592
2913
  method: 'POST',
2593
- url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
2914
+ url: '/api/v1/{region}/bean/reconciliations',
2594
2915
  path: {
2595
- importerId: data.importerId,
2596
2916
  region: data.region
2597
2917
  },
2918
+ body: data.requestBody,
2919
+ mediaType: 'application/json',
2598
2920
  errors: {
2599
- 400: 'Invalid input - Unsupported importer'
2921
+ 404: 'Account not found'
2600
2922
  }
2601
2923
  });
2602
2924
  }
2603
- }
2604
2925
 
2605
- export class BeanPlatformsService {
2606
2926
  /**
2607
- * Get all platforms with statistics
2608
- * @returns unknown List of platforms with binding and account counts
2927
+ * Record a balance assertion
2928
+ * Persists the reconciliation as a BeanBalance assertion (amount = actual, diffAmount = book − actual). Re-reconciling the same day/currency upserts.
2929
+ * @param data The data for the request.
2930
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2931
+ * @param data.requestBody
2932
+ * @returns ReconciliationRecordDto Balance assertion recorded
2609
2933
  * @throws ApiError
2610
2934
  */
2611
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2935
+ public static reconciliationControllerAssert(
2936
+ data: ReconciliationControllerAssertData
2937
+ ): CancelablePromise<ReconciliationControllerAssertResponse> {
2612
2938
  return __request(OpenAPI, {
2613
- method: 'GET',
2614
- url: '/api/v1/bean/platforms'
2939
+ method: 'POST',
2940
+ url: '/api/v1/{region}/bean/reconciliations/assert',
2941
+ path: {
2942
+ region: data.region
2943
+ },
2944
+ body: data.requestBody,
2945
+ mediaType: 'application/json',
2946
+ errors: {
2947
+ 404: 'Account not found'
2948
+ }
2615
2949
  });
2616
2950
  }
2617
2951
 
2618
2952
  /**
2619
- * Create a new platform
2953
+ * Generate a pad adjusting entry
2954
+ * 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.
2620
2955
  * @param data The data for the request.
2956
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2621
2957
  * @param data.requestBody
2622
- * @returns unknown Platform created successfully
2958
+ * @returns PadResultDto Pad adjusting entry generated
2623
2959
  * @throws ApiError
2624
2960
  */
2625
- public static platformControllerCreate(
2626
- data: PlatformControllerCreateData
2627
- ): CancelablePromise<PlatformControllerCreateResponse> {
2961
+ public static reconciliationControllerPad(
2962
+ data: ReconciliationControllerPadData
2963
+ ): CancelablePromise<ReconciliationControllerPadResponse> {
2628
2964
  return __request(OpenAPI, {
2629
2965
  method: 'POST',
2630
- url: '/api/v1/bean/platforms',
2966
+ url: '/api/v1/{region}/bean/reconciliations/pad',
2967
+ path: {
2968
+ region: data.region
2969
+ },
2631
2970
  body: data.requestBody,
2632
2971
  mediaType: 'application/json',
2633
2972
  errors: {
2634
- 409: 'Platform already exists'
2973
+ 400: 'Book already within tolerance — no pad needed',
2974
+ 404: 'Account not found'
2635
2975
  }
2636
2976
  });
2637
2977
  }
2638
2978
 
2639
2979
  /**
2640
- * Get platform list for current user
2641
- * @returns unknown List of platforms with user binding status
2980
+ * List reconciliation history for an account
2981
+ * Returns recorded balance assertions (most recent first). The latest drives the account-detail "Last <date>" badge.
2982
+ * @param data The data for the request.
2983
+ * @param data.accountId BeanAccount id
2984
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2985
+ * @returns ReconciliationRecordDto Reconciliation history
2642
2986
  * @throws ApiError
2643
2987
  */
2644
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
2988
+ public static reconciliationControllerHistory(
2989
+ data: ReconciliationControllerHistoryData
2990
+ ): CancelablePromise<ReconciliationControllerHistoryResponse> {
2645
2991
  return __request(OpenAPI, {
2646
2992
  method: 'GET',
2647
- url: '/api/v1/bean/platforms/list'
2993
+ url: '/api/v1/{region}/bean/accounts/{accountId}/reconciliations',
2994
+ path: {
2995
+ accountId: data.accountId,
2996
+ region: data.region
2997
+ },
2998
+ errors: {
2999
+ 404: 'Account not found'
3000
+ }
2648
3001
  });
2649
3002
  }
3003
+ }
2650
3004
 
3005
+ export class BeanExportService {
2651
3006
  /**
2652
- * Match platforms by name or alias
3007
+ * Export Beancount ledger as ZIP
3008
+ * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
3009
+ * @returns unknown
3010
+ * @throws ApiError
3011
+ */
3012
+ public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
3013
+ return __request(OpenAPI, {
3014
+ method: 'GET',
3015
+ url: '/api/v1/{region}/bean/export/beancount'
3016
+ });
3017
+ }
3018
+ }
3019
+
3020
+ export class BeanImportService {
3021
+ /**
3022
+ * Import a bill file
3023
+ * 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).
2653
3024
  * @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
3025
+ * @param data.region Region code for tenant context
3026
+ * @param data.formData Bill file to import
3027
+ * @returns ImportResultDto File imported successfully
2657
3028
  * @throws ApiError
2658
3029
  */
2659
- public static platformControllerMatchPlatforms(
2660
- data: PlatformControllerMatchPlatformsData
2661
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3030
+ public static fileImportControllerImportFile(
3031
+ data: FileImportControllerImportFileData
3032
+ ): CancelablePromise<FileImportControllerImportFileResponse> {
3033
+ return __request(OpenAPI, {
3034
+ method: 'POST',
3035
+ url: '/api/v1/{region}/bean/import/file',
3036
+ path: {
3037
+ region: data.region
3038
+ },
3039
+ formData: data.formData,
3040
+ mediaType: 'multipart/form-data',
3041
+ errors: {
3042
+ 400: 'Bad request - file-format-unsupported or file-import-failed',
3043
+ 413: 'Payload too large - file exceeds 50MB limit',
3044
+ 429: 'Too many requests - user already has import in progress',
3045
+ 500: 'Internal server error - DATABASE_ERROR'
3046
+ }
3047
+ });
3048
+ }
3049
+
3050
+ /**
3051
+ * Identify file type
3052
+ * 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.
3053
+ * @param data The data for the request.
3054
+ * @param data.region Region code for tenant context
3055
+ * @param data.formData File to identify
3056
+ * @returns IdentifyResultDto File identification result
3057
+ * @throws ApiError
3058
+ */
3059
+ public static fileImportControllerIdentifyFile(
3060
+ data: FileImportControllerIdentifyFileData
3061
+ ): CancelablePromise<FileImportControllerIdentifyFileResponse> {
3062
+ return __request(OpenAPI, {
3063
+ method: 'POST',
3064
+ url: '/api/v1/{region}/bean/import/identify',
3065
+ path: {
3066
+ region: data.region
3067
+ },
3068
+ formData: data.formData,
3069
+ mediaType: 'multipart/form-data',
3070
+ errors: {
3071
+ 400: 'Bad request - No file uploaded'
3072
+ }
3073
+ });
3074
+ }
3075
+
3076
+ /**
3077
+ * Import a Beancount file in community format
3078
+ * 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.
3079
+ * @param data The data for the request.
3080
+ * @param data.region Region code for tenant context
3081
+ * @param data.formData Beancount file to import
3082
+ * @returns unknown Beancount file imported successfully
3083
+ * @throws ApiError
3084
+ */
3085
+ public static fileImportControllerImportBeancount(
3086
+ data: FileImportControllerImportBeancountData
3087
+ ): CancelablePromise<FileImportControllerImportBeancountResponse> {
3088
+ return __request(OpenAPI, {
3089
+ method: 'POST',
3090
+ url: '/api/v1/{region}/bean/import/beancount',
3091
+ path: {
3092
+ region: data.region
3093
+ },
3094
+ formData: data.formData,
3095
+ mediaType: 'multipart/form-data',
3096
+ errors: {
3097
+ 400: 'Bad request - invalid file or no file uploaded'
3098
+ }
3099
+ });
3100
+ }
3101
+
3102
+ /**
3103
+ * Get importer configuration
3104
+ * Returns the current configuration for the specified importer. Creates default configuration if none exists.
3105
+ * @param data The data for the request.
3106
+ * @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
3107
+ * @param data.region Region code for tenant context
3108
+ * @returns ImporterConfigDto Configuration retrieved successfully
3109
+ * @throws ApiError
3110
+ */
3111
+ public static importerConfigControllerGetConfig(
3112
+ data: ImporterConfigControllerGetConfigData
3113
+ ): CancelablePromise<ImporterConfigControllerGetConfigResponse> {
2662
3114
  return __request(OpenAPI, {
2663
3115
  method: 'GET',
2664
- url: '/api/v1/bean/platforms/match',
2665
- query: {
2666
- q: data.q,
3116
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
3117
+ path: {
3118
+ importerId: data.importerId,
2667
3119
  region: data.region
3120
+ },
3121
+ errors: {
3122
+ 400: 'Invalid input - Unsupported importer',
3123
+ 401: 'Unauthorized - Authentication required'
2668
3124
  }
2669
3125
  });
2670
3126
  }
2671
3127
 
2672
3128
  /**
2673
- * Update a platform
3129
+ * Update importer configuration
3130
+ * Updates the configuration for the specified importer. Partial updates are supported.
2674
3131
  * @param data The data for the request.
2675
- * @param data.id Platform ID
2676
- * @param data.requestBody
2677
- * @returns unknown Platform updated successfully
3132
+ * @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
3133
+ * @param data.region Region code for tenant context
3134
+ * @param data.requestBody Partial configuration update. Only provided fields will be updated.
3135
+ * @returns ImporterConfigDto Configuration updated successfully
2678
3136
  * @throws ApiError
2679
3137
  */
2680
- public static platformControllerUpdate(
2681
- data: PlatformControllerUpdateData
2682
- ): CancelablePromise<PlatformControllerUpdateResponse> {
3138
+ public static importerConfigControllerUpdateConfig(
3139
+ data: ImporterConfigControllerUpdateConfigData
3140
+ ): CancelablePromise<ImporterConfigControllerUpdateConfigResponse> {
2683
3141
  return __request(OpenAPI, {
2684
3142
  method: 'PUT',
2685
- url: '/api/v1/bean/platforms/{id}',
3143
+ url: '/api/v1/{region}/bean/import/config/{importerId}',
2686
3144
  path: {
2687
- id: data.id
3145
+ importerId: data.importerId,
3146
+ region: data.region
2688
3147
  },
2689
3148
  body: data.requestBody,
2690
3149
  mediaType: 'application/json',
2691
3150
  errors: {
2692
- 404: 'Platform not found'
3151
+ 400: 'Invalid input - Validation failed',
3152
+ 404: 'Configuration not found'
2693
3153
  }
2694
3154
  });
2695
3155
  }
2696
3156
 
2697
3157
  /**
2698
- * Delete a platform
3158
+ * Reset configuration to default
3159
+ * Resets the configuration for the specified importer to default values. This operation overwrites all existing configuration.
2699
3160
  * @param data The data for the request.
2700
- * @param data.id Platform ID
2701
- * @returns void Platform deleted successfully
3161
+ * @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
3162
+ * @param data.region Region code for tenant context
3163
+ * @returns ImporterConfigDto Configuration reset successfully
2702
3164
  * @throws ApiError
2703
3165
  */
2704
- public static platformControllerDelete(
2705
- data: PlatformControllerDeleteData
2706
- ): CancelablePromise<PlatformControllerDeleteResponse> {
3166
+ public static importerConfigControllerResetConfig(
3167
+ data: ImporterConfigControllerResetConfigData
3168
+ ): CancelablePromise<ImporterConfigControllerResetConfigResponse> {
2707
3169
  return __request(OpenAPI, {
2708
- method: 'DELETE',
2709
- url: '/api/v1/bean/platforms/{id}',
3170
+ method: 'POST',
3171
+ url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
2710
3172
  path: {
2711
- id: data.id
3173
+ importerId: data.importerId,
3174
+ region: data.region
2712
3175
  },
2713
3176
  errors: {
2714
- 404: 'Platform not found'
3177
+ 400: 'Invalid input - Unsupported importer'
2715
3178
  }
2716
3179
  });
2717
3180
  }
@@ -2719,11 +3182,33 @@ export class BeanPlatformsService {
2719
3182
 
2720
3183
  export class ProviderSyncService {
2721
3184
  /**
3185
+ * Sync transactions from financial data provider
3186
+ *
3187
+ * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
3188
+ *
3189
+ * **Supported Providers:**
3190
+ * - **plaid**: Plaid API (US, Canada, Europe)
3191
+ * - **teller**: Teller API (US)
3192
+ * - **truelayer**: TrueLayer Open Banking (UK, Europe)
3193
+ * - **gocardless**: GoCardless Bank Account Data (Europe)
3194
+ * - **simplefin**: SimpleFIN (Self-hosted)
3195
+ * - **yodlee**: Yodlee (Global)
3196
+ * - **beancount-direct**: Beancount format transactions
3197
+ * - **parsed-bill**: Client-side parsed bill transactions
3198
+ *
3199
+ * **Processing Flow:**
3200
+ * 1. Transform raw data via provider adapter
3201
+ * 2. Validate transaction format
3202
+ * 3. Deduplicate using originalId
3203
+ * 4. Classify using rule engine
3204
+ * 5. Route low-confidence to Review Center
3205
+ * 6. Persist validated transactions
3206
+ *
2722
3207
  * @param data The data for the request.
2723
- * @param data.providerName
3208
+ * @param data.providerName Provider name
2724
3209
  * @param data.region Region code for tenant context
2725
3210
  * @param data.requestBody
2726
- * @returns unknown
3211
+ * @returns ProviderSyncResponseDto Sync completed successfully
2727
3212
  * @throws ApiError
2728
3213
  */
2729
3214
  public static providerSyncControllerSync(
@@ -2737,7 +3222,12 @@ export class ProviderSyncService {
2737
3222
  region: data.region
2738
3223
  },
2739
3224
  body: data.requestBody,
2740
- mediaType: 'application/json'
3225
+ mediaType: 'application/json',
3226
+ errors: {
3227
+ 400: 'Invalid request data',
3228
+ 401: 'Missing or invalid authentication',
3229
+ 404: 'Provider not supported'
3230
+ }
2741
3231
  });
2742
3232
  }
2743
3233
 
@@ -2790,6 +3280,101 @@ export class ProviderSyncService {
2790
3280
  }
2791
3281
  }
2792
3282
 
3283
+ export class ExternalAccountLinksService {
3284
+ /**
3285
+ * Create an external account → BeanAccount mapping (ADR-0113)
3286
+ * @param data The data for the request.
3287
+ * @param data.region Region code for tenant context
3288
+ * @param data.requestBody
3289
+ * @returns ExternalAccountLinkResponseDto Link created.
3290
+ * @throws ApiError
3291
+ */
3292
+ public static externalAccountLinkControllerCreate(
3293
+ data: ExternalAccountLinkControllerCreateData
3294
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
3295
+ return __request(OpenAPI, {
3296
+ method: 'POST',
3297
+ url: '/api/v1/{region}/bean/external-account-links',
3298
+ path: {
3299
+ region: data.region
3300
+ },
3301
+ body: data.requestBody,
3302
+ mediaType: 'application/json',
3303
+ errors: {
3304
+ 422: 'beanAccountId not owned, or an active link already exists.'
3305
+ }
3306
+ });
3307
+ }
3308
+
3309
+ /**
3310
+ * List the user's active external account links
3311
+ * @param data The data for the request.
3312
+ * @param data.provider
3313
+ * @param data.region Region code for tenant context
3314
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
3315
+ * @throws ApiError
3316
+ */
3317
+ public static externalAccountLinkControllerFindAll(
3318
+ data: ExternalAccountLinkControllerFindAllData
3319
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
3320
+ return __request(OpenAPI, {
3321
+ method: 'GET',
3322
+ url: '/api/v1/{region}/bean/external-account-links',
3323
+ path: {
3324
+ region: data.region
3325
+ },
3326
+ query: {
3327
+ provider: data.provider
3328
+ }
3329
+ });
3330
+ }
3331
+
3332
+ /**
3333
+ * Get a single external account link
3334
+ * @param data The data for the request.
3335
+ * @param data.id
3336
+ * @param data.region Region code for tenant context
3337
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
3338
+ * @throws ApiError
3339
+ */
3340
+ public static externalAccountLinkControllerFindOne(
3341
+ data: ExternalAccountLinkControllerFindOneData
3342
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
3343
+ return __request(OpenAPI, {
3344
+ method: 'GET',
3345
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3346
+ path: {
3347
+ id: data.id,
3348
+ region: data.region
3349
+ },
3350
+ errors: {
3351
+ 422: 'Link not found or not owned by the user.'
3352
+ }
3353
+ });
3354
+ }
3355
+
3356
+ /**
3357
+ * Soft-delete (disconnect) an external account link
3358
+ * @param data The data for the request.
3359
+ * @param data.id
3360
+ * @param data.region Region code for tenant context
3361
+ * @returns void Link soft-deleted; historical transactions are unaffected.
3362
+ * @throws ApiError
3363
+ */
3364
+ public static externalAccountLinkControllerRemove(
3365
+ data: ExternalAccountLinkControllerRemoveData
3366
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
3367
+ return __request(OpenAPI, {
3368
+ method: 'DELETE',
3369
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3370
+ path: {
3371
+ id: data.id,
3372
+ region: data.region
3373
+ }
3374
+ });
3375
+ }
3376
+ }
3377
+
2793
3378
  export class ImportTelemetryService {
2794
3379
  /**
2795
3380
  * Receive anonymous parser failure telemetry
@@ -2867,10 +3452,12 @@ export class ImportTelemetryService {
2867
3452
 
2868
3453
  export class BeanNlpService {
2869
3454
  /**
3455
+ * Process natural language input
3456
+ * 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"
2870
3457
  * @param data The data for the request.
2871
3458
  * @param data.region Region code for tenant context
2872
- * @param data.requestBody
2873
- * @returns unknown
3459
+ * @param data.requestBody Natural language transaction input with optional session ID
3460
+ * @returns NlpResponseDto NLP processing result - either created transaction or asking for more info
2874
3461
  * @throws ApiError
2875
3462
  */
2876
3463
  public static nlpControllerProcessNaturalLanguage(
@@ -2883,7 +3470,11 @@ export class BeanNlpService {
2883
3470
  region: data.region
2884
3471
  },
2885
3472
  body: data.requestBody,
2886
- mediaType: 'application/json'
3473
+ mediaType: 'application/json',
3474
+ errors: {
3475
+ 400: 'Invalid input',
3476
+ 401: 'Unauthorized'
3477
+ }
2887
3478
  });
2888
3479
  }
2889
3480
 
@@ -2896,47 +3487,162 @@ export class BeanNlpService {
2896
3487
  * @returns void Session cleared successfully
2897
3488
  * @throws ApiError
2898
3489
  */
2899
- public static nlpControllerClearSession(
2900
- data: NlpControllerClearSessionData
2901
- ): CancelablePromise<NlpControllerClearSessionResponse> {
3490
+ public static nlpControllerClearSession(
3491
+ data: NlpControllerClearSessionData
3492
+ ): CancelablePromise<NlpControllerClearSessionResponse> {
3493
+ return __request(OpenAPI, {
3494
+ method: 'DELETE',
3495
+ url: '/api/v1/{region}/bean/nlp/session',
3496
+ path: {
3497
+ region: data.region
3498
+ },
3499
+ query: {
3500
+ sessionId: data.sessionId
3501
+ },
3502
+ errors: {
3503
+ 401: 'Unauthorized'
3504
+ }
3505
+ });
3506
+ }
3507
+
3508
+ /**
3509
+ * Get current session state
3510
+ * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
3511
+ * @param data The data for the request.
3512
+ * @param data.region Region code for tenant context
3513
+ * @param data.sessionId Specific session ID to get (defaults to user session)
3514
+ * @returns unknown Current session state (or null if no active session)
3515
+ * @throws ApiError
3516
+ */
3517
+ public static nlpControllerGetSession(
3518
+ data: NlpControllerGetSessionData
3519
+ ): CancelablePromise<NlpControllerGetSessionResponse> {
3520
+ return __request(OpenAPI, {
3521
+ method: 'GET',
3522
+ url: '/api/v1/{region}/bean/nlp/session',
3523
+ path: {
3524
+ region: data.region
3525
+ },
3526
+ query: {
3527
+ sessionId: data.sessionId
3528
+ },
3529
+ errors: {
3530
+ 401: 'Unauthorized'
3531
+ }
3532
+ });
3533
+ }
3534
+ }
3535
+
3536
+ export class BeanPlatformsService {
3537
+ /**
3538
+ * Get all platforms with statistics
3539
+ * @returns unknown List of platforms with binding and account counts
3540
+ * @throws ApiError
3541
+ */
3542
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
3543
+ return __request(OpenAPI, {
3544
+ method: 'GET',
3545
+ url: '/api/v1/bean/platforms'
3546
+ });
3547
+ }
3548
+
3549
+ /**
3550
+ * Create a new platform
3551
+ * @param data The data for the request.
3552
+ * @param data.requestBody
3553
+ * @returns unknown Platform created successfully
3554
+ * @throws ApiError
3555
+ */
3556
+ public static platformControllerCreate(
3557
+ data: PlatformControllerCreateData
3558
+ ): CancelablePromise<PlatformControllerCreateResponse> {
3559
+ return __request(OpenAPI, {
3560
+ method: 'POST',
3561
+ url: '/api/v1/bean/platforms',
3562
+ body: data.requestBody,
3563
+ mediaType: 'application/json',
3564
+ errors: {
3565
+ 409: 'Platform already exists'
3566
+ }
3567
+ });
3568
+ }
3569
+
3570
+ /**
3571
+ * Get platform list for current user
3572
+ * @returns PlatformListItemDto List of platforms with user binding status
3573
+ * @throws ApiError
3574
+ */
3575
+ public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3576
+ return __request(OpenAPI, {
3577
+ method: 'GET',
3578
+ url: '/api/v1/bean/platforms/list'
3579
+ });
3580
+ }
3581
+
3582
+ /**
3583
+ * Match platforms by name or alias
3584
+ * @param data The data for the request.
3585
+ * @param data.q Search query — Chinese name, English name, or abbreviation
3586
+ * @param data.region Region code for category override lookup
3587
+ * @returns PlatformMatchResponseDto Matching platforms with overall match type and truncation flag
3588
+ * @throws ApiError
3589
+ */
3590
+ public static platformControllerMatchPlatforms(
3591
+ data: PlatformControllerMatchPlatformsData
3592
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3593
+ return __request(OpenAPI, {
3594
+ method: 'GET',
3595
+ url: '/api/v1/bean/platforms/match',
3596
+ query: {
3597
+ q: data.q,
3598
+ region: data.region
3599
+ }
3600
+ });
3601
+ }
3602
+
3603
+ /**
3604
+ * Update a platform
3605
+ * @param data The data for the request.
3606
+ * @param data.id Platform ID
3607
+ * @param data.requestBody
3608
+ * @returns unknown Platform updated successfully
3609
+ * @throws ApiError
3610
+ */
3611
+ public static platformControllerUpdate(
3612
+ data: PlatformControllerUpdateData
3613
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
2902
3614
  return __request(OpenAPI, {
2903
- method: 'DELETE',
2904
- url: '/api/v1/{region}/bean/nlp/session',
3615
+ method: 'PUT',
3616
+ url: '/api/v1/bean/platforms/{id}',
2905
3617
  path: {
2906
- region: data.region
2907
- },
2908
- query: {
2909
- sessionId: data.sessionId
3618
+ id: data.id
2910
3619
  },
3620
+ body: data.requestBody,
3621
+ mediaType: 'application/json',
2911
3622
  errors: {
2912
- 401: 'Unauthorized'
3623
+ 404: 'Platform not found'
2913
3624
  }
2914
3625
  });
2915
3626
  }
2916
3627
 
2917
3628
  /**
2918
- * Get current session state
2919
- * Get the current NLP dialogue session state. Useful for debugging and displaying session context in UI.
3629
+ * Delete a platform
2920
3630
  * @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)
3631
+ * @param data.id Platform ID
3632
+ * @returns void Platform deleted successfully
2924
3633
  * @throws ApiError
2925
3634
  */
2926
- public static nlpControllerGetSession(
2927
- data: NlpControllerGetSessionData
2928
- ): CancelablePromise<NlpControllerGetSessionResponse> {
3635
+ public static platformControllerDelete(
3636
+ data: PlatformControllerDeleteData
3637
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
2929
3638
  return __request(OpenAPI, {
2930
- method: 'GET',
2931
- url: '/api/v1/{region}/bean/nlp/session',
3639
+ method: 'DELETE',
3640
+ url: '/api/v1/bean/platforms/{id}',
2932
3641
  path: {
2933
- region: data.region
2934
- },
2935
- query: {
2936
- sessionId: data.sessionId
3642
+ id: data.id
2937
3643
  },
2938
3644
  errors: {
2939
- 401: 'Unauthorized'
3645
+ 404: 'Platform not found'
2940
3646
  }
2941
3647
  });
2942
3648
  }
@@ -3028,207 +3734,72 @@ export class DashboardService {
3028
3734
  }
3029
3735
  });
3030
3736
  }
3031
- }
3032
3737
 
3033
- export class InvestmentService {
3034
3738
  /**
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).
3739
+ * Get expenses/income grouped by functional category
3740
+ * 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)
3037
3741
  * @param data The data for the request.
3038
3742
  * @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
3743
+ * @param data.groupBy Grouping strategy
3744
+ * @param data.period Time window (1m = current calendar month)
3745
+ * @param data.flow Account root to aggregate (expense → ^Expenses:, income → ^Income:)
3746
+ * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3043
3747
  * @throws ApiError
3044
3748
  */
3045
- public static holdingPnlControllerGetHoldingPnl(
3046
- data: HoldingPnlControllerGetHoldingPnlData
3047
- ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3749
+ public static dashboardControllerGetExpenses(
3750
+ data: DashboardControllerGetExpensesData
3751
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3048
3752
  return __request(OpenAPI, {
3049
3753
  method: 'GET',
3050
- url: '/api/v1/{region}/investment/holdings/pnl',
3754
+ url: '/api/v1/{region}/dashboard/expenses',
3051
3755
  path: {
3052
3756
  region: data.region
3053
3757
  },
3054
3758
  query: {
3055
- asOf: data.asOf,
3056
- accountId: data.accountId,
3057
- method: data.method
3759
+ groupBy: data.groupBy,
3760
+ period: data.period,
3761
+ flow: data.flow
3058
3762
  },
3059
3763
  errors: {
3060
- 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3764
+ 400: 'Invalid groupBy or period',
3061
3765
  401: 'User not authenticated'
3062
3766
  }
3063
3767
  });
3064
3768
  }
3065
3769
  }
3066
3770
 
3067
- export class BeanPricesService {
3068
- /**
3069
- * Create a new price
3070
- * Creates a new price entry for the authenticated user
3071
- * @param data The data for the request.
3072
- * @param data.region Region code for tenant context
3073
- * @param data.requestBody
3074
- * @returns PriceResponseDto Price created successfully
3075
- * @throws ApiError
3076
- */
3077
- public static priceControllerCreate(
3078
- data: PriceControllerCreateData
3079
- ): CancelablePromise<PriceControllerCreateResponse> {
3080
- return __request(OpenAPI, {
3081
- method: 'POST',
3082
- url: '/api/v1/{region}/bean/prices',
3083
- path: {
3084
- region: data.region
3085
- },
3086
- body: data.requestBody,
3087
- mediaType: 'application/json',
3088
- errors: {
3089
- 404: 'Currency or quoteCurrency commodity not found',
3090
- 409: 'Price already exists for this currency pair and date'
3091
- }
3092
- });
3093
- }
3094
-
3771
+ export class InvestmentService {
3095
3772
  /**
3096
- * List user prices
3097
- * Returns all price entries for the authenticated user with optional filtering
3773
+ * Get per-holding unrealized + realized P&L
3774
+ * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3098
3775
  * @param data The data for the request.
3099
3776
  * @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
3777
+ * @param data.asOf As-of date (ISO 8601), defaults to today
3778
+ * @param data.accountId Scope to a single account
3779
+ * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
3780
+ * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3108
3781
  * @throws ApiError
3109
3782
  */
3110
- public static priceControllerFindAll(
3111
- data: PriceControllerFindAllData
3112
- ): CancelablePromise<PriceControllerFindAllResponse> {
3783
+ public static holdingPnlControllerGetHoldingPnl(
3784
+ data: HoldingPnlControllerGetHoldingPnlData
3785
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3113
3786
  return __request(OpenAPI, {
3114
3787
  method: 'GET',
3115
- url: '/api/v1/{region}/bean/prices',
3788
+ url: '/api/v1/{region}/investment/holdings/pnl',
3116
3789
  path: {
3117
3790
  region: data.region
3118
3791
  },
3119
3792
  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
3127
- }
3128
- });
3129
- }
3130
-
3131
- /**
3132
- * Get price by ID
3133
- * Returns a single price entry by its ID
3134
- * @param data The data for the request.
3135
- * @param data.id Price ID
3136
- * @param data.region Region code for tenant context
3137
- * @returns PriceResponseDto Price retrieved successfully
3138
- * @throws ApiError
3139
- */
3140
- public static priceControllerFindOne(
3141
- data: PriceControllerFindOneData
3142
- ): CancelablePromise<PriceControllerFindOneResponse> {
3143
- return __request(OpenAPI, {
3144
- method: 'GET',
3145
- url: '/api/v1/{region}/bean/prices/{id}',
3146
- path: {
3147
- id: data.id,
3148
- region: data.region
3149
- },
3150
- errors: {
3151
- 404: 'Price not found'
3152
- }
3153
- });
3154
- }
3155
-
3156
- /**
3157
- * Update a price
3158
- * Updates an existing price entry
3159
- * @param data The data for the request.
3160
- * @param data.id Price ID
3161
- * @param data.region Region code for tenant context
3162
- * @param data.requestBody
3163
- * @returns PriceResponseDto Price updated successfully
3164
- * @throws ApiError
3165
- */
3166
- public static priceControllerUpdate(
3167
- data: PriceControllerUpdateData
3168
- ): CancelablePromise<PriceControllerUpdateResponse> {
3169
- return __request(OpenAPI, {
3170
- method: 'PUT',
3171
- url: '/api/v1/{region}/bean/prices/{id}',
3172
- path: {
3173
- id: data.id,
3174
- region: data.region
3175
- },
3176
- body: data.requestBody,
3177
- mediaType: 'application/json',
3178
- errors: {
3179
- 404: 'Price not found',
3180
- 409: 'Updated price conflicts with existing price'
3181
- }
3182
- });
3183
- }
3184
-
3185
- /**
3186
- * Delete a price
3187
- * Deletes a price entry (hard delete)
3188
- * @param data The data for the request.
3189
- * @param data.id Price ID
3190
- * @param data.region Region code for tenant context
3191
- * @returns void Price deleted successfully
3192
- * @throws ApiError
3193
- */
3194
- public static priceControllerDelete(
3195
- data: PriceControllerDeleteData
3196
- ): CancelablePromise<PriceControllerDeleteResponse> {
3197
- return __request(OpenAPI, {
3198
- method: 'DELETE',
3199
- url: '/api/v1/{region}/bean/prices/{id}',
3200
- path: {
3201
- id: data.id,
3202
- region: data.region
3793
+ asOf: data.asOf,
3794
+ accountId: data.accountId,
3795
+ method: data.method
3203
3796
  },
3204
3797
  errors: {
3205
- 404: 'Price not found'
3798
+ 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3799
+ 401: 'User not authenticated'
3206
3800
  }
3207
3801
  });
3208
3802
  }
3209
-
3210
- /**
3211
- * Bulk create prices
3212
- * Creates multiple price entries at once (skips duplicates)
3213
- * @param data The data for the request.
3214
- * @param data.region Region code for tenant context
3215
- * @param data.requestBody
3216
- * @returns PriceResponseDto Prices created successfully
3217
- * @throws ApiError
3218
- */
3219
- public static priceControllerBulkCreate(
3220
- data: PriceControllerBulkCreateData
3221
- ): CancelablePromise<PriceControllerBulkCreateResponse> {
3222
- return __request(OpenAPI, {
3223
- method: 'POST',
3224
- url: '/api/v1/{region}/bean/prices/bulk',
3225
- path: {
3226
- region: data.region
3227
- },
3228
- body: data.requestBody,
3229
- mediaType: 'application/json'
3230
- });
3231
- }
3232
3803
  }
3233
3804
 
3234
3805
  export class ReportingService {
@@ -3272,6 +3843,42 @@ export class ReportingService {
3272
3843
  });
3273
3844
  }
3274
3845
 
3846
+ /**
3847
+ * Get cash-flow trends
3848
+ *
3849
+ * Monthly income / expense / netSavings over a fixed N-month window
3850
+ * (current month + N−1 prior). Missing months are zero-filled (flow metric).
3851
+ *
3852
+ * **Parameters:**
3853
+ * - `period`: 1m | 3m | 6m | 1y (default 6m)
3854
+ * - `granularity`: accepted for API symmetry; v1 returns month buckets
3855
+ *
3856
+ * @param data The data for the request.
3857
+ * @param data.region Region code for tenant context
3858
+ * @param data.period Time period
3859
+ * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
3860
+ * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
3861
+ * @throws ApiError
3862
+ */
3863
+ public static reportingControllerGetCashFlowTrends(
3864
+ data: ReportingControllerGetCashFlowTrendsData
3865
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
3866
+ return __request(OpenAPI, {
3867
+ method: 'GET',
3868
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
3869
+ path: {
3870
+ region: data.region
3871
+ },
3872
+ query: {
3873
+ period: data.period,
3874
+ granularity: data.granularity
3875
+ },
3876
+ errors: {
3877
+ 401: 'User not authenticated'
3878
+ }
3879
+ });
3880
+ }
3881
+
3275
3882
  /**
3276
3883
  * Generate portfolio snapshot
3277
3884
  *
@@ -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(