openapi: 3.1.0 info: # Do not change the title, if the title changes, the import paths will be broken title: Api version: 0.2.0 description: Altwel — Multi-tenant alternative wealth platform API servers: - url: /api description: Base API path tags: - name: health description: Health operations - name: tenants description: Tenant / GP firm management (platform admin) - name: funds description: Funds and SPVs (console) - name: lps description: Limited partners / investors (console) - name: households description: Wealth households (advisor desktop) - name: clients description: Wealth clients (advisor desktop) - name: accounts description: Wealth accounts (advisor desktop) - name: subscriptions description: LP subscriptions to funds (console + investor) - name: platform-packages description: Platform package catalog - name: platform-users description: Altwel internal platform users (super-admins and staff) - name: platform-settings description: Global platform configuration settings - name: platform-summary description: Platform-level aggregate summaries - name: console-summary description: Tenant/GP aggregate summaries - name: kyc description: KYC form builder — sections, questions, and answer options - name: platform-auth description: Platform user authentication - name: activity-logs description: Platform audit activity logs - name: uploads description: Tenant asset uploads - name: securities description: Security master — global reference data (platform admin) - name: market-data description: Market-data ingestion triggers & price coverage (platform admin) - name: positions description: Holdings / positions (tenant) - name: holding-transactions description: Holdings transaction ledger (tenant) - name: custodian description: Custodian connections & file-drop import / reconciliation (tenant admin) - name: performance description: Performance & valuation — TWR/MWR, contribution, attribution (tenant) - name: risk description: Risk & exposure breakdowns (tenant) - name: risk-analytics description: Advanced risk — VaR, stress testing, factor exposures (tenant) - name: security-lookup description: Tenant-readable security-master lookup & autocomplete (tenant) - name: benchmarks description: Benchmark picker source (tenant) - name: models description: Model portfolios, target lines & assignments (tenant) - name: rebalance description: Drift & rebalancing runs / proposals (tenant) - name: orders description: Order blotter — orders, allocations, fills, restricted list (tenant) - name: fees description: AUM fee billing — schedules, tiers, assignments, runs, invoices (tenant admin) - name: sleeves description: Sleeve picker source (tenant) - name: reporting-groups description: Reporting-group picker source (tenant) paths: /healthz: get: operationId: healthCheck tags: [health] summary: Health check responses: "200": description: Healthy content: application/json: schema: $ref: "#/components/schemas/HealthStatus" # ─── PLATFORM AUTH / AUDIT / UPLOADS ───────────────────────────────────────── /platform-auth/session: get: operationId: getPlatformAuthSession tags: [platform-auth] summary: Get current platform auth session responses: "200": description: Current session content: application/json: schema: $ref: "#/components/schemas/PlatformAuthSession" "401": description: Not authenticated content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /platform-auth/login: post: operationId: loginPlatformUser tags: [platform-auth] summary: Sign in a platform user requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PlatformLoginBody" responses: "200": description: Authenticated session content: application/json: schema: $ref: "#/components/schemas/PlatformAuthSession" "401": description: Invalid credentials content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /platform-auth/logout: post: operationId: logoutPlatformUser tags: [platform-auth] summary: Sign out current platform user responses: "204": description: Signed out /activity-logs: get: operationId: listActivityLogs tags: [activity-logs] summary: List platform activity logs parameters: - name: q in: query required: false schema: type: string - name: limit in: query required: false schema: type: integer minimum: 1 maximum: 500 responses: "200": description: Activity logs content: application/json: schema: type: array items: $ref: "#/components/schemas/ActivityLog" /uploads/tenant-asset: post: operationId: uploadTenantAsset tags: [uploads] summary: Upload a tenant branding asset requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TenantAssetUploadBody" responses: "200": description: Uploaded asset reference content: application/json: schema: $ref: "#/components/schemas/TenantAssetUploadResponse" # ─── TENANTS ───────────────────────────────────────────────────────────────── /tenants: get: operationId: listTenants tags: [tenants] summary: List all tenants parameters: - name: status in: query required: false schema: type: string enum: [active, suspended, trial, churned] - name: plan in: query required: false schema: type: string enum: [starter, growth, enterprise] responses: "200": description: List of tenants content: application/json: schema: type: array items: $ref: "#/components/schemas/Tenant" post: operationId: createTenant tags: [tenants] summary: Create a new tenant requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateTenantBody" responses: "201": description: Created tenant content: application/json: schema: $ref: "#/components/schemas/Tenant" /tenants/{id}/members: get: operationId: listTenantMembers tags: [tenants] summary: List members for a tenant parameters: - name: id in: path required: true schema: type: integer responses: "200": description: List of tenant members content: application/json: schema: type: array items: $ref: "#/components/schemas/TenantMember" post: operationId: createTenantMember tags: [tenants] summary: Add a member to a tenant parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateTenantMemberBody" responses: "201": description: Created member content: application/json: schema: $ref: "#/components/schemas/TenantMember" /tenants/{id}/members/{memberId}: patch: operationId: updateTenantMember tags: [tenants] summary: Update a tenant member parameters: - name: id in: path required: true schema: type: integer - name: memberId in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateTenantMemberBody" responses: "200": description: Updated member content: application/json: schema: $ref: "#/components/schemas/TenantMember" delete: operationId: deleteTenantMember tags: [tenants] summary: Remove a member from a tenant parameters: - name: id in: path required: true schema: type: integer - name: memberId in: path required: true schema: type: integer responses: "204": description: Deleted /tenants/{id}: get: operationId: getTenant tags: [tenants] summary: Get tenant by ID parameters: - name: id in: path required: true schema: type: integer responses: "200": description: Tenant content: application/json: schema: $ref: "#/components/schemas/Tenant" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateTenant tags: [tenants] summary: Update a tenant parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateTenantBody" responses: "200": description: Updated tenant content: application/json: schema: $ref: "#/components/schemas/Tenant" delete: operationId: deleteTenant tags: [tenants] summary: Delete a tenant parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Deleted # ─── SUBSCRIPTION PACKAGES ─────────────────────────────────────────────────── /platform-packages: get: operationId: listPlatformPackages tags: [platform-packages] summary: List platform packages responses: "200": description: List of platform packages content: application/json: schema: type: array items: $ref: "#/components/schemas/PlatformPackage" post: operationId: createPlatformPackage tags: [platform-packages] summary: Create a platform package requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreatePlatformPackageBody" responses: "201": description: Created package content: application/json: schema: $ref: "#/components/schemas/PlatformPackage" /platform-packages/{id}: put: operationId: updatePlatformPackage tags: [platform-packages] summary: Update a platform package parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdatePlatformPackageBody" responses: "200": description: Updated package content: application/json: schema: $ref: "#/components/schemas/PlatformPackage" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" delete: operationId: deletePlatformPackage tags: [platform-packages] summary: Delete a platform package parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Deleted # ─── FUNDS ─────────────────────────────────────────────────────────────────── /funds: get: operationId: listFunds tags: [funds] summary: List funds/SPVs for a tenant parameters: - name: tenantId in: query required: false schema: type: integer - name: status in: query required: false schema: type: string enum: [drafting, fundraising, closed, active, liquidating, fully_realized] - name: type in: query required: false schema: type: string enum: [spv, fund, co_invest, syndicate] responses: "200": description: List of funds content: application/json: schema: type: array items: $ref: "#/components/schemas/Fund" post: operationId: createFund tags: [funds] summary: Create a new fund or SPV requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateFundBody" responses: "201": description: Created fund content: application/json: schema: $ref: "#/components/schemas/Fund" /funds/{id}: get: operationId: getFund tags: [funds] summary: Get fund by ID parameters: - name: id in: path required: true schema: type: integer responses: "200": description: Fund content: application/json: schema: $ref: "#/components/schemas/Fund" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateFund tags: [funds] summary: Update a fund parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateFundBody" responses: "200": description: Updated fund content: application/json: schema: $ref: "#/components/schemas/Fund" delete: operationId: deleteFund tags: [funds] summary: Delete a fund parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Deleted # ─── LPS ───────────────────────────────────────────────────────────────────── /lps: get: operationId: listLps tags: [lps] summary: List limited partners for a tenant parameters: - name: tenantId in: query required: false schema: type: integer - name: status in: query required: false schema: type: string enum: [prospect, invited, kyc_pending, accredited, active, inactive] responses: "200": description: List of LPs content: application/json: schema: type: array items: $ref: "#/components/schemas/Lp" post: operationId: createLp tags: [lps] summary: Create a new LP requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateLpBody" responses: "201": description: Created LP content: application/json: schema: $ref: "#/components/schemas/Lp" /lps/{id}: get: operationId: getLp tags: [lps] summary: Get LP by ID parameters: - name: id in: path required: true schema: type: integer responses: "200": description: LP content: application/json: schema: $ref: "#/components/schemas/Lp" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateLp tags: [lps] summary: Update an LP parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateLpBody" responses: "200": description: Updated LP content: application/json: schema: $ref: "#/components/schemas/Lp" # ─── WEALTH ADVISOR DESKTOP ────────────────────────────────────────────────── /households: get: operationId: listHouseholds tags: [households] summary: List wealth households for the signed-in tenant parameters: - name: baseCurrency in: query required: false schema: type: string responses: "200": description: List of households content: application/json: schema: type: array items: $ref: "#/components/schemas/Household" post: operationId: createHousehold tags: [households] summary: Create a household requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateHouseholdBody" responses: "201": description: Created household content: application/json: schema: $ref: "#/components/schemas/Household" "400": description: Invalid body content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /households/{id}: get: operationId: getHousehold tags: [households] summary: Get household by ID parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Household content: application/json: schema: $ref: "#/components/schemas/Household" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateHousehold tags: [households] summary: Update a household parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateHouseholdBody" responses: "200": description: Updated household content: application/json: schema: $ref: "#/components/schemas/Household" delete: operationId: deleteHousehold tags: [households] summary: Delete a household parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "204": description: Deleted /clients: get: operationId: listClients tags: [clients] summary: List wealth clients for the signed-in tenant parameters: - name: status in: query required: false schema: type: string enum: [prospect, onboarding, active, inactive, archived] - name: type in: query required: false schema: type: string enum: [individual, entity, trust, foundation, other] responses: "200": description: List of clients content: application/json: schema: type: array items: $ref: "#/components/schemas/Client" post: operationId: createClient tags: [clients] summary: Create a client requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateClientBody" responses: "201": description: Created client content: application/json: schema: $ref: "#/components/schemas/Client" /clients/{id}: get: operationId: getClient tags: [clients] summary: Get client by ID parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Client content: application/json: schema: $ref: "#/components/schemas/Client" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateClient tags: [clients] summary: Update a client parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateClientBody" responses: "200": description: Updated client content: application/json: schema: $ref: "#/components/schemas/Client" delete: operationId: deleteClient tags: [clients] summary: Delete a client parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "204": description: Deleted /accounts: get: operationId: listAccounts tags: [accounts] summary: List wealth accounts for the signed-in tenant parameters: - name: clientId in: query required: false schema: type: integer format: int32 minimum: 1 - name: householdId in: query required: false schema: type: integer format: int32 minimum: 1 - name: status in: query required: false schema: type: string enum: [pending, open, restricted, closed, archived] - name: type in: query required: false schema: type: string enum: [taxable, retirement, trust, corporate, cash, custody, other] responses: "200": description: List of accounts content: application/json: schema: type: array items: $ref: "#/components/schemas/Account" post: operationId: createAccount tags: [accounts] summary: Create a wealth account requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateAccountBody" responses: "201": description: Created account content: application/json: schema: $ref: "#/components/schemas/Account" /accounts/{id}: get: operationId: getAccount tags: [accounts] summary: Get account by ID parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Account content: application/json: schema: $ref: "#/components/schemas/Account" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateAccount tags: [accounts] summary: Update a wealth account parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateAccountBody" responses: "200": description: Updated account content: application/json: schema: $ref: "#/components/schemas/Account" delete: operationId: deleteAccount tags: [accounts] summary: Delete a wealth account parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "204": description: Deleted # ─── WEALTH-MANAGEMENT / PUBLIC MARKETS (v1) ───────────────────────────────── # Auth is enforced at runtime by router middleware (platform vs tenant); per the # existing house style the spec does not declare security schemes. /securities: get: operationId: listSecurities tags: [securities] summary: List wealth securities (security master) parameters: - name: q in: query required: false schema: type: string - name: ticker in: query required: false schema: type: string - name: cusip in: query required: false schema: type: string - name: isin in: query required: false schema: type: string - name: instrumentType in: query required: false schema: $ref: "#/components/schemas/InstrumentType" - name: status in: query required: false schema: $ref: "#/components/schemas/SecurityStatus" - name: limit in: query required: false schema: type: integer format: int32 minimum: 1 maximum: 200 responses: "200": description: List of securities content: application/json: schema: type: array items: $ref: "#/components/schemas/Security" post: operationId: createSecurity tags: [securities] summary: Create a wealth security (global reference data) requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateSecurityBody" responses: "201": description: Created security content: application/json: schema: $ref: "#/components/schemas/Security" /securities/{id}: get: operationId: getSecurity tags: [securities] summary: Get a wealth security by ID parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Security content: application/json: schema: $ref: "#/components/schemas/Security" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateSecurity tags: [securities] summary: Update a wealth security parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateSecurityBody" responses: "200": description: Updated security content: application/json: schema: $ref: "#/components/schemas/Security" # ─── MARKET DATA ────────────────────────────────────────────────────────────── /market-data/sync/prices: post: operationId: syncMarketDataPrices tags: [market-data] summary: Enqueue a wealth price sync requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PriceSyncBody" responses: "202": description: Job enqueued content: application/json: schema: $ref: "#/components/schemas/MarketDataSyncResult" /market-data/sync/fx: post: operationId: syncMarketDataFx tags: [market-data] summary: Enqueue a wealth FX sync requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/FxSyncBody" responses: "202": description: Job enqueued content: application/json: schema: $ref: "#/components/schemas/MarketDataSyncResult" /market-data/sync/corporate-actions: post: operationId: syncMarketDataCorporateActions tags: [market-data] summary: Enqueue a wealth corporate-action sync requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CorporateActionSyncBody" responses: "202": description: Job enqueued content: application/json: schema: $ref: "#/components/schemas/MarketDataSyncResult" /market-data/coverage/{securityId}: get: operationId: getMarketDataCoverage tags: [market-data] summary: Get wealth price coverage for a security parameters: - name: securityId in: path required: true schema: type: integer format: int32 minimum: 1 - name: from in: query required: true schema: type: string - name: to in: query required: true schema: type: string responses: "200": description: Coverage report content: application/json: schema: $ref: "#/components/schemas/PriceCoverage" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" # ─── POSITIONS ───────────────────────────────────────────────────────────────── /positions: get: operationId: listPositions tags: [positions] summary: List wealth positions for the signed-in tenant parameters: - name: wealthAccountId in: query required: false schema: type: integer format: int32 minimum: 1 - name: householdId in: query required: false schema: type: integer format: int32 minimum: 1 - name: sleeveId in: query required: false schema: type: integer format: int32 minimum: 1 - name: asOf in: query required: false schema: type: string responses: "200": description: List of positions content: application/json: schema: type: array items: $ref: "#/components/schemas/Position" /positions/rollup/{reportingGroupId}: get: operationId: getPositionsRollup tags: [positions] summary: Get wealth holdings rollup for a reporting group parameters: - name: reportingGroupId in: path required: true schema: type: integer format: int32 minimum: 1 - name: asOf in: query required: false schema: type: string responses: "200": description: Holdings rollup content: application/json: schema: $ref: "#/components/schemas/PositionsRollup" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" # ─── HOLDING TRANSACTIONS ──────────────────────────────────────────────────── /holding-transactions: get: operationId: listHoldingTransactions tags: [holding-transactions] summary: List wealth holding transactions parameters: - name: wealthAccountId in: query required: false schema: type: integer format: int32 minimum: 1 - name: from in: query required: false schema: type: string - name: to in: query required: false schema: type: string responses: "200": description: List of holding transactions content: application/json: schema: type: array items: $ref: "#/components/schemas/HoldingTransaction" post: operationId: createHoldingTransaction tags: [holding-transactions] summary: Create a wealth holding transaction (manual entry) requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateHoldingTransactionBody" responses: "201": description: Created holding transaction content: application/json: schema: $ref: "#/components/schemas/HoldingTransaction" # ─── CUSTODIAN ─────────────────────────────────────────────────────────────── /custodian/connections: get: operationId: listCustodianConnections tags: [custodian] summary: List wealth custodian connections responses: "200": description: List of connections content: application/json: schema: type: array items: $ref: "#/components/schemas/CustodianConnection" post: operationId: createCustodianConnection tags: [custodian] summary: Create a wealth custodian connection requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateCustodianConnectionBody" responses: "201": description: Created connection content: application/json: schema: $ref: "#/components/schemas/CustodianConnection" /custodian/connections/{id}: get: operationId: getCustodianConnection tags: [custodian] summary: Get a wealth custodian connection by ID parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Connection content: application/json: schema: $ref: "#/components/schemas/CustodianConnection" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateCustodianConnection tags: [custodian] summary: Update a wealth custodian connection parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateCustodianConnectionBody" responses: "200": description: Updated connection content: application/json: schema: $ref: "#/components/schemas/CustodianConnection" delete: operationId: deleteCustodianConnection tags: [custodian] summary: Delete a wealth custodian connection parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "204": description: Deleted /custodian/batches: get: operationId: listCustodianBatches tags: [custodian] summary: List wealth custodian import batches parameters: - name: connectionId in: query required: false schema: type: integer format: int32 minimum: 1 responses: "200": description: List of import batches content: application/json: schema: type: array items: $ref: "#/components/schemas/ImportBatch" post: operationId: createCustodianBatch tags: [custodian] summary: Upload a wealth custodian file and create an import batch requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UploadBatchBody" responses: "201": description: Created import batch content: application/json: schema: $ref: "#/components/schemas/ImportBatch" /custodian/batches/{id}: get: operationId: getCustodianBatch tags: [custodian] summary: Get a wealth custodian import batch by ID parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Import batch content: application/json: schema: $ref: "#/components/schemas/ImportBatch" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /custodian/batches/{id}/import: post: operationId: triggerCustodianBatchImport tags: [custodian] summary: Trigger import of a wealth custodian batch parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "202": description: Import queued content: application/json: schema: $ref: "#/components/schemas/CustodianImportTriggerResult" /custodian/batches/{id}/records: get: operationId: listCustodianBatchRecords tags: [custodian] summary: List staged records for a wealth custodian batch parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Staged import records content: application/json: schema: type: array items: $ref: "#/components/schemas/ImportRecord" /custodian/batches/{id}/breaks: get: operationId: listCustodianBatchBreaks tags: [custodian] summary: List reconciliation breaks for a wealth custodian batch parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Reconciliation results content: application/json: schema: type: array items: $ref: "#/components/schemas/ReconciliationResult" /custodian/breaks/{id}/resolve: post: operationId: resolveCustodianBreak tags: [custodian] summary: Resolve a wealth custodian reconciliation break parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Resolved break content: application/json: schema: $ref: "#/components/schemas/ReconciliationResult" # ─── PERFORMANCE ────────────────────────────────────────────────────────────── /performance: get: operationId: getPerformance tags: [performance] summary: Get wealth performance (TWR/MWR) for an entity/period parameters: - name: entityKind in: query required: true schema: $ref: "#/components/schemas/PerformanceEntityKind" - name: entityId in: query required: true schema: type: integer format: int32 minimum: 1 - name: periodStart in: query required: true schema: type: string - name: periodEnd in: query required: true schema: type: string - name: method in: query required: false schema: type: string enum: [twr, mwr] - name: benchmarkId in: query required: false schema: type: integer format: int32 minimum: 1 responses: "200": description: Performance result content: application/json: schema: $ref: "#/components/schemas/PerformanceResult" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /performance/valuations: get: operationId: getPerformanceValuations tags: [performance] summary: Get wealth NAV history series for an entity parameters: - name: entityKind in: query required: true schema: $ref: "#/components/schemas/PerformanceEntityKind" - name: entityId in: query required: true schema: type: integer format: int32 minimum: 1 - name: periodStart in: query required: true schema: type: string - name: periodEnd in: query required: true schema: type: string responses: "200": description: Valuation series content: application/json: schema: $ref: "#/components/schemas/PerformanceValuations" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /performance/contribution: get: operationId: getPerformanceContribution tags: [performance] summary: Get wealth per-security contribution for a period parameters: - name: entityKind in: query required: true schema: $ref: "#/components/schemas/PerformanceEntityKind" - name: entityId in: query required: true schema: type: integer format: int32 minimum: 1 - name: periodStart in: query required: true schema: type: string - name: periodEnd in: query required: true schema: type: string - name: benchmarkId in: query required: false schema: type: integer format: int32 minimum: 1 responses: "200": description: Contribution result content: application/json: schema: $ref: "#/components/schemas/PerformanceContribution" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /performance/attribution: get: operationId: getPerformanceAttribution tags: [performance] summary: Get wealth Brinson-Fachler attribution by sector parameters: - name: entityKind in: query required: true schema: $ref: "#/components/schemas/PerformanceEntityKind" - name: entityId in: query required: true schema: type: integer format: int32 minimum: 1 - name: periodStart in: query required: true schema: type: string - name: periodEnd in: query required: true schema: type: string - name: benchmarkId in: query required: false schema: type: integer format: int32 minimum: 1 responses: "200": description: Attribution result content: application/json: schema: $ref: "#/components/schemas/PerformanceAttribution" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" # ─── RISK ─────────────────────────────────────────────────────────────────── /risk/exposure: get: operationId: getRiskExposure tags: [risk] summary: Get wealth exposure breakdowns for an entity parameters: - name: entityKind in: query required: true schema: $ref: "#/components/schemas/RiskEntityKind" - name: entityId in: query required: true schema: type: integer format: int32 minimum: 1 - name: asOf in: query required: false schema: type: string - name: topN in: query required: false schema: type: integer format: int32 minimum: 1 maximum: 100 responses: "200": description: Exposure breakdowns content: application/json: schema: $ref: "#/components/schemas/RiskExposure" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /risk/concentration: get: operationId: getRiskConcentration tags: [risk] summary: Get wealth concentration metrics for an entity parameters: - name: entityKind in: query required: true schema: $ref: "#/components/schemas/RiskEntityKind" - name: entityId in: query required: true schema: type: integer format: int32 minimum: 1 - name: asOf in: query required: false schema: type: string - name: topN in: query required: false schema: type: integer format: int32 minimum: 1 maximum: 100 - name: maxIssuerWeight in: query required: false schema: type: number - name: maxPositionWeight in: query required: false schema: type: number - name: mandateId in: query required: false schema: type: integer format: int32 minimum: 1 responses: "200": description: Concentration metrics content: application/json: schema: $ref: "#/components/schemas/RiskConcentration" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" # ─── RISK ANALYTICS ─────────────────────────────────────────────────────────── /risk-analytics/var: get: operationId: getRiskAnalyticsVar tags: [risk-analytics] summary: Get wealth VaR (historical + parametric) for an entity parameters: - name: entityKind in: query required: true schema: $ref: "#/components/schemas/RiskAnalyticsEntityKind" - name: entityId in: query required: true schema: type: integer format: int32 minimum: 1 - name: asOf in: query required: false schema: type: string - name: confidence in: query required: false schema: type: number - name: horizon in: query required: false schema: type: integer format: int32 minimum: 1 maximum: 250 - name: lookback in: query required: false schema: type: integer format: int32 minimum: 2 maximum: 2000 responses: "200": description: VaR result content: application/json: schema: $ref: "#/components/schemas/VarResult" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /risk-analytics/stress: post: operationId: runRiskAnalyticsStress tags: [risk-analytics] summary: Run a wealth stress scenario on an entity's positions requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/StressBody" responses: "200": description: Stress result content: application/json: schema: $ref: "#/components/schemas/StressResult" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /risk-analytics/factors: get: operationId: getRiskAnalyticsFactors tags: [risk-analytics] summary: Get wealth portfolio factor exposures for a factor model parameters: - name: entityKind in: query required: true schema: $ref: "#/components/schemas/RiskAnalyticsEntityKind" - name: entityId in: query required: true schema: type: integer format: int32 minimum: 1 - name: asOf in: query required: false schema: type: string - name: factorModelId in: query required: true schema: type: integer format: int32 minimum: 1 - name: factorAsOf in: query required: false schema: type: string responses: "200": description: Factor exposures result content: application/json: schema: $ref: "#/components/schemas/FactorExposuresResult" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" # ─── SECURITY LOOKUP ────────────────────────────────────────────────────────── /security-lookup: get: operationId: lookupSecurities tags: [security-lookup] summary: Resolve wealth security ids to display fields parameters: - name: ids in: query required: true schema: type: string responses: "200": description: Resolved securities content: application/json: schema: type: array items: $ref: "#/components/schemas/SecurityLookupResult" /security-lookup/search: get: operationId: searchSecurities tags: [security-lookup] summary: Autocomplete wealth securities by name/ticker parameters: - name: q in: query required: true schema: type: string - name: limit in: query required: false schema: type: integer format: int32 minimum: 1 maximum: 50 responses: "200": description: Matching securities content: application/json: schema: type: array items: $ref: "#/components/schemas/SecurityLookupResult" # ─── BENCHMARKS ─────────────────────────────────────────────────────────────── /benchmarks: get: operationId: listBenchmarks tags: [benchmarks] summary: List wealth benchmarks visible to the tenant responses: "200": description: List of benchmarks content: application/json: schema: type: array items: $ref: "#/components/schemas/Benchmark" # ─── MODELS ─────────────────────────────────────────────────────────────────── /models: get: operationId: listModels tags: [models] summary: List wealth model portfolios responses: "200": description: List of model portfolios content: application/json: schema: type: array items: $ref: "#/components/schemas/ModelPortfolio" post: operationId: createModel tags: [models] summary: Create a wealth model portfolio requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateModelBody" responses: "201": description: Created model portfolio content: application/json: schema: $ref: "#/components/schemas/ModelPortfolio" /models/{id}: get: operationId: getModel tags: [models] summary: Get a wealth model portfolio with its target lines parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Model portfolio with positions content: application/json: schema: $ref: "#/components/schemas/ModelPortfolioDetail" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateModel tags: [models] summary: Update a wealth model portfolio parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateModelBody" responses: "200": description: Updated model portfolio content: application/json: schema: $ref: "#/components/schemas/ModelPortfolio" delete: operationId: deleteModel tags: [models] summary: Delete a wealth model portfolio parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "204": description: Deleted /models/{id}/positions: put: operationId: setModelPositions tags: [models] summary: Replace a wealth model portfolio's target lines parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SetModelPositionsBody" responses: "200": description: Replaced model positions content: application/json: schema: type: array items: $ref: "#/components/schemas/ModelPosition" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /models/{id}/assignments: get: operationId: listModelAssignments tags: [models] summary: List a wealth model portfolio's assignments parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Model assignments content: application/json: schema: type: array items: $ref: "#/components/schemas/AccountModelAssignment" post: operationId: createModelAssignment tags: [models] summary: Assign a wealth model portfolio to an account or sleeve parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateModelAssignmentBody" responses: "201": description: Created assignment content: application/json: schema: $ref: "#/components/schemas/AccountModelAssignment" # ─── REBALANCE ──────────────────────────────────────────────────────────────── /rebalance/runs: get: operationId: listRebalanceRuns tags: [rebalance] summary: List wealth rebalance runs parameters: - name: modelId in: query required: false schema: type: integer format: int32 minimum: 1 responses: "200": description: List of rebalance runs content: application/json: schema: type: array items: $ref: "#/components/schemas/RebalanceRun" post: operationId: triggerRebalanceRun tags: [rebalance] summary: Enqueue a wealth rebalance run requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TriggerRebalanceBody" responses: "202": description: Run enqueued content: application/json: schema: $ref: "#/components/schemas/RebalanceTriggerResult" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /rebalance/runs/{id}: get: operationId: getRebalanceRun tags: [rebalance] summary: Get a wealth rebalance run with its proposals parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Rebalance run with proposals content: application/json: schema: $ref: "#/components/schemas/RebalanceRunDetail" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /rebalance/runs/{id}/approve: post: operationId: approveRebalanceRun tags: [rebalance] summary: Approve a wealth rebalance run parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Approved run content: application/json: schema: $ref: "#/components/schemas/RebalanceRun" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /rebalance/runs/{id}/reject: post: operationId: rejectRebalanceRun tags: [rebalance] summary: Reject a wealth rebalance run parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Rejected run content: application/json: schema: $ref: "#/components/schemas/RebalanceRun" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" # ─── ORDERS ─────────────────────────────────────────────────────────────────── /orders: get: operationId: listOrders tags: [orders] summary: List wealth orders (blotter) parameters: - name: status in: query required: false schema: $ref: "#/components/schemas/OrderStatus" responses: "200": description: List of orders content: application/json: schema: type: array items: $ref: "#/components/schemas/Order" post: operationId: createOrder tags: [orders] summary: Create a wealth order on the blotter requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateOrderBody" responses: "201": description: Created order content: application/json: schema: $ref: "#/components/schemas/Order" /orders/{id}: get: operationId: getOrder tags: [orders] summary: Get a wealth order with allocations and executions parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Order with allocations and executions content: application/json: schema: $ref: "#/components/schemas/OrderDetail" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /orders/{id}/cancel: post: operationId: cancelOrder tags: [orders] summary: Cancel a wealth order parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Cancelled order content: application/json: schema: $ref: "#/components/schemas/Order" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /orders/{id}/allocations: post: operationId: createOrderAllocations tags: [orders] summary: Split a wealth block order across accounts parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/OrderAllocationsBody" responses: "201": description: Created allocations content: application/json: schema: type: array items: $ref: "#/components/schemas/OrderAllocation" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /orders/{id}/approve: post: operationId: approveOrder tags: [orders] summary: Approve a wealth order (re-runs pre-trade checks) parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/ApproveOrderBody" responses: "200": description: Approved order content: application/json: schema: $ref: "#/components/schemas/Order" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /orders/{id}/fills: post: operationId: recordOrderFill tags: [orders] summary: Record a fill against a wealth order parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/OrderFillBody" responses: "201": description: Recorded fill content: application/json: schema: $ref: "#/components/schemas/OrderFillResult" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /orders/restricted-securities/list: get: operationId: listRestrictedSecurities tags: [orders] summary: List the wealth tenant restricted-securities list responses: "200": description: Restricted securities content: application/json: schema: type: array items: $ref: "#/components/schemas/RestrictedSecurity" /orders/restricted-securities: post: operationId: createRestrictedSecurity tags: [orders] summary: Add a security to the wealth restricted list requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateRestrictedSecurityBody" responses: "201": description: Created restricted security content: application/json: schema: $ref: "#/components/schemas/RestrictedSecurity" /orders/restricted-securities/{id}: delete: operationId: deleteRestrictedSecurity tags: [orders] summary: Remove a security from the wealth restricted list parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "204": description: Deleted # ─── FEES ───────────────────────────────────────────────────────────────────── /fees/schedules: get: operationId: listFeeSchedules tags: [fees] summary: List wealth fee schedules responses: "200": description: List of fee schedules content: application/json: schema: type: array items: $ref: "#/components/schemas/FeeSchedule" post: operationId: createFeeSchedule tags: [fees] summary: Create a wealth fee schedule requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateFeeScheduleBody" responses: "201": description: Created fee schedule content: application/json: schema: $ref: "#/components/schemas/FeeSchedule" /fees/schedules/{id}: get: operationId: getFeeSchedule tags: [fees] summary: Get a wealth fee schedule with its tiers parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Fee schedule with tiers content: application/json: schema: $ref: "#/components/schemas/FeeScheduleDetail" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateFeeSchedule tags: [fees] summary: Update a wealth fee schedule parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateFeeScheduleBody" responses: "200": description: Updated fee schedule content: application/json: schema: $ref: "#/components/schemas/FeeSchedule" delete: operationId: deleteFeeSchedule tags: [fees] summary: Delete a wealth fee schedule parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "204": description: Deleted /fees/schedules/{scheduleId}/tiers: get: operationId: listFeeTiers tags: [fees] summary: List a wealth fee schedule's tiers parameters: - name: scheduleId in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Fee tiers content: application/json: schema: type: array items: $ref: "#/components/schemas/FeeTier" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" post: operationId: createFeeTier tags: [fees] summary: Add a tier to a wealth fee schedule parameters: - name: scheduleId in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateFeeTierBody" responses: "201": description: Created fee tier content: application/json: schema: $ref: "#/components/schemas/FeeTier" /fees/tiers/{id}: put: operationId: updateFeeTier tags: [fees] summary: Update a wealth fee tier parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateFeeTierBody" responses: "200": description: Updated fee tier content: application/json: schema: $ref: "#/components/schemas/FeeTier" delete: operationId: deleteFeeTier tags: [fees] summary: Delete a wealth fee tier parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "204": description: Deleted /fees/assignments: get: operationId: listFeeAssignments tags: [fees] summary: List wealth fee assignments parameters: - name: scheduleId in: query required: false schema: type: integer format: int32 minimum: 1 responses: "200": description: Fee assignments content: application/json: schema: type: array items: $ref: "#/components/schemas/FeeAssignment" post: operationId: createFeeAssignment tags: [fees] summary: Assign a wealth fee schedule to an entity requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateFeeAssignmentBody" responses: "201": description: Created fee assignment content: application/json: schema: $ref: "#/components/schemas/FeeAssignment" /fees/assignments/{id}: put: operationId: updateFeeAssignment tags: [fees] summary: Update a wealth fee assignment parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateFeeAssignmentBody" responses: "200": description: Updated fee assignment content: application/json: schema: $ref: "#/components/schemas/FeeAssignment" delete: operationId: deleteFeeAssignment tags: [fees] summary: Delete a wealth fee assignment parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "204": description: Deleted /fees/runs: get: operationId: listBillingRuns tags: [fees] summary: List wealth billing runs responses: "200": description: List of billing runs content: application/json: schema: type: array items: $ref: "#/components/schemas/BillingRun" post: operationId: triggerBillingRun tags: [fees] summary: Enqueue a wealth billing run requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TriggerBillingRunBody" responses: "202": description: Billing run queued content: application/json: schema: $ref: "#/components/schemas/BillingRunTriggerResult" /fees/runs/{id}: get: operationId: getBillingRun tags: [fees] summary: Get a wealth billing run with its invoices parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 responses: "200": description: Billing run with invoices content: application/json: schema: $ref: "#/components/schemas/BillingRunDetail" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" /fees/invoices: get: operationId: listFeeInvoices tags: [fees] summary: List wealth fee invoices parameters: - name: runId in: query required: false schema: type: integer format: int32 minimum: 1 - name: status in: query required: false schema: $ref: "#/components/schemas/FeeInvoiceStatus" responses: "200": description: Fee invoices content: application/json: schema: type: array items: $ref: "#/components/schemas/FeeInvoice" /fees/invoices/{id}/status: put: operationId: updateFeeInvoiceStatus tags: [fees] summary: Mark a wealth fee invoice's status parameters: - name: id in: path required: true schema: type: integer format: int32 minimum: 1 requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateFeeInvoiceStatusBody" responses: "200": description: Updated fee invoice content: application/json: schema: $ref: "#/components/schemas/FeeInvoice" # ─── SLEEVES ────────────────────────────────────────────────────────────────── /sleeves: get: operationId: listSleeves tags: [sleeves] summary: List wealth sleeves (picker options) parameters: - name: accountId in: query required: false schema: type: integer format: int32 minimum: 1 responses: "200": description: Sleeve picker options content: application/json: schema: type: array items: $ref: "#/components/schemas/SleeveOption" # ─── REPORTING GROUPS ───────────────────────────────────────────────────────── /reporting-groups: get: operationId: listReportingGroups tags: [reporting-groups] summary: List wealth reporting groups (picker options) responses: "200": description: Reporting-group picker options content: application/json: schema: type: array items: $ref: "#/components/schemas/ReportingGroupOption" # ─── SUBSCRIPTIONS ──────────────────────────────────────────────────────────── /subscriptions: get: operationId: listSubscriptions tags: [subscriptions] summary: List subscriptions parameters: - name: fundId in: query required: false schema: type: integer - name: lpId in: query required: false schema: type: integer - name: status in: query required: false schema: type: string enum: [pending, docs_sent, docs_signed, kyc_review, approved, funded, rejected, withdrawn] responses: "200": description: List of subscriptions content: application/json: schema: type: array items: $ref: "#/components/schemas/Subscription" post: operationId: createSubscription tags: [subscriptions] summary: Create a new subscription requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateSubscriptionBody" responses: "201": description: Created subscription content: application/json: schema: $ref: "#/components/schemas/Subscription" /subscriptions/{id}: get: operationId: getSubscription tags: [subscriptions] summary: Get subscription by ID parameters: - name: id in: path required: true schema: type: integer responses: "200": description: Subscription content: application/json: schema: $ref: "#/components/schemas/Subscription" "404": description: Not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" put: operationId: updateSubscription tags: [subscriptions] summary: Update a subscription parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateSubscriptionBody" responses: "200": description: Updated subscription content: application/json: schema: $ref: "#/components/schemas/Subscription" # ─── PLATFORM USERS ────────────────────────────────────────────────────────── /platform-users: get: operationId: listPlatformUsers tags: [platform-users] summary: List all platform users responses: "200": description: List of platform users content: application/json: schema: type: array items: $ref: "#/components/schemas/PlatformUser" post: operationId: createPlatformUser tags: [platform-users] summary: Invite a new platform user requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreatePlatformUserBody" responses: "201": description: Created platform user content: application/json: schema: $ref: "#/components/schemas/PlatformUser" /platform-users/{id}: patch: operationId: updatePlatformUser tags: [platform-users] summary: Update a platform user parameters: - name: id in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdatePlatformUserBody" responses: "200": description: Updated platform user content: application/json: schema: $ref: "#/components/schemas/PlatformUser" delete: operationId: deletePlatformUser tags: [platform-users] summary: Remove a platform user parameters: - name: id in: path required: true schema: type: integer responses: "204": description: Deleted # ─── PLATFORM SETTINGS ─────────────────────────────────────────────────────── /platform/settings: get: operationId: getPlatformSettings tags: [platform-settings] summary: Get global platform settings responses: "200": description: Platform settings content: application/json: schema: $ref: "#/components/schemas/PlatformSettings" put: operationId: updatePlatformSettings tags: [platform-settings] summary: Update global platform settings requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PlatformSettings" responses: "200": description: Updated platform settings content: application/json: schema: $ref: "#/components/schemas/PlatformSettings" # ─── PLATFORM SUMMARY ──────────────────────────────────────────────────────── /platform/summary: get: operationId: getPlatformSummary tags: [platform-summary] summary: Platform-wide KPI summary responses: "200": description: Platform summary content: application/json: schema: $ref: "#/components/schemas/PlatformSummary" /platform/tenant-breakdown: get: operationId: getTenantBreakdown tags: [platform-summary] summary: Tenant counts broken down by status and plan responses: "200": description: Tenant breakdown content: application/json: schema: $ref: "#/components/schemas/TenantBreakdown" # ─── CONSOLE SUMMARY ───────────────────────────────────────────────────────── /console/summary: get: operationId: getConsoleSummary tags: [console-summary] summary: GP/Tenant dashboard summary parameters: - name: tenantId in: query required: true schema: type: integer responses: "200": description: Console summary content: application/json: schema: $ref: "#/components/schemas/ConsoleSummary" /console/fundraising-pipeline: get: operationId: getFundraisingPipeline tags: [console-summary] summary: Fundraising pipeline across all funds parameters: - name: tenantId in: query required: true schema: type: integer responses: "200": description: Fundraising pipeline content: application/json: schema: type: array items: $ref: "#/components/schemas/FundraisingPipelineItem" /console/recent-activity: get: operationId: getRecentActivity tags: [console-summary] summary: Recent subscription and LP activity parameters: - name: tenantId in: query required: true schema: type: integer - name: limit in: query required: false schema: type: integer default: 20 responses: "200": description: Recent activity content: application/json: schema: type: array items: $ref: "#/components/schemas/ActivityItem" # ─── KYC MANAGER ───────────────────────────────────────────────────────────── /kyc/sections: get: operationId: listKycSections tags: [kyc] summary: List all KYC sections with nested questions and answers responses: "200": description: KYC sections content: application/json: schema: type: array items: $ref: "#/components/schemas/KycSection" post: operationId: createKycSection tags: [kyc] summary: Create a KYC section requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateKycSectionBody" responses: "201": description: Created section content: application/json: schema: $ref: "#/components/schemas/KycSection" /kyc/sections/{sectionId}: patch: operationId: updateKycSection tags: [kyc] summary: Update a KYC section parameters: - name: sectionId in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateKycSectionBody" responses: "200": description: Updated section content: application/json: schema: $ref: "#/components/schemas/KycSection" "404": description: Not found delete: operationId: deleteKycSection tags: [kyc] summary: Delete a KYC section and all its questions/answers parameters: - name: sectionId in: path required: true schema: type: integer responses: "204": description: Deleted /kyc/sections/{sectionId}/questions: post: operationId: createKycQuestion tags: [kyc] summary: Create a question within a section parameters: - name: sectionId in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateKycQuestionBody" responses: "201": description: Created question content: application/json: schema: $ref: "#/components/schemas/KycQuestion" /kyc/questions/{questionId}: patch: operationId: updateKycQuestion tags: [kyc] summary: Update a KYC question parameters: - name: questionId in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateKycQuestionBody" responses: "200": description: Updated question content: application/json: schema: $ref: "#/components/schemas/KycQuestion" "404": description: Not found delete: operationId: deleteKycQuestion tags: [kyc] summary: Delete a KYC question and its answers parameters: - name: questionId in: path required: true schema: type: integer responses: "204": description: Deleted /kyc/questions/{questionId}/answers: post: operationId: createKycAnswer tags: [kyc] summary: Create an answer option for a question parameters: - name: questionId in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateKycAnswerBody" responses: "201": description: Created answer content: application/json: schema: $ref: "#/components/schemas/KycAnswer" /kyc/answers/{answerId}: patch: operationId: updateKycAnswer tags: [kyc] summary: Update a KYC answer option parameters: - name: answerId in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateKycAnswerBody" responses: "200": description: Updated answer content: application/json: schema: $ref: "#/components/schemas/KycAnswer" "404": description: Not found delete: operationId: deleteKycAnswer tags: [kyc] summary: Delete a KYC answer option parameters: - name: answerId in: path required: true schema: type: integer responses: "204": description: Deleted components: schemas: HealthStatus: type: object properties: status: type: string required: [status] ErrorResponse: type: object properties: error: type: string required: [error] # ─── TENANT ──────────────────────────────────────────────────────────────── BrandingAsset: type: object properties: light: type: string description: Data URL or CDN URL for the light-mode variant dark: type: string description: Data URL or CDN URL for the dark-mode variant PlatformAuthUser: type: object properties: id: type: integer name: type: string email: type: string role: type: string status: type: string required: [id, name, email, role, status] PlatformAuthSession: type: object properties: user: $ref: "#/components/schemas/PlatformAuthUser" required: [user] PlatformLoginBody: type: object properties: email: type: string format: email password: type: string required: [email, password] ActivityLog: type: object properties: id: type: integer actorId: type: integer nullable: true actorName: type: string nullable: true actorEmail: type: string nullable: true action: type: string resource: type: string method: type: string path: type: string statusCode: type: integer nullable: true ipAddress: type: string nullable: true userAgent: type: string nullable: true metadata: type: object additionalProperties: true createdAt: type: string format: date-time required: [id, action, resource, method, path, metadata, createdAt] TenantAssetUploadBody: type: object properties: tenantId: type: integer assetType: type: string enum: [logo, logo-icon, favicon] variant: type: string enum: [light, dark] fileName: type: string contentType: type: string dataBase64: type: string required: [tenantId, assetType, variant, fileName, contentType, dataBase64] TenantAssetUploadResponse: type: object properties: key: type: string publicUrl: type: string required: [key, publicUrl] PlatformPackage: type: object properties: id: type: integer name: type: string description: type: string monthlyPrice: type: string nullable: true yearlyPrice: type: string nullable: true freeTrialDays: type: integer isFeatured: type: boolean isActive: type: boolean sortOrder: type: integer features: type: array items: type: string createdAt: type: string format: date-time required: [id, name, description, freeTrialDays, isFeatured, isActive, sortOrder, features, createdAt] CreatePlatformPackageBody: type: object properties: name: type: string description: type: string monthlyPrice: type: string nullable: true yearlyPrice: type: string nullable: true freeTrialDays: type: integer isFeatured: type: boolean isActive: type: boolean sortOrder: type: integer features: type: array items: type: string required: [name] UpdatePlatformPackageBody: type: object properties: name: type: string description: type: string monthlyPrice: type: string nullable: true yearlyPrice: type: string nullable: true freeTrialDays: type: integer isFeatured: type: boolean isActive: type: boolean sortOrder: type: integer features: type: array items: type: string TenantBranding: type: object properties: logo: $ref: "#/components/schemas/BrandingAsset" logoIcon: $ref: "#/components/schemas/BrandingAsset" favicon: $ref: "#/components/schemas/BrandingAsset" primaryColor: type: string description: Hex color used for the investor portal theme Tenant: type: object properties: id: type: integer name: type: string slug: type: string status: type: string enum: [active, suspended, trial, churned] plan: type: string enum: [starter, growth, enterprise] platformPackageId: type: integer nullable: true logoUrl: type: string primaryColor: type: string branding: $ref: "#/components/schemas/TenantBranding" subdomain: type: string customDomain: type: string domainWhitelist: type: array items: type: string settings: type: object additionalProperties: true contactEmail: type: string contactName: type: string trialEndsAt: type: string format: date-time createdAt: type: string format: date-time required: [id, name, slug, status, plan, contactEmail, contactName, createdAt] CreateTenantBody: type: object properties: name: type: string slug: type: string status: type: string enum: [active, suspended, trial, churned] plan: type: string enum: [starter, growth, enterprise] platformPackageId: type: integer nullable: true contactEmail: type: string contactName: type: string logoUrl: type: string primaryColor: type: string branding: $ref: "#/components/schemas/TenantBranding" subdomain: type: string customDomain: type: string domainWhitelist: type: array items: type: string settings: type: object additionalProperties: true trialEndsAt: type: string format: date-time required: [name, slug, contactEmail, contactName] PlatformUser: type: object properties: id: type: integer name: type: string email: type: string role: type: string enum: [super_admin, operations, support, read_only] status: type: string enum: [active, invited, suspended] createdAt: type: string format: date-time lastSeenAt: type: string format: date-time required: [id, name, email, role, status, createdAt] CreatePlatformUserBody: type: object properties: name: type: string email: type: string role: type: string enum: [super_admin, operations, support, read_only] required: [name, email] UpdatePlatformUserBody: type: object properties: name: type: string email: type: string role: type: string enum: [super_admin, operations, support, read_only] status: type: string enum: [active, invited, suspended] TenantMember: type: object properties: id: type: integer tenantId: type: integer name: type: string email: type: string role: type: string enum: [admin, editor, viewer] status: type: string enum: [active, invited, suspended] createdAt: type: string format: date-time required: [id, tenantId, name, email, role, status, createdAt] CreateTenantMemberBody: type: object properties: name: type: string email: type: string role: type: string enum: [admin, editor, viewer] required: [name, email] # ─── FUND ────────────────────────────────────────────────────────────────── Fund: type: object properties: id: type: integer tenantId: type: integer name: type: string legalName: type: string type: type: string enum: [spv, fund, co_invest, syndicate] status: type: string enum: [drafting, fundraising, closed, active, liquidating, fully_realized] currency: type: string enum: [USD, EUR, GBP, SGD, AUD] targetSize: type: number hardCap: type: number managementFeePercent: type: number carryPercent: type: number vintage: type: integer investmentStrategy: type: string sector: type: string geography: type: string closeDate: type: string format: date-time createdAt: type: string format: date-time required: [id, tenantId, name, type, status, currency, createdAt] CreateFundBody: type: object properties: tenantId: type: integer name: type: string legalName: type: string type: type: string enum: [spv, fund, co_invest, syndicate] status: type: string enum: [drafting, fundraising, closed, active, liquidating, fully_realized] currency: type: string enum: [USD, EUR, GBP, SGD, AUD] targetSize: type: number hardCap: type: number managementFeePercent: type: number carryPercent: type: number vintage: type: integer investmentStrategy: type: string sector: type: string geography: type: string closeDate: type: string format: date-time required: [tenantId, name, type] # ─── LP ──────────────────────────────────────────────────────────────────── Lp: type: object properties: id: type: integer tenantId: type: integer householdId: type: integer nullable: true description: Optional household relationship for unified advisor/private-capital relationship views. displayName: type: string entityName: type: string type: type: string enum: [individual, family_office, institutional, fund_of_funds, endowment, pension, other] status: type: string enum: [prospect, invited, kyc_pending, accredited, active, inactive] accreditation: type: string enum: [accredited, qualified_purchaser, non_accredited, pending] email: type: string phone: type: string country: type: string jurisdiction: type: string portalAccessEnabled: type: boolean kycVerifiedAt: type: string format: date-time createdAt: type: string format: date-time required: [id, tenantId, displayName, type, status, accreditation, email, portalAccessEnabled, createdAt] CreateLpBody: type: object properties: tenantId: type: integer householdId: type: integer nullable: true description: Optional household relationship for unified advisor/private-capital relationship views. displayName: type: string entityName: type: string type: type: string enum: [individual, family_office, institutional, fund_of_funds, endowment, pension, other] status: type: string enum: [prospect, invited, kyc_pending, accredited, active, inactive] accreditation: type: string enum: [accredited, qualified_purchaser, non_accredited, pending] email: type: string phone: type: string country: type: string jurisdiction: type: string required: [tenantId, displayName, email, type] # ─── WEALTH ADVISOR DESKTOP ──────────────────────────────────────────────── Household: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 displayName: type: string legalName: type: [string, "null"] primaryEmail: type: [string, "null"] primaryPhone: type: [string, "null"] taxCountry: type: [string, "null"] baseCurrency: type: string notes: type: [string, "null"] createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, displayName, baseCurrency, createdAt, updatedAt] CreateHouseholdBody: type: object properties: tenantId: type: integer format: int32 minimum: 1 description: Ignored; tenant is derived from the signed-in tenant session. displayName: type: string legalName: type: [string, "null"] primaryEmail: type: [string, "null"] primaryPhone: type: [string, "null"] taxCountry: type: [string, "null"] baseCurrency: type: string notes: type: [string, "null"] required: [displayName] UpdateHouseholdBody: type: object properties: tenantId: type: integer format: int32 minimum: 1 description: Ignored; tenant is derived from the signed-in tenant session. displayName: type: string legalName: type: [string, "null"] primaryEmail: type: [string, "null"] primaryPhone: type: [string, "null"] taxCountry: type: [string, "null"] baseCurrency: type: string notes: type: [string, "null"] Client: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 displayName: type: string legalName: type: [string, "null"] type: type: string enum: [individual, entity, trust, foundation, other] status: type: string enum: [prospect, onboarding, active, inactive, archived] email: type: [string, "null"] phone: type: [string, "null"] dateOfBirth: type: [string, "null"] format: date-time taxCountry: type: [string, "null"] taxIdLast4: type: [string, "null"] externalRef: type: [string, "null"] onboardingCompletedAt: type: [string, "null"] format: date-time notes: type: [string, "null"] metadata: type: [object, "null"] additionalProperties: true createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, displayName, type, status, createdAt, updatedAt] CreateClientBody: type: object properties: tenantId: type: integer format: int32 minimum: 1 description: Ignored; tenant is derived from the signed-in tenant session. displayName: type: string legalName: type: [string, "null"] type: type: string enum: [individual, entity, trust, foundation, other] status: type: string enum: [prospect, onboarding, active, inactive, archived] email: type: [string, "null"] phone: type: [string, "null"] dateOfBirth: type: [string, "null"] format: date-time taxCountry: type: [string, "null"] taxIdLast4: type: [string, "null"] externalRef: type: [string, "null"] onboardingCompletedAt: type: [string, "null"] format: date-time notes: type: [string, "null"] metadata: type: [object, "null"] additionalProperties: true householdId: type: [integer, "null"] format: int32 minimum: 1 householdRole: type: string enum: [primary, spouse, dependent, trustee, advisor, other] isPrimaryHouseholdMember: type: boolean required: [displayName] UpdateClientBody: type: object properties: tenantId: type: integer format: int32 minimum: 1 description: Ignored; tenant is derived from the signed-in tenant session. displayName: type: string legalName: type: [string, "null"] type: type: string enum: [individual, entity, trust, foundation, other] status: type: string enum: [prospect, onboarding, active, inactive, archived] email: type: [string, "null"] phone: type: [string, "null"] dateOfBirth: type: [string, "null"] format: date-time taxCountry: type: [string, "null"] taxIdLast4: type: [string, "null"] externalRef: type: [string, "null"] onboardingCompletedAt: type: [string, "null"] format: date-time notes: type: [string, "null"] metadata: type: [object, "null"] additionalProperties: true Account: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 clientId: type: integer format: int32 minimum: 1 householdId: type: [integer, "null"] format: int32 minimum: 1 mandateId: type: [integer, "null"] format: int32 minimum: 1 accountNumber: type: string name: type: string type: type: string enum: [taxable, retirement, trust, corporate, cash, custody, other] status: type: string enum: [pending, open, restricted, closed, archived] custodian: type: [string, "null"] baseCurrency: type: string reliefMethod: type: string enum: [fifo, lifo, hifo, average, specific] description: Tax-lot relief method applied when reducing positions. openedAt: type: [string, "null"] format: date-time closedAt: type: [string, "null"] format: date-time createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, clientId, accountNumber, name, type, status, baseCurrency, createdAt, updatedAt] CreateAccountBody: type: object properties: tenantId: type: integer format: int32 minimum: 1 description: Ignored; tenant is derived from the signed-in tenant session. clientId: type: integer format: int32 minimum: 1 householdId: type: [integer, "null"] format: int32 minimum: 1 mandateId: type: [integer, "null"] format: int32 minimum: 1 accountNumber: type: string name: type: string type: type: string enum: [taxable, retirement, trust, corporate, cash, custody, other] status: type: string enum: [pending, open, restricted, closed, archived] custodian: type: [string, "null"] baseCurrency: type: string reliefMethod: type: string enum: [fifo, lifo, hifo, average, specific] description: Tax-lot relief method applied when reducing positions. openedAt: type: [string, "null"] format: date-time closedAt: type: [string, "null"] format: date-time required: [clientId, accountNumber, name] UpdateAccountBody: type: object properties: tenantId: type: integer format: int32 minimum: 1 description: Ignored; tenant is derived from the signed-in tenant session. clientId: type: integer format: int32 minimum: 1 householdId: type: [integer, "null"] format: int32 minimum: 1 mandateId: type: [integer, "null"] format: int32 minimum: 1 accountNumber: type: string name: type: string type: type: string enum: [taxable, retirement, trust, corporate, cash, custody, other] status: type: string enum: [pending, open, restricted, closed, archived] custodian: type: [string, "null"] baseCurrency: type: string reliefMethod: type: string enum: [fifo, lifo, hifo, average, specific] description: Tax-lot relief method applied when reducing positions. openedAt: type: [string, "null"] format: date-time closedAt: type: [string, "null"] format: date-time # ─── SUBSCRIPTION ────────────────────────────────────────────────────────── Subscription: type: object properties: id: type: integer fundId: type: integer lpId: type: integer status: type: string enum: [pending, docs_sent, docs_signed, kyc_review, approved, funded, rejected, withdrawn] committedAmount: type: number calledAmount: type: number distributedAmount: type: number subscriptionAgreementSentAt: type: string format: date-time subscriptionAgreementSignedAt: type: string format: date-time approvedAt: type: string format: date-time fundedAt: type: string format: date-time sideLetterRequired: type: boolean notes: type: string createdAt: type: string format: date-time required: [id, fundId, lpId, status, committedAmount, calledAmount, distributedAmount, sideLetterRequired, createdAt] CreateSubscriptionBody: type: object properties: fundId: type: integer lpId: type: integer committedAmount: type: number sideLetterRequired: type: boolean notes: type: string required: [fundId, lpId, committedAmount] UpdateSubscriptionBody: type: object properties: status: type: string enum: [pending, docs_sent, docs_signed, kyc_review, approved, funded, rejected, withdrawn] committedAmount: type: number calledAmount: type: number distributedAmount: type: number sideLetterRequired: type: boolean notes: type: string # ─── SUMMARIES ───────────────────────────────────────────────────────────── PlatformSummary: type: object properties: totalTenants: type: integer activeTenants: type: integer trialTenants: type: integer totalFunds: type: integer totalLps: type: integer totalAum: type: number mrrUsd: type: number newTenantsThisMonth: type: integer required: [totalTenants, activeTenants, trialTenants, totalFunds, totalLps, totalAum, mrrUsd, newTenantsThisMonth] TenantBreakdown: type: object properties: byStatus: type: array items: type: object properties: status: type: string count: type: integer required: [status, count] byPlan: type: array items: type: object properties: plan: type: string count: type: integer required: [plan, count] required: [byStatus, byPlan] ConsoleSummary: type: object properties: tenantId: type: integer totalFunds: type: integer activeFunds: type: integer fundraisingFunds: type: integer totalLps: type: integer activeLps: type: integer totalCommitted: type: number totalCalled: type: number totalDistributed: type: number pendingSubscriptions: type: integer required: [tenantId, totalFunds, activeFunds, fundraisingFunds, totalLps, activeLps, totalCommitted, totalCalled, totalDistributed, pendingSubscriptions] FundraisingPipelineItem: type: object properties: fundId: type: integer fundName: type: string type: type: string status: type: string targetSize: type: number committed: type: number percentFilled: type: number lpCount: type: integer closeDate: type: string format: date-time required: [fundId, fundName, type, status, committed, percentFilled, lpCount] PlatformSettings: type: object properties: general: type: object properties: platformName: type: string supportEmail: type: string defaultCurrency: type: string required: [platformName, supportEmail, defaultCurrency] trial: type: object properties: trialDurationDays: type: integer maxTrialFunds: type: integer maxTrialLps: type: integer required: [trialDurationDays, maxTrialFunds, maxTrialLps] fundStructures: type: array items: type: string jurisdictions: type: array items: type: string languages: type: array items: type: string currencies: type: array items: type: string required: [general, trial, fundStructures, jurisdictions, languages, currencies] ActivityItem: type: object properties: id: type: integer type: type: string enum: [subscription_created, subscription_funded, lp_kyc_submitted, lp_invited, fund_created, subscription_approved] description: type: string entityId: type: integer entityName: type: string occurredAt: type: string format: date-time required: [id, type, description, entityId, entityName, occurredAt] KycAnswer: type: object properties: id: type: integer questionId: type: integer order: type: integer value: type: string entityTypes: type: ["array", "null"] items: type: string jurisdictions: type: ["array", "null"] items: type: string translations: type: object additionalProperties: true createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, questionId, order, value, translations, createdAt, updatedAt] KycQuestion: type: object properties: id: type: integer sectionId: type: integer order: type: integer type: type: string enum: [text, textarea, single_choice, multiple_choice, boolean, date, file, number] required: type: boolean entityTypes: type: ["array", "null"] items: type: string jurisdictions: type: ["array", "null"] items: type: string translations: type: object additionalProperties: true answers: type: array items: $ref: "#/components/schemas/KycAnswer" createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, sectionId, order, type, required, translations, answers, createdAt, updatedAt] KycSection: type: object properties: id: type: integer order: type: integer entityTypes: type: ["array", "null"] items: type: string jurisdictions: type: ["array", "null"] items: type: string translations: type: object additionalProperties: true questions: type: array items: $ref: "#/components/schemas/KycQuestion" createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, order, translations, questions, createdAt, updatedAt] CreateKycSectionBody: type: object properties: translations: type: object additionalProperties: true entityTypes: type: ["array", "null"] items: type: string jurisdictions: type: ["array", "null"] items: type: string order: type: integer required: [translations] UpdateKycSectionBody: type: object properties: translations: type: object additionalProperties: true entityTypes: type: ["array", "null"] items: type: string jurisdictions: type: ["array", "null"] items: type: string order: type: integer CreateKycQuestionBody: type: object properties: type: type: string enum: [text, textarea, single_choice, multiple_choice, boolean, date, file, number] required: type: boolean translations: type: object additionalProperties: true entityTypes: type: ["array", "null"] items: type: string jurisdictions: type: ["array", "null"] items: type: string order: type: integer required: [type, translations] UpdateKycQuestionBody: type: object properties: type: type: string enum: [text, textarea, single_choice, multiple_choice, boolean, date, file, number] required: type: boolean translations: type: object additionalProperties: true entityTypes: type: ["array", "null"] items: type: string jurisdictions: type: ["array", "null"] items: type: string order: type: integer CreateKycAnswerBody: type: object properties: value: type: string translations: type: object additionalProperties: true entityTypes: type: ["array", "null"] items: type: string jurisdictions: type: ["array", "null"] items: type: string order: type: integer required: [value, translations] UpdateKycAnswerBody: type: object properties: value: type: string translations: type: object additionalProperties: true entityTypes: type: ["array", "null"] items: type: string jurisdictions: type: ["array", "null"] items: type: string order: type: integer # ─── WEALTH-MANAGEMENT / PUBLIC MARKETS ────────────────────────────────── # Money / weight / ratio values are emitted as strings by the routes (numeric # DB columns and .toFixed()/.toString() formatting), so they are modelled as # string here to match runtime behaviour. InstrumentType: type: string enum: [equity, etf, mutual_fund, fixed_income, option, future, fx, cash, alternative, other] SecurityStatus: type: string enum: [active, inactive, delisted] SecurityAssetClass: type: string enum: [equity, fixed_income, cash, alternative, real_asset, multi_asset] SecurityAttributes: type: ["object", "null"] properties: coupon: type: number maturity: type: string duration: type: number underlyingSecurityId: type: number strike: type: number expiry: type: string optionType: type: string enum: [call, put] Security: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: [integer, "null"] format: int32 minimum: 1 instrumentType: $ref: "#/components/schemas/InstrumentType" name: type: string ticker: type: [string, "null"] cusip: type: [string, "null"] isin: type: [string, "null"] figi: type: [string, "null"] currency: type: string exchange: type: [string, "null"] sector: type: [string, "null"] industry: type: [string, "null"] country: type: [string, "null"] issuer: type: [string, "null"] status: $ref: "#/components/schemas/SecurityStatus" assetClass: oneOf: - $ref: "#/components/schemas/SecurityAssetClass" - type: "null" attributes: $ref: "#/components/schemas/SecurityAttributes" createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, instrumentType, name, currency, status, createdAt, updatedAt] CreateSecurityBody: type: object properties: instrumentType: $ref: "#/components/schemas/InstrumentType" name: type: string ticker: type: [string, "null"] cusip: type: [string, "null"] isin: type: [string, "null"] figi: type: [string, "null"] currency: type: string exchange: type: [string, "null"] sector: type: [string, "null"] industry: type: [string, "null"] country: type: [string, "null"] issuer: type: [string, "null"] status: $ref: "#/components/schemas/SecurityStatus" assetClass: oneOf: - $ref: "#/components/schemas/SecurityAssetClass" - type: "null" attributes: $ref: "#/components/schemas/SecurityAttributes" required: [instrumentType, name] UpdateSecurityBody: type: object properties: instrumentType: $ref: "#/components/schemas/InstrumentType" name: type: string ticker: type: [string, "null"] cusip: type: [string, "null"] isin: type: [string, "null"] figi: type: [string, "null"] currency: type: string exchange: type: [string, "null"] sector: type: [string, "null"] industry: type: [string, "null"] country: type: [string, "null"] issuer: type: [string, "null"] status: $ref: "#/components/schemas/SecurityStatus" assetClass: oneOf: - $ref: "#/components/schemas/SecurityAssetClass" - type: "null" attributes: $ref: "#/components/schemas/SecurityAttributes" PriceSyncBody: type: object properties: securityIds: type: array items: type: integer format: int32 minimum: 1 from: type: string to: type: string required: [securityIds, from, to] FxSyncBody: type: object properties: pairs: type: array items: type: object properties: baseCurrency: type: string quoteCurrency: type: string required: [baseCurrency, quoteCurrency] from: type: string to: type: string required: [pairs, from, to] CorporateActionSyncBody: type: object properties: securityIds: type: array items: type: integer format: int32 minimum: 1 from: type: string to: type: string required: [securityIds, from, to] MarketDataSyncResult: type: object properties: enqueued: type: boolean job: type: string securityCount: type: integer pairCount: type: integer symbol: type: string required: [enqueued, job] PriceCoverage: type: object properties: securityId: type: integer format: int32 minimum: 1 from: type: string to: type: string expectedDays: type: integer coveredDays: type: integer gaps: type: array items: type: string required: [securityId, from, to, expectedDays, coveredDays, gaps] Position: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 wealthAccountId: type: integer format: int32 minimum: 1 sleeveId: type: [integer, "null"] format: int32 minimum: 1 securityId: type: integer format: int32 minimum: 1 quantity: type: string avgCost: type: [string, "null"] marketPrice: type: [string, "null"] marketValue: type: [string, "null"] currency: type: string asOf: type: string updatedAt: type: string format: date-time required: [id, tenantId, wealthAccountId, securityId, quantity, currency, asOf, updatedAt] RollupHolding: type: object properties: securityId: type: integer format: int32 minimum: 1 quantity: type: string marketValue: type: string currency: type: string weight: type: string required: [securityId, quantity, marketValue, currency, weight] PositionsRollup: type: object properties: reportingGroupId: type: integer format: int32 minimum: 1 baseCurrency: type: string holdings: type: array items: $ref: "#/components/schemas/RollupHolding" totalMarketValue: type: string required: [reportingGroupId, baseCurrency, holdings, totalMarketValue] HoldingTxnType: type: string enum: [buy, sell, dividend, interest, fee, deposit, withdrawal, transfer_in, transfer_out, corporate_action, fx, other] HoldingTxnSource: type: string enum: [manual, custodian_import, system] HoldingTransaction: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 wealthAccountId: type: integer format: int32 minimum: 1 securityId: type: [integer, "null"] format: int32 minimum: 1 txnType: $ref: "#/components/schemas/HoldingTxnType" tradeDate: type: string settleDate: type: [string, "null"] quantity: type: [string, "null"] price: type: [string, "null"] grossAmount: type: [string, "null"] fees: type: [string, "null"] netAmount: type: [string, "null"] currency: type: string externalRef: type: [string, "null"] source: $ref: "#/components/schemas/HoldingTxnSource" metadata: type: ["object", "null"] additionalProperties: true createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, wealthAccountId, txnType, tradeDate, currency, source, createdAt, updatedAt] CreateHoldingTransactionBody: type: object properties: wealthAccountId: type: integer format: int32 minimum: 1 securityId: type: [integer, "null"] format: int32 minimum: 1 txnType: $ref: "#/components/schemas/HoldingTxnType" tradeDate: type: string settleDate: type: [string, "null"] quantity: oneOf: - type: string - type: number - type: "null" price: oneOf: - type: string - type: number - type: "null" grossAmount: oneOf: - type: string - type: number - type: "null" fees: oneOf: - type: string - type: number - type: "null" netAmount: oneOf: - type: string - type: number - type: "null" currency: type: string externalRef: type: [string, "null"] metadata: type: ["object", "null"] additionalProperties: true required: [wealthAccountId, txnType, tradeDate] CustodianKind: type: string enum: [schwab, fidelity, pershing, nbin, interactive_brokers, aggregator, file] CustodianConnectionStatus: type: string enum: [pending, active, error, disabled] ImportBatchKind: type: string enum: [positions, transactions, both] ImportBatchStatus: type: string enum: [received, parsing, reconciling, applied, failed] ReconciliationSeverity: type: string enum: [info, warning, break] CustodianConnection: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 custodian: $ref: "#/components/schemas/CustodianKind" displayName: type: string status: $ref: "#/components/schemas/CustodianConnectionStatus" config: type: ["object", "null"] additionalProperties: true lastSyncedAt: type: [string, "null"] format: date-time lastError: type: [string, "null"] createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, custodian, displayName, status, createdAt, updatedAt] CreateCustodianConnectionBody: type: object properties: custodian: $ref: "#/components/schemas/CustodianKind" displayName: type: string status: $ref: "#/components/schemas/CustodianConnectionStatus" config: type: ["object", "null"] additionalProperties: true required: [custodian, displayName] UpdateCustodianConnectionBody: type: object properties: displayName: type: string status: $ref: "#/components/schemas/CustodianConnectionStatus" config: type: ["object", "null"] additionalProperties: true ImportBatch: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 connectionId: type: integer format: int32 minimum: 1 kind: $ref: "#/components/schemas/ImportBatchKind" status: $ref: "#/components/schemas/ImportBatchStatus" asOf: type: [string, "null"] recordCount: type: integer summary: type: ["object", "null"] additionalProperties: true error: type: [string, "null"] createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, connectionId, kind, status, recordCount, createdAt, updatedAt] UploadBatchBody: type: object properties: connectionId: type: integer format: int32 minimum: 1 kind: type: string enum: [positions, transactions] asOf: type: string fileName: type: string dataBase64: type: string required: [connectionId, kind, fileName, dataBase64] CustodianImportTriggerResult: type: object properties: batchId: type: integer format: int32 minimum: 1 status: type: string required: [batchId, status] ImportRecord: type: object properties: id: type: integer format: int32 minimum: 1 batchId: type: integer format: int32 minimum: 1 rowType: type: string raw: type: ["object", "null"] additionalProperties: true parsed: type: ["object", "null"] additionalProperties: true status: type: string error: type: [string, "null"] createdAt: type: string format: date-time required: [id, batchId, rowType, status, createdAt] ReconciliationResult: type: object properties: id: type: integer format: int32 minimum: 1 batchId: type: integer format: int32 minimum: 1 wealthAccountId: type: integer format: int32 minimum: 1 securityId: type: [integer, "null"] format: int32 minimum: 1 field: type: string expected: type: [string, "null"] actual: type: [string, "null"] severity: $ref: "#/components/schemas/ReconciliationSeverity" resolvedAt: type: [string, "null"] format: date-time createdAt: type: string format: date-time required: [id, batchId, wealthAccountId, field, severity, createdAt] PerformanceEntityKind: type: string enum: [account, household, reporting_group] PerformanceResult: type: object properties: entityKind: $ref: "#/components/schemas/PerformanceEntityKind" entityId: type: integer format: int32 minimum: 1 periodStart: type: string periodEnd: type: string method: type: string enum: [twr, mwr] benchmarkId: type: [integer, "null"] format: int32 minimum: 1 return: type: string grossReturn: type: string netReturn: type: string benchmarkReturn: type: [string, "null"] activeReturn: type: [string, "null"] inputsHash: type: string cache: type: string required: [entityKind, entityId, periodStart, periodEnd, method, return] ValuationPoint: type: object properties: date: type: string marketValue: type: string required: [date, marketValue] FlowPoint: type: object properties: date: type: string amount: type: string required: [date, amount] PerformanceValuations: type: object properties: entityKind: $ref: "#/components/schemas/PerformanceEntityKind" entityId: type: integer format: int32 minimum: 1 periodStart: type: string periodEnd: type: string valuations: type: array items: $ref: "#/components/schemas/ValuationPoint" flows: type: array items: $ref: "#/components/schemas/FlowPoint" required: [entityKind, entityId, periodStart, periodEnd, valuations, flows] ContributionSegment: type: object properties: securityId: type: integer format: int32 minimum: 1 weight: type: string return: type: string contribution: type: string required: [securityId, weight, return, contribution] PerformanceContribution: type: object properties: entityKind: $ref: "#/components/schemas/PerformanceEntityKind" entityId: type: integer format: int32 minimum: 1 periodStart: type: string periodEnd: type: string totalReturn: type: string segments: type: array items: $ref: "#/components/schemas/ContributionSegment" required: [entityKind, entityId, periodStart, periodEnd, totalReturn, segments] AttributionSegment: type: object properties: sector: type: string allocation: type: string selection: type: string interaction: type: string total: type: string required: [sector, allocation, selection, interaction, total] PerformanceAttribution: type: object properties: entityKind: $ref: "#/components/schemas/PerformanceEntityKind" entityId: type: integer format: int32 minimum: 1 periodStart: type: string periodEnd: type: string benchmarkId: type: [integer, "null"] format: int32 minimum: 1 totals: type: object properties: allocation: type: string selection: type: string interaction: type: string activeReturn: type: string required: [allocation, selection, interaction, activeReturn] segments: type: array items: $ref: "#/components/schemas/AttributionSegment" required: [entityKind, entityId, periodStart, periodEnd, totals, segments] RiskEntityKind: type: string enum: [account, household, sleeve, reporting_group] AllocationRow: type: object properties: key: type: string marketValue: type: string weight: type: string required: [key, marketValue, weight] ConcentrationHolding: type: object properties: securityId: type: integer format: int32 minimum: 1 label: type: [string, "null"] marketValue: type: string weight: type: string required: [securityId, marketValue, weight] RiskExposure: type: object properties: entityKind: $ref: "#/components/schemas/RiskEntityKind" entityId: type: integer format: int32 minimum: 1 asOf: type: [string, "null"] totalMarketValue: type: string byAssetClass: type: array items: $ref: "#/components/schemas/AllocationRow" bySector: type: array items: $ref: "#/components/schemas/AllocationRow" byGeography: type: array items: $ref: "#/components/schemas/AllocationRow" byCurrency: type: array items: $ref: "#/components/schemas/AllocationRow" concentration: type: object properties: totalMarketValue: type: string topHoldings: type: array items: $ref: "#/components/schemas/ConcentrationHolding" singleIssuerMax: type: [string, "null"] singleIssuerMaxKey: type: [string, "null"] singlePositionMax: type: [string, "null"] singlePositionMaxKey: type: [string, "null"] required: [totalMarketValue, topHoldings] fixedIncome: type: ["object", "null"] properties: marketValue: type: string weightedDuration: type: [string, "null"] weightedYield: type: [string, "null"] required: [entityKind, entityId, totalMarketValue, byAssetClass, bySector, byGeography, byCurrency, concentration] RiskConcentration: type: object properties: entityKind: $ref: "#/components/schemas/RiskEntityKind" entityId: type: integer format: int32 minimum: 1 asOf: type: [string, "null"] totalMarketValue: type: string topHoldings: type: array items: $ref: "#/components/schemas/ConcentrationHolding" singleIssuerMax: type: [string, "null"] singleIssuerMaxKey: type: [string, "null"] singlePositionMax: type: [string, "null"] singlePositionMaxKey: type: [string, "null"] limits: type: object properties: maxIssuerWeight: type: [number, "null"] maxPositionWeight: type: [number, "null"] issuerBreach: type: [boolean, "null"] positionBreach: type: [boolean, "null"] mandate: type: ["object", "null"] properties: id: type: integer format: int32 minimum: 1 name: type: string type: type: string maxDrawdown: type: [string, "null"] targetReturn: type: [string, "null"] required: [maxIssuerWeight, maxPositionWeight, issuerBreach, positionBreach, mandate] required: [entityKind, entityId, totalMarketValue, topHoldings, limits] RiskAnalyticsEntityKind: type: string enum: [account, household, sleeve] VarMeasure: type: object properties: var: type: string expectedShortfall: type: string required: [var, expectedShortfall] VarResult: type: object properties: entityKind: $ref: "#/components/schemas/RiskAnalyticsEntityKind" entityId: type: integer format: int32 minimum: 1 asOf: type: [string, "null"] confidence: type: number horizon: type: integer observations: type: integer securitiesCovered: type: integer totalMarketValue: type: string historical: $ref: "#/components/schemas/VarMeasure" parametric: $ref: "#/components/schemas/VarMeasure" required: [entityKind, entityId, confidence, horizon, observations, securitiesCovered, totalMarketValue, historical, parametric] Shock: type: object properties: dimension: type: string enum: [assetClass, sector, country, currency] key: type: string shockPct: type: number required: [dimension, key, shockPct] StressBody: type: object properties: entityKind: $ref: "#/components/schemas/RiskAnalyticsEntityKind" entityId: type: integer format: int32 minimum: 1 asOf: type: string shocks: type: array items: $ref: "#/components/schemas/Shock" required: [entityKind, entityId, shocks] StressPositionResult: type: object properties: securityId: type: integer format: int32 minimum: 1 label: type: [string, "null"] marketValue: type: string appliedShockPct: type: string pnl: type: string newValue: type: string required: [securityId, marketValue, appliedShockPct, pnl, newValue] StressResult: type: object properties: entityKind: $ref: "#/components/schemas/RiskAnalyticsEntityKind" entityId: type: integer format: int32 minimum: 1 asOf: type: [string, "null"] baseMarketValue: type: string totalPnl: type: string newMarketValue: type: string pnlPct: type: string positions: type: array items: $ref: "#/components/schemas/StressPositionResult" required: [entityKind, entityId, baseMarketValue, totalPnl, newMarketValue, pnlPct, positions] FactorExposure: type: object properties: factor: type: string exposure: type: string required: [factor, exposure] FactorExposuresResult: type: object properties: entityKind: $ref: "#/components/schemas/RiskAnalyticsEntityKind" entityId: type: integer format: int32 minimum: 1 asOf: type: [string, "null"] factorModelId: type: integer format: int32 minimum: 1 factorModelName: type: string factorAsOf: type: [string, "null"] totalMarketValue: type: string exposures: type: array items: $ref: "#/components/schemas/FactorExposure" required: [entityKind, entityId, factorModelId, factorModelName, totalMarketValue, exposures] SecurityLookupResult: type: object properties: id: type: integer format: int32 minimum: 1 name: type: string ticker: type: [string, "null"] assetClass: oneOf: - $ref: "#/components/schemas/SecurityAssetClass" - type: "null" sector: type: [string, "null"] currency: type: string instrumentType: $ref: "#/components/schemas/InstrumentType" required: [id, name, currency, instrumentType] Benchmark: type: object properties: id: type: integer format: int32 minimum: 1 name: type: string code: type: [string, "null"] currency: type: string kind: type: string required: [id, name, currency, kind] ModelPortfolioStatus: type: string enum: [draft, active, paused, archived] ModelPortfolio: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 name: type: string baseCurrency: type: string status: $ref: "#/components/schemas/ModelPortfolioStatus" createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, name, baseCurrency, status, createdAt, updatedAt] ModelPosition: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 modelId: type: integer format: int32 minimum: 1 securityId: type: [integer, "null"] format: int32 minimum: 1 assetClass: type: [string, "null"] targetWeight: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, modelId, targetWeight, createdAt, updatedAt] ModelPortfolioDetail: allOf: - $ref: "#/components/schemas/ModelPortfolio" - type: object properties: positions: type: array items: $ref: "#/components/schemas/ModelPosition" required: [positions] CreateModelBody: type: object properties: name: type: string baseCurrency: type: string status: $ref: "#/components/schemas/ModelPortfolioStatus" required: [name] UpdateModelBody: type: object properties: name: type: string baseCurrency: type: string status: $ref: "#/components/schemas/ModelPortfolioStatus" ModelPositionLine: type: object properties: securityId: type: integer format: int32 minimum: 1 assetClass: type: string targetWeight: type: number required: [targetWeight] SetModelPositionsBody: type: object properties: positions: type: array items: $ref: "#/components/schemas/ModelPositionLine" required: [positions] AccountModelAssignment: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 modelId: type: integer format: int32 minimum: 1 wealthAccountId: type: [integer, "null"] format: int32 minimum: 1 sleeveId: type: [integer, "null"] format: int32 minimum: 1 effectiveFrom: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, modelId, effectiveFrom, createdAt, updatedAt] CreateModelAssignmentBody: type: object properties: wealthAccountId: type: integer format: int32 minimum: 1 sleeveId: type: integer format: int32 minimum: 1 effectiveFrom: type: string required: [effectiveFrom] RebalanceRunStatus: type: string enum: [pending, running, completed, approved, rejected, failed] RebalanceRun: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 modelId: type: [integer, "null"] format: int32 minimum: 1 wealthAccountId: type: [integer, "null"] format: int32 minimum: 1 sleeveId: type: [integer, "null"] format: int32 minimum: 1 status: $ref: "#/components/schemas/RebalanceRunStatus" toleranceBand: type: [string, "null"] summary: type: ["object", "null"] additionalProperties: true error: type: [string, "null"] computedAt: type: [string, "null"] format: date-time createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, status, createdAt, updatedAt] RebalanceProposal: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 runId: type: integer format: int32 minimum: 1 securityId: type: integer format: int32 minimum: 1 side: type: string enum: [buy, sell] quantity: type: string estimatedValue: type: [string, "null"] currentWeight: type: [string, "null"] targetWeight: type: [string, "null"] driftWeight: type: [string, "null"] currency: type: string rationale: type: [string, "null"] createdAt: type: string format: date-time required: [id, tenantId, runId, securityId, side, quantity, currency, createdAt] RebalanceRunDetail: allOf: - $ref: "#/components/schemas/RebalanceRun" - type: object properties: proposals: type: array items: $ref: "#/components/schemas/RebalanceProposal" required: [proposals] TriggerRebalanceBody: type: object properties: modelId: type: integer format: int32 minimum: 1 wealthAccountId: type: integer format: int32 minimum: 1 sleeveId: type: integer format: int32 minimum: 1 asOf: type: string tolerance: type: number minTradeValue: type: number taxAware: type: boolean required: [modelId, asOf] RebalanceTriggerResult: type: object properties: status: type: string required: [status] OrderSide: type: string enum: [buy, sell] OrderType: type: string enum: [market, limit] OrderStatus: type: string enum: [draft, pending_approval, approved, sent, partial, filled, cancelled, rejected] OrderSource: type: string enum: [manual, rebalance] ComplianceNote: type: object properties: check: type: string passed: type: boolean reason: type: string required: [check, passed] Order: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 wealthAccountId: type: [integer, "null"] format: int32 minimum: 1 sleeveId: type: [integer, "null"] format: int32 minimum: 1 securityId: type: integer format: int32 minimum: 1 side: $ref: "#/components/schemas/OrderSide" quantity: type: string orderType: $ref: "#/components/schemas/OrderType" limitPrice: type: [string, "null"] status: $ref: "#/components/schemas/OrderStatus" source: $ref: "#/components/schemas/OrderSource" rebalanceProposalId: type: [integer, "null"] format: int32 minimum: 1 currency: type: string complianceNotes: type: ["array", "null"] items: $ref: "#/components/schemas/ComplianceNote" violations: type: array items: $ref: "#/components/schemas/ComplianceNote" createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, securityId, side, quantity, orderType, status, source, currency, createdAt, updatedAt] OrderAllocation: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 orderId: type: integer format: int32 minimum: 1 wealthAccountId: type: integer format: int32 minimum: 1 sleeveId: type: [integer, "null"] format: int32 minimum: 1 quantity: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, orderId, wealthAccountId, quantity, createdAt, updatedAt] Execution: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 orderId: type: integer format: int32 minimum: 1 quantity: type: string price: type: string fees: type: [string, "null"] grossAmount: type: [string, "null"] netAmount: type: [string, "null"] currency: type: string tradeDate: type: string settleDate: type: [string, "null"] externalRef: type: [string, "null"] createdAt: type: string format: date-time required: [id, tenantId, orderId, quantity, price, currency, tradeDate, createdAt] OrderDetail: allOf: - $ref: "#/components/schemas/Order" - type: object properties: allocations: type: array items: $ref: "#/components/schemas/OrderAllocation" executions: type: array items: $ref: "#/components/schemas/Execution" required: [allocations, executions] CreateOrderBody: type: object properties: wealthAccountId: type: [integer, "null"] format: int32 minimum: 1 sleeveId: type: [integer, "null"] format: int32 minimum: 1 securityId: type: integer format: int32 minimum: 1 side: $ref: "#/components/schemas/OrderSide" quantity: oneOf: - type: string - type: number orderType: $ref: "#/components/schemas/OrderType" limitPrice: oneOf: - type: string - type: number - type: "null" source: $ref: "#/components/schemas/OrderSource" currency: type: string required: [securityId, side, quantity] OrderAllocationLine: type: object properties: wealthAccountId: type: integer format: int32 minimum: 1 sleeveId: type: [integer, "null"] format: int32 minimum: 1 quantity: oneOf: - type: string - type: number required: [wealthAccountId, quantity] OrderAllocationsBody: type: object properties: allocations: type: array items: $ref: "#/components/schemas/OrderAllocationLine" required: [allocations] ApproveOrderBody: type: object properties: concentrationLimit: type: [number, "null"] OrderFillBody: type: object properties: quantity: oneOf: - type: string - type: number price: oneOf: - type: string - type: number fees: oneOf: - type: string - type: number - type: "null" tradeDate: type: string settleDate: type: [string, "null"] externalRef: type: [string, "null"] required: [quantity, price, tradeDate] OrderFillResult: type: object properties: execution: $ref: "#/components/schemas/Execution" holdingTransaction: $ref: "#/components/schemas/HoldingTransaction" order: $ref: "#/components/schemas/Order" required: [execution, holdingTransaction, order] RestrictedSecurity: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 securityId: type: integer format: int32 minimum: 1 reason: type: [string, "null"] effectiveFrom: type: [string, "null"] effectiveTo: type: [string, "null"] createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, securityId, createdAt, updatedAt] CreateRestrictedSecurityBody: type: object properties: securityId: type: integer format: int32 minimum: 1 reason: type: [string, "null"] effectiveFrom: type: [string, "null"] effectiveTo: type: [string, "null"] required: [securityId] FeeBasis: type: string enum: [aum, flat, performance] FeeFrequency: type: string enum: [monthly, quarterly, annual] FeeTierMode: type: string enum: [flat, tiered, marginal] FeeAssignmentEntityKind: type: string enum: [household, account, reporting_group] BillingRunStatus: type: string enum: [pending, running, completed, failed] FeeInvoiceStatus: type: string enum: [draft, issued, paid, void] FeeSchedule: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 name: type: string basis: $ref: "#/components/schemas/FeeBasis" frequency: $ref: "#/components/schemas/FeeFrequency" tierMode: $ref: "#/components/schemas/FeeTierMode" flatRate: type: [string, "null"] currency: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, name, basis, frequency, tierMode, currency, createdAt, updatedAt] FeeTier: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 scheduleId: type: integer format: int32 minimum: 1 lowerBound: type: string upperBound: type: [string, "null"] rate: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, scheduleId, lowerBound, rate, createdAt, updatedAt] FeeScheduleDetail: allOf: - $ref: "#/components/schemas/FeeSchedule" - type: object properties: tiers: type: array items: $ref: "#/components/schemas/FeeTier" required: [tiers] CreateFeeScheduleBody: type: object properties: name: type: string basis: $ref: "#/components/schemas/FeeBasis" frequency: $ref: "#/components/schemas/FeeFrequency" tierMode: $ref: "#/components/schemas/FeeTierMode" flatRate: type: [number, "null"] currency: type: string required: [name] UpdateFeeScheduleBody: type: object properties: name: type: string basis: $ref: "#/components/schemas/FeeBasis" frequency: $ref: "#/components/schemas/FeeFrequency" tierMode: $ref: "#/components/schemas/FeeTierMode" flatRate: type: [number, "null"] currency: type: string CreateFeeTierBody: type: object properties: lowerBound: type: number upperBound: type: [number, "null"] rate: type: number required: [lowerBound, rate] UpdateFeeTierBody: type: object properties: lowerBound: type: number upperBound: type: [number, "null"] rate: type: number FeeAssignment: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 scheduleId: type: integer format: int32 minimum: 1 entityKind: $ref: "#/components/schemas/FeeAssignmentEntityKind" entityId: type: integer format: int32 minimum: 1 effectiveFrom: type: string effectiveTo: type: [string, "null"] createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, scheduleId, entityKind, entityId, effectiveFrom, createdAt, updatedAt] CreateFeeAssignmentBody: type: object properties: scheduleId: type: integer format: int32 minimum: 1 entityKind: $ref: "#/components/schemas/FeeAssignmentEntityKind" entityId: type: integer format: int32 minimum: 1 effectiveFrom: type: string effectiveTo: type: [string, "null"] required: [scheduleId, entityKind, entityId, effectiveFrom] UpdateFeeAssignmentBody: type: object properties: effectiveFrom: type: string effectiveTo: type: [string, "null"] BillingRun: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 periodStart: type: string periodEnd: type: string status: $ref: "#/components/schemas/BillingRunStatus" invoiceCount: type: integer totalFees: type: [string, "null"] error: type: [string, "null"] computedAt: type: [string, "null"] format: date-time createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, periodStart, periodEnd, status, invoiceCount, createdAt, updatedAt] FeeInvoice: type: object properties: id: type: integer format: int32 minimum: 1 tenantId: type: integer format: int32 minimum: 1 runId: type: integer format: int32 minimum: 1 scheduleId: type: [integer, "null"] format: int32 minimum: 1 entityKind: $ref: "#/components/schemas/FeeAssignmentEntityKind" entityId: type: integer format: int32 minimum: 1 periodStart: type: string periodEnd: type: string avgAum: type: [string, "null"] feeAmount: type: string currency: type: string status: $ref: "#/components/schemas/FeeInvoiceStatus" createdAt: type: string format: date-time updatedAt: type: string format: date-time required: [id, tenantId, runId, entityKind, entityId, periodStart, periodEnd, feeAmount, currency, status, createdAt, updatedAt] BillingRunDetail: allOf: - $ref: "#/components/schemas/BillingRun" - type: object properties: invoices: type: array items: $ref: "#/components/schemas/FeeInvoice" required: [invoices] TriggerBillingRunBody: type: object properties: periodStart: type: string periodEnd: type: string assignmentIds: type: array items: type: integer format: int32 minimum: 1 required: [periodStart, periodEnd] BillingRunTriggerResult: type: object properties: status: type: string periodStart: type: string periodEnd: type: string required: [status, periodStart, periodEnd] UpdateFeeInvoiceStatusBody: type: object properties: status: $ref: "#/components/schemas/FeeInvoiceStatus" required: [status] SleeveOption: type: object properties: id: type: integer format: int32 minimum: 1 name: type: string status: type: string enum: [draft, active, paused, closed] accountId: type: integer format: int32 minimum: 1 required: [id, name, status, accountId] ReportingGroupOption: type: object properties: id: type: integer format: int32 minimum: 1 name: type: string type: type: string enum: [household, client, portfolio, custom] baseCurrency: type: string isDefault: type: boolean required: [id, name, type, baseCurrency, isDefault]