@firela/api-types 0.0.0-canary.f2efa2bf → 0.0.0-canary.f73c3118

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,48 @@ import type {
97
99
  CommodityControllerGetOrCreateResponse,
98
100
  CommodityControllerBulkCreateData,
99
101
  CommodityControllerBulkCreateResponse,
102
+ ReportingControllerGetPortfolioTrendsData,
103
+ ReportingControllerGetPortfolioTrendsResponse,
104
+ ReportingControllerGetCashFlowTrendsData,
105
+ ReportingControllerGetCashFlowTrendsResponse,
106
+ ReportingControllerGenerateSnapshotData,
107
+ ReportingControllerGenerateSnapshotResponse,
108
+ ReportingControllerBackfillSnapshotsData,
109
+ ReportingControllerBackfillSnapshotsResponse,
110
+ PriceControllerCreateData,
111
+ PriceControllerCreateResponse,
112
+ PriceControllerFindAllData,
113
+ PriceControllerFindAllResponse,
114
+ PriceControllerFindOneData,
115
+ PriceControllerFindOneResponse,
116
+ PriceControllerUpdateData,
117
+ PriceControllerUpdateResponse,
118
+ PriceControllerDeleteData,
119
+ PriceControllerDeleteResponse,
120
+ PriceControllerBulkCreateData,
121
+ PriceControllerBulkCreateResponse,
122
+ UserControllerDeleteOwnUserData,
123
+ UserControllerDeleteOwnUserResponse,
124
+ UserControllerGetUserData,
125
+ UserControllerGetUserResponse,
126
+ UserControllerSignupUserData,
127
+ UserControllerSignupUserResponse,
128
+ UserControllerDeleteUserData,
129
+ UserControllerDeleteUserResponse,
130
+ UserControllerGetUserInfoData,
131
+ UserControllerGetUserInfoResponse,
132
+ UserControllerUpdateUserSettingData,
133
+ UserControllerUpdateUserSettingResponse,
134
+ UserControllerGetAllUserSettingsByPageData,
135
+ UserControllerGetAllUserSettingsByPageResponse,
136
+ UserControllerGetAssetLiabilitySummaryResponse,
137
+ PropertyControllerGetAllResponse,
138
+ PropertyControllerGetByKeyData,
139
+ PropertyControllerGetByKeyResponse,
140
+ PropertyControllerUpdateData,
141
+ PropertyControllerUpdateResponse,
142
+ PropertyControllerDeleteData,
143
+ PropertyControllerDeleteResponse,
100
144
  RecurringRuleControllerCreateData,
101
145
  RecurringRuleControllerCreateResponse,
102
146
  RecurringRuleControllerFindAllData,
@@ -149,28 +193,30 @@ import type {
149
193
  TransactionRuleControllerDeleteResponse,
150
194
  TransactionRuleControllerTestData,
151
195
  TransactionRuleControllerTestResponse,
152
- UserControllerDeleteOwnUserData,
153
- UserControllerDeleteOwnUserResponse,
154
- UserControllerGetUserData,
155
- UserControllerGetUserResponse,
156
- UserControllerSignupUserData,
157
- UserControllerSignupUserResponse,
158
- UserControllerDeleteUserData,
159
- UserControllerDeleteUserResponse,
160
- UserControllerGetUserInfoData,
161
- UserControllerGetUserInfoResponse,
162
- UserControllerUpdateUserSettingData,
163
- UserControllerUpdateUserSettingResponse,
164
- UserControllerGetAllUserSettingsByPageData,
165
- UserControllerGetAllUserSettingsByPageResponse,
166
- UserControllerGetAssetLiabilitySummaryResponse,
167
- PropertyControllerGetAllResponse,
168
- PropertyControllerGetByKeyData,
169
- PropertyControllerGetByKeyResponse,
170
- PropertyControllerUpdateData,
171
- PropertyControllerUpdateResponse,
172
- PropertyControllerDeleteData,
173
- PropertyControllerDeleteResponse,
196
+ CategoryCatalogControllerListData,
197
+ CategoryCatalogControllerListResponse,
198
+ EventControllerCreateData,
199
+ EventControllerCreateResponse,
200
+ EventControllerFindAllData,
201
+ EventControllerFindAllResponse,
202
+ EventControllerFindOneData,
203
+ EventControllerFindOneResponse,
204
+ EventControllerUpdateData,
205
+ EventControllerUpdateResponse,
206
+ EventControllerDeleteData,
207
+ EventControllerDeleteResponse,
208
+ EventControllerGetSliceData,
209
+ EventControllerGetSliceResponse,
210
+ OnboardingControllerBootstrapData,
211
+ OnboardingControllerBootstrapResponse,
212
+ ReconciliationControllerComputeData,
213
+ ReconciliationControllerComputeResponse,
214
+ ReconciliationControllerAssertData,
215
+ ReconciliationControllerAssertResponse,
216
+ ReconciliationControllerPadData,
217
+ ReconciliationControllerPadResponse,
218
+ ReconciliationControllerHistoryData,
219
+ ReconciliationControllerHistoryResponse,
174
220
  ExportControllerExportBeancountResponse,
175
221
  FileImportControllerImportFileData,
176
222
  FileImportControllerImportFileResponse,
@@ -184,22 +230,20 @@ import type {
184
230
  ImporterConfigControllerUpdateConfigResponse,
185
231
  ImporterConfigControllerResetConfigData,
186
232
  ImporterConfigControllerResetConfigResponse,
187
- PlatformControllerFindAllResponse,
188
- PlatformControllerCreateData,
189
- PlatformControllerCreateResponse,
190
- PlatformControllerGetPlatformListResponse,
191
- PlatformControllerMatchPlatformsData,
192
- PlatformControllerMatchPlatformsResponse,
193
- PlatformControllerUpdateData,
194
- PlatformControllerUpdateResponse,
195
- PlatformControllerDeleteData,
196
- PlatformControllerDeleteResponse,
197
233
  ProviderSyncControllerSyncData,
198
234
  ProviderSyncControllerSyncResponse,
199
235
  ProviderSyncControllerGetSupportedProvidersData,
200
236
  ProviderSyncControllerGetSupportedProvidersResponse,
201
237
  ProviderSyncControllerIsProviderSupportedData,
202
238
  ProviderSyncControllerIsProviderSupportedResponse,
239
+ ExternalAccountLinkControllerCreateData,
240
+ ExternalAccountLinkControllerCreateResponse,
241
+ ExternalAccountLinkControllerFindAllData,
242
+ ExternalAccountLinkControllerFindAllResponse,
243
+ ExternalAccountLinkControllerFindOneData,
244
+ ExternalAccountLinkControllerFindOneResponse,
245
+ ExternalAccountLinkControllerRemoveData,
246
+ ExternalAccountLinkControllerRemoveResponse,
203
247
  TelemetryControllerReportTelemetryData,
204
248
  TelemetryControllerReportTelemetryResponse,
205
249
  TelemetryControllerReportCoverageMissData,
@@ -212,35 +256,34 @@ import type {
212
256
  NlpControllerClearSessionResponse,
213
257
  NlpControllerGetSessionData,
214
258
  NlpControllerGetSessionResponse,
259
+ PlatformControllerFindAllResponse,
260
+ PlatformControllerCreateData,
261
+ PlatformControllerCreateResponse,
262
+ PlatformControllerGetPlatformListData,
263
+ PlatformControllerGetPlatformListResponse,
264
+ PlatformControllerMatchPlatformsData,
265
+ PlatformControllerMatchPlatformsResponse,
266
+ PlatformControllerGetPlatformStandardsData,
267
+ PlatformControllerGetPlatformStandardsResponse,
268
+ PlatformControllerUpdateData,
269
+ PlatformControllerUpdateResponse,
270
+ PlatformControllerDeleteData,
271
+ PlatformControllerDeleteResponse,
215
272
  DashboardControllerGetNetWorthData,
216
273
  DashboardControllerGetNetWorthResponse,
217
274
  DashboardControllerGetAccountsData,
218
275
  DashboardControllerGetAccountsResponse,
219
276
  DashboardControllerGetCashFlowData,
220
277
  DashboardControllerGetCashFlowResponse,
278
+ DashboardControllerGetExpensesData,
279
+ DashboardControllerGetExpensesResponse,
221
280
  HoldingPnlControllerGetHoldingPnlData,
222
281
  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
282
  ApiKeysControllerCreateApiKeyResponse,
242
283
  AuthControllerAccessTokenLoginData,
243
284
  AuthControllerAccessTokenLoginResponse,
285
+ ParserContributionControllerCreateData,
286
+ ParserContributionControllerCreateResponse,
244
287
  CacheControllerFlushCacheResponse,
245
288
  ExchangeRateControllerGetExchangeRateData,
246
289
  ExchangeRateControllerGetExchangeRateResponse,
@@ -252,15 +295,21 @@ import type {
252
295
  HealthControllerResetCircuitBreakerData,
253
296
  HealthControllerResetCircuitBreakerResponse,
254
297
  HealthControllerGetMetricsResponse,
255
- InfoControllerGetInfoResponse
298
+ InfoControllerGetInfoResponse,
299
+ SymbolControllerSearchData,
300
+ SymbolControllerSearchResponse,
301
+ SymbolControllerGetQuoteData,
302
+ SymbolControllerGetQuoteResponse
256
303
  } from './types.gen';
257
304
 
258
305
  export class BeanAccountsService {
259
306
  /**
307
+ * Create a new account
308
+ * Creates a new account (Beancount Open directive)
260
309
  * @param data The data for the request.
261
310
  * @param data.region Region code for tenant context
262
311
  * @param data.requestBody
263
- * @returns unknown
312
+ * @returns AccountResponseDto Account created successfully
264
313
  * @throws ApiError
265
314
  */
266
315
  public static accountControllerCreate(
@@ -273,7 +322,10 @@ export class BeanAccountsService {
273
322
  region: data.region
274
323
  },
275
324
  body: data.requestBody,
276
- mediaType: 'application/json'
325
+ mediaType: 'application/json',
326
+ errors: {
327
+ 409: 'Account already exists'
328
+ }
277
329
  });
278
330
  }
279
331
 
@@ -285,7 +337,7 @@ export class BeanAccountsService {
285
337
  * @param data.type Filter by account type
286
338
  * @param data.status Filter by status
287
339
  * @param data.isCustom Filter by custom (user-created) accounts only
288
- * @param data.search Search term for path or i18nKey
340
+ * @param data.search Search term for account path
289
341
  * @param data.limit Maximum number of results
290
342
  * @param data.offset Number of results to skip
291
343
  * @returns AccountListResponseDto Accounts retrieved successfully
@@ -337,11 +389,13 @@ export class BeanAccountsService {
337
389
  }
338
390
 
339
391
  /**
392
+ * Update account
393
+ * Updates account metadata (path cannot be changed)
340
394
  * @param data The data for the request.
341
- * @param data.id
395
+ * @param data.id Account UUID
342
396
  * @param data.region Region code for tenant context
343
397
  * @param data.requestBody
344
- * @returns unknown
398
+ * @returns AccountResponseDto Account updated successfully
345
399
  * @throws ApiError
346
400
  */
347
401
  public static accountControllerUpdate(
@@ -355,15 +409,20 @@ export class BeanAccountsService {
355
409
  region: data.region
356
410
  },
357
411
  body: data.requestBody,
358
- mediaType: 'application/json'
412
+ mediaType: 'application/json',
413
+ errors: {
414
+ 404: 'Account not found'
415
+ }
359
416
  });
360
417
  }
361
418
 
362
419
  /**
420
+ * Delete account
421
+ * Deletes an account (only if no active transactions; voided/superseded residual postings are cleaned up)
363
422
  * @param data The data for the request.
364
- * @param data.id
423
+ * @param data.id Account UUID
365
424
  * @param data.region Region code for tenant context
366
- * @returns unknown
425
+ * @returns void Account deleted successfully
367
426
  * @throws ApiError
368
427
  */
369
428
  public static accountControllerDelete(
@@ -375,16 +434,22 @@ export class BeanAccountsService {
375
434
  path: {
376
435
  id: data.id,
377
436
  region: data.region
437
+ },
438
+ errors: {
439
+ 404: 'Account not found',
440
+ 409: 'Account has active transactions and cannot be deleted'
378
441
  }
379
442
  });
380
443
  }
381
444
 
382
445
  /**
446
+ * Close account
447
+ * Closes an account (Beancount Close directive)
383
448
  * @param data The data for the request.
384
- * @param data.id
449
+ * @param data.id Account UUID
385
450
  * @param data.region Region code for tenant context
386
451
  * @param data.requestBody
387
- * @returns unknown
452
+ * @returns AccountResponseDto Account closed successfully
388
453
  * @throws ApiError
389
454
  */
390
455
  public static accountControllerClose(
@@ -398,16 +463,22 @@ export class BeanAccountsService {
398
463
  region: data.region
399
464
  },
400
465
  body: data.requestBody,
401
- mediaType: 'application/json'
466
+ mediaType: 'application/json',
467
+ errors: {
468
+ 400: 'Account is already closed',
469
+ 404: 'Account not found'
470
+ }
402
471
  });
403
472
  }
404
473
 
405
474
  /**
475
+ * Reopen account
476
+ * Reopens a previously closed account
406
477
  * @param data The data for the request.
407
- * @param data.id
478
+ * @param data.id Account UUID
408
479
  * @param data.region Region code for tenant context
409
480
  * @param data.requestBody
410
- * @returns unknown
481
+ * @returns AccountResponseDto Account reopened successfully
411
482
  * @throws ApiError
412
483
  */
413
484
  public static accountControllerReopen(
@@ -421,7 +492,40 @@ export class BeanAccountsService {
421
492
  region: data.region
422
493
  },
423
494
  body: data.requestBody,
424
- mediaType: 'application/json'
495
+ mediaType: 'application/json',
496
+ errors: {
497
+ 400: 'Account is not closed',
498
+ 404: 'Account not found'
499
+ }
500
+ });
501
+ }
502
+
503
+ /**
504
+ * Post an opening-balance transaction
505
+ * Posts a double-entry opening-balance transaction against Equity:Opening-Balances for an existing Assets/Liabilities account. At most one active opening balance per account.
506
+ * @param data The data for the request.
507
+ * @param data.id Account UUID
508
+ * @param data.region Region code for tenant context
509
+ * @param data.requestBody
510
+ * @returns OpeningBalanceResultDto Opening-balance transaction created
511
+ * @throws ApiError
512
+ */
513
+ public static accountControllerAddOpeningBalance(
514
+ data: AccountControllerAddOpeningBalanceData
515
+ ): CancelablePromise<AccountControllerAddOpeningBalanceResponse> {
516
+ return __request(OpenAPI, {
517
+ method: 'POST',
518
+ url: '/api/v1/{region}/bean/accounts/{id}/opening-balance',
519
+ path: {
520
+ id: data.id,
521
+ region: data.region
522
+ },
523
+ body: data.requestBody,
524
+ mediaType: 'application/json',
525
+ errors: {
526
+ 404: 'Account not found',
527
+ 409: 'An opening balance already exists for this account'
528
+ }
425
529
  });
426
530
  }
427
531
  }
@@ -429,11 +533,11 @@ export class BeanAccountsService {
429
533
  export class BeanAccountStandardsService {
430
534
  /**
431
535
  * Get account templates
432
- * Returns predefined account templates for a region. Supports filtering by account type and search term.
536
+ * Returns predefined account templates for a region. Supports filtering by account type and search term. Not-yet-open region codes return the universal-only catalog (#759).
433
537
  * @param data The data for the request.
434
- * @param data.region Region code (cn, us, de)
538
+ * @param data.region Region code (any ISO alpha-2; not-yet-open codes return the universal-only catalog)
435
539
  * @param data.type Filter by account type
436
- * @param data.search Search term for path or description
540
+ * @param data.search Search term for path, description, aliases, or localized display name
437
541
  * @returns AccountStandardListResponseDto Account templates retrieved successfully
438
542
  * @throws ApiError
439
543
  */
@@ -455,9 +559,9 @@ export class BeanAccountStandardsService {
455
559
 
456
560
  /**
457
561
  * Get template metadata for an account path
458
- * Returns extendable status and root type for a template path.
562
+ * Returns root type for a template path.
459
563
  * @param data The data for the request.
460
- * @param data.region Region code for tenant context
564
+ * @param data.region Region code for tenant context. Not-yet-open codes degrade to the universal-only catalog (#759)
461
565
  * @param data.path Account path to check
462
566
  * @returns TemplateMetadataResponseDto Template metadata retrieved successfully
463
567
  * @throws ApiError
@@ -479,9 +583,9 @@ export class BeanAccountStandardsService {
479
583
 
480
584
  /**
481
585
  * Get available regions with hierarchy
482
- * Returns supported regions with inheritance metadata
586
+ * Returns the full region catalog (every ISO 3166-1 entry) with an 'open' flag and inheritance metadata (#759)
483
587
  * @param data The data for the request.
484
- * @param data.region Region code for tenant context
588
+ * @param data.region Region code for tenant context. Not-yet-open codes degrade to the universal-only catalog (#759)
485
589
  * @returns RegionsMetadataResponseDto Regions metadata retrieved successfully
486
590
  * @throws ApiError
487
591
  */
@@ -538,9 +642,11 @@ export class BeanTransactionsService {
538
642
  * @param data.offset Number of items to skip (default: 0)
539
643
  * @param data.dateFrom Filter by start date (inclusive), format: YYYY-MM-DD
540
644
  * @param data.dateTo Filter by end date (inclusive), format: YYYY-MM-DD
541
- * @param data.status Filter by transaction status
645
+ * @param data.status Filter by transaction status: single value, comma-separated multi-value (e.g. VOIDED,SUPERSEDED), or ALL to include audit rows. Defaults to ACTIVE-only (ADR-0128; previously unfiltered — breaking change).
542
646
  * @param data.search Search in narration and payee fields (max 200 chars)
543
647
  * @param data.accountId Filter by account ID (transactions with postings to this account)
648
+ * @param data.category Filter by ADR-0075 functional category (Group segment); matches any posting to an account whose derived Group segment equals this value. Must be accompanied by flow (ADR-0126).
649
+ * @param data.flow Required when category is present (400 otherwise) and vice versa (ADR-0126). Restricts the category account set to the flow root (income → Income:, expense → Expenses:) and drives the per-leg sign normalization of row viewpointAmount and the summary. OpenAPI cannot express conditional requiredness — the pairing is enforced at runtime.
544
650
  * @returns TransactionListResponseDto Transaction list
545
651
  * @throws ApiError
546
652
  */
@@ -560,7 +666,9 @@ export class BeanTransactionsService {
560
666
  dateTo: data.dateTo,
561
667
  status: data.status,
562
668
  search: data.search,
563
- accountId: data.accountId
669
+ accountId: data.accountId,
670
+ category: data.category,
671
+ flow: data.flow
564
672
  },
565
673
  errors: {
566
674
  400: 'Validation failed',
@@ -748,7 +856,7 @@ export class BeanBalancesService {
748
856
  * Query account balance
749
857
  * Calculate account balance at a specific date for a single currency
750
858
  * @param data The data for the request.
751
- * @param data.account Account name (e.g., "Assets:Bank:Checking")
859
+ * @param data.account Account name (e.g., "Assets:Checking")
752
860
  * @param data.region Region code for tenant context
753
861
  * @param data.date Date to calculate balance at (ISO 8601 format)
754
862
  * @param data.currency Currency to query (e.g., "USD", "CNY")
@@ -1273,7 +1381,7 @@ export class AdminPayeeProfilesService {
1273
1381
  * Removes verification status by setting verifiedAt to null.
1274
1382
  * @param data The data for the request.
1275
1383
  * @param data.id Payee profile ID (UUID)
1276
- * @returns PayeeProfileResponseDto Payee profile unverified successfully
1384
+ * @returns void Payee profile unverified successfully
1277
1385
  * @throws ApiError
1278
1386
  */
1279
1387
  public static payeeProfileAdminControllerUnverify(
@@ -1469,96 +1577,675 @@ export class BeanCommoditiesService {
1469
1577
  }
1470
1578
  }
1471
1579
 
1472
- export class RecurringRulesService {
1580
+ export class ReportingService {
1473
1581
  /**
1474
- * Create a new recurring rule
1475
- * Creates a new recurring transaction rule for the authenticated user
1582
+ * Get portfolio value trends
1583
+ *
1584
+ * Returns time series data of portfolio net worth.
1585
+ *
1586
+ * **Multi-currency Support:**
1587
+ * - `series[].byCurrency` - Currency breakdown for each data point
1588
+ * - `byCurrency` - Separate time series grouped by currency
1589
+ * - `warnings` - Exchange rate warnings if conversion failed
1590
+ *
1591
+ * **Parameters:**
1592
+ * - `period`: Time period (1m, 3m, 6m, 1y)
1593
+ * - `granularity`: Data granularity (day, week, month)
1594
+ *
1476
1595
  * @param data The data for the request.
1477
1596
  * @param data.region Region code for tenant context
1478
- * @param data.requestBody
1479
- * @returns RecurringRuleResponseDto Rule created successfully
1597
+ * @param data.period Time period
1598
+ * @param data.granularity Data granularity
1599
+ * @returns PortfolioTrendsResponseDto Trends retrieved successfully
1480
1600
  * @throws ApiError
1481
1601
  */
1482
- public static recurringRuleControllerCreate(
1483
- data: RecurringRuleControllerCreateData
1484
- ): CancelablePromise<RecurringRuleControllerCreateResponse> {
1602
+ public static reportingControllerGetPortfolioTrends(
1603
+ data: ReportingControllerGetPortfolioTrendsData
1604
+ ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
1485
1605
  return __request(OpenAPI, {
1486
- method: 'POST',
1487
- url: '/api/v1/{region}/bean/recurring-rules',
1606
+ method: 'GET',
1607
+ url: '/api/v1/{region}/reporting/portfolio/trends',
1488
1608
  path: {
1489
1609
  region: data.region
1490
1610
  },
1491
- body: data.requestBody,
1492
- mediaType: 'application/json',
1611
+ query: {
1612
+ period: data.period,
1613
+ granularity: data.granularity
1614
+ },
1493
1615
  errors: {
1494
- 400: 'Invalid input data (e.g., autoCreate without accounts)',
1495
- 409: 'Rule with same name already exists'
1616
+ 401: 'User not authenticated'
1496
1617
  }
1497
1618
  });
1498
1619
  }
1499
1620
 
1500
1621
  /**
1501
- * List recurring rules
1502
- * Returns all recurring rules for the authenticated user with optional filtering
1622
+ * Get cash-flow trends
1623
+ *
1624
+ * Monthly income / expense / netSavings over a fixed N-month window
1625
+ * (current month + N−1 prior). Missing months are zero-filled (flow metric).
1626
+ *
1627
+ * **Parameters:**
1628
+ * - `period`: 1m | 3m | 6m | 1y (default 6m)
1629
+ * - `granularity`: accepted for API symmetry; v1 returns month buckets
1630
+ *
1503
1631
  * @param data The data for the request.
1504
1632
  * @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
1633
+ * @param data.period Time period
1634
+ * @param data.granularity Data granularity (accepted for API symmetry; v1 returns month buckets)
1635
+ * @returns CashFlowTrendsResponseDto Cash-flow trends retrieved successfully
1509
1636
  * @throws ApiError
1510
1637
  */
1511
- public static recurringRuleControllerFindAll(
1512
- data: RecurringRuleControllerFindAllData
1513
- ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
1638
+ public static reportingControllerGetCashFlowTrends(
1639
+ data: ReportingControllerGetCashFlowTrendsData
1640
+ ): CancelablePromise<ReportingControllerGetCashFlowTrendsResponse> {
1514
1641
  return __request(OpenAPI, {
1515
1642
  method: 'GET',
1516
- url: '/api/v1/{region}/bean/recurring-rules',
1643
+ url: '/api/v1/{region}/reporting/cash-flow/trends',
1517
1644
  path: {
1518
1645
  region: data.region
1519
1646
  },
1520
1647
  query: {
1521
- isActive: data.isActive,
1522
- frequency: data.frequency,
1523
- hasAutoCreate: data.hasAutoCreate
1648
+ period: data.period,
1649
+ granularity: data.granularity
1650
+ },
1651
+ errors: {
1652
+ 401: 'User not authenticated'
1524
1653
  }
1525
1654
  });
1526
1655
  }
1527
1656
 
1528
1657
  /**
1529
- * Create recurring rule from transaction
1530
- * Auto-creates a recurring rule using transaction data. User only confirms frequency.
1658
+ * Generate portfolio snapshot
1659
+ *
1660
+ * Manually generate a portfolio snapshot for a specific date.
1661
+ *
1662
+ * **Multi-currency Support:**
1663
+ * - Fetches balances grouped by currency
1664
+ * - Uses user's baseCurrency setting for conversion
1665
+ * - Stores exchange rates and warnings
1666
+ *
1667
+ * **Use Cases:**
1668
+ * - Testing snapshot generation
1669
+ * - Force regeneration after data correction
1670
+ * - Initial setup for new users
1671
+ *
1531
1672
  * @param data The data for the request.
1532
- * @param data.transactionId Source transaction ID
1533
1673
  * @param data.region Region code for tenant context
1534
- * @param data.requestBody
1535
- * @returns RecurringRuleResponseDto Rule created successfully
1674
+ * @param data.requestBody Optional date (defaults to today)
1675
+ * @returns GenerateSnapshotResponse Snapshot generated successfully
1536
1676
  * @throws ApiError
1537
1677
  */
1538
- public static recurringRuleControllerCreateFromTransaction(
1539
- data: RecurringRuleControllerCreateFromTransactionData
1540
- ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
1678
+ public static reportingControllerGenerateSnapshot(
1679
+ data: ReportingControllerGenerateSnapshotData
1680
+ ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
1541
1681
  return __request(OpenAPI, {
1542
1682
  method: 'POST',
1543
- url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
1683
+ url: '/api/v1/{region}/reporting/snapshots/generate',
1544
1684
  path: {
1545
- transactionId: data.transactionId,
1546
1685
  region: data.region
1547
1686
  },
1548
1687
  body: data.requestBody,
1549
1688
  mediaType: 'application/json',
1550
1689
  errors: {
1551
- 404: 'Transaction not found',
1552
- 409: 'Rule with same name already exists or transaction already linked'
1690
+ 400: 'Invalid date format',
1691
+ 401: 'User not authenticated'
1553
1692
  }
1554
1693
  });
1555
1694
  }
1556
1695
 
1557
1696
  /**
1558
- * Get recurring rule by ID
1559
- * Returns a specific recurring rule with its details
1560
- * @param data The data for the request.
1561
- * @param data.id Rule ID
1697
+ * Backfill portfolio snapshots
1698
+ *
1699
+ * Generate snapshots for a date range (historical data backfill).
1700
+ *
1701
+ * **Multi-currency Support:**
1702
+ * - Each snapshot includes multi-currency data
1703
+ * - Uses exchange rates available at generation time
1704
+ * - Warnings stored for missing exchange rates
1705
+ *
1706
+ * **Best Practices:**
1707
+ * - Use for initial setup after account configuration
1708
+ * - Run during low-traffic periods for large date ranges
1709
+ * - Existing snapshots are skipped (not regenerated)
1710
+ *
1711
+ * @param data The data for the request.
1712
+ * @param data.region Region code for tenant context
1713
+ * @param data.requestBody
1714
+ * @returns BackfillSnapshotsResponse Backfill completed successfully
1715
+ * @throws ApiError
1716
+ */
1717
+ public static reportingControllerBackfillSnapshots(
1718
+ data: ReportingControllerBackfillSnapshotsData
1719
+ ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
1720
+ return __request(OpenAPI, {
1721
+ method: 'POST',
1722
+ url: '/api/v1/{region}/reporting/snapshots/backfill',
1723
+ path: {
1724
+ region: data.region
1725
+ },
1726
+ body: data.requestBody,
1727
+ mediaType: 'application/json',
1728
+ errors: {
1729
+ 400: 'Invalid date format or range',
1730
+ 401: 'User not authenticated',
1731
+ 409: 'Backfill already in progress for this user'
1732
+ }
1733
+ });
1734
+ }
1735
+ }
1736
+
1737
+ export class BeanPricesService {
1738
+ /**
1739
+ * Create a new price
1740
+ * Creates a new price entry for the authenticated user
1741
+ * @param data The data for the request.
1742
+ * @param data.region Region code for tenant context
1743
+ * @param data.requestBody
1744
+ * @returns PriceResponseDto Price created successfully
1745
+ * @throws ApiError
1746
+ */
1747
+ public static priceControllerCreate(
1748
+ data: PriceControllerCreateData
1749
+ ): CancelablePromise<PriceControllerCreateResponse> {
1750
+ return __request(OpenAPI, {
1751
+ method: 'POST',
1752
+ url: '/api/v1/{region}/bean/prices',
1753
+ path: {
1754
+ region: data.region
1755
+ },
1756
+ body: data.requestBody,
1757
+ mediaType: 'application/json',
1758
+ errors: {
1759
+ 404: 'Currency or quoteCurrency commodity not found',
1760
+ 409: 'Price already exists for this currency pair and date'
1761
+ }
1762
+ });
1763
+ }
1764
+
1765
+ /**
1766
+ * List user prices
1767
+ * Returns all price entries for the authenticated user with optional filtering
1768
+ * @param data The data for the request.
1769
+ * @param data.region Region code for tenant context
1770
+ * @param data.currency Filter by currency (e.g., BTC, AAPL, USD)
1771
+ * @param data.quoteCurrency Filter by quote currency (pricing currency, e.g., USD, CNY)
1772
+ * @param data.dateFrom Filter prices from this date (ISO 8601 format)
1773
+ * @param data.dateTo Filter prices to this date (ISO 8601 format)
1774
+ * @param data.search Search term for currency or quoteCurrency (case-insensitive partial match)
1775
+ * @param data.page Page number for pagination (default: 1)
1776
+ * @param data.limit Number of items per page (default: 20, max: 100)
1777
+ * @returns PriceListResponseDto Prices retrieved successfully
1778
+ * @throws ApiError
1779
+ */
1780
+ public static priceControllerFindAll(
1781
+ data: PriceControllerFindAllData
1782
+ ): CancelablePromise<PriceControllerFindAllResponse> {
1783
+ return __request(OpenAPI, {
1784
+ method: 'GET',
1785
+ url: '/api/v1/{region}/bean/prices',
1786
+ path: {
1787
+ region: data.region
1788
+ },
1789
+ query: {
1790
+ currency: data.currency,
1791
+ quoteCurrency: data.quoteCurrency,
1792
+ dateFrom: data.dateFrom,
1793
+ dateTo: data.dateTo,
1794
+ search: data.search,
1795
+ page: data.page,
1796
+ limit: data.limit
1797
+ }
1798
+ });
1799
+ }
1800
+
1801
+ /**
1802
+ * Get price by ID
1803
+ * Returns a single price entry by its ID
1804
+ * @param data The data for the request.
1805
+ * @param data.id Price ID
1806
+ * @param data.region Region code for tenant context
1807
+ * @returns PriceResponseDto Price retrieved successfully
1808
+ * @throws ApiError
1809
+ */
1810
+ public static priceControllerFindOne(
1811
+ data: PriceControllerFindOneData
1812
+ ): CancelablePromise<PriceControllerFindOneResponse> {
1813
+ return __request(OpenAPI, {
1814
+ method: 'GET',
1815
+ url: '/api/v1/{region}/bean/prices/{id}',
1816
+ path: {
1817
+ id: data.id,
1818
+ region: data.region
1819
+ },
1820
+ errors: {
1821
+ 404: 'Price not found'
1822
+ }
1823
+ });
1824
+ }
1825
+
1826
+ /**
1827
+ * Update a price
1828
+ * Updates an existing price entry
1829
+ * @param data The data for the request.
1830
+ * @param data.id Price ID
1831
+ * @param data.region Region code for tenant context
1832
+ * @param data.requestBody
1833
+ * @returns PriceResponseDto Price updated successfully
1834
+ * @throws ApiError
1835
+ */
1836
+ public static priceControllerUpdate(
1837
+ data: PriceControllerUpdateData
1838
+ ): CancelablePromise<PriceControllerUpdateResponse> {
1839
+ return __request(OpenAPI, {
1840
+ method: 'PUT',
1841
+ url: '/api/v1/{region}/bean/prices/{id}',
1842
+ path: {
1843
+ id: data.id,
1844
+ region: data.region
1845
+ },
1846
+ body: data.requestBody,
1847
+ mediaType: 'application/json',
1848
+ errors: {
1849
+ 404: 'Price not found',
1850
+ 409: 'Updated price conflicts with existing price'
1851
+ }
1852
+ });
1853
+ }
1854
+
1855
+ /**
1856
+ * Delete a price
1857
+ * Deletes a price entry (hard delete)
1858
+ * @param data The data for the request.
1859
+ * @param data.id Price ID
1860
+ * @param data.region Region code for tenant context
1861
+ * @returns void Price deleted successfully
1862
+ * @throws ApiError
1863
+ */
1864
+ public static priceControllerDelete(
1865
+ data: PriceControllerDeleteData
1866
+ ): CancelablePromise<PriceControllerDeleteResponse> {
1867
+ return __request(OpenAPI, {
1868
+ method: 'DELETE',
1869
+ url: '/api/v1/{region}/bean/prices/{id}',
1870
+ path: {
1871
+ id: data.id,
1872
+ region: data.region
1873
+ },
1874
+ errors: {
1875
+ 404: 'Price not found'
1876
+ }
1877
+ });
1878
+ }
1879
+
1880
+ /**
1881
+ * Bulk create prices
1882
+ * Creates multiple price entries at once (skips duplicates)
1883
+ * @param data The data for the request.
1884
+ * @param data.region Region code for tenant context
1885
+ * @param data.requestBody
1886
+ * @returns PriceResponseDto Prices created successfully
1887
+ * @throws ApiError
1888
+ */
1889
+ public static priceControllerBulkCreate(
1890
+ data: PriceControllerBulkCreateData
1891
+ ): CancelablePromise<PriceControllerBulkCreateResponse> {
1892
+ return __request(OpenAPI, {
1893
+ method: 'POST',
1894
+ url: '/api/v1/{region}/bean/prices/bulk',
1895
+ path: {
1896
+ region: data.region
1897
+ },
1898
+ body: data.requestBody,
1899
+ mediaType: 'application/json'
1900
+ });
1901
+ }
1902
+ }
1903
+
1904
+ export class UsersService {
1905
+ /**
1906
+ * Delete own user account
1907
+ * @param data The data for the request.
1908
+ * @param data.requestBody
1909
+ * @returns void User deleted successfully
1910
+ * @throws ApiError
1911
+ */
1912
+ public static userControllerDeleteOwnUser(
1913
+ data: UserControllerDeleteOwnUserData
1914
+ ): CancelablePromise<UserControllerDeleteOwnUserResponse> {
1915
+ return __request(OpenAPI, {
1916
+ method: 'DELETE',
1917
+ url: '/api/v1/users',
1918
+ body: data.requestBody,
1919
+ mediaType: 'application/json',
1920
+ errors: {
1921
+ 403: 'Invalid access token'
1922
+ }
1923
+ });
1924
+ }
1925
+
1926
+ /**
1927
+ * Get current authenticated user
1928
+ * @param data The data for the request.
1929
+ * @param data.acceptLanguage
1930
+ * @returns UserResponseDto User retrieved successfully
1931
+ * @throws ApiError
1932
+ */
1933
+ public static userControllerGetUser(
1934
+ data: UserControllerGetUserData
1935
+ ): CancelablePromise<UserControllerGetUserResponse> {
1936
+ return __request(OpenAPI, {
1937
+ method: 'GET',
1938
+ url: '/api/v1/users',
1939
+ headers: {
1940
+ 'accept-language': data.acceptLanguage
1941
+ }
1942
+ });
1943
+ }
1944
+
1945
+ /**
1946
+ * Sign up new user
1947
+ * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
1948
+ * @param data The data for the request.
1949
+ * @param data.requestBody
1950
+ * @returns SignupResponseDto User created successfully
1951
+ * @throws ApiError
1952
+ */
1953
+ public static userControllerSignupUser(
1954
+ data: UserControllerSignupUserData
1955
+ ): CancelablePromise<UserControllerSignupUserResponse> {
1956
+ return __request(OpenAPI, {
1957
+ method: 'POST',
1958
+ url: '/api/v1/users',
1959
+ body: data.requestBody,
1960
+ mediaType: 'application/json',
1961
+ errors: {
1962
+ 400: 'Invalid Turnstile token (when Turnstile is enabled)',
1963
+ 403: 'User signup is disabled'
1964
+ }
1965
+ });
1966
+ }
1967
+
1968
+ /**
1969
+ * Delete user by ID (admin only)
1970
+ * @param data The data for the request.
1971
+ * @param data.id User ID to delete
1972
+ * @returns void User deleted successfully
1973
+ * @throws ApiError
1974
+ */
1975
+ public static userControllerDeleteUser(
1976
+ data: UserControllerDeleteUserData
1977
+ ): CancelablePromise<UserControllerDeleteUserResponse> {
1978
+ return __request(OpenAPI, {
1979
+ method: 'DELETE',
1980
+ url: '/api/v1/users/{id}',
1981
+ path: {
1982
+ id: data.id
1983
+ },
1984
+ errors: {
1985
+ 403: 'Cannot delete own account or insufficient permissions'
1986
+ }
1987
+ });
1988
+ }
1989
+
1990
+ /**
1991
+ * Get user info by user ID
1992
+ * @param data The data for the request.
1993
+ * @param data.id User ID
1994
+ * @returns unknown User info retrieved successfully
1995
+ * @throws ApiError
1996
+ */
1997
+ public static userControllerGetUserInfo(
1998
+ data: UserControllerGetUserInfoData
1999
+ ): CancelablePromise<UserControllerGetUserInfoResponse> {
2000
+ return __request(OpenAPI, {
2001
+ method: 'GET',
2002
+ url: '/api/v1/users/{id}/info',
2003
+ path: {
2004
+ id: data.id
2005
+ },
2006
+ errors: {
2007
+ 403: 'Cannot access other user info without admin permission'
2008
+ }
2009
+ });
2010
+ }
2011
+
2012
+ /**
2013
+ * Update user settings
2014
+ * @param data The data for the request.
2015
+ * @param data.requestBody
2016
+ * @returns unknown Settings updated successfully
2017
+ * @throws ApiError
2018
+ */
2019
+ public static userControllerUpdateUserSetting(
2020
+ data: UserControllerUpdateUserSettingData
2021
+ ): CancelablePromise<UserControllerUpdateUserSettingResponse> {
2022
+ return __request(OpenAPI, {
2023
+ method: 'PUT',
2024
+ url: '/api/v1/users/setting',
2025
+ body: data.requestBody,
2026
+ mediaType: 'application/json',
2027
+ errors: {
2028
+ 403: 'Insufficient permissions'
2029
+ }
2030
+ });
2031
+ }
2032
+
2033
+ /**
2034
+ * Get all user settings paginated (admin only)
2035
+ * @param data The data for the request.
2036
+ * @param data.pageNo Page number
2037
+ * @param data.pageSize Page size
2038
+ * @returns unknown Settings list retrieved successfully
2039
+ * @throws ApiError
2040
+ */
2041
+ public static userControllerGetAllUserSettingsByPage(
2042
+ data: UserControllerGetAllUserSettingsByPageData
2043
+ ): CancelablePromise<UserControllerGetAllUserSettingsByPageResponse> {
2044
+ return __request(OpenAPI, {
2045
+ method: 'GET',
2046
+ url: '/api/v1/users/settings-by-page',
2047
+ query: {
2048
+ pageNo: data.pageNo,
2049
+ pageSize: data.pageSize
2050
+ }
2051
+ });
2052
+ }
2053
+
2054
+ /**
2055
+ * Get asset and liability summary for current user
2056
+ * @returns unknown Summary retrieved successfully
2057
+ * @throws ApiError
2058
+ */
2059
+ public static userControllerGetAssetLiabilitySummary(): CancelablePromise<UserControllerGetAssetLiabilitySummaryResponse> {
2060
+ return __request(OpenAPI, {
2061
+ method: 'GET',
2062
+ url: '/api/v1/users/asset-liability-summary'
2063
+ });
2064
+ }
2065
+ }
2066
+
2067
+ export class PropertiesService {
2068
+ /**
2069
+ * Get all system properties
2070
+ * @returns unknown Properties retrieved successfully
2071
+ * @throws ApiError
2072
+ */
2073
+ public static propertyControllerGetAll(): CancelablePromise<PropertyControllerGetAllResponse> {
2074
+ return __request(OpenAPI, {
2075
+ method: 'GET',
2076
+ url: '/api/v1/admin/properties',
2077
+ errors: {
2078
+ 401: 'Unauthorized',
2079
+ 403: 'Forbidden - insufficient permissions'
2080
+ }
2081
+ });
2082
+ }
2083
+
2084
+ /**
2085
+ * Get property by key
2086
+ * @param data The data for the request.
2087
+ * @param data.key Property key
2088
+ * @returns unknown Property retrieved successfully
2089
+ * @throws ApiError
2090
+ */
2091
+ public static propertyControllerGetByKey(
2092
+ data: PropertyControllerGetByKeyData
2093
+ ): CancelablePromise<PropertyControllerGetByKeyResponse> {
2094
+ return __request(OpenAPI, {
2095
+ method: 'GET',
2096
+ url: '/api/v1/admin/properties/{key}',
2097
+ path: {
2098
+ key: data.key
2099
+ },
2100
+ errors: {
2101
+ 401: 'Unauthorized',
2102
+ 403: 'Forbidden - insufficient permissions',
2103
+ 404: 'Property not found'
2104
+ }
2105
+ });
2106
+ }
2107
+
2108
+ /**
2109
+ * Update a system property
2110
+ * @param data The data for the request.
2111
+ * @param data.key Property key
2112
+ * @param data.requestBody
2113
+ * @returns unknown Property updated successfully
2114
+ * @throws ApiError
2115
+ */
2116
+ public static propertyControllerUpdate(
2117
+ data: PropertyControllerUpdateData
2118
+ ): CancelablePromise<PropertyControllerUpdateResponse> {
2119
+ return __request(OpenAPI, {
2120
+ method: 'PUT',
2121
+ url: '/api/v1/admin/properties/{key}',
2122
+ path: {
2123
+ key: data.key
2124
+ },
2125
+ body: data.requestBody,
2126
+ mediaType: 'application/json',
2127
+ errors: {
2128
+ 401: 'Unauthorized',
2129
+ 403: 'Forbidden - insufficient permissions'
2130
+ }
2131
+ });
2132
+ }
2133
+
2134
+ /**
2135
+ * Delete a system property
2136
+ * @param data The data for the request.
2137
+ * @param data.key Property key
2138
+ * @returns void Property deleted successfully
2139
+ * @throws ApiError
2140
+ */
2141
+ public static propertyControllerDelete(
2142
+ data: PropertyControllerDeleteData
2143
+ ): CancelablePromise<PropertyControllerDeleteResponse> {
2144
+ return __request(OpenAPI, {
2145
+ method: 'DELETE',
2146
+ url: '/api/v1/admin/properties/{key}',
2147
+ path: {
2148
+ key: data.key
2149
+ },
2150
+ errors: {
2151
+ 401: 'Unauthorized',
2152
+ 403: 'Forbidden - insufficient permissions',
2153
+ 404: 'Property not found'
2154
+ }
2155
+ });
2156
+ }
2157
+ }
2158
+
2159
+ export class RecurringRulesService {
2160
+ /**
2161
+ * Create a new recurring rule
2162
+ * Creates a new recurring transaction rule for the authenticated user
2163
+ * @param data The data for the request.
2164
+ * @param data.region Region code for tenant context
2165
+ * @param data.requestBody
2166
+ * @returns RecurringRuleResponseDto Rule created successfully
2167
+ * @throws ApiError
2168
+ */
2169
+ public static recurringRuleControllerCreate(
2170
+ data: RecurringRuleControllerCreateData
2171
+ ): CancelablePromise<RecurringRuleControllerCreateResponse> {
2172
+ return __request(OpenAPI, {
2173
+ method: 'POST',
2174
+ url: '/api/v1/{region}/bean/recurring-rules',
2175
+ path: {
2176
+ region: data.region
2177
+ },
2178
+ body: data.requestBody,
2179
+ mediaType: 'application/json',
2180
+ errors: {
2181
+ 400: 'Invalid input data (e.g., autoCreate without accounts)',
2182
+ 409: 'Rule with same name already exists'
2183
+ }
2184
+ });
2185
+ }
2186
+
2187
+ /**
2188
+ * List recurring rules
2189
+ * Returns all recurring rules for the authenticated user with optional filtering
2190
+ * @param data The data for the request.
2191
+ * @param data.region Region code for tenant context
2192
+ * @param data.isActive Filter by active status
2193
+ * @param data.frequency Filter by frequency (WEEKLY, MONTHLY, etc.)
2194
+ * @param data.hasAutoCreate Filter by autoCreate enabled
2195
+ * @returns RecurringRuleResponseDto Rules retrieved successfully
2196
+ * @throws ApiError
2197
+ */
2198
+ public static recurringRuleControllerFindAll(
2199
+ data: RecurringRuleControllerFindAllData
2200
+ ): CancelablePromise<RecurringRuleControllerFindAllResponse> {
2201
+ return __request(OpenAPI, {
2202
+ method: 'GET',
2203
+ url: '/api/v1/{region}/bean/recurring-rules',
2204
+ path: {
2205
+ region: data.region
2206
+ },
2207
+ query: {
2208
+ isActive: data.isActive,
2209
+ frequency: data.frequency,
2210
+ hasAutoCreate: data.hasAutoCreate
2211
+ }
2212
+ });
2213
+ }
2214
+
2215
+ /**
2216
+ * Create recurring rule from transaction
2217
+ * Auto-creates a recurring rule using transaction data. User only confirms frequency.
2218
+ * @param data The data for the request.
2219
+ * @param data.transactionId Source transaction ID
2220
+ * @param data.region Region code for tenant context
2221
+ * @param data.requestBody
2222
+ * @returns RecurringRuleResponseDto Rule created successfully
2223
+ * @throws ApiError
2224
+ */
2225
+ public static recurringRuleControllerCreateFromTransaction(
2226
+ data: RecurringRuleControllerCreateFromTransactionData
2227
+ ): CancelablePromise<RecurringRuleControllerCreateFromTransactionResponse> {
2228
+ return __request(OpenAPI, {
2229
+ method: 'POST',
2230
+ url: '/api/v1/{region}/bean/recurring-rules/from-transaction/{transactionId}',
2231
+ path: {
2232
+ transactionId: data.transactionId,
2233
+ region: data.region
2234
+ },
2235
+ body: data.requestBody,
2236
+ mediaType: 'application/json',
2237
+ errors: {
2238
+ 404: 'Transaction not found',
2239
+ 409: 'Rule with same name already exists or transaction already linked'
2240
+ }
2241
+ });
2242
+ }
2243
+
2244
+ /**
2245
+ * Get recurring rule by ID
2246
+ * Returns a specific recurring rule with its details
2247
+ * @param data The data for the request.
2248
+ * @param data.id Rule ID
1562
2249
  * @param data.region Region code for tenant context
1563
2250
  * @returns RecurringRuleResponseDto Rule retrieved successfully
1564
2251
  * @throws ApiError
@@ -1767,7 +2454,7 @@ export class ExpectedTransactionsService {
1767
2454
  * @param data The data for the request.
1768
2455
  * @param data.id Expected transaction ID
1769
2456
  * @param data.region Region code for tenant context
1770
- * @returns ExpectedTransactionResponseDto Skip undone successfully
2457
+ * @returns void Skip undone successfully
1771
2458
  * @throws ApiError
1772
2459
  */
1773
2460
  public static expectedTransactionControllerUndoSkip(
@@ -1823,7 +2510,7 @@ export class ExpectedTransactionsService {
1823
2510
  * @param data The data for the request.
1824
2511
  * @param data.id Expected transaction ID
1825
2512
  * @param data.region Region code for tenant context
1826
- * @returns unknown Match removed successfully
2513
+ * @returns void Match removed successfully
1827
2514
  * @throws ApiError
1828
2515
  */
1829
2516
  public static expectedTransactionControllerUnmatch(
@@ -2177,256 +2864,337 @@ export class BeanTransactionRulesService {
2177
2864
  }
2178
2865
  }
2179
2866
 
2180
- export class UsersService {
2867
+ export class BeanCategoryCatalogService {
2181
2868
  /**
2182
- * Delete own user account
2869
+ * List category catalog for a region
2870
+ * Returns the region-scoped category slugs (expense/income/investment/banking/transfer/payment) for the NLP result picker. CN-exclusive payment instruments (huabei/baitiao) appear only under /cn.
2183
2871
  * @param data The data for the request.
2184
- * @param data.requestBody
2185
- * @returns void User deleted successfully
2872
+ * @param data.region Region code for tenant context
2873
+ * @param data.scenario Filter by scenario
2874
+ * @param data.routeBearing Filter by routeBearing (entity-router route() consumes it)
2875
+ * @returns CategoryCatalogListResponseDto Category catalog retrieved successfully
2186
2876
  * @throws ApiError
2187
2877
  */
2188
- public static userControllerDeleteOwnUser(
2189
- data: UserControllerDeleteOwnUserData
2190
- ): CancelablePromise<UserControllerDeleteOwnUserResponse> {
2878
+ public static categoryCatalogControllerList(
2879
+ data: CategoryCatalogControllerListData
2880
+ ): CancelablePromise<CategoryCatalogControllerListResponse> {
2191
2881
  return __request(OpenAPI, {
2192
- method: 'DELETE',
2193
- url: '/api/v1/users',
2194
- body: data.requestBody,
2195
- mediaType: 'application/json',
2196
- errors: {
2197
- 403: 'Invalid access token'
2882
+ method: 'GET',
2883
+ url: '/api/v1/{region}/bean/categories',
2884
+ path: {
2885
+ region: data.region
2886
+ },
2887
+ query: {
2888
+ scenario: data.scenario,
2889
+ routeBearing: data.routeBearing
2198
2890
  }
2199
2891
  });
2200
2892
  }
2893
+ }
2201
2894
 
2895
+ export class LifeEventsService {
2202
2896
  /**
2203
- * Get current authenticated user
2897
+ * Create a new life event
2898
+ * Creates a new life event entry for the authenticated user. Returns ETag header carrying the row updatedAt.
2204
2899
  * @param data The data for the request.
2205
- * @param data.acceptLanguage
2206
- * @returns unknown User retrieved successfully
2900
+ * @param data.region Region code for tenant context (decorative for life events)
2901
+ * @param data.requestBody
2902
+ * @returns EventResponseDto Life event created successfully
2207
2903
  * @throws ApiError
2208
2904
  */
2209
- public static userControllerGetUser(
2210
- data: UserControllerGetUserData
2211
- ): CancelablePromise<UserControllerGetUserResponse> {
2905
+ public static eventControllerCreate(
2906
+ data: EventControllerCreateData
2907
+ ): CancelablePromise<EventControllerCreateResponse> {
2212
2908
  return __request(OpenAPI, {
2213
- method: 'GET',
2214
- url: '/api/v1/users',
2215
- headers: {
2216
- 'accept-language': data.acceptLanguage
2909
+ method: 'POST',
2910
+ url: '/api/v1/{region}/bean/events',
2911
+ path: {
2912
+ region: data.region
2913
+ },
2914
+ body: data.requestBody,
2915
+ mediaType: 'application/json',
2916
+ errors: {
2917
+ 409: 'Life event already exists for this (userId, type, date) combination'
2217
2918
  }
2218
2919
  });
2219
2920
  }
2220
2921
 
2221
2922
  /**
2222
- * Sign up new user
2223
- * Create a new account with auto-generated access token. Protected by Cloudflare Turnstile to prevent automated signup (when enabled).
2923
+ * List user life events
2924
+ * Returns life events for the authenticated user with optional filtering by type, description search, and date range.
2224
2925
  * @param data The data for the request.
2225
- * @param data.requestBody
2226
- * @returns unknown User created successfully
2926
+ * @param data.region Region code for tenant context (decorative for life events)
2927
+ * @param data.type Filter by life event type (exact match)
2928
+ * @param data.q Search term for description (case-insensitive partial match)
2929
+ * @param data.from Filter life events from this date (ISO 8601 format)
2930
+ * @param data.to Filter life events to this date (ISO 8601 format)
2931
+ * @param data.page Page number for pagination (default: 1)
2932
+ * @param data.limit Number of items per page (default: 20, max: 100)
2933
+ * @returns EventListResponseDto Life events retrieved successfully
2227
2934
  * @throws ApiError
2228
2935
  */
2229
- public static userControllerSignupUser(
2230
- data: UserControllerSignupUserData
2231
- ): CancelablePromise<UserControllerSignupUserResponse> {
2936
+ public static eventControllerFindAll(
2937
+ data: EventControllerFindAllData
2938
+ ): CancelablePromise<EventControllerFindAllResponse> {
2232
2939
  return __request(OpenAPI, {
2233
- method: 'POST',
2234
- url: '/api/v1/users',
2235
- body: data.requestBody,
2236
- mediaType: 'application/json',
2237
- errors: {
2238
- 400: 'Invalid Turnstile token (when Turnstile is enabled)',
2239
- 403: 'User signup is disabled'
2940
+ method: 'GET',
2941
+ url: '/api/v1/{region}/bean/events',
2942
+ path: {
2943
+ region: data.region
2944
+ },
2945
+ query: {
2946
+ type: data.type,
2947
+ q: data.q,
2948
+ from: data.from,
2949
+ to: data.to,
2950
+ page: data.page,
2951
+ limit: data.limit
2240
2952
  }
2241
2953
  });
2242
2954
  }
2243
2955
 
2244
2956
  /**
2245
- * Delete user by ID (admin only)
2957
+ * Get life event by ID
2958
+ * Returns a single life event by its ID. Returns ETag header.
2246
2959
  * @param data The data for the request.
2247
- * @param data.id User ID to delete
2248
- * @returns void User deleted successfully
2960
+ * @param data.id Life event ID
2961
+ * @param data.region Region code for tenant context (decorative for life events)
2962
+ * @returns EventResponseDto Life event retrieved successfully
2249
2963
  * @throws ApiError
2250
2964
  */
2251
- public static userControllerDeleteUser(
2252
- data: UserControllerDeleteUserData
2253
- ): CancelablePromise<UserControllerDeleteUserResponse> {
2965
+ public static eventControllerFindOne(
2966
+ data: EventControllerFindOneData
2967
+ ): CancelablePromise<EventControllerFindOneResponse> {
2254
2968
  return __request(OpenAPI, {
2255
- method: 'DELETE',
2256
- url: '/api/v1/users/{id}',
2969
+ method: 'GET',
2970
+ url: '/api/v1/{region}/bean/events/{id}',
2257
2971
  path: {
2258
- id: data.id
2972
+ id: data.id,
2973
+ region: data.region
2259
2974
  },
2260
2975
  errors: {
2261
- 403: 'Cannot delete own account or insufficient permissions'
2976
+ 404: 'Life event not found'
2262
2977
  }
2263
2978
  });
2264
2979
  }
2265
2980
 
2266
2981
  /**
2267
- * Get user info by user ID
2982
+ * Update a life event
2983
+ * Updates an existing life event. If If-Match header is provided, performs optimistic concurrency check; mismatched updatedAt returns 412.
2268
2984
  * @param data The data for the request.
2269
- * @param data.id User ID
2270
- * @returns unknown User info retrieved successfully
2985
+ * @param data.id Life event ID
2986
+ * @param data.region Region code for tenant context (decorative for life events)
2987
+ * @param data.requestBody
2988
+ * @returns EventResponseDto Life event updated successfully
2271
2989
  * @throws ApiError
2272
2990
  */
2273
- public static userControllerGetUserInfo(
2274
- data: UserControllerGetUserInfoData
2275
- ): CancelablePromise<UserControllerGetUserInfoResponse> {
2991
+ public static eventControllerUpdate(
2992
+ data: EventControllerUpdateData
2993
+ ): CancelablePromise<EventControllerUpdateResponse> {
2276
2994
  return __request(OpenAPI, {
2277
- method: 'GET',
2278
- url: '/api/v1/users/{id}/info',
2995
+ method: 'PUT',
2996
+ url: '/api/v1/{region}/bean/events/{id}',
2279
2997
  path: {
2280
- id: data.id
2998
+ id: data.id,
2999
+ region: data.region
2281
3000
  },
3001
+ body: data.requestBody,
3002
+ mediaType: 'application/json',
2282
3003
  errors: {
2283
- 403: 'Cannot access other user info without admin permission'
3004
+ 400: 'If-Match header is not a valid ISO 8601 date',
3005
+ 404: 'Life event not found',
3006
+ 409: 'Updated event conflicts with an existing (userId, type, date) combination',
3007
+ 412: 'If-Match precondition failed (updatedAt mismatch)'
2284
3008
  }
2285
3009
  });
2286
3010
  }
2287
3011
 
2288
3012
  /**
2289
- * Update user settings
3013
+ * Delete a life event
3014
+ * Deletes a life event entry (hard delete). Returns 204.
2290
3015
  * @param data The data for the request.
2291
- * @param data.requestBody
2292
- * @returns unknown Settings updated successfully
3016
+ * @param data.id Life event ID
3017
+ * @param data.region Region code for tenant context (decorative for life events)
3018
+ * @returns void Life event deleted successfully
2293
3019
  * @throws ApiError
2294
3020
  */
2295
- public static userControllerUpdateUserSetting(
2296
- data: UserControllerUpdateUserSettingData
2297
- ): CancelablePromise<UserControllerUpdateUserSettingResponse> {
3021
+ public static eventControllerDelete(
3022
+ data: EventControllerDeleteData
3023
+ ): CancelablePromise<EventControllerDeleteResponse> {
2298
3024
  return __request(OpenAPI, {
2299
- method: 'PUT',
2300
- url: '/api/v1/users/setting',
2301
- body: data.requestBody,
2302
- mediaType: 'application/json',
3025
+ method: 'DELETE',
3026
+ url: '/api/v1/{region}/bean/events/{id}',
3027
+ path: {
3028
+ id: data.id,
3029
+ region: data.region
3030
+ },
2303
3031
  errors: {
2304
- 403: 'Insufficient permissions'
3032
+ 404: 'Life event not found'
2305
3033
  }
2306
3034
  });
2307
3035
  }
2308
3036
 
2309
3037
  /**
2310
- * Get all user settings paginated (admin only)
3038
+ * Slice time-series by a life event (Phase 79)
3039
+ * Returns aggregated time-series for postings matching accountPattern within the half-open date range of the given life event.
2311
3040
  * @param data The data for the request.
2312
- * @param data.pageNo Page number
2313
- * @param data.pageSize Page size
2314
- * @returns unknown Settings list retrieved successfully
3041
+ * @param data.id Life event ID
3042
+ * @param data.accountPattern
3043
+ * @param data.granularity
3044
+ * @param data.region Region code for tenant context (decorative for life events)
3045
+ * @returns unknown Time-series sliced by the life event range
2315
3046
  * @throws ApiError
2316
3047
  */
2317
- public static userControllerGetAllUserSettingsByPage(
2318
- data: UserControllerGetAllUserSettingsByPageData
2319
- ): CancelablePromise<UserControllerGetAllUserSettingsByPageResponse> {
3048
+ public static eventControllerGetSlice(
3049
+ data: EventControllerGetSliceData
3050
+ ): CancelablePromise<EventControllerGetSliceResponse> {
2320
3051
  return __request(OpenAPI, {
2321
3052
  method: 'GET',
2322
- url: '/api/v1/users/settings-by-page',
3053
+ url: '/api/v1/{region}/bean/events/{id}/slice',
3054
+ path: {
3055
+ id: data.id,
3056
+ region: data.region
3057
+ },
2323
3058
  query: {
2324
- pageNo: data.pageNo,
2325
- pageSize: data.pageSize
3059
+ accountPattern: data.accountPattern,
3060
+ granularity: data.granularity
3061
+ },
3062
+ errors: {
3063
+ 400: 'accountPattern query param is empty',
3064
+ 404: 'Life event not found'
2326
3065
  }
2327
3066
  });
2328
3067
  }
3068
+ }
2329
3069
 
3070
+ export class OnboardingService {
2330
3071
  /**
2331
- * Get asset and liability summary for current user
2332
- * @returns unknown Summary retrieved successfully
3072
+ * Bootstrap core accounts + register asset accounts with opening balances (ADR-0113)
3073
+ * @param data The data for the request.
3074
+ * @param data.region Region code for tenant context. Not-yet-open codes are accepted: the universal catalog backs onboarding regardless of region (#759)
3075
+ * @param data.requestBody
3076
+ * @returns unknown Onboarding bootstrap result.
2333
3077
  * @throws ApiError
2334
3078
  */
2335
- public static userControllerGetAssetLiabilitySummary(): CancelablePromise<UserControllerGetAssetLiabilitySummaryResponse> {
3079
+ public static onboardingControllerBootstrap(
3080
+ data: OnboardingControllerBootstrapData
3081
+ ): CancelablePromise<OnboardingControllerBootstrapResponse> {
2336
3082
  return __request(OpenAPI, {
2337
- method: 'GET',
2338
- url: '/api/v1/users/asset-liability-summary'
3083
+ method: 'POST',
3084
+ url: '/api/v1/{region}/bean/onboarding',
3085
+ path: {
3086
+ region: data.region
3087
+ },
3088
+ body: data.requestBody,
3089
+ mediaType: 'application/json',
3090
+ errors: {
3091
+ 422: 'Invalid region/account path/duplicate paths.'
3092
+ }
2339
3093
  });
2340
3094
  }
2341
3095
  }
2342
3096
 
2343
- export class PropertiesService {
3097
+ export class BalanceReconciliationService {
2344
3098
  /**
2345
- * Get all system properties
2346
- * @returns unknown Properties retrieved successfully
3099
+ * Preview reconciliation (book vs actual)
3100
+ * Computes book balance, diff, Beancount-inferred tolerance, and suggested action without persisting.
3101
+ * @param data The data for the request.
3102
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3103
+ * @param data.requestBody
3104
+ * @returns ReconciliationComputeResultDto Reconciliation preview
2347
3105
  * @throws ApiError
2348
3106
  */
2349
- public static propertyControllerGetAll(): CancelablePromise<PropertyControllerGetAllResponse> {
3107
+ public static reconciliationControllerCompute(
3108
+ data: ReconciliationControllerComputeData
3109
+ ): CancelablePromise<ReconciliationControllerComputeResponse> {
2350
3110
  return __request(OpenAPI, {
2351
- method: 'GET',
2352
- url: '/api/v1/admin/properties',
3111
+ method: 'POST',
3112
+ url: '/api/v1/{region}/bean/reconciliations',
3113
+ path: {
3114
+ region: data.region
3115
+ },
3116
+ body: data.requestBody,
3117
+ mediaType: 'application/json',
2353
3118
  errors: {
2354
- 401: 'Unauthorized',
2355
- 403: 'Forbidden - insufficient permissions'
3119
+ 404: 'Account not found'
2356
3120
  }
2357
3121
  });
2358
3122
  }
2359
3123
 
2360
3124
  /**
2361
- * Get property by key
3125
+ * Record a balance assertion
3126
+ * Persists the reconciliation as a BeanBalance assertion (amount = actual, diffAmount = book − actual). Re-reconciling the same day/currency upserts.
2362
3127
  * @param data The data for the request.
2363
- * @param data.key Property key
2364
- * @returns unknown Property retrieved successfully
3128
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3129
+ * @param data.requestBody
3130
+ * @returns ReconciliationRecordDto Balance assertion recorded
2365
3131
  * @throws ApiError
2366
3132
  */
2367
- public static propertyControllerGetByKey(
2368
- data: PropertyControllerGetByKeyData
2369
- ): CancelablePromise<PropertyControllerGetByKeyResponse> {
3133
+ public static reconciliationControllerAssert(
3134
+ data: ReconciliationControllerAssertData
3135
+ ): CancelablePromise<ReconciliationControllerAssertResponse> {
2370
3136
  return __request(OpenAPI, {
2371
- method: 'GET',
2372
- url: '/api/v1/admin/properties/{key}',
3137
+ method: 'POST',
3138
+ url: '/api/v1/{region}/bean/reconciliations/assert',
2373
3139
  path: {
2374
- key: data.key
3140
+ region: data.region
2375
3141
  },
3142
+ body: data.requestBody,
3143
+ mediaType: 'application/json',
2376
3144
  errors: {
2377
- 401: 'Unauthorized',
2378
- 403: 'Forbidden - insufficient permissions',
2379
- 404: 'Property not found'
3145
+ 404: 'Account not found'
2380
3146
  }
2381
3147
  });
2382
3148
  }
2383
3149
 
2384
3150
  /**
2385
- * Update a system property
3151
+ * Generate a pad adjusting entry
3152
+ * When book is outside tolerance, synthesizes a Beancount pad transaction (flag P) booking the diff from source_account and persists it. Source defaults to Equity:Opening-Balances.
2386
3153
  * @param data The data for the request.
2387
- * @param data.key Property key
3154
+ * @param data.region Region code for tenant context (decorative for reconciliation)
2388
3155
  * @param data.requestBody
2389
- * @returns unknown Property updated successfully
3156
+ * @returns PadResultDto Pad adjusting entry generated
2390
3157
  * @throws ApiError
2391
3158
  */
2392
- public static propertyControllerUpdate(
2393
- data: PropertyControllerUpdateData
2394
- ): CancelablePromise<PropertyControllerUpdateResponse> {
3159
+ public static reconciliationControllerPad(
3160
+ data: ReconciliationControllerPadData
3161
+ ): CancelablePromise<ReconciliationControllerPadResponse> {
2395
3162
  return __request(OpenAPI, {
2396
- method: 'PUT',
2397
- url: '/api/v1/admin/properties/{key}',
3163
+ method: 'POST',
3164
+ url: '/api/v1/{region}/bean/reconciliations/pad',
2398
3165
  path: {
2399
- key: data.key
3166
+ region: data.region
2400
3167
  },
2401
3168
  body: data.requestBody,
2402
3169
  mediaType: 'application/json',
2403
3170
  errors: {
2404
- 401: 'Unauthorized',
2405
- 403: 'Forbidden - insufficient permissions'
3171
+ 400: 'Book already within tolerance — no pad needed',
3172
+ 404: 'Account not found'
2406
3173
  }
2407
3174
  });
2408
3175
  }
2409
3176
 
2410
3177
  /**
2411
- * Delete a system property
3178
+ * List reconciliation history for an account
3179
+ * Returns recorded balance assertions (most recent first). The latest drives the account-detail "Last <date>" badge.
2412
3180
  * @param data The data for the request.
2413
- * @param data.key Property key
2414
- * @returns void Property deleted successfully
3181
+ * @param data.accountId BeanAccount id
3182
+ * @param data.region Region code for tenant context (decorative for reconciliation)
3183
+ * @returns ReconciliationRecordDto Reconciliation history
2415
3184
  * @throws ApiError
2416
3185
  */
2417
- public static propertyControllerDelete(
2418
- data: PropertyControllerDeleteData
2419
- ): CancelablePromise<PropertyControllerDeleteResponse> {
3186
+ public static reconciliationControllerHistory(
3187
+ data: ReconciliationControllerHistoryData
3188
+ ): CancelablePromise<ReconciliationControllerHistoryResponse> {
2420
3189
  return __request(OpenAPI, {
2421
- method: 'DELETE',
2422
- url: '/api/v1/admin/properties/{key}',
3190
+ method: 'GET',
3191
+ url: '/api/v1/{region}/bean/accounts/{accountId}/reconciliations',
2423
3192
  path: {
2424
- key: data.key
3193
+ accountId: data.accountId,
3194
+ region: data.region
2425
3195
  },
2426
3196
  errors: {
2427
- 401: 'Unauthorized',
2428
- 403: 'Forbidden - insufficient permissions',
2429
- 404: 'Property not found'
3197
+ 404: 'Account not found'
2430
3198
  }
2431
3199
  });
2432
3200
  }
@@ -2436,7 +3204,7 @@ export class BeanExportService {
2436
3204
  /**
2437
3205
  * Export Beancount ledger as ZIP
2438
3206
  * Export all user Beancount data as a ZIP file containing ledger.beancount and yearly files in community format.
2439
- * @returns unknown
3207
+ * @returns binary ZIP archive (application/zip) streamed as an attachment
2440
3208
  * @throws ApiError
2441
3209
  */
2442
3210
  public static exportControllerExportBeancount(): CancelablePromise<ExportControllerExportBeancountResponse> {
@@ -2504,9 +3272,12 @@ export class BeanImportService {
2504
3272
  }
2505
3273
 
2506
3274
  /**
3275
+ * Import a Beancount file in community format
3276
+ * 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.
2507
3277
  * @param data The data for the request.
2508
3278
  * @param data.region Region code for tenant context
2509
- * @returns unknown
3279
+ * @param data.formData Beancount file to import
3280
+ * @returns unknown Beancount file imported successfully
2510
3281
  * @throws ApiError
2511
3282
  */
2512
3283
  public static fileImportControllerImportBeancount(
@@ -2517,6 +3288,11 @@ export class BeanImportService {
2517
3288
  url: '/api/v1/{region}/bean/import/beancount',
2518
3289
  path: {
2519
3290
  region: data.region
3291
+ },
3292
+ formData: data.formData,
3293
+ mediaType: 'multipart/form-data',
3294
+ errors: {
3295
+ 400: 'Bad request - invalid file or no file uploaded'
2520
3296
  }
2521
3297
  });
2522
3298
  }
@@ -2592,126 +3368,11 @@ export class BeanImportService {
2592
3368
  method: 'POST',
2593
3369
  url: '/api/v1/{region}/bean/import/config/{importerId}/reset',
2594
3370
  path: {
2595
- importerId: data.importerId,
2596
- region: data.region
2597
- },
2598
- errors: {
2599
- 400: 'Invalid input - Unsupported importer'
2600
- }
2601
- });
2602
- }
2603
- }
2604
-
2605
- export class BeanPlatformsService {
2606
- /**
2607
- * Get all platforms with statistics
2608
- * @returns unknown List of platforms with binding and account counts
2609
- * @throws ApiError
2610
- */
2611
- public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2612
- return __request(OpenAPI, {
2613
- method: 'GET',
2614
- url: '/api/v1/bean/platforms'
2615
- });
2616
- }
2617
-
2618
- /**
2619
- * Create a new platform
2620
- * @param data The data for the request.
2621
- * @param data.requestBody
2622
- * @returns unknown Platform created successfully
2623
- * @throws ApiError
2624
- */
2625
- public static platformControllerCreate(
2626
- data: PlatformControllerCreateData
2627
- ): CancelablePromise<PlatformControllerCreateResponse> {
2628
- return __request(OpenAPI, {
2629
- method: 'POST',
2630
- url: '/api/v1/bean/platforms',
2631
- body: data.requestBody,
2632
- mediaType: 'application/json',
2633
- errors: {
2634
- 409: 'Platform already exists'
2635
- }
2636
- });
2637
- }
2638
-
2639
- /**
2640
- * Get platform list for current user
2641
- * @returns unknown List of platforms with user binding status
2642
- * @throws ApiError
2643
- */
2644
- public static platformControllerGetPlatformList(): CancelablePromise<PlatformControllerGetPlatformListResponse> {
2645
- return __request(OpenAPI, {
2646
- method: 'GET',
2647
- url: '/api/v1/bean/platforms/list'
2648
- });
2649
- }
2650
-
2651
- /**
2652
- * Match platforms by name or alias
2653
- * @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
2657
- * @throws ApiError
2658
- */
2659
- public static platformControllerMatchPlatforms(
2660
- data: PlatformControllerMatchPlatformsData
2661
- ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
2662
- return __request(OpenAPI, {
2663
- method: 'GET',
2664
- url: '/api/v1/bean/platforms/match',
2665
- query: {
2666
- q: data.q,
2667
- region: data.region
2668
- }
2669
- });
2670
- }
2671
-
2672
- /**
2673
- * Update a platform
2674
- * @param data The data for the request.
2675
- * @param data.id Platform ID
2676
- * @param data.requestBody
2677
- * @returns unknown Platform updated successfully
2678
- * @throws ApiError
2679
- */
2680
- public static platformControllerUpdate(
2681
- data: PlatformControllerUpdateData
2682
- ): CancelablePromise<PlatformControllerUpdateResponse> {
2683
- return __request(OpenAPI, {
2684
- method: 'PUT',
2685
- url: '/api/v1/bean/platforms/{id}',
2686
- path: {
2687
- id: data.id
2688
- },
2689
- body: data.requestBody,
2690
- mediaType: 'application/json',
2691
- errors: {
2692
- 404: 'Platform not found'
2693
- }
2694
- });
2695
- }
2696
-
2697
- /**
2698
- * Delete a platform
2699
- * @param data The data for the request.
2700
- * @param data.id Platform ID
2701
- * @returns void Platform deleted successfully
2702
- * @throws ApiError
2703
- */
2704
- public static platformControllerDelete(
2705
- data: PlatformControllerDeleteData
2706
- ): CancelablePromise<PlatformControllerDeleteResponse> {
2707
- return __request(OpenAPI, {
2708
- method: 'DELETE',
2709
- url: '/api/v1/bean/platforms/{id}',
2710
- path: {
2711
- id: data.id
3371
+ importerId: data.importerId,
3372
+ region: data.region
2712
3373
  },
2713
3374
  errors: {
2714
- 404: 'Platform not found'
3375
+ 400: 'Invalid input - Unsupported importer'
2715
3376
  }
2716
3377
  });
2717
3378
  }
@@ -2719,11 +3380,33 @@ export class BeanPlatformsService {
2719
3380
 
2720
3381
  export class ProviderSyncService {
2721
3382
  /**
3383
+ * Sync transactions from financial data provider
3384
+ *
3385
+ * Accepts raw transactions from external financial data providers, transforms them to Beancount format, and processes them through the ingestion pipeline.
3386
+ *
3387
+ * **Supported Providers:**
3388
+ * - **plaid**: Plaid API (US, Canada, Europe)
3389
+ * - **teller**: Teller API (US)
3390
+ * - **truelayer**: TrueLayer Open Banking (UK, Europe)
3391
+ * - **gocardless**: GoCardless Bank Account Data (Europe)
3392
+ * - **simplefin**: SimpleFIN (Self-hosted)
3393
+ * - **yodlee**: Yodlee (Global)
3394
+ * - **beancount-direct**: Beancount format transactions
3395
+ * - **parsed-bill**: Client-side parsed bill transactions
3396
+ *
3397
+ * **Processing Flow:**
3398
+ * 1. Transform raw data via provider adapter
3399
+ * 2. Validate transaction format
3400
+ * 3. Deduplicate using originalId
3401
+ * 4. Classify using rule engine
3402
+ * 5. Route low-confidence to Review Center
3403
+ * 6. Persist validated transactions
3404
+ *
2722
3405
  * @param data The data for the request.
2723
- * @param data.providerName
3406
+ * @param data.providerName Provider name
2724
3407
  * @param data.region Region code for tenant context
2725
3408
  * @param data.requestBody
2726
- * @returns unknown
3409
+ * @returns ProviderSyncResponseDto Sync completed successfully
2727
3410
  * @throws ApiError
2728
3411
  */
2729
3412
  public static providerSyncControllerSync(
@@ -2737,7 +3420,12 @@ export class ProviderSyncService {
2737
3420
  region: data.region
2738
3421
  },
2739
3422
  body: data.requestBody,
2740
- mediaType: 'application/json'
3423
+ mediaType: 'application/json',
3424
+ errors: {
3425
+ 400: 'Invalid request data',
3426
+ 401: 'Missing or invalid authentication',
3427
+ 404: 'Provider not supported'
3428
+ }
2741
3429
  });
2742
3430
  }
2743
3431
 
@@ -2790,6 +3478,101 @@ export class ProviderSyncService {
2790
3478
  }
2791
3479
  }
2792
3480
 
3481
+ export class ExternalAccountLinksService {
3482
+ /**
3483
+ * Create an external account → BeanAccount mapping (ADR-0113)
3484
+ * @param data The data for the request.
3485
+ * @param data.region Region code for tenant context
3486
+ * @param data.requestBody
3487
+ * @returns ExternalAccountLinkResponseDto Link created.
3488
+ * @throws ApiError
3489
+ */
3490
+ public static externalAccountLinkControllerCreate(
3491
+ data: ExternalAccountLinkControllerCreateData
3492
+ ): CancelablePromise<ExternalAccountLinkControllerCreateResponse> {
3493
+ return __request(OpenAPI, {
3494
+ method: 'POST',
3495
+ url: '/api/v1/{region}/bean/external-account-links',
3496
+ path: {
3497
+ region: data.region
3498
+ },
3499
+ body: data.requestBody,
3500
+ mediaType: 'application/json',
3501
+ errors: {
3502
+ 422: 'beanAccountId not owned, or an active link already exists.'
3503
+ }
3504
+ });
3505
+ }
3506
+
3507
+ /**
3508
+ * List the user's active external account links
3509
+ * @param data The data for the request.
3510
+ * @param data.provider
3511
+ * @param data.region Region code for tenant context
3512
+ * @returns ExternalAccountLinkListResponseDto Links retrieved.
3513
+ * @throws ApiError
3514
+ */
3515
+ public static externalAccountLinkControllerFindAll(
3516
+ data: ExternalAccountLinkControllerFindAllData
3517
+ ): CancelablePromise<ExternalAccountLinkControllerFindAllResponse> {
3518
+ return __request(OpenAPI, {
3519
+ method: 'GET',
3520
+ url: '/api/v1/{region}/bean/external-account-links',
3521
+ path: {
3522
+ region: data.region
3523
+ },
3524
+ query: {
3525
+ provider: data.provider
3526
+ }
3527
+ });
3528
+ }
3529
+
3530
+ /**
3531
+ * Get a single external account link
3532
+ * @param data The data for the request.
3533
+ * @param data.id
3534
+ * @param data.region Region code for tenant context
3535
+ * @returns ExternalAccountLinkResponseDto Link retrieved.
3536
+ * @throws ApiError
3537
+ */
3538
+ public static externalAccountLinkControllerFindOne(
3539
+ data: ExternalAccountLinkControllerFindOneData
3540
+ ): CancelablePromise<ExternalAccountLinkControllerFindOneResponse> {
3541
+ return __request(OpenAPI, {
3542
+ method: 'GET',
3543
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3544
+ path: {
3545
+ id: data.id,
3546
+ region: data.region
3547
+ },
3548
+ errors: {
3549
+ 422: 'Link not found or not owned by the user.'
3550
+ }
3551
+ });
3552
+ }
3553
+
3554
+ /**
3555
+ * Soft-delete (disconnect) an external account link
3556
+ * @param data The data for the request.
3557
+ * @param data.id
3558
+ * @param data.region Region code for tenant context
3559
+ * @returns void Link soft-deleted; historical transactions are unaffected.
3560
+ * @throws ApiError
3561
+ */
3562
+ public static externalAccountLinkControllerRemove(
3563
+ data: ExternalAccountLinkControllerRemoveData
3564
+ ): CancelablePromise<ExternalAccountLinkControllerRemoveResponse> {
3565
+ return __request(OpenAPI, {
3566
+ method: 'DELETE',
3567
+ url: '/api/v1/{region}/bean/external-account-links/{id}',
3568
+ path: {
3569
+ id: data.id,
3570
+ region: data.region
3571
+ }
3572
+ });
3573
+ }
3574
+ }
3575
+
2793
3576
  export class ImportTelemetryService {
2794
3577
  /**
2795
3578
  * Receive anonymous parser failure telemetry
@@ -2867,10 +3650,12 @@ export class ImportTelemetryService {
2867
3650
 
2868
3651
  export class BeanNlpService {
2869
3652
  /**
3653
+ * Process natural language input
3654
+ * Parse natural language text (Chinese/English) describing a transaction. Supports multi-turn dialogue for collecting missing information. When confidence < 0.75, returns "confirm" action requiring user verification. User can reply with confirmation words (确认/yes/ok) or provide corrections. Examples: "yesterday Starbucks spent 35 yuan", "today lunch 28 yuan", "spent $50 at Walmart"
2870
3655
  * @param data The data for the request.
2871
3656
  * @param data.region Region code for tenant context
2872
- * @param data.requestBody
2873
- * @returns unknown
3657
+ * @param data.requestBody Natural language transaction input with optional session ID
3658
+ * @returns NlpResponseDto NLP processing result - either created transaction or asking for more info
2874
3659
  * @throws ApiError
2875
3660
  */
2876
3661
  public static nlpControllerProcessNaturalLanguage(
@@ -2883,7 +3668,11 @@ export class BeanNlpService {
2883
3668
  region: data.region
2884
3669
  },
2885
3670
  body: data.requestBody,
2886
- mediaType: 'application/json'
3671
+ mediaType: 'application/json',
3672
+ errors: {
3673
+ 400: 'Invalid input',
3674
+ 401: 'Unauthorized'
3675
+ }
2887
3676
  });
2888
3677
  }
2889
3678
 
@@ -2942,411 +3731,302 @@ export class BeanNlpService {
2942
3731
  }
2943
3732
  }
2944
3733
 
2945
- export class DashboardService {
3734
+ export class BeanPlatformsService {
2946
3735
  /**
2947
- * Get net worth overview
2948
- * Returns total net worth with breakdown of assets and liabilities
2949
- * @param data The data for the request.
2950
- * @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
3736
+ * Get all platforms with statistics
3737
+ * @returns unknown List of platforms with binding and account counts
2953
3738
  * @throws ApiError
2954
3739
  */
2955
- public static dashboardControllerGetNetWorth(
2956
- data: DashboardControllerGetNetWorthData
2957
- ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3740
+ public static platformControllerFindAll(): CancelablePromise<PlatformControllerFindAllResponse> {
2958
3741
  return __request(OpenAPI, {
2959
3742
  method: 'GET',
2960
- url: '/api/v1/{region}/dashboard/net-worth',
2961
- path: {
2962
- region: data.region
2963
- },
2964
- query: {
2965
- date: data.date
2966
- },
2967
- errors: {
2968
- 401: 'User not authenticated'
2969
- }
3743
+ url: '/api/v1/bean/platforms'
2970
3744
  });
2971
3745
  }
2972
3746
 
2973
3747
  /**
2974
- * Get accounts grouped by platform
2975
- * Returns accounts with balances grouped by financial platform
3748
+ * Create a new platform
2976
3749
  * @param data The data for the request.
2977
- * @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.
3750
+ * @param data.requestBody
3751
+ * @returns unknown Platform created successfully
2982
3752
  * @throws ApiError
2983
3753
  */
2984
- public static dashboardControllerGetAccounts(
2985
- data: DashboardControllerGetAccountsData
2986
- ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3754
+ public static platformControllerCreate(
3755
+ data: PlatformControllerCreateData
3756
+ ): CancelablePromise<PlatformControllerCreateResponse> {
2987
3757
  return __request(OpenAPI, {
2988
- method: 'GET',
2989
- url: '/api/v1/{region}/dashboard/accounts',
2990
- path: {
2991
- region: data.region
2992
- },
2993
- query: {
2994
- groupBy: data.groupBy,
2995
- date: data.date,
2996
- accountId: data.accountId
2997
- },
3758
+ method: 'POST',
3759
+ url: '/api/v1/bean/platforms',
3760
+ body: data.requestBody,
3761
+ mediaType: 'application/json',
2998
3762
  errors: {
2999
- 401: 'User not authenticated'
3763
+ 409: 'Platform already exists'
3000
3764
  }
3001
3765
  });
3002
3766
  }
3003
3767
 
3004
3768
  /**
3005
- * Get cash flow summary
3006
- * Returns income, expenses, and savings for a monthly period
3769
+ * Get platform list for current user
3007
3770
  * @param data The data for the request.
3008
- * @param data.period Period in YYYY-MM format
3009
- * @param data.region Region code for tenant context
3010
- * @returns CashFlowResponseDto Cash flow retrieved successfully
3771
+ * @param data.region Region code (ISO 3166-1 alpha-2) that biases within-type-bucket ordering (local-region platforms first). Case-insensitive — stored/compared UPPERCASE ("cn" == "CN").
3772
+ * @returns PlatformListItemDto List of platforms with user binding status
3011
3773
  * @throws ApiError
3012
3774
  */
3013
- public static dashboardControllerGetCashFlow(
3014
- data: DashboardControllerGetCashFlowData
3015
- ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3775
+ public static platformControllerGetPlatformList(
3776
+ data: PlatformControllerGetPlatformListData = {}
3777
+ ): CancelablePromise<PlatformControllerGetPlatformListResponse> {
3016
3778
  return __request(OpenAPI, {
3017
3779
  method: 'GET',
3018
- url: '/api/v1/{region}/dashboard/cash-flow',
3019
- path: {
3020
- region: data.region
3021
- },
3780
+ url: '/api/v1/bean/platforms/list',
3022
3781
  query: {
3023
- period: data.period
3024
- },
3025
- errors: {
3026
- 400: 'Invalid period format',
3027
- 401: 'User not authenticated'
3782
+ region: data.region
3028
3783
  }
3029
3784
  });
3030
3785
  }
3031
- }
3032
3786
 
3033
- export class InvestmentService {
3034
3787
  /**
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).
3788
+ * Match platforms by name or alias
3037
3789
  * @param data The data for the request.
3038
- * @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
3790
+ * @param data.q Search query Chinese name, English name, or abbreviation
3791
+ * @param data.region Region code (ISO 3166-1 alpha-2) that biases within-tier ordering (local-region platforms first); also the intended categoryOverrides key. Case-insensitive — stored/compared UPPERCASE ("cn" == "CN").
3792
+ * @returns PlatformMatchResponseDto Matching platforms with overall match type and truncation flag
3043
3793
  * @throws ApiError
3044
3794
  */
3045
- public static holdingPnlControllerGetHoldingPnl(
3046
- data: HoldingPnlControllerGetHoldingPnlData
3047
- ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3795
+ public static platformControllerMatchPlatforms(
3796
+ data: PlatformControllerMatchPlatformsData
3797
+ ): CancelablePromise<PlatformControllerMatchPlatformsResponse> {
3048
3798
  return __request(OpenAPI, {
3049
3799
  method: 'GET',
3050
- url: '/api/v1/{region}/investment/holdings/pnl',
3051
- path: {
3052
- region: data.region
3053
- },
3800
+ url: '/api/v1/bean/platforms/match',
3054
3801
  query: {
3055
- asOf: data.asOf,
3056
- accountId: data.accountId,
3057
- method: data.method
3058
- },
3059
- errors: {
3060
- 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
3061
- 401: 'User not authenticated'
3062
- }
3063
- });
3064
- }
3065
- }
3066
-
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: {
3802
+ q: data.q,
3084
3803
  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
3804
  }
3092
3805
  });
3093
3806
  }
3094
3807
 
3095
3808
  /**
3096
- * List user prices
3097
- * Returns all price entries for the authenticated user with optional filtering
3809
+ * Get the region and candidate account standards for a platform
3098
3810
  * @param data The data for the request.
3099
- * @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
3811
+ * @param data.id Platform ID (from a match result)
3812
+ * @param data.region Region code (ISO 3166-1 alpha-2, case-insensitive). Required for global platforms (countryCode null) — resolved as their template region; ignored when the platform has its own countryCode.
3813
+ * @param data.type Filter templates by account type (path first segment)
3814
+ * @returns PlatformStandardsResponseDto Resolved region plus the merged account-standard catalog of that region (groupable by productCategory client-side)
3108
3815
  * @throws ApiError
3109
3816
  */
3110
- public static priceControllerFindAll(
3111
- data: PriceControllerFindAllData
3112
- ): CancelablePromise<PriceControllerFindAllResponse> {
3817
+ public static platformControllerGetPlatformStandards(
3818
+ data: PlatformControllerGetPlatformStandardsData
3819
+ ): CancelablePromise<PlatformControllerGetPlatformStandardsResponse> {
3113
3820
  return __request(OpenAPI, {
3114
3821
  method: 'GET',
3115
- url: '/api/v1/{region}/bean/prices',
3822
+ url: '/api/v1/bean/platforms/{id}/standards',
3116
3823
  path: {
3117
- region: data.region
3824
+ id: data.id
3118
3825
  },
3119
3826
  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
3827
+ region: data.region,
3828
+ type: data.type
3127
3829
  }
3128
3830
  });
3129
3831
  }
3130
3832
 
3131
3833
  /**
3132
- * Get price by ID
3133
- * Returns a single price entry by its ID
3834
+ * Update a platform
3134
3835
  * @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
3836
+ * @param data.id Platform ID
3837
+ * @param data.requestBody
3838
+ * @returns unknown Platform updated successfully
3138
3839
  * @throws ApiError
3139
3840
  */
3140
- public static priceControllerFindOne(
3141
- data: PriceControllerFindOneData
3142
- ): CancelablePromise<PriceControllerFindOneResponse> {
3841
+ public static platformControllerUpdate(
3842
+ data: PlatformControllerUpdateData
3843
+ ): CancelablePromise<PlatformControllerUpdateResponse> {
3143
3844
  return __request(OpenAPI, {
3144
- method: 'GET',
3145
- url: '/api/v1/{region}/bean/prices/{id}',
3845
+ method: 'PUT',
3846
+ url: '/api/v1/bean/platforms/{id}',
3146
3847
  path: {
3147
- id: data.id,
3148
- region: data.region
3848
+ id: data.id
3149
3849
  },
3850
+ body: data.requestBody,
3851
+ mediaType: 'application/json',
3150
3852
  errors: {
3151
- 404: 'Price not found'
3853
+ 404: 'Platform not found'
3152
3854
  }
3153
3855
  });
3154
3856
  }
3155
3857
 
3156
3858
  /**
3157
- * Update a price
3158
- * Updates an existing price entry
3859
+ * Delete a platform
3159
3860
  * @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
3861
+ * @param data.id Platform ID
3862
+ * @returns void Platform deleted successfully
3164
3863
  * @throws ApiError
3165
3864
  */
3166
- public static priceControllerUpdate(
3167
- data: PriceControllerUpdateData
3168
- ): CancelablePromise<PriceControllerUpdateResponse> {
3865
+ public static platformControllerDelete(
3866
+ data: PlatformControllerDeleteData
3867
+ ): CancelablePromise<PlatformControllerDeleteResponse> {
3169
3868
  return __request(OpenAPI, {
3170
- method: 'PUT',
3171
- url: '/api/v1/{region}/bean/prices/{id}',
3869
+ method: 'DELETE',
3870
+ url: '/api/v1/bean/platforms/{id}',
3172
3871
  path: {
3173
- id: data.id,
3174
- region: data.region
3872
+ id: data.id
3175
3873
  },
3176
- body: data.requestBody,
3177
- mediaType: 'application/json',
3178
3874
  errors: {
3179
- 404: 'Price not found',
3180
- 409: 'Updated price conflicts with existing price'
3875
+ 404: 'Platform not found'
3181
3876
  }
3182
3877
  });
3183
3878
  }
3879
+ }
3184
3880
 
3881
+ export class DashboardService {
3185
3882
  /**
3186
- * Delete a price
3187
- * Deletes a price entry (hard delete)
3883
+ * Get net worth overview
3884
+ * Returns total net worth with breakdown of assets and liabilities
3188
3885
  * @param data The data for the request.
3189
- * @param data.id Price ID
3190
3886
  * @param data.region Region code for tenant context
3191
- * @returns void Price deleted successfully
3887
+ * @param data.date Date for balance calculation (ISO 8601 format)
3888
+ * @returns NetWorthResponseDto Net worth retrieved successfully
3192
3889
  * @throws ApiError
3193
3890
  */
3194
- public static priceControllerDelete(
3195
- data: PriceControllerDeleteData
3196
- ): CancelablePromise<PriceControllerDeleteResponse> {
3891
+ public static dashboardControllerGetNetWorth(
3892
+ data: DashboardControllerGetNetWorthData
3893
+ ): CancelablePromise<DashboardControllerGetNetWorthResponse> {
3197
3894
  return __request(OpenAPI, {
3198
- method: 'DELETE',
3199
- url: '/api/v1/{region}/bean/prices/{id}',
3895
+ method: 'GET',
3896
+ url: '/api/v1/{region}/dashboard/net-worth',
3200
3897
  path: {
3201
- id: data.id,
3202
3898
  region: data.region
3203
3899
  },
3900
+ query: {
3901
+ date: data.date
3902
+ },
3204
3903
  errors: {
3205
- 404: 'Price not found'
3904
+ 401: 'User not authenticated'
3206
3905
  }
3207
3906
  });
3208
3907
  }
3209
3908
 
3210
3909
  /**
3211
- * Bulk create prices
3212
- * Creates multiple price entries at once (skips duplicates)
3910
+ * Get accounts grouped by platform
3911
+ * Returns accounts with balances grouped by financial platform
3213
3912
  * @param data The data for the request.
3214
3913
  * @param data.region Region code for tenant context
3215
- * @param data.requestBody
3216
- * @returns PriceResponseDto Prices created successfully
3914
+ * @param data.groupBy Grouping strategy
3915
+ * @param data.date Date for balance calculation (ISO 8601 format)
3916
+ * @param data.accountId Scope to a single account (only valid with groupBy=holdingAssetClass, ADR-0105 §6)
3917
+ * @returns unknown Accounts retrieved successfully. Response type depends on groupBy parameter.
3217
3918
  * @throws ApiError
3218
3919
  */
3219
- public static priceControllerBulkCreate(
3220
- data: PriceControllerBulkCreateData
3221
- ): CancelablePromise<PriceControllerBulkCreateResponse> {
3920
+ public static dashboardControllerGetAccounts(
3921
+ data: DashboardControllerGetAccountsData
3922
+ ): CancelablePromise<DashboardControllerGetAccountsResponse> {
3222
3923
  return __request(OpenAPI, {
3223
- method: 'POST',
3224
- url: '/api/v1/{region}/bean/prices/bulk',
3924
+ method: 'GET',
3925
+ url: '/api/v1/{region}/dashboard/accounts',
3225
3926
  path: {
3226
3927
  region: data.region
3227
3928
  },
3228
- body: data.requestBody,
3229
- mediaType: 'application/json'
3929
+ query: {
3930
+ groupBy: data.groupBy,
3931
+ date: data.date,
3932
+ accountId: data.accountId
3933
+ },
3934
+ errors: {
3935
+ 401: 'User not authenticated'
3936
+ }
3230
3937
  });
3231
3938
  }
3232
- }
3233
3939
 
3234
- export class ReportingService {
3235
3940
  /**
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
- *
3941
+ * Get cash flow summary
3942
+ * Returns income, expenses, and savings for a monthly period
3249
3943
  * @param data The data for the request.
3944
+ * @param data.period Period in YYYY-MM format
3250
3945
  * @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
3946
+ * @returns CashFlowResponseDto Cash flow retrieved successfully
3254
3947
  * @throws ApiError
3255
3948
  */
3256
- public static reportingControllerGetPortfolioTrends(
3257
- data: ReportingControllerGetPortfolioTrendsData
3258
- ): CancelablePromise<ReportingControllerGetPortfolioTrendsResponse> {
3949
+ public static dashboardControllerGetCashFlow(
3950
+ data: DashboardControllerGetCashFlowData
3951
+ ): CancelablePromise<DashboardControllerGetCashFlowResponse> {
3259
3952
  return __request(OpenAPI, {
3260
3953
  method: 'GET',
3261
- url: '/api/v1/{region}/reporting/portfolio/trends',
3954
+ url: '/api/v1/{region}/dashboard/cash-flow',
3262
3955
  path: {
3263
3956
  region: data.region
3264
3957
  },
3265
3958
  query: {
3266
- period: data.period,
3267
- granularity: data.granularity
3959
+ period: data.period
3268
3960
  },
3269
3961
  errors: {
3962
+ 400: 'Invalid period format',
3270
3963
  401: 'User not authenticated'
3271
3964
  }
3272
3965
  });
3273
3966
  }
3274
3967
 
3275
3968
  /**
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
- *
3969
+ * Get expenses/income grouped by functional category
3970
+ * Returns amounts pre-aggregated by functional category (account-path Group segment) with server-side multi-currency conversion. flow=expense (default) aggregates ^Expenses: accounts; flow=income aggregates ^Income: accounts (issue #518)
3290
3971
  * @param data The data for the request.
3291
3972
  * @param data.region Region code for tenant context
3292
- * @param data.requestBody Optional date (defaults to today)
3293
- * @returns GenerateSnapshotResponse Snapshot generated successfully
3973
+ * @param data.groupBy Grouping strategy
3974
+ * @param data.period Time window (1m = current calendar month)
3975
+ * @param data.flow Account root to aggregate (expense → ^Expenses:, income → ^Income:)
3976
+ * @returns ExpensesByCategoryResponseDto Expenses retrieved successfully
3294
3977
  * @throws ApiError
3295
3978
  */
3296
- public static reportingControllerGenerateSnapshot(
3297
- data: ReportingControllerGenerateSnapshotData
3298
- ): CancelablePromise<ReportingControllerGenerateSnapshotResponse> {
3979
+ public static dashboardControllerGetExpenses(
3980
+ data: DashboardControllerGetExpensesData
3981
+ ): CancelablePromise<DashboardControllerGetExpensesResponse> {
3299
3982
  return __request(OpenAPI, {
3300
- method: 'POST',
3301
- url: '/api/v1/{region}/reporting/snapshots/generate',
3983
+ method: 'GET',
3984
+ url: '/api/v1/{region}/dashboard/expenses',
3302
3985
  path: {
3303
3986
  region: data.region
3304
3987
  },
3305
- body: data.requestBody,
3306
- mediaType: 'application/json',
3988
+ query: {
3989
+ groupBy: data.groupBy,
3990
+ period: data.period,
3991
+ flow: data.flow
3992
+ },
3307
3993
  errors: {
3308
- 400: 'Invalid date format',
3994
+ 400: 'Invalid groupBy or period',
3309
3995
  401: 'User not authenticated'
3310
3996
  }
3311
3997
  });
3312
3998
  }
3999
+ }
3313
4000
 
4001
+ export class InvestmentService {
3314
4002
  /**
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
- *
4003
+ * Get per-holding unrealized + realized P&L
4004
+ * Average-cost unrealized P&L per account × commodity, plus cumulative realized P&L on sold lots (method = FIFO | average, default average).
3329
4005
  * @param data The data for the request.
3330
4006
  * @param data.region Region code for tenant context
3331
- * @param data.requestBody
3332
- * @returns BackfillSnapshotsResponse Backfill completed successfully
4007
+ * @param data.asOf As-of date (ISO 8601), defaults to today
4008
+ * @param data.accountId Scope to a single account
4009
+ * @param data.method Realized-P&L lot-matching method (default average). Does not affect the average-cost unrealized basis.
4010
+ * @returns HoldingPnlResponseDto Holding P&L retrieved successfully
3333
4011
  * @throws ApiError
3334
4012
  */
3335
- public static reportingControllerBackfillSnapshots(
3336
- data: ReportingControllerBackfillSnapshotsData
3337
- ): CancelablePromise<ReportingControllerBackfillSnapshotsResponse> {
4013
+ public static holdingPnlControllerGetHoldingPnl(
4014
+ data: HoldingPnlControllerGetHoldingPnlData
4015
+ ): CancelablePromise<HoldingPnlControllerGetHoldingPnlResponse> {
3338
4016
  return __request(OpenAPI, {
3339
- method: 'POST',
3340
- url: '/api/v1/{region}/reporting/snapshots/backfill',
4017
+ method: 'GET',
4018
+ url: '/api/v1/{region}/investment/holdings/pnl',
3341
4019
  path: {
3342
4020
  region: data.region
3343
4021
  },
3344
- body: data.requestBody,
3345
- mediaType: 'application/json',
4022
+ query: {
4023
+ asOf: data.asOf,
4024
+ accountId: data.accountId,
4025
+ method: data.method
4026
+ },
3346
4027
  errors: {
3347
- 400: 'Invalid date format or range',
3348
- 401: 'User not authenticated',
3349
- 409: 'Backfill already in progress for this user'
4028
+ 400: 'Invalid asOf format/value/future date, invalid accountId format, or unsupported method',
4029
+ 401: 'User not authenticated'
3350
4030
  }
3351
4031
  });
3352
4032
  }
@@ -3375,7 +4055,7 @@ export class AuthService {
3375
4055
  * Anonymous login with access token
3376
4056
  * @param data The data for the request.
3377
4057
  * @param data.requestBody
3378
- * @returns unknown Login successful
4058
+ * @returns AnonymousLoginResponseDto Login successful
3379
4059
  * @throws ApiError
3380
4060
  */
3381
4061
  public static authControllerAccessTokenLogin(
@@ -3393,15 +4073,52 @@ export class AuthService {
3393
4073
  }
3394
4074
  }
3395
4075
 
3396
- export class DefaultService {
4076
+ export class CommunityService {
4077
+ /**
4078
+ * Relay a sanitized parser-contribution payload
4079
+ * A server-side bot re-sanitizes the payload and opens an issue on the target repository; the issue URL is returned. The payload is never persisted or logged (forward-and-drop).
4080
+ * @param data The data for the request.
4081
+ * @param data.region Region code for tenant context (routing only; the institution region rides in the payload meta)
4082
+ * @param data.requestBody
4083
+ * @returns ParserContributionRelayResponseDto Issue created by the bot
4084
+ * @throws ApiError
4085
+ */
4086
+ public static parserContributionControllerCreate(
4087
+ data: ParserContributionControllerCreateData
4088
+ ): CancelablePromise<ParserContributionControllerCreateResponse> {
4089
+ return __request(OpenAPI, {
4090
+ method: 'POST',
4091
+ url: '/api/v1/{region}/community/parser-contributions',
4092
+ path: {
4093
+ region: data.region
4094
+ },
4095
+ body: data.requestBody,
4096
+ mediaType: 'application/json',
4097
+ errors: {
4098
+ 401: 'Unauthorized',
4099
+ 422: 'Validation failed (institution slug, empty samples, row/cell size limits)',
4100
+ 429: 'Rate limited (5 submissions per user per hour)',
4101
+ 501: 'Relay not configured on this deployment — clients fall back to the clipboard flow',
4102
+ 502: 'GitHub bot failure (upstream), safe to retry'
4103
+ }
4104
+ });
4105
+ }
4106
+ }
4107
+
4108
+ export class AdminCacheService {
3397
4109
  /**
3398
- * @returns unknown
4110
+ * Flush entire cache (L1 + L2)
4111
+ * Clears ALL cache entries across ALL namespaces and users. Use only for emergency cache corruption recovery, maintenance-window refresh, or development resets.
4112
+ * @returns unknown Cache flushed successfully
3399
4113
  * @throws ApiError
3400
4114
  */
3401
4115
  public static cacheControllerFlushCache(): CancelablePromise<CacheControllerFlushCacheResponse> {
3402
4116
  return __request(OpenAPI, {
3403
4117
  method: 'POST',
3404
- url: '/api/v1/cache/flush'
4118
+ url: '/api/v1/cache/flush',
4119
+ errors: {
4120
+ 403: 'Admin access required'
4121
+ }
3405
4122
  });
3406
4123
  }
3407
4124
  }
@@ -3562,3 +4279,53 @@ export class InfoService {
3562
4279
  });
3563
4280
  }
3564
4281
  }
4282
+
4283
+ export class MarketDataService {
4284
+ /**
4285
+ * Search market symbols by name or code
4286
+ * Ranked search over the openbb catalog. Empty `q` returns [].
4287
+ * @param data The data for the request.
4288
+ * @param data.q Search term — matched against symbol and instrument name. Empty string returns [].
4289
+ * @param data.limit Maximum number of results (clamped 1..50)
4290
+ * @param data.exchange Filter by exchange code (e.g. US, HK, SS, SZ)
4291
+ * @param data.assetType Filter by OpenBB asset_type (e.g. stock, etf)
4292
+ * @returns SymbolSearchResultDto Ranked search results
4293
+ * @throws ApiError
4294
+ */
4295
+ public static symbolControllerSearch(
4296
+ data: SymbolControllerSearchData
4297
+ ): CancelablePromise<SymbolControllerSearchResponse> {
4298
+ return __request(OpenAPI, {
4299
+ method: 'GET',
4300
+ url: '/api/v1/market/symbols/search',
4301
+ query: {
4302
+ q: data.q,
4303
+ limit: data.limit,
4304
+ exchange: data.exchange,
4305
+ assetType: data.assetType
4306
+ }
4307
+ });
4308
+ }
4309
+
4310
+ /**
4311
+ * Get a market symbol quote
4312
+ * @param data The data for the request.
4313
+ * @param data.symbol
4314
+ * @returns SymbolQuoteDto Symbol quote
4315
+ * @throws ApiError
4316
+ */
4317
+ public static symbolControllerGetQuote(
4318
+ data: SymbolControllerGetQuoteData
4319
+ ): CancelablePromise<SymbolControllerGetQuoteResponse> {
4320
+ return __request(OpenAPI, {
4321
+ method: 'GET',
4322
+ url: '/api/v1/market/symbols/{symbol}/quote',
4323
+ path: {
4324
+ symbol: data.symbol
4325
+ },
4326
+ errors: {
4327
+ 404: 'Symbol not found in the openbb catalog'
4328
+ }
4329
+ });
4330
+ }
4331
+ }