{ "openapi": "3.1.0", "info": {}, "paths": { "/banking.v1.AllocationsService/GetAllocation": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "GetAllocation", "description": "One allocation by service id. Readable by any authenticated user in any state —\n an investor holding units of a closed product still needs to render it — but a\n product whose effective level for the caller is `hidden` is NOT_FOUND, the same\n answer an unregistered slug gets, so the catalog cannot be probed for locked\n products. An `AllocationManage` holder reads any allocation.", "operationId": "banking.v1.AllocationsService.GetAllocation", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetAllocationRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Allocation" } } } } } } }, "/banking.v1.AllocationsService/GrantAllocationAccess": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "GrantAllocationAccess", "description": "Raise one investor above the default (AllocationManage): `view` | `invest`. A\n repeat grant for the same user overwrites the level. A grant can only ever add —\n an investor's effective level is the higher of the default and the grant — so\n `hidden` is not a level a grant can carry; use Revoke to take one back.", "operationId": "banking.v1.AllocationsService.GrantAllocationAccess", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GrantAllocationAccessRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.AllocationAccessGrant" } } } } } } }, "/banking.v1.AllocationsService/IssueUnits": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "Mint units to a holder with no cash leg (AllocationManage). The allocation must be\n registered, in any state — a product is normally seeded before it opens. The mint\n is priced at the current (fresh) NAV for the record and the holder's cost basis,\n and counts against the unit cap exactly as a subscription does: an operator sizing\n a product below what they mean to issue raises the cap first, then issues.", "description": "Idempotent by `idempotency_key`, unique per service: a retry of a timed-out call\n returns the issuance the key already names and mints nothing. A key reused for a\n DIFFERENT holder or amount is ALREADY_EXISTS — the retry is the case the key exists\n for, the reuse is the mistake it has to catch.", "operationId": "banking.v1.AllocationsService.IssueUnits", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.IssueUnitsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UnitIssuance" } } } } } } }, "/banking.v1.AllocationsService/ListAllocationAccessGrants": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "ListAllocationAccessGrants", "description": "Every standing grant on one allocation (AllocationManage), ordered by `user_id`.", "operationId": "banking.v1.AllocationsService.ListAllocationAccessGrants", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListAllocationAccessGrantsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.AllocationAccessGrantList" } } } } } } }, "/banking.v1.AllocationsService/ListAllocations": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "ListAllocations", "description": "The catalog. Any authenticated user sees the `open` allocations they may at least\n view; an `AllocationManage` holder may set `include_unlisted` to see drafts,\n closed and hidden ones too. Ordered by `service`.", "operationId": "banking.v1.AllocationsService.ListAllocations", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListAllocationsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.AllocationList" } } } } } } }, "/banking.v1.AllocationsService/ListUnitHolders": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "ListUnitHolders", "description": "The cap table of one product (AllocationManage): the settled supply and every\n holder of it — people, and the reserved `fee` allocation holding the product's fee\n class — largest first. Read straight from the ledger — the number an operator\n checks against the registration before opening a product to the market.", "operationId": "banking.v1.AllocationsService.ListUnitHolders", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListUnitHoldersRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UnitHolders" } } } } } } }, "/banking.v1.AllocationsService/RegisterAllocation": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "RegisterAllocation", "description": "Register a new allocation in `draft` (AllocationManage). The service id is a\n 1..64 char `[A-Za-z0-9_-]` slug and is immutable once registered; re-registering\n an existing one is a conflict, never a silent update.", "operationId": "banking.v1.AllocationsService.RegisterAllocation", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RegisterAllocationRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Allocation" } } } } } } }, "/banking.v1.AllocationsService/RetireUnits": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "Burn a holder's units with no cash leg (AllocationManage) — the reverse of\n IssueUnits: `units` leave the holder's account and the supply shrinks by the same\n amount. Nothing is paid; this is a cap-table correction,\n the way an in-kind mint was. The holder must have at least `units` AVAILABLE\n (Read-First; units resting on the book or reserved by a redemption do not count) —\n otherwise INVALID_ARGUMENT — and the allocation must be `closed`, because burning a\n holder's units out of a live product is a decision that deserves a closed door\n first; `force` is the explicit override for a live product (FAILED_PRECONDITION\n without it). Priced at the current (fresh) NAV for the record; the default\n `cost_basis` is `units × NAV`, the book value written off.", "description": "Answers a `UnitIssuance` with `source = \"retire\"` and POSITIVE `units`: the row is\n the magnitude, the source is the direction, and the console lists mints and\n retirements as one history. Idempotent by `idempotency_key` in the same key space\n as IssueUnits: the same key naming a mint and then a retirement is ALREADY_EXISTS,\n not a retry.", "operationId": "banking.v1.AllocationsService.RetireUnits", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RetireUnitsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UnitIssuance" } } } } } } }, "/banking.v1.AllocationsService/RevokeAllocationAccess": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "RevokeAllocationAccess", "description": "Take a per-user grant back (AllocationManage). Idempotent — revoking a grant that\n does not exist succeeds and changes nothing. The investor falls back to the\n default level; units they already hold are unaffected and still redeemable.", "operationId": "banking.v1.AllocationsService.RevokeAllocationAccess", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RevokeAllocationAccessRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RevokeAllocationAccessResponse" } } } } } } }, "/banking.v1.AllocationsService/SetAllocationAccess": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "SetAllocationAccess", "description": "Set the default access level (AllocationManage): `hidden` | `view` | `invest`.\n Idempotent. Separate from SetAllocationState because the two answer different\n questions — `state` is whether the product deals, `access` is who it deals with —\n and collapsing them would make \"open but invite-only\" unexpressible. Lowering\n the default never touches a per-user grant, and never touches redemptions.", "operationId": "banking.v1.AllocationsService.SetAllocationAccess", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SetAllocationAccessRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Allocation" } } } } } } }, "/banking.v1.AllocationsService/SetAllocationBacking": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "SetAllocationBacking", "description": "Declare what stands behind a product's units (AllocationManage): `cash` |\n `in_kind`. Idempotent. `in_kind` is set automatically by the first `IssueUnits`,\n never the reverse: this RPC is how an operator says the fund now holds cash for\n the units and `Redeem` may pay it out again — or corrects a product back to\n `in_kind`. Lifecycle, access and holdings are untouched.", "operationId": "banking.v1.AllocationsService.SetAllocationBacking", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SetAllocationBackingRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Allocation" } } } } } } }, "/banking.v1.AllocationsService/SetAllocationState": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "SetAllocationState", "description": "Drive the lifecycle (AllocationManage): `open` or `close`. Idempotent — setting\n the state an allocation already holds succeeds and changes nothing.", "operationId": "banking.v1.AllocationsService.SetAllocationState", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SetAllocationStateRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Allocation" } } } } } } }, "/banking.v1.AllocationsService/SetAllocationUnitCap": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "SetAllocationUnitCap", "description": "Resize the authorised unit supply (AllocationManage). Idempotent. Separate from\n UpdateAllocation because this one gates money: `Subscribe` refuses a mint that\n would carry the issued supply past the cap. A cap below what is already issued is\n legal and means \"no more units\" — nothing minted is affected and redemptions are\n untouched, so this can never strand a holder. Zero is refused: use\n SetAllocationState(`closed`) to stop new money, which says so in the state.", "operationId": "banking.v1.AllocationsService.SetAllocationUnitCap", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SetAllocationUnitCapRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Allocation" } } } } } } }, "/banking.v1.AllocationsService/UpdateAllocation": { "post": { "tags": [ "banking.v1.AllocationsService" ], "summary": "UpdateAllocation", "description": "Update the presentation fields of an existing allocation (AllocationManage).\n Never changes state or identity.", "operationId": "banking.v1.AllocationsService.UpdateAllocation", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UpdateAllocationRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Allocation" } } } } } } }, "/banking.v1.AuthService/IssueUserToken": { "post": { "tags": [ "banking.v1.AuthService" ], "summary": "IssueUserToken", "description": "Mint the money-plane token pair for an already-identified user, keyed by their\n concierge user id. Service-to-service: authenticated by the shared issuance token\n in the `authorization` metadata (Bearer), never a user token. The user must already\n exist locally (provisioned by the cross-plane bridge) and not be frozen.", "operationId": "banking.v1.AuthService.IssueUserToken", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.IssueUserTokenRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.TokenResponse" } } } } } } }, "/banking.v1.AuthService/Jwks": { "post": { "tags": [ "banking.v1.AuthService" ], "summary": "Jwks", "description": "Publish the current signing public keys (JWKS). Polled by downstream services'\n `evbanking_auth` verifier to refresh its local cache; also consulted on an\n unknown-`kid` miss. Carries only public key material.", "operationId": "banking.v1.AuthService.Jwks", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.JwksRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.JwksResponse" } } } } } } }, "/banking.v1.AuthService/ListSessions": { "post": { "tags": [ "banking.v1.AuthService" ], "summary": "ListSessions", "description": "List the caller's active sessions (refresh-token families). Identity is proven by\n the presented refresh token (the BFF holds it server-side); the family that owns\n that token is flagged `current`.", "operationId": "banking.v1.AuthService.ListSessions", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListSessionsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListSessionsResponse" } } } } } } }, "/banking.v1.AuthService/Logout": { "post": { "tags": [ "banking.v1.AuthService" ], "summary": "Logout", "description": "Revoke the presented refresh token's family. With `revoke_all` set, also bumps\n the user's `token_version` so every outstanding access token is rejected hub-side.", "operationId": "banking.v1.AuthService.Logout", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.LogoutRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.LogoutResponse" } } } } } } }, "/banking.v1.AuthService/Refresh": { "post": { "tags": [ "banking.v1.AuthService" ], "summary": "Refresh", "description": "Rotate a refresh token: returns a fresh access+refresh pair and invalidates\n the presented refresh token (rotation + reuse detection in the central store).", "operationId": "banking.v1.AuthService.Refresh", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RefreshRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.TokenResponse" } } } } } } }, "/banking.v1.AuthService/RevokeSession": { "post": { "tags": [ "banking.v1.AuthService" ], "summary": "RevokeSession", "description": "Revoke one of the caller's sessions by id (must belong to the same user). Revoking\n the current session is allowed (acts like a sign-out of this device).", "operationId": "banking.v1.AuthService.RevokeSession", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RevokeSessionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RevokeSessionResponse" } } } } } } }, "/banking.v1.BalanceService/DispatchWithdrawal": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "DispatchWithdrawal", "description": "Dispatch a queued withdrawal to custody once its rail has liquidity (the treasury\n worker). Stands in for an automated rebalance/top-up trigger. Idempotent.", "operationId": "banking.v1.BalanceService.DispatchWithdrawal", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.DispatchWithdrawalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.DispatchWithdrawalResponse" } } } } } } }, "/banking.v1.BalanceService/FailRedemption": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "FailRedemption", "description": "Fail a queued fund redemption (operator): voids the reserved burn, returning the\n user's units. Idempotent.", "operationId": "banking.v1.BalanceService.FailRedemption", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FailRedemptionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Redemption" } } } } } } }, "/banking.v1.BalanceService/FailWithdrawal": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "FailWithdrawal", "description": "Fail a processing user withdrawal that never reached the chain: voids the\n reservation, refunding the user. NEVER call this if the broadcast may have landed\n on-chain — that would double-pay. Idempotent.", "operationId": "banking.v1.BalanceService.FailWithdrawal", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FailWithdrawalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FailWithdrawalResponse" } } } } } } }, "/banking.v1.BalanceService/GetFundRevenue": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "GetFundRevenue", "description": "What the platform has EARNED: the `fee` allocation, in the same shape the treasury\n lists every allocation in — its cash (settled / reserved / available), its supply,\n its price and who holds it. Admin/Owner. Nothing pays it out from here: a holder is\n paid by redeeming their units, and a payment out of its claim is an order the owners\n approve (`PaymentsService.OpenPayment` with source `{kind: \"service\", id: \"fee\"}`).", "operationId": "banking.v1.BalanceService.GetFundRevenue", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetFundRevenueRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.AllocationTreasury" } } } } } } }, "/banking.v1.BalanceService/GetOperationsMode": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "GetOperationsMode", "description": "Operator (TreasuryRead): the money-plane operations mode (the read-only kill-switch).", "operationId": "banking.v1.BalanceService.GetOperationsMode", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetOperationsModeRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.OperationsMode" } } } } } } }, "/banking.v1.BalanceService/GetTreasury": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "GetTreasury", "description": "The treasury: per-rail on-chain liquidity (Layer 2) and the claims it backs\n (Layer 1), read live from TigerBeetle (Read-First).", "operationId": "banking.v1.BalanceService.GetTreasury", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetTreasuryRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Treasury" } } } } } } }, "/banking.v1.BalanceService/ListParkedEvents": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "ListParkedEvents", "description": "Operator (TreasuryRead): outbox rows the relay parked (needs-intervention).", "operationId": "banking.v1.BalanceService.ListParkedEvents", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListParkedEventsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ParkedEventList" } } } } } } }, "/banking.v1.BalanceService/ListRails": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "ListRails", "description": "Operator (TreasuryRead): every rail, whether this deployment runs it, and whether an\n operator froze it.", "operationId": "banking.v1.BalanceService.ListRails", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListRailsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RailList" } } } } } } }, "/banking.v1.BalanceService/ListRedemptionQueue": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "ListRedemptionQueue", "description": "Operator (RedemptionSettle): the cross-user queue of redemptions awaiting settle,\n oldest first — the \"Valuation \u0026 redemptions\" screen's clear-the-queue surface.\n (Est. cash = units × current NAV is computed client-side from the posted NAV.)", "operationId": "banking.v1.BalanceService.ListRedemptionQueue", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListRedemptionQueueRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RedemptionQueue" } } } } } } }, "/banking.v1.BalanceService/ListWithdrawalQueue": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "ListWithdrawalQueue", "description": "Admin (WithdrawalSettle): the cross-user queue of withdrawals awaiting operator\n action, oldest first — `queued` (awaiting liquidity/dispatch) and `processing`\n (broadcast in flight: settle with the mined tx ref, or fail ONLY if nothing\n reached the chain). The admin Withdrawals screen's clear-the-queue surface.", "operationId": "banking.v1.BalanceService.ListWithdrawalQueue", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListWithdrawalQueueRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.WithdrawalQueue" } } } } } } }, "/banking.v1.BalanceService/MigrateDepositAddressToCustodian": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "Admin (DepositAddressMigrate): retire a user's HEALTHY, KEK-sealed deposit address\n in favour of one minted inside the key custodian's enclave (phase 4 of\n docs/MIGRATION-turnkey.md), and refresh the hub's address cache.", "description": "NOT the rotation path. Rotation recovers a key that is already dead; this retires a\n live one, so the hub must first prove the address has nothing left on it — refused\n while the user has any credited deposit on this rail that no sweep has observed\n drained. The signer independently refuses a dead key, an already-migrated row, and\n an address other than the one this hub cleared.", "operationId": "banking.v1.BalanceService.MigrateDepositAddressToCustodian", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.MigrateDepositAddressToCustodianRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.MigrateDepositAddressToCustodianResponse" } } } } } } }, "/banking.v1.BalanceService/PostFundValuation": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "PostFundValuation", "description": "Post a fund's total AUM; NAV is derived = AUM / units_outstanding (units read live\n from TigerBeetle). Rejects zero units and a NAV move beyond the safety threshold —\n measured against BOTH the previous mark and the mark that anchored the rolling\n window, so the cap cannot be walked past in steps. There is NO per-request override:\n a move past the cap is put to the owners through\n `ConsiliumService.OpenValuationOverride`, and only an executed consilium records it.", "operationId": "banking.v1.BalanceService.PostFundValuation", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.PostFundValuationRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FundNav" } } } } } } }, "/banking.v1.BalanceService/RecordDeposit": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "RecordDeposit", "description": "Record a settled on-chain deposit, crediting a party's claim. Idempotent by\n `tx_ref` — recording the same chain tx twice credits once.", "operationId": "banking.v1.BalanceService.RecordDeposit", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RecordDepositRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RecordDepositResponse" } } } } } } }, "/banking.v1.BalanceService/RotateDepositAddress": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "RotateDepositAddress", "description": "Admin (DepositAddressRotate): supersede a user's PROVABLY DEAD deposit address\n (the signer can no longer unseal its key — the KEK-epoch casualty class) with a\n freshly minted keypair, and refresh the hub's address cache. The signer refuses\n to rotate a key that still unseals. Funds already on the old address remain\n unrecoverable; this restores the user's ability to receive FUTURE deposits.", "operationId": "banking.v1.BalanceService.RotateDepositAddress", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RotateDepositAddressRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RotateDepositAddressResponse" } } } } } } }, "/banking.v1.BalanceService/SeedCapital": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "SeedCapital", "description": "Propose a seed of the platform's capital: a transfer that reached a rail's treasury\n address from outside, PROVEN against the chain, to be booked as the depositor's\n deposit and subscribed into the `fund` allocation — units of `fund` for the person\n whose money it was. This OPENS A CONSILIUM and books nothing: the chain proves the\n dollar arrived, it cannot say whose it is, and the first administrator to name a\n reference must not be the one who decides. The caller must hold an owner seat. The\n arrival is verified now (same verification as RecordDeposit, against\n `expected_amount`); a transfer to a user's deposit address is that user's deposit\n and is refused (record it with RecordDeposit); the sweep is refused; a reference\n already recorded is a conflict.", "operationId": "banking.v1.BalanceService.SeedCapital", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SeedCapitalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SeedCapitalResponse" } } } } } } }, "/banking.v1.BalanceService/SetOperationsMode": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "SetOperationsMode", "description": "Admin (OperationsManage): toggle read-only mode. When on, every user money mutation\n (withdraw / subscribe / redeem) is rejected — \"pause deposits \u0026 withdrawals\".", "operationId": "banking.v1.BalanceService.SetOperationsMode", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SetOperationsModeRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.OperationsMode" } } } } } } }, "/banking.v1.BalanceService/SetRailFrozen": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "SetRailFrozen", "description": "Admin (OperationsManage): freeze/unfreeze a rail — no new deposit addresses or\n withdrawals on it, queued withdrawals held, and no treasury gas alert.", "operationId": "banking.v1.BalanceService.SetRailFrozen", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SetRailFrozenRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RailList" } } } } } } }, "/banking.v1.BalanceService/SettleRedemption": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "SettleRedemption", "description": "Settle a queued fund redemption once the fund's claim is liquid (the treasury\n worker): prices at the settle-time NAV and pays the cash. Idempotent.", "operationId": "banking.v1.BalanceService.SettleRedemption", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SettleRedemptionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Redemption" } } } } } } }, "/banking.v1.BalanceService/SettleWithdrawal": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "SettleWithdrawal", "description": "Settle a user withdrawal once it has the required on-chain confirmations: posts the\n reservation and moves the net out of custody. `tx_ref` is the chain transaction.\n Stands in for a chain watcher + custody confirmation callback. Idempotent.", "operationId": "banking.v1.BalanceService.SettleWithdrawal", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SettleWithdrawalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SettleWithdrawalResponse" } } } } } } }, "/banking.v1.BalanceService/UnparkEvent": { "post": { "tags": [ "banking.v1.BalanceService" ], "summary": "UnparkEvent", "description": "Admin (OutboxManage): clear `parked_at` so the relay re-drives the event once the\n cause is fixed; refused for a compensated row — it parked half-applied with\n compensation owed, so re-driving would re-apply the legs that already posted.", "operationId": "banking.v1.BalanceService.UnparkEvent", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UnparkEventRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UnparkEventResponse" } } } } } } }, "/banking.v1.BookService/CancelOrder": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "CancelOrder", "description": "Take the caller's resting order off the book; its unspent escrow is released.\n Idempotent on an already-cancelled order; a filled one is ALREADY_EXISTS.", "operationId": "banking.v1.BookService.CancelOrder", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.CancelOrderRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Order" } } } } } } }, "/banking.v1.BookService/GetBook": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "GetBook", "description": "The aggregated book: the top `depth` price levels a side, the last trade, the\n 24h figures, and the fund's NAV for the ticker. Readable by anyone who may view the\n allocation; a hidden one is NOT_FOUND, as on AllocationsService.", "operationId": "banking.v1.BookService.GetBook", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetBookRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.BookSnapshot" } } } } } } }, "/banking.v1.BookService/GetBookPolicy": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "GetBookPolicy", "description": "The allocation's trading terms. Readable by anyone who may view the allocation.", "operationId": "banking.v1.BookService.GetBookPolicy", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetBookPolicyRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.BookPolicy" } } } } } } }, "/banking.v1.BookService/ListCandles": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "ListCandles", "description": "OHLCV candles aggregated from the tape over `[from, to)`, one per non-empty bucket\n at `resolution` (1m | 5m | 15m | 1h | 4h | 1d). Buckets with no trade are omitted —\n a chart carries the last close forward itself.", "operationId": "banking.v1.BookService.ListCandles", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListCandlesRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.CandleList" } } } } } } }, "/banking.v1.BookService/ListOpenOrders": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "ListOpenOrders", "description": "The caller's resting orders (`open` | `partially_filled`), oldest first, optionally\n on one allocation.", "operationId": "banking.v1.BookService.ListOpenOrders", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListOpenOrdersRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.OrderList" } } } } } } }, "/banking.v1.BookService/ListOrderHistory": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "ListOrderHistory", "description": "The caller's orders in every state, newest first, optionally on one allocation.", "operationId": "banking.v1.BookService.ListOrderHistory", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListOrderHistoryRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.OrderList" } } } } } } }, "/banking.v1.BookService/ListTrades": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "ListTrades", "description": "The public tape, newest first: price, size, the taker's side and the time. No\n order ids and no parties — a counterparty is never disclosed.", "operationId": "banking.v1.BookService.ListTrades", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListTradesRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.TradeList" } } } } } } }, "/banking.v1.BookService/ListUserTrades": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "ListUserTrades", "description": "The caller's own fills, newest first: each carries the caller's side, their order\n id and the fee they paid on it.", "operationId": "banking.v1.BookService.ListUserTrades", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListUserTradesRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.TradeList" } } } } } } }, "/banking.v1.BookService/PlaceOrder": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "Place an order for the caller. Limit orders carry a `price` on the policy's tick;\n market orders leave it empty and are priced by the hub from the best opposite quote\n ± the policy's slippage, then run as an IOC limit at that price (an empty opposite\n side is FAILED_PRECONDITION). `size` is on the policy's lot.", "description": "Refusals: `book_open = false`, or the caller below `invest` — FAILED_PRECONDITION;\n a post-only (`alo`) order that would cross, or one that would trade against the\n caller's own resting order — INVALID_ARGUMENT, nothing recorded; an insufficient\n available balance or holding — INVALID_ARGUMENT.\n\n Idempotent by `client_order_id`, unique per caller: a retry of a timed-out call\n returns the order the id already names. The same id for a DIFFERENT order is\n ALREADY_EXISTS.", "operationId": "banking.v1.BookService.PlaceOrder", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.PlaceOrderRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Order" } } } } } } }, "/banking.v1.BookService/SetBookPolicy": { "post": { "tags": [ "banking.v1.BookService" ], "summary": "SetBookPolicy", "description": "Replace the allocation's trading terms (AllocationManage). Closing the book\n (`book_open = false`) stops new orders; resting ones stay and may still be cancelled.", "operationId": "banking.v1.BookService.SetBookPolicy", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SetBookPolicyRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.BookPolicy" } } } } } } }, "/banking.v1.BookService/WatchBook": {}, "/banking.v1.ConsiliumApprovalService/GetInvitation": { "post": { "tags": [ "banking.v1.ConsiliumApprovalService" ], "summary": "GetInvitation", "description": "The redacted invitation behind an emailed token. Side-effect free. Unknown,\n expired, spent and wrong-state tokens all return the SAME NOT_FOUND, so this\n cannot be used to probe which is which.", "operationId": "banking.v1.ConsiliumApprovalService.GetInvitation", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetInvitationRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ConsiliumInvitation" } } } } } } }, "/banking.v1.ConsiliumApprovalService/SubmitDecision": { "post": { "tags": [ "banking.v1.ConsiliumApprovalService" ], "summary": "SubmitDecision", "description": "Cast this owner's vote. Requires the token AND the secret code from the mail.\n Five failed code attempts burn the token permanently.", "operationId": "banking.v1.ConsiliumApprovalService.SubmitDecision", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SubmitDecisionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SubmitDecisionResponse" } } } } } } }, "/banking.v1.ConsiliumService/CancelConsilium": { "post": { "tags": [ "banking.v1.ConsiliumService" ], "summary": "CancelConsilium", "description": "Withdraw an invoice the caller opened, while it is still OPEN.", "operationId": "banking.v1.ConsiliumService.CancelConsilium", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.CancelConsiliumRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Consilium" } } } } } } }, "/banking.v1.ConsiliumService/GetConsilium": { "post": { "tags": [ "banking.v1.ConsiliumService" ], "summary": "GetConsilium", "description": "One consilium in full, including per-voter state (Owner only).", "operationId": "banking.v1.ConsiliumService.GetConsilium", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetConsiliumRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Consilium" } } } } } } }, "/banking.v1.ConsiliumService/ListConsilia": { "post": { "tags": [ "banking.v1.ConsiliumService" ], "summary": "ListConsilia", "description": "Consilia newest first — the governance history (Owner only).", "operationId": "banking.v1.ConsiliumService.ListConsilia", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListConsiliaRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ConsiliumList" } } } } } } }, "/banking.v1.ConsiliumService/OpenHolderGrant": { "post": { "tags": [ "banking.v1.ConsiliumService" ], "summary": "OpenHolderGrant", "description": "Seat a new holder of a reserved allocation (Owner only): `units` of `fee` or `fund`\n minted to a person, with no cash leg, once the quorum carries. The units are\n frozen into the terms, not a cash figure — what they are worth is the allocation's\n NAV at execution, as a subscription is priced at its own moment. Refused when the\n person is not an active user, when the allocation is not reserved, or when the\n roster is too small. This is the ONLY way a person comes to hold `fee` or `fund`\n other than a seed (`BalanceService.SeedCapital`) or the book.", "operationId": "banking.v1.ConsiliumService.OpenHolderGrant", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.OpenHolderGrantRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Consilium" } } } } } } }, "/banking.v1.ConsiliumService/OpenValuationOverride": { "post": { "tags": [ "banking.v1.ConsiliumService" ], "summary": "OpenValuationOverride", "description": "Put a NAV mark the move guard refuses to the owners (ValuationPost holders — the\n poster proposes, the owners decide). Executing it records the mark at exactly this\n AUM, guard or no guard; there is no other way past the guard. One open request per\n fund: it shares the fund's `service:\u003cid\u003e` claim with a payment out of that claim.", "operationId": "banking.v1.ConsiliumService.OpenValuationOverride", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.OpenValuationOverrideRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Consilium" } } } } } } }, "/banking.v1.FeesService/AcknowledgeUndeliveredNotices": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "AcknowledgeUndeliveredNotices", "description": "Take responsibility for the holders of a scheduled change who could not be told\n (AllocationManage, AND the caller must be the one who requested the change or a fund\n owner). A change that TIGHTENS the terms does not bind while a holder's notice is\n undelivered; for a holder the identity plane can never reach that is forever. This\n records who acknowledged, when, and exactly which holders' notices the mailer had\n GIVEN UP on by that moment (`notices_given_up`, never a notice still being tried), and\n the change then binds over those holders — and over nobody else who turns out untold\n later. A later call ADDS the holders given up on since (`notices_unacknowledged`) and\n stands as the latest: its caller and moment replace the record's, taking\n responsibility for the whole list. A repeat that would add nobody returns the record\n unchanged. ALREADY_EXISTS when the change is not scheduled, only loosens the terms (it\n binds by itself), or has no notice given up on yet that is not already covered —\n there is nothing to take responsibility for; PERMISSION_DENIED for a caller who is\n neither the requester nor an owner.", "operationId": "banking.v1.FeesService.AcknowledgeUndeliveredNotices", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.AcknowledgeUndeliveredNoticesRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeePolicyChange" } } } } } } }, "/banking.v1.FeesService/CancelFeePolicyChange": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "CancelFeePolicyChange", "description": "Withdraw a pending change (AllocationManage). One still awaiting the owners takes its\n consilium down with it. Idempotent on an already-cancelled change.", "operationId": "banking.v1.FeesService.CancelFeePolicyChange", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.CancelFeePolicyChangeRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeePolicyChange" } } } } } } }, "/banking.v1.FeesService/GetAccruedFees": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "GetAccruedFees", "description": "What the caller's holding owes right now WITHOUT charging it: the management fee\n accrued since the last charge, the performance fee that would crystallize at\n today's NAV, and any carried debt. This is what a position's \"value net of fees\"\n must subtract, and it carries the investor's own mark so the figure is explicable.", "operationId": "banking.v1.FeesService.GetAccruedFees", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetAccruedFeesRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.AccruedFees" } } } } } } }, "/banking.v1.FeesService/GetFeePolicy": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "GetFeePolicy", "description": "One fund's terms, or an empty policy when the product charges nothing. Readable\n by any authenticated user — an investor is entitled to know what they are paying.", "operationId": "banking.v1.FeesService.GetFeePolicy", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetFeePolicyRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeePolicy" } } } } } } }, "/banking.v1.FeesService/GetFeeShares": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "GetFeeShares", "description": "The fund's accumulated, unconverted fee units and what they are worth\n (AllocationManage).", "operationId": "banking.v1.FeesService.GetFeeShares", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetFeeSharesRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeeShares" } } } } } } }, "/banking.v1.FeesService/ListFeeAssessments": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "ListFeeAssessments", "description": "The caller's own fee statement, newest first — every charge, what it was for, and\n anything that deferred.", "operationId": "banking.v1.FeesService.ListFeeAssessments", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListFeeAssessmentsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeeAssessmentList" } } } } } } }, "/banking.v1.FeesService/ListFeePolicies": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "ListFeePolicies", "description": "Every configured policy, ordered by service. Readable by any authenticated user.", "operationId": "banking.v1.FeesService.ListFeePolicies", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListFeePoliciesRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeePolicyList" } } } } } } }, "/banking.v1.FeesService/ListFeePolicyChanges": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "ListFeePolicyChanges", "description": "A fund's whole history of terms, newest version first. Readable by any\n authenticated user — the terms one is on, and how they came to be, are public\n information about a product.", "operationId": "banking.v1.FeesService.ListFeePolicyChanges", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListFeePolicyChangesRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeePolicyChangeList" } } } } } } }, "/banking.v1.FeesService/ListFundFeeAssessments": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "ListFundFeeAssessments", "description": "Every charge against one fund (AllocationManage).", "operationId": "banking.v1.FeesService.ListFundFeeAssessments", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListFundFeeAssessmentsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeeAssessmentList" } } } } } } }, "/banking.v1.FeesService/ScheduleFeePolicy": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "Propose a change of a fund's terms (AllocationManage — the same trust seam as\n bringing the product into existence or posting its valuation). The service must\n already be a registered allocation. Rates are basis points, capped at 500\n (management, 5% p.a.) and 5000 (performance, 50% of the gain); the hurdle at 10000.", "description": "A policy is never edited in place. The change is recorded with a version and takes\n effect no earlier than 24h after it was scheduled while anyone holds units (at once\n for a fund with no holders); `effective_from` may ask for later, never earlier. A\n change that TIGHTENS the terms beyond the house envelope (2-and-20 on invested\n capital, annual) needs the owners' consilium, which the caller must be an owner to\n open, and `reason` is then required; every other change is scheduled at once. The\n holders are mailed when the change is scheduled. One pending change per fund: a\n second is refused with ALREADY_EXISTS until the first is cancelled.", "operationId": "banking.v1.FeesService.ScheduleFeePolicy", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ScheduleFeePolicyRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeePolicyChange" } } } } } } }, "/banking.v1.FeesService/SettleFeeShares": { "post": { "tags": [ "banking.v1.FeesService" ], "summary": "SettleFeeShares", "description": "Convert accumulated fee units into the `fee` allocation's cash (AllocationManage).\n Omit `units` to settle the whole balance. Refused — never queued — when the fund's\n claim cannot cover the payout: nobody is waiting on this, and unconverted fee units\n keep accumulating at no cost. The settler is the CALLER, never a field: whoever\n posted the product's latest mark cannot settle its fee class for 7 days, so a\n request cannot name somebody else to get past that.", "operationId": "banking.v1.FeesService.SettleFeeShares", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SettleFeeSharesRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FeeSettlement" } } } } } } }, "/banking.v1.FundsService/CancelRedemption": { "post": { "tags": [ "banking.v1.FundsService" ], "summary": "CancelRedemption", "description": "Cancel a still-queued redemption (returns the reserved units).", "operationId": "banking.v1.FundsService.CancelRedemption", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.CancelRedemptionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Redemption" } } } } } } }, "/banking.v1.FundsService/GetFundNav": { "post": { "tags": [ "banking.v1.FundsService" ], "summary": "GetFundNav", "description": "The current NAV (price per share) for a fund, plus freshness.", "operationId": "banking.v1.FundsService.GetFundNav", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetFundNavRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FundNav" } } } } } } }, "/banking.v1.FundsService/GetPosition": { "post": { "tags": [ "banking.v1.FundsService" ], "summary": "GetPosition", "description": "The caller's position in one fund (units, NAV, value, cost basis, P\u0026L).", "operationId": "banking.v1.FundsService.GetPosition", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetPositionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Position" } } } } } } }, "/banking.v1.FundsService/ListFundNavHistory": { "post": { "tags": [ "banking.v1.FundsService" ], "summary": "ListFundNavHistory", "description": "The posted valuation marks of one allocation over a window, plus the caller's own\n participation (units held × NAV) through it — the two series of the performance chart.", "operationId": "banking.v1.FundsService.ListFundNavHistory", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListFundNavHistoryRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.FundNavHistory" } } } } } } }, "/banking.v1.FundsService/ListPositions": { "post": { "tags": [ "banking.v1.FundsService" ], "summary": "ListPositions", "description": "All of the caller's fund positions.", "operationId": "banking.v1.FundsService.ListPositions", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListPositionsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.PositionList" } } } } } } }, "/banking.v1.FundsService/ListRedemptions": { "post": { "tags": [ "banking.v1.FundsService" ], "summary": "ListRedemptions", "description": "The caller's redemptions for the fund surface (newest first).", "operationId": "banking.v1.FundsService.ListRedemptions", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListRedemptionsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RedemptionList" } } } } } } }, "/banking.v1.FundsService/Redeem": { "post": { "tags": [ "banking.v1.FundsService" ], "summary": "Redeem", "description": "Redeem `units` of a fund back to cash (accept-and-queue; settle-time priced).", "operationId": "banking.v1.FundsService.Redeem", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RedeemRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Redemption" } } } } } } }, "/banking.v1.FundsService/Subscribe": { "post": { "tags": [ "banking.v1.FundsService" ], "summary": "Subscribe", "description": "Subscribe `amount` of free balance into a fund, minting units at the current NAV.\n Returns the mint receipt; the holding updates once the relay applies it.", "operationId": "banking.v1.FundsService.Subscribe", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SubscribeRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Subscription" } } } } } } }, "/banking.v1.HealthService/Check": { "post": { "tags": [ "banking.v1.HealthService" ], "summary": "Check", "operationId": "banking.v1.HealthService.Check", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.CheckRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.CheckResponse" } } } } } } }, "/banking.v1.HealthService/Readiness": { "post": { "tags": [ "banking.v1.HealthService" ], "summary": "Readiness", "operationId": "banking.v1.HealthService.Readiness", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ReadinessRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ReadinessResponse" } } } } } } }, "/banking.v1.OperationsService/ListOperations": { "post": { "tags": [ "banking.v1.OperationsService" ], "summary": "ListOperations", "description": "The caller's operations, newest first, across all four kinds.", "operationId": "banking.v1.OperationsService.ListOperations", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListOperationsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.OperationList" } } } } } } }, "/banking.v1.PaymentConsentService/GetConsentInvitation": { "post": { "tags": [ "banking.v1.PaymentConsentService" ], "summary": "GetConsentInvitation", "description": "The redacted invitation behind an emailed token. Side-effect free. Unknown, expired,\n spent, burned and closed tokens all return the SAME NOT_FOUND.", "operationId": "banking.v1.PaymentConsentService.GetConsentInvitation", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetConsentInvitationRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.PaymentConsentInvitation" } } } } } } }, "/banking.v1.PaymentConsentService/SubmitConsent": { "post": { "tags": [ "banking.v1.PaymentConsentService" ], "summary": "SubmitConsent", "description": "Answer the consent. Requires the token AND the secret code from the mail. Five failed\n code attempts burn the token permanently — and, with one seat, fail the payment closed.", "operationId": "banking.v1.PaymentConsentService.SubmitConsent", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SubmitConsentRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.SubmitConsentResponse" } } } } } } }, "/banking.v1.PaymentsService/CancelPayment": { "post": { "tags": [ "banking.v1.PaymentsService" ], "summary": "CancelPayment", "description": "Withdraw an order the CALLER opened, while it is still pending. Anyone else is refused.", "operationId": "banking.v1.PaymentsService.CancelPayment", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.CancelPaymentRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Payment" } } } } } } }, "/banking.v1.PaymentsService/GetPayment": { "post": { "tags": [ "banking.v1.PaymentsService" ], "summary": "GetPayment", "description": "One order in full (Admin/Owner).", "operationId": "banking.v1.PaymentsService.GetPayment", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetPaymentRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Payment" } } } } } } }, "/banking.v1.PaymentsService/ListPayments": { "post": { "tags": [ "banking.v1.PaymentsService" ], "summary": "ListPayments", "description": "The payment history, newest first, filtered (Admin/Owner). Nothing is ever deleted.", "operationId": "banking.v1.PaymentsService.ListPayments", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListPaymentsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.PaymentList" } } } } } } }, "/banking.v1.PaymentsService/OpenPayment": { "post": { "tags": [ "banking.v1.PaymentsService" ], "summary": "OpenPayment", "description": "Open a payment order (Admin/Owner). Refused when the source cannot cover the amount\n right now, when the shape could never execute (an unconfigured rail, a sub-minimum\n external amount, an external destination out of a service claim), or when another\n order is already open against the same service claim.", "operationId": "banking.v1.PaymentsService.OpenPayment", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.OpenPaymentRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Payment" } } } } } } }, "/banking.v1.UsersService/DisableUser": { "post": { "tags": [ "banking.v1.UsersService" ], "summary": "DisableUser", "description": "Admin (allowlist): disable a user, freezing future sign-in/refresh without\n deleting the record.", "operationId": "banking.v1.UsersService.DisableUser", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.DisableUserRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.DisableUserResponse" } } } } } } }, "/banking.v1.UsersService/GetBalance": { "post": { "tags": [ "banking.v1.UsersService" ], "summary": "GetBalance", "description": "The calling user's live balance, read straight from TigerBeetle (Read-First).\n No Postgres-stored amount exists; the response is authoritative as of `as_of`.", "operationId": "banking.v1.UsersService.GetBalance", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetUserBalanceRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UserBalanceResponse" } } } } } } }, "/banking.v1.UsersService/GetMe": { "post": { "tags": [ "banking.v1.UsersService" ], "summary": "GetMe", "description": "The calling user's own identity (resolved from the access-token `sub`).", "operationId": "banking.v1.UsersService.GetMe", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetMeRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UserProfile" } } } } } } }, "/banking.v1.UsersService/GetUserBalance": { "post": { "tags": [ "banking.v1.UsersService" ], "summary": "GetUserBalance", "description": "Admin (UserBalanceRead): read ANY user's live balance by id — the operator\n console's user-detail drawer. The self-service GetBalance above acts on the\n caller's own `sub`; this one takes an explicit target and is role-gated.", "operationId": "banking.v1.UsersService.GetUserBalance", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.AdminBalanceRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UserBalanceResponse" } } } } } } }, "/banking.v1.UsersService/RevokeTokens": { "post": { "tags": [ "banking.v1.UsersService" ], "summary": "RevokeTokens", "description": "Admin (allowlist): bump a user's token_version so all their outstanding access\n tokens are rejected hub-side. The token-revocation control surface.", "operationId": "banking.v1.UsersService.RevokeTokens", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RevokeTokensRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RevokeTokensResponse" } } } } } } }, "/banking.v1.UsersService/UpdateProfile": { "post": { "tags": [ "banking.v1.UsersService" ], "summary": "UpdateProfile", "description": "Update the caller's own editable profile fields (full-replace of the set in\n UpdateProfileRequest). Identity/auth fields (email, status) are not editable here.", "operationId": "banking.v1.UsersService.UpdateProfile", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UpdateProfileRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.UserProfile" } } } } } } }, "/banking.v1.WalletService/CancelWithdrawal": { "post": { "tags": [ "banking.v1.WalletService" ], "summary": "CancelWithdrawal", "description": "Cancel one of the caller's still-queued withdrawals (refund). Rejected once the\n withdrawal is processing (a broadcast may have landed).", "operationId": "banking.v1.WalletService.CancelWithdrawal", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.CancelWithdrawalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Withdrawal" } } } } } } }, "/banking.v1.WalletService/GetDepositAddress": { "post": { "tags": [ "banking.v1.WalletService" ], "summary": "GetDepositAddress", "description": "The caller's deposit address on a network (stable; derived once and reused).", "operationId": "banking.v1.WalletService.GetDepositAddress", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetDepositAddressRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.DepositAddress" } } } } } } }, "/banking.v1.WalletService/GetWallet": { "post": { "tags": [ "banking.v1.WalletService" ], "summary": "GetWallet", "description": "The caller's wallet — the unified lifecycle balance, deposit addresses, and the\n per-rail withdrawable view.", "operationId": "banking.v1.WalletService.GetWallet", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.GetWalletRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Wallet" } } } } } } }, "/banking.v1.WalletService/ListDeposits": { "post": { "tags": [ "banking.v1.WalletService" ], "summary": "ListDeposits", "description": "The caller's confirmed on-chain deposits, newest first.", "operationId": "banking.v1.WalletService.ListDeposits", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListDepositsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.DepositList" } } } } } } }, "/banking.v1.WalletService/ListWithdrawals": { "post": { "tags": [ "banking.v1.WalletService" ], "summary": "ListWithdrawals", "description": "The caller's withdrawals, newest first.", "operationId": "banking.v1.WalletService.ListWithdrawals", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.ListWithdrawalsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.WithdrawalList" } } } } } } }, "/banking.v1.WalletService/RequestWithdrawal": { "post": { "tags": [ "banking.v1.WalletService" ], "summary": "RequestWithdrawal", "description": "Request an on-chain withdrawal of free balance to an external address. Accepted\n (and reserved) as long as the unified balance covers it; it ships immediately when\n the chosen rail is liquid, otherwise it is queued until the treasury tops it up.", "operationId": "banking.v1.WalletService.RequestWithdrawal", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.RequestWithdrawalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/banking.v1.Withdrawal" } } } } } } }, "/concierge.v1.AuthService/ExchangeCode": { "post": { "tags": [ "concierge.v1.AuthService" ], "summary": "Redeem a one-time authorization code for a RELYING PARTY's own token pair — the\n back half of the code flow a first-party client on another origin (the Service-Arb\n panel) runs against `GET /auth/authorize` (publicly `evinvest.ltd/api/auth/authorize`).\n Called server-to-server by the client's backend, authenticated by its client\n secret. The code is single-use, lives 60s, and is bound to the client, the exact\n redirect_uri and the PKCE (S256) challenge sent to authorize; presenting a code\n twice is refused AND revokes every token issued off it.", "description": "The access token is `typ=access` with `aud=\u003cthe client's audience\u003e` (e.g. `sa`) and\n a TTL of at most 15 minutes. It opens exactly one RPC in this plane —\n `UserDirectory.GetMe`, which answers it with a trimmed profile (no identity-document\n fields, no KYC level) — and is refused (UNAUTHENTICATED) everywhere else, here and\n on the money plane. Signing out of evinvest.ltd (Logout, RevokeSession, revoke-all)\n revokes the client sessions that sign-in authorized. The refresh token is opaque and bound to the client.", "operationId": "concierge.v1.AuthService.ExchangeCode", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ExchangeCodeRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ClientTokenResponse" } } } } } } }, "/concierge.v1.AuthService/Jwks": { "post": { "tags": [ "concierge.v1.AuthService" ], "summary": "Jwks", "description": "Publish the current signing public keys (JWKS). Polled by downstream services'\n `evconcierge_auth` verifier to refresh its local cache; also consulted on an\n unknown-`kid` miss. Carries only public key material.", "operationId": "concierge.v1.AuthService.Jwks", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.JwksRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.JwksResponse" } } } } } } }, "/concierge.v1.AuthService/ListSessions": { "post": { "tags": [ "concierge.v1.AuthService" ], "summary": "ListSessions", "description": "List the caller's active sessions (refresh-token families). Identity is proven by\n the presented refresh token (the BFF holds it server-side); the family that owns\n that token is flagged `current`.", "operationId": "concierge.v1.AuthService.ListSessions", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListSessionsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListSessionsResponse" } } } } } } }, "/concierge.v1.AuthService/Logout": { "post": { "tags": [ "concierge.v1.AuthService" ], "summary": "Logout", "description": "Revoke the presented refresh token's family. With `revoke_all` set, also bumps\n the user's `token_version` so every outstanding access token is rejected.", "operationId": "concierge.v1.AuthService.Logout", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.LogoutRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.LogoutResponse" } } } } } } }, "/concierge.v1.AuthService/PublishCatalog": { "post": { "tags": [ "concierge.v1.AuthService" ], "summary": "PublishCatalog", "description": "A relying party publishes its tenant's catalog: the permissions and aliases its\n namespace defines. Authenticated by the client secret, like ExchangeCode. Refused\n (INVALID_ARGUMENT) when anything lies outside the tenant's namespace, an alias names\n a permission the catalog does not define, a delegated alias delegates in turn, the\n catalog exceeds 1024 permissions or 128 aliases or a name exceeds 128 characters, or\n `version` lies more than a day ahead of this plane's clock; FAILED_PRECONDITION when\n `version` is older than the stored one, or equal with different content. Every\n published catalog is kept. Grants whose target the new catalog drops stay, grant\n nothing, and are listed as orphaned.", "operationId": "concierge.v1.AuthService.PublishCatalog", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.PublishCatalogRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.PublishCatalogResponse" } } } } } } }, "/concierge.v1.AuthService/Refresh": { "post": { "tags": [ "concierge.v1.AuthService" ], "summary": "Refresh", "description": "Rotate a refresh token: returns a fresh access+refresh pair and invalidates\n the presented refresh token (rotation + reuse detection in the central store).", "operationId": "concierge.v1.AuthService.Refresh", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.RefreshRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.TokenResponse" } } } } } } }, "/concierge.v1.AuthService/RefreshClientToken": { "post": { "tags": [ "concierge.v1.AuthService" ], "summary": "RefreshClientToken", "description": "Rotate a relying party's refresh token. The account is re-checked on EVERY rotation,\n so a suspension ends the session at the next refresh rather than at the family's\n deadline; presenting a rotated-out token revokes the family.", "operationId": "concierge.v1.AuthService.RefreshClientToken", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.RefreshClientTokenRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ClientTokenResponse" } } } } } } }, "/concierge.v1.AuthService/RevokeSession": { "post": { "tags": [ "concierge.v1.AuthService" ], "summary": "RevokeSession", "description": "Revoke one of the caller's sessions by id (must belong to the same user). Revoking\n the current session is allowed (acts like a sign-out of this device).", "operationId": "concierge.v1.AuthService.RevokeSession", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.RevokeSessionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.RevokeSessionResponse" } } } } } } }, "/concierge.v1.GovernanceService/CancelOwnerAdmission": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "CancelOwnerAdmission", "description": "Withdraw an admission the caller opened, while it is still OPEN.", "operationId": "concierge.v1.GovernanceService.CancelOwnerAdmission", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.CancelOwnerAdmissionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerAdmission" } } } } } } }, "/concierge.v1.GovernanceService/CancelOwnerRemoval": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "CancelOwnerRemoval", "description": "Withdraw a proposal the caller opened, while it is still OPEN.", "operationId": "concierge.v1.GovernanceService.CancelOwnerRemoval", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.CancelOwnerRemovalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerRemoval" } } } } } } }, "/concierge.v1.GovernanceService/CancelUserProposal": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "CancelUserProposal", "description": "Withdraw a user proposal the caller opened, while it is still OPEN.", "operationId": "concierge.v1.GovernanceService.CancelUserProposal", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.CancelUserProposalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProposal" } } } } } } }, "/concierge.v1.GovernanceService/GetOwnerAdmission": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "GetOwnerAdmission", "operationId": "concierge.v1.GovernanceService.GetOwnerAdmission", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.GetOwnerAdmissionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerAdmission" } } } } } } }, "/concierge.v1.GovernanceService/GetOwnerRemoval": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "GetOwnerRemoval", "operationId": "concierge.v1.GovernanceService.GetOwnerRemoval", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.GetOwnerRemovalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerRemoval" } } } } } } }, "/concierge.v1.GovernanceService/GetUserProposal": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "GetUserProposal", "operationId": "concierge.v1.GovernanceService.GetUserProposal", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.GetUserProposalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProposal" } } } } } } }, "/concierge.v1.GovernanceService/ListOwnerAdmissions": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "ListOwnerAdmissions", "operationId": "concierge.v1.GovernanceService.ListOwnerAdmissions", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListOwnerAdmissionsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerAdmissionList" } } } } } } }, "/concierge.v1.GovernanceService/ListOwnerRemovals": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "ListOwnerRemovals", "operationId": "concierge.v1.GovernanceService.ListOwnerRemovals", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListOwnerRemovalsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerRemovalList" } } } } } } }, "/concierge.v1.GovernanceService/ListOwners": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "ListOwners", "description": "The current owner roster (Owner only).", "operationId": "concierge.v1.GovernanceService.ListOwners", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListOwnersRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerList" } } } } } } }, "/concierge.v1.GovernanceService/ListUserProposals": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "ListUserProposals", "operationId": "concierge.v1.GovernanceService.ListUserProposals", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListUserProposalsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProposalList" } } } } } } }, "/concierge.v1.GovernanceService/OpenAdminAdmission": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "Propose granting Role::Admin (Owner only). UserDirectory.SetRole refuses that role\n in the granting direction and names this, for the same reason it already refuses\n `owner`: an operator who can appoint operators can appoint accomplices, and the\n admin seat carries every identity mutation except role granting.", "description": "Taking the role away is NOT here and stays one act on purpose — containing a rogue\n operator must never be the slower path.", "operationId": "concierge.v1.GovernanceService.OpenAdminAdmission", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OpenAdminAdmissionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProposal" } } } } } } }, "/concierge.v1.GovernanceService/OpenOwnerAdmission": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "Propose GRANTING a seat (Owner only). The candidate does not vote — they are not\n yet an owner — and neither does the initiator, so the voters are every OTHER\n current owner and all of them must agree. A lone owner cannot open one at all.", "description": "This is the only way `Role::Owner` is granted: UserDirectory.SetRole refuses it\n outside an executed admission.", "operationId": "concierge.v1.GovernanceService.OpenOwnerAdmission", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OpenOwnerAdmissionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerAdmission" } } } } } } }, "/concierge.v1.GovernanceService/OpenOwnerRemoval": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "OpenOwnerRemoval", "description": "Propose removing an owner (Owner only). The initiator casts no vote — proposing is\n not agreeing, and counting it would let two owners remove a third.", "operationId": "concierge.v1.GovernanceService.OpenOwnerRemoval", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OpenOwnerRemovalRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerRemoval" } } } } } } }, "/concierge.v1.GovernanceService/OpenUserReinstatement": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "Propose lifting a suspension THE OWNERS imposed (Owner only). It exists because\n UserDirectory.ReinstateUser refuses those: without this RPC the consilium's verdict\n would be either permanent or reversible by any one admin, and both are wrong.", "description": "A hold needs nothing from here — ReinstateUser lifts one in a single act.", "operationId": "concierge.v1.GovernanceService.OpenUserReinstatement", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OpenUserReinstatementRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProposal" } } } } } } }, "/concierge.v1.GovernanceService/OpenUserSuspension": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "Propose PERMANENTLY suspending a user (Owner only). The half of the old\n DisableUser verb that is not an emergency: UserDirectory.HoldUser freezes the\n account now and lapses in 24h, and this is what makes it stay.", "description": "A reason is required. It is what the other owners are voting on, and a decision to\n freeze somebody's account with no stated cause cannot be reviewed afterwards.", "operationId": "concierge.v1.GovernanceService.OpenUserSuspension", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OpenUserSuspensionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProposal" } } } } } } }, "/concierge.v1.GovernanceService/ResignOwnership": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "ResignOwnership", "description": "Resign your own seat. No consilium — but the same floor applies, so the last two\n owners cannot leave the fund without governance.", "operationId": "concierge.v1.GovernanceService.ResignOwnership", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ResignOwnershipRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerList" } } } } } } }, "/concierge.v1.GovernanceService/SubmitAdmissionVote": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "SubmitAdmissionVote", "description": "A peer owner's vote on an admission, cast in the cabinet while signed in. One\n REJECT ends it: admission passes only on unanimity.", "operationId": "concierge.v1.GovernanceService.SubmitAdmissionVote", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SubmitAdmissionVoteRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerAdmission" } } } } } } }, "/concierge.v1.GovernanceService/SubmitPeerVote": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "SubmitPeerVote", "description": "A peer owner's vote, cast in the cabinet while signed in — this is the live\n consilium, not an emailed link. The target and the initiator are both refused.", "operationId": "concierge.v1.GovernanceService.SubmitPeerVote", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SubmitPeerVoteRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerRemoval" } } } } } } }, "/concierge.v1.GovernanceService/SubmitUserProposalVote": { "post": { "tags": [ "concierge.v1.GovernanceService" ], "summary": "SubmitUserProposalVote", "description": "An owner's vote on a user proposal. Unlike the OWNER consilia this passes on a\n MAJORITY of the snapshotted voters rather than unanimity — see UserProposal.", "operationId": "concierge.v1.GovernanceService.SubmitUserProposalVote", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SubmitUserProposalVoteRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProposal" } } } } } } }, "/concierge.v1.GovernanceService/WatchGovernance": {}, "/concierge.v1.MailRelayService/SendGovernanceMail": { "post": { "tags": [ "concierge.v1.MailRelayService" ], "summary": "SendGovernanceMail", "description": "Enqueue one governance mail. Idempotent by `dedupe_key`, so an at-least-once\n caller may retry without sending twice.", "operationId": "concierge.v1.MailRelayService.SendGovernanceMail", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SendGovernanceMailRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SendGovernanceMailResponse" } } } } } } }, "/concierge.v1.OwnerRemovalApprovalService/GetInvitation": { "post": { "tags": [ "concierge.v1.OwnerRemovalApprovalService" ], "summary": "GetInvitation", "description": "The redacted invitation behind an emailed token. Unknown, expired, spent and\n wrong-state tokens all return the same NOT_FOUND.", "operationId": "concierge.v1.OwnerRemovalApprovalService.GetInvitation", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.GetRemovalInvitationRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.OwnerRemovalInvitation" } } } } } } }, "/concierge.v1.OwnerRemovalApprovalService/SubmitSelfDecision": { "post": { "tags": [ "concierge.v1.OwnerRemovalApprovalService" ], "summary": "SubmitSelfDecision", "description": "The target accepting — or refusing — their own removal. Five failed code attempts\n burn the token permanently.", "operationId": "concierge.v1.OwnerRemovalApprovalService.SubmitSelfDecision", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SubmitSelfDecisionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SubmitSelfDecisionResponse" } } } } } } }, "/concierge.v1.UserDirectory/DisableUser": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "DEPRECATED — always refuses, naming HoldUser or\n GovernanceService.OpenUserSuspension.", "description": "The verb was ambiguous in the one way that mattered: it was both the emergency\n brake (the frozen flag the money plane re-reads at dispatch, which stops a\n withdrawal already in the queue) and a permanent judgement on an account, decided\n by one person with no record of why. Those need opposite treatments — the first\n must stay instant, the second must not be one person's to make — so the caller now\n has to say which one they mean. Kept in the contract rather than deleted so an\n older console gets an explanatory refusal instead of an UNIMPLEMENTED.", "operationId": "concierge.v1.UserDirectory.DisableUser", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.DisableUserRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.DisableUserResponse" } } } } }, "deprecated": true } }, "/concierge.v1.UserDirectory/GetMe": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "GetMe", "description": "The calling user's own identity (resolved from the access-token `sub`).", "operationId": "concierge.v1.UserDirectory.GetMe", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.GetMeRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProfile" } } } } } } }, "/concierge.v1.UserDirectory/GetUser": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "GetUser", "description": "Admin (UserRead): the full profile of ANY user by id (the admin sibling of the\n self-only GetMe), for the user-detail drawer.", "operationId": "concierge.v1.UserDirectory.GetUser", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.GetUserRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProfile" } } } } } } }, "/concierge.v1.UserDirectory/GrantPermission": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "Grant a user a target inside a tenant's namespace: an alias (`sa:operator`), a\n permission (`sa:work:leads:read`) or a `*` pattern (`sa:work:*`). Nothing grants\n anything in the `iam`, `concierge`, `bank` or `seat` namespaces (INVALID_ARGUMENT),\n and nobody grants to their own account (PERMISSION_DENIED). A target the tenant's\n catalog does not define grants nothing and is INVALID_ARGUMENT. Re-granting what is\n held is a no-op.", "description": "Who may: a seat holding `iam:tenants:grant` — any target. The holder of an alias the\n catalog lets delegate (`delegations`) — exactly the aliases it delegates, naming the\n user by `account` (an email or a username) only (a `user_id` is PERMISSION_DENIED:\n ids are visible in the roster, and granting one would reveal its owner's address).\n Anyone else, or a target outside the delegation: PERMISSION_DENIED, before the user\n is looked up. An email names the accounts it is verified on or backs a password of;\n only when it names none is the handle read as a username.\n\n To a seat: an unknown user or handle is NOT_FOUND; a handle naming several\n accounts, or a disabled/held account, is FAILED_PRECONDITION with the reason. To a\n delegate all three are the SAME FAILED_PRECONDITION (\"this address cannot be granted\n access\"), so a grant never tells them whether, or how, a handle is known. A\n delegate gets a budget of GrantPermission + RevokePermission calls per hour\n (refusals included); past it, RESOURCE_EXHAUSTED.", "operationId": "concierge.v1.UserDirectory.GrantPermission", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.GrantPermissionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.GrantPermissionResponse" } } } } } } }, "/concierge.v1.UserDirectory/HoldUser": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "HoldUser", "description": "Admin (UserSuspend): the emergency brake. Freezes the account NOW and lapses on\n its own after 24h unless the owners ratify it with OpenUserSuspension. One actor\n may stop money temporarily; one actor may never stop it permanently. Emits\n SUSPENDED across the cross-plane bridge, and REINSTATED again when it lapses.", "operationId": "concierge.v1.UserDirectory.HoldUser", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.HoldUserRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.HoldUserResponse" } } } } } } }, "/concierge.v1.UserDirectory/ListGrants": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "ListGrants", "description": "The active grants inside one tenant namespace, with each holder's identity. A seat\n holding `iam:tenants:grant`, or a delegate of that namespace — who gets `legal_name`\n AND `preferred_name` empty: the team sees each other's email, username and grant, and\n nothing that says who an address belongs to.", "operationId": "concierge.v1.UserDirectory.ListGrants", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListGrantsRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListGrantsResponse" } } } } } } }, "/concierge.v1.UserDirectory/ListUsers": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "ListUsers", "description": "Admin (UserRead): list/search users for the operator console — paginated, with a\n free-text query and optional role/status filters (see ListUsersRequest). Returns\n lightweight summaries, not full profiles.", "operationId": "concierge.v1.UserDirectory.ListUsers", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListUsersRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ListUsersResponse" } } } } } } }, "/concierge.v1.UserDirectory/ReinstateUser": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "Admin (allowlist): re-enable a disabled user, lifting the sign-in/refresh\n freeze. Emits REINSTATED across the cross-plane bridge.", "description": "Refuses with FAILED_PRECONDITION when the suspension was the owners' verdict,\n naming GovernanceService.OpenUserReinstatement — otherwise one admin could\n overturn a consilium and the consilium would be advisory.", "operationId": "concierge.v1.UserDirectory.ReinstateUser", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ReinstateUserRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.ReinstateUserResponse" } } } } } } }, "/concierge.v1.UserDirectory/RevokePermission": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "RevokePermission", "description": "Take a grant away. Same authority as GrantPermission, either addressing form for a\n delegate too: the answer depends only on a grant they can already list. NOT_FOUND when\n the user holds no active grant of that target — including a handle naming nobody, or\n several accounts. Shares GrantPermission's budget.", "operationId": "concierge.v1.UserDirectory.RevokePermission", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.RevokePermissionRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.RevokePermissionResponse" } } } } } } }, "/concierge.v1.UserDirectory/RevokeTokens": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "RevokeTokens", "description": "Admin (allowlist): bump a user's token_version so all their outstanding access\n tokens are rejected. The token-revocation control surface.", "operationId": "concierge.v1.UserDirectory.RevokeTokens", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.RevokeTokensRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.RevokeTokensResponse" } } } } } } }, "/concierge.v1.UserDirectory/SetKycLevel": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "Admin (allowlist): set a user's KYC level. Emits KYC_CHANGED across the\n cross-plane bridge (so the money plane learns the new level). Echoes the\n level now in effect.", "description": "Refuses with PERMISSION_DENIED when user_id is the CALLER's own account.\n KycManage is held by Admin as well as Owner, and tier 1 is the floor for\n withdrawals on the money plane, so without this an operator could lift their\n own money gate. A console must not offer this control on the operator's own\n row: the refusal is decided from the session alone and belongs in front of\n the call. Raising your own level goes through the verification front door,\n which reaches tier 1; above that, and for any downgrade, another holder of\n KycManage acts.", "operationId": "concierge.v1.UserDirectory.SetKycLevel", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SetKycLevelRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SetKycLevelResponse" } } } } } } }, "/concierge.v1.UserDirectory/SetRole": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "SetRole", "description": "Admin (RoleGrant, Owner only): set a user's platform access role. Emits\n ROLE_CHANGED across the cross-plane bridge so the money plane mirrors it. Echoes\n the role now in effect.", "operationId": "concierge.v1.UserDirectory.SetRole", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SetRoleRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.SetRoleResponse" } } } } } } }, "/concierge.v1.UserDirectory/UpdateProfile": { "post": { "tags": [ "concierge.v1.UserDirectory" ], "summary": "UpdateProfile", "description": "Update the caller's own editable profile fields (full-replace of the set in\n UpdateProfileRequest). Identity/auth fields (email, status) are not editable here.", "operationId": "concierge.v1.UserDirectory.UpdateProfile", "parameters": [ { "name": "Connect-Protocol-Version", "in": "header", "required": true, "schema": { "$ref": "#/components/schemas/connect-protocol-version" } }, { "name": "Connect-Timeout-Ms", "in": "header", "schema": { "$ref": "#/components/schemas/connect-timeout-header" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UpdateProfileRequest" } } }, "required": true }, "responses": { "default": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/connect.error" } } } }, "200": { "description": "Success", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/concierge.v1.UserProfile" } } } } } } } }, "components": { "schemas": { "banking.v1.AccruedFees": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "configured": { "type": "boolean", "title": "configured" }, "management": { "type": "string", "title": "management", "description": "accrued since the last charge" }, "performance": { "type": "string", "title": "performance", "description": "what would crystallize at today's NAV" }, "debt": { "type": "string", "title": "debt", "description": "carried from earlier charges" }, "total": { "type": "string", "title": "total", "description": "management + performance + debt" }, "high_water_mark": { "type": "string", "title": "high_water_mark", "description": "the investor's own mark — why their fee differs" } }, "title": "AccruedFees", "additionalProperties": false, "description": "What a holding owes right now. `configured` is false when the fund charges no fee." }, "banking.v1.AcknowledgeUndeliveredNoticesRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "change_id": { "type": "string", "title": "change_id" } }, "title": "AcknowledgeUndeliveredNoticesRequest", "additionalProperties": false }, "banking.v1.AdminBalanceRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id", "description": "The target: the CONCIERGE user id (the handle the operator console carries from\n the identity plane's ListUsers) or the banking user id. Resolution is\n concierge-first via the bridge mirror (`users.concierge_user_id`), falling back\n to the banking id (existing money-plane callers stay valid); an id matching\n neither returns NOT_FOUND — never an authoritative zero." } }, "title": "AdminBalanceRequest", "additionalProperties": false }, "banking.v1.Allocation": { "type": "object", "properties": { "service": { "type": "string", "title": "service", "description": "the slug — the id used by every FundsService RPC" }, "title": { "type": "string", "title": "title", "description": "display name (\"EV Trading\")" }, "summary": { "type": "string", "title": "summary", "description": "one-line description for the catalog card" }, "state": { "type": "string", "title": "state", "description": "draft | open | closed" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64", "description": "unix seconds" }, "updated_at": { "type": [ "integer", "string" ], "title": "updated_at", "format": "int64", "description": "unix seconds" }, "unit_cap": { "type": "string", "title": "unit_cap", "description": "authorised unit supply, decimal (default 100000000)" }, "icon": { "type": "string", "title": "icon", "description": "Catalog glyph the client maps onto one of its SVGs. Presentation only. One of:\n fund | real_estate | trading | yield | venture | treasury | commodity | credit |\n index | arbitrage. Always populated on a response — `fund` is the default." }, "access": { "type": "string", "title": "access", "description": "The product's default access level: hidden | view | invest. What an investor\n with no grant holds. A registration lands on `view`." }, "caller_access": { "type": "string", "title": "caller_access", "description": "The level the CALLER effectively holds — the higher of `access` and the caller's\n own grant, if any. Populated honestly for everyone, an `AllocationManage` holder\n included: their permission lets them read and administer the product, it does not\n make them an investor in it, so a manager's `caller_access` says what they would\n get as one. A client renders the card off `access` and the subscribe control off\n this — never off `state` alone." }, "backing": { "type": "string", "title": "backing", "description": "What stands behind the units: `cash` | `in_kind`. `cash` — the units were paid for\n into the fund's claim and a redemption pays out of it. `in_kind` — the units stand\n for an asset the holders own; the fund holds no cash for them, so `Redeem` is\n refused (FAILED_PRECONDITION) and holders exit through the book. Set to `in_kind`\n automatically by the first IssueUnits on the product; only SetAllocationBacking\n takes it back to `cash`. A registration lands on `cash`." } }, "title": "Allocation", "additionalProperties": false, "description": "One registered investable product. Carries no money: units, NAV and positions are\n read from FundsService against the same `service` id." }, "banking.v1.AllocationAccessGrant": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "user_id": { "type": "string", "title": "user_id", "description": "the investor (banking user id)" }, "level": { "type": "string", "title": "level", "description": "view | invest" }, "granted_by": { "type": "string", "title": "granted_by", "description": "the AllocationManage holder who granted it" }, "granted_at": { "type": [ "integer", "string" ], "title": "granted_at", "format": "int64", "description": "unix seconds" } }, "title": "AllocationAccessGrant", "additionalProperties": false, "description": "One investor raised above an allocation's default level." }, "banking.v1.AllocationAccessGrantList": { "type": "object", "properties": { "grants": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.AllocationAccessGrant" }, "title": "grants" } }, "title": "AllocationAccessGrantList", "additionalProperties": false }, "banking.v1.AllocationClaim": { "type": "object", "properties": { "posted": { "type": "string", "title": "posted" }, "available": { "type": "string", "title": "available" }, "reserved": { "type": "string", "title": "reserved" } }, "title": "AllocationClaim", "additionalProperties": false, "description": "An allocation's cash claim (`service:\u003cid\u003e`), split the way every reader needs it and\n read off ONE ledger balance, so the three can never disagree: `posted` is settled,\n `reserved` is spoken for by approved payments out of it that have not settled, and\n `available = posted − reserved` is what a redemption or a new payment may take." }, "banking.v1.AllocationList": { "type": "object", "properties": { "allocations": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Allocation" }, "title": "allocations" } }, "title": "AllocationList", "additionalProperties": false }, "banking.v1.AllocationTreasury": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "title": { "type": "string", "title": "title" }, "access": { "type": "string", "title": "access", "description": "hidden | view | invest" }, "claim": { "title": "claim", "$ref": "#/components/schemas/banking.v1.AllocationClaim" }, "units_outstanding": { "type": "string", "title": "units_outstanding", "description": "decimal units" }, "nav": { "type": "string", "title": "nav", "description": "decimal USDT per unit" }, "nav_posted_at_unix": { "type": [ "integer", "string" ], "title": "nav_posted_at_unix", "format": "int64" }, "holders": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.UnitHolding" }, "title": "holders" } }, "title": "AllocationTreasury", "additionalProperties": false, "description": "One allocation as the treasury shows it (#245): the registry's name for it, its cash,\n its supply, its price and who holds it — the same shape for a product and for the\n reserved `fee` / `fund` allocations, whose `access` is `hidden`. `nav` is a product's\n posted mark, or the computed value of a reserved allocation (its cash plus every fee\n class it holds at that product's NAV) over its supply; `nav_posted_at_unix` is 0\n while nothing under it has been marked (seed-priced). `holders` are largest first —\n people, or the `fee` allocation holding a product's fee class." }, "banking.v1.Balance": { "type": "object", "properties": { "available": { "type": "string", "title": "available", "description": "free, spendable now" }, "invested": { "type": "string", "title": "invested", "description": "held in fund units at NAV, the units escrowed by resting sell orders included" }, "pending_withdrawal": { "type": "string", "title": "pending_withdrawal", "description": "locked by queued/in-flight withdrawals" }, "total": { "type": "string", "title": "total", "description": "available + in_orders + invested + pending_withdrawal" }, "in_orders": { "type": "string", "title": "in_orders", "description": "cash escrowed by the caller's resting buy orders on the book (still theirs)" } }, "title": "Balance", "additionalProperties": false, "description": "The user's single, network-agnostic balance, segmented by lifecycle. Every figure is\n a TigerBeetle-authoritative decimal USDT string; total = available + in_orders +\n invested + pending_withdrawal." }, "banking.v1.BookEvent": { "type": "object", "properties": { "snapshot": { "title": "snapshot", "$ref": "#/components/schemas/banking.v1.BookSnapshot" }, "trades": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Trade" }, "title": "trades", "description": "the latest public trades, newest first" }, "orders_revision": { "type": [ "integer", "string" ], "title": "orders_revision", "format": "int64" } }, "title": "BookEvent", "additionalProperties": false, "description": "One frame of WatchBook. `orders_revision` is the book revision at which the caller's\n own orders on this allocation last changed (0 = never) — compare it with the previous\n frame's to know whether to refetch ListOpenOrders." }, "banking.v1.BookLevel": { "type": "object", "properties": { "price": { "type": "string", "title": "price", "description": "decimal USDT per unit" }, "size": { "type": "string", "title": "size", "description": "decimal units resting at this price" }, "orders": { "type": "integer", "title": "orders", "description": "how many orders make it up" } }, "title": "BookLevel", "additionalProperties": false, "description": "One aggregated price level of one side." }, "banking.v1.BookPolicy": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "book_open": { "type": "boolean", "title": "book_open" }, "taker_fee_bps": { "type": "integer", "title": "taker_fee_bps" }, "price_tick": { "type": "string", "title": "price_tick", "description": "decimal USDT" }, "lot_size": { "type": "string", "title": "lot_size", "description": "decimal units" }, "market_slippage_bps": { "type": "integer", "title": "market_slippage_bps" }, "updated_at": { "type": [ "integer", "string" ], "title": "updated_at", "format": "int64", "description": "unix seconds; 0 when the product has no policy row (the defaults)" }, "allow_unbacked_trading": { "type": "boolean", "title": "allow_unbacked_trading", "description": "See SetBookPolicyRequest.allow_unbacked_trading. When true the terminal tells buyers the\n units are not backed by fund cash and cannot be redeemed — the book is their only exit." } }, "title": "BookPolicy", "additionalProperties": false, "description": "One allocation's trading terms." }, "banking.v1.BookSnapshot": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "revision": { "type": [ "integer", "string" ], "title": "revision", "format": "int64" }, "bids": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.BookLevel" }, "title": "bids" }, "asks": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.BookLevel" }, "title": "asks" }, "last_price": { "type": "string", "title": "last_price" }, "last_side": { "type": "string", "title": "last_side", "description": "buy | sell — the taker's side of the last trade" }, "mid": { "type": "string", "title": "mid" }, "spread": { "type": "string", "title": "spread" }, "nav": { "type": "string", "title": "nav" }, "volume_24h": { "type": "string", "title": "volume_24h", "description": "decimal units" }, "change_24h": { "type": "string", "title": "change_24h", "description": "signed decimal percent, e.g. \"-2.5\"" }, "as_of": { "type": [ "integer", "string" ], "title": "as_of", "format": "int64", "description": "unix seconds the snapshot was taken" } }, "title": "BookSnapshot", "additionalProperties": false, "description": "The book as of `revision`. `bids` are best (highest) first, `asks` best (lowest)\n first. `last_price` / `last_side` describe the latest trade (empty before the first);\n `mid` and `spread` are empty unless both sides have a level. `volume_24h` is the units\n traded in the trailing day and `change_24h` the signed percent move of the last price\n against the last trade at or before 24h ago (empty when there is none). `nav` is the\n fund's current mark, carried so a ticker can show the two prices side by side." }, "banking.v1.CancelConsiliumRequest": { "type": "object", "properties": { "consilium_id": { "type": "string", "title": "consilium_id" } }, "title": "CancelConsiliumRequest", "additionalProperties": false }, "banking.v1.CancelFeePolicyChangeRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "change_id": { "type": "string", "title": "change_id" } }, "title": "CancelFeePolicyChangeRequest", "additionalProperties": false }, "banking.v1.CancelOrderRequest": { "type": "object", "properties": { "order_id": { "type": "string", "title": "order_id" } }, "title": "CancelOrderRequest", "additionalProperties": false }, "banking.v1.CancelPaymentRequest": { "type": "object", "properties": { "payment_id": { "type": "string", "title": "payment_id" } }, "title": "CancelPaymentRequest", "additionalProperties": false }, "banking.v1.CancelRedemptionRequest": { "type": "object", "properties": { "redemption_id": { "type": "string", "title": "redemption_id" } }, "title": "CancelRedemptionRequest", "additionalProperties": false }, "banking.v1.CancelWithdrawalRequest": { "type": "object", "properties": { "withdrawal_id": { "type": "string", "title": "withdrawal_id" } }, "title": "CancelWithdrawalRequest", "additionalProperties": false }, "banking.v1.Candle": { "type": "object", "properties": { "time": { "type": [ "integer", "string" ], "title": "time", "format": "int64" }, "open": { "type": "string", "title": "open" }, "high": { "type": "string", "title": "high" }, "low": { "type": "string", "title": "low" }, "close": { "type": "string", "title": "close" }, "volume": { "type": "string", "title": "volume", "description": "decimal units" } }, "title": "Candle", "additionalProperties": false, "description": "One OHLCV bucket. `time` is the bucket's start, unix seconds." }, "banking.v1.CandleList": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "resolution": { "type": "string", "title": "resolution" }, "candles": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Candle" }, "title": "candles" } }, "title": "CandleList", "additionalProperties": false }, "banking.v1.CheckRequest": { "type": "object", "title": "CheckRequest", "additionalProperties": false }, "banking.v1.CheckResponse": { "type": "object", "properties": { "status": { "type": "string", "title": "status" } }, "title": "CheckResponse", "additionalProperties": false }, "banking.v1.ConsentDecision": { "type": "string", "title": "ConsentDecision", "enum": [ "CONSENT_DECISION_UNSPECIFIED", "CONSENT_DECISION_PENDING", "CONSENT_DECISION_APPROVE", "CONSENT_DECISION_REJECT" ], "description": "What the emailed investor answered." }, "banking.v1.Consilium": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "state": { "title": "state", "$ref": "#/components/schemas/banking.v1.ConsiliumState" }, "payload_hash": { "type": "string", "title": "payload_hash", "description": "Hex SHA-256 over the canonical terms. Shown (short prefix) in the mail so an owner\n can tell that what they approved is what will execute." }, "initiator_user_id": { "type": "string", "title": "initiator_user_id" }, "initiator_email": { "type": "string", "title": "initiator_email" }, "owner_count": { "type": "integer", "title": "owner_count", "description": "N — owners at open. The threshold is frozen from this, never recomputed later." }, "threshold": { "type": "integer", "title": "threshold" }, "approvals": { "type": "integer", "title": "approvals", "description": "Votes that are still valid: an approver who has since lost ownership does not count." }, "rejections": { "type": "integer", "title": "rejections" }, "voters": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.ConsiliumVoter" }, "title": "voters" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "decided_at": { "type": [ "integer", "string" ], "title": "decided_at", "format": "int64" }, "executed_withdrawal_id": { "type": "string", "title": "executed_withdrawal_id", "description": "Set exactly once, on EXECUTED — and exactly ONE of the effect ids is\n (`executed_withdrawal_id`, `executed_payment_id`, `executed_valuation_id`,\n `executed_fee_policy_change_id`, `executed_issuance_id`, `executed_subscription_id`),\n because a consilium has one effect. `consilium_execution_is_recorded` states that to\n the database as `num_nonnulls(...) = 1`." }, "failure_reason": { "type": "string", "title": "failure_reason" }, "version": { "type": [ "integer", "string" ], "title": "version", "format": "int64", "description": "Monotonic per consilium. The live page watches this and refetches when it moves —\n the socket carries a version, never a tally." }, "payment": { "title": "payment", "$ref": "#/components/schemas/banking.v1.ConsiliumPaymentTerms" }, "executed_payment_id": { "type": "string", "title": "executed_payment_id", "description": "The payment order an executed PAYMENT consilium carried." }, "valuation_override": { "title": "valuation_override", "description": "A terms sibling — see the \"exactly one\" note above.", "$ref": "#/components/schemas/banking.v1.ValuationOverrideTerms" }, "executed_valuation_id": { "type": "string", "title": "executed_valuation_id", "description": "The `fund_valuations` row an executed VALUATION-OVERRIDE consilium recorded." }, "fee_policy": { "title": "fee_policy", "description": "The fourth terms sibling — set exactly for a FEE_POLICY consilium.", "$ref": "#/components/schemas/banking.v1.ConsiliumFeePolicyTerms" }, "executed_fee_policy_change_id": { "type": "string", "title": "executed_fee_policy_change_id", "description": "The fee-policy change an executed FEE_POLICY consilium scheduled." }, "holder_grant": { "title": "holder_grant", "description": "The fifth terms sibling — set exactly for a HOLDER_GRANT consilium.", "$ref": "#/components/schemas/banking.v1.HolderGrantTerms" }, "seed_capital": { "title": "seed_capital", "description": "The sixth — set exactly for a SEED_CAPITAL consilium.", "$ref": "#/components/schemas/banking.v1.SeedCapitalTerms" }, "executed_issuance_id": { "type": "string", "title": "executed_issuance_id", "description": "The in-kind issuance an executed HOLDER_GRANT consilium minted\n (`AllocationsService.UnitIssuance`)." }, "executed_subscription_id": { "type": "string", "title": "executed_subscription_id", "description": "The `fund` subscription an executed SEED_CAPITAL consilium booked\n (`FundsService.Subscription`)." } }, "title": "Consilium", "additionalProperties": false }, "banking.v1.ConsiliumFeePolicyTerms": { "type": "object", "properties": { "change_id": { "type": "string", "title": "change_id", "description": "The change this quorum authorizes. Inside the hashed subject, so an approval of one\n change is never a valid signature over another naming the same numbers." }, "service": { "type": "string", "title": "service" }, "allocation_name": { "type": "string", "title": "allocation_name", "description": "The product's display name, read live from the registry." }, "from_configured": { "type": "boolean", "title": "from_configured", "description": "The terms in force when the change was proposed. `from_configured` is false when the\n fund charged nothing — a different fact from a policy whose rates are zero — and the\n `from_*` fields are then zero / default." }, "from_management_bps": { "type": "integer", "title": "from_management_bps" }, "from_performance_bps": { "type": "integer", "title": "from_performance_bps" }, "from_hurdle_bps": { "type": "integer", "title": "from_hurdle_bps" }, "from_basis": { "type": "string", "title": "from_basis" }, "from_crystallization": { "type": "string", "title": "from_crystallization" }, "to_management_bps": { "type": "integer", "title": "to_management_bps" }, "to_performance_bps": { "type": "integer", "title": "to_performance_bps" }, "to_hurdle_bps": { "type": "integer", "title": "to_hurdle_bps" }, "to_basis": { "type": "string", "title": "to_basis" }, "to_crystallization": { "type": "string", "title": "to_crystallization" }, "effective_from": { "type": [ "integer", "string" ], "title": "effective_from", "format": "int64", "description": "Unix seconds the requester asked the change to bind from; 0 = as soon as the notice\n allows. The moment actually fixed is never earlier than 24h after the carrying vote\n while anyone holds units." }, "holder_count": { "type": "integer", "title": "holder_count", "description": "How many investors hold units right now — who the change binds." }, "reason": { "type": "string", "title": "reason", "description": "Why, in the requester's words. Required for this kind, shown verbatim." } }, "title": "ConsiliumFeePolicyTerms", "additionalProperties": false, "description": "The immutable subject of a FEE-POLICY consilium — a change of a product's fee terms\n that tightens them beyond the house envelope (docs/FEES.md § \"Changing the terms\").\n Not a money move: carrying it schedules the change, and the fee sweeper promotes it once\n the holders' notice period has run." }, "banking.v1.ConsiliumInvitation": { "type": "object", "properties": { "consilium_id": { "type": "string", "title": "consilium_id" }, "state": { "title": "state", "$ref": "#/components/schemas/banking.v1.ConsiliumState" }, "payload_hash": { "type": "string", "title": "payload_hash" }, "initiator_email": { "type": "string", "title": "initiator_email", "description": "Who opened it, masked." }, "voter_email": { "type": "string", "title": "voter_email", "description": "The recipient's own masked address, so they can confirm the mail reached the right\n seat before typing the code." }, "threshold": { "type": "integer", "title": "threshold" }, "approvals": { "type": "integer", "title": "approvals" }, "owner_count": { "type": "integer", "title": "owner_count" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "decision": { "title": "decision", "description": "This seat's own answer, so a reopened link shows what was already said.", "$ref": "#/components/schemas/banking.v1.VoteDecision" }, "attempts_remaining": { "type": "integer", "title": "attempts_remaining", "description": "Code attempts left before the token burns." }, "payment": { "title": "payment", "$ref": "#/components/schemas/banking.v1.ConsiliumPaymentTerms" }, "valuation_override": { "title": "valuation_override", "$ref": "#/components/schemas/banking.v1.ValuationOverrideTerms" }, "fee_policy": { "title": "fee_policy", "$ref": "#/components/schemas/banking.v1.ConsiliumFeePolicyTerms" }, "holder_grant": { "title": "holder_grant", "$ref": "#/components/schemas/banking.v1.HolderGrantTerms" }, "seed_capital": { "title": "seed_capital", "$ref": "#/components/schemas/banking.v1.SeedCapitalTerms" } }, "title": "ConsiliumInvitation", "additionalProperties": false, "description": "What the emailed owner is shown BEFORE they vote. Deliberately narrower than\n `Consilium`: no other owner's identity, no vote-by-vote breakdown." }, "banking.v1.ConsiliumList": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Consilium" }, "title": "items" } }, "title": "ConsiliumList", "additionalProperties": false }, "banking.v1.ConsiliumPaymentTerms": { "type": "object", "properties": { "payment_id": { "type": "string", "title": "payment_id", "description": "The order this quorum authorizes. Inside the hashed subject too, so an approval of one\n payment is never a valid signature over another with identical terms." }, "tier": { "type": "string", "title": "tier", "description": "internal | service | external — DERIVED from the destination, never supplied." }, "source": { "type": "string", "title": "source", "description": "Where the money leaves from." }, "destination": { "type": "string", "title": "destination", "description": "Where it lands. An external destination is rendered in FULL, address and rail: a\n truncated address in an approval flow is an invitation to approve the wrong one." }, "amount": { "type": "string", "title": "amount", "description": "Decimal USDT string, as everywhere else on this wire." }, "reason": { "type": "string", "title": "reason", "description": "Why, in the initiator's words. Required, shown verbatim, never interpreted." } }, "title": "ConsiliumPaymentTerms", "additionalProperties": false, "description": "The immutable subject of a PAYMENT consilium — the §3 rule that money pooled in an\n allocation (`service:\u003cid\u003e`, the reserved `fee` and `fund` included) moves only on the\n owners' quorum, at every tier.\n\n A PROJECTION OF THE ORDER, not the order. `banking.v1.Payment` (payments.proto) is what\n the payments screen reads; this is what an owner needs in order to judge one request:\n where the money leaves from, where it lands, how much, and why. The two ends are rendered\n as LABELS rather than as `(kind, id)` pairs because the question an owner is answering is\n \"should this money move\", and an account id is not an answer to it." }, "banking.v1.ConsiliumState": { "type": "string", "title": "ConsiliumState", "enum": [ "CONSILIUM_STATE_UNSPECIFIED", "CONSILIUM_STATE_OPEN", "CONSILIUM_STATE_APPROVED", "CONSILIUM_STATE_REJECTED", "CONSILIUM_STATE_EXPIRED", "CONSILIUM_STATE_CANCELLED", "CONSILIUM_STATE_EXECUTED", "CONSILIUM_STATE_EXECUTION_FAILED" ], "description": "Where a consilium stands. Terminal everywhere except OPEN." }, "banking.v1.ConsiliumVoter": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email", "description": "Masked (`a***@example.com`) on every surface a non-owner can reach." }, "decision": { "title": "decision", "$ref": "#/components/schemas/banking.v1.VoteDecision" }, "decided_at": { "type": [ "integer", "string" ], "title": "decided_at", "format": "int64", "description": "Unix seconds; 0 while pending." }, "notified": { "type": "boolean", "title": "notified", "description": "True once the mail has actually been handed to the delivery queue." } }, "title": "ConsiliumVoter", "additionalProperties": false, "description": "One owner's seat in a consilium." }, "banking.v1.Deposit": { "type": "object", "properties": { "tx_ref": { "type": "string", "title": "tx_ref", "description": "on-chain transaction reference" }, "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton" }, "amount": { "type": "string", "title": "amount", "description": "credited decimal USDT" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64", "description": "unix seconds the hub recorded the credit" } }, "title": "Deposit", "additionalProperties": false, "description": "A confirmed on-chain deposit credited to the caller's unified balance." }, "banking.v1.DepositAddress": { "type": "object", "properties": { "network": { "type": "string", "title": "network" }, "address": { "type": "string", "title": "address" }, "min_confirmations": { "type": "integer", "title": "min_confirmations", "description": "confirmations before a deposit is credited" }, "is_testnet": { "type": "boolean", "title": "is_testnet", "description": "Whether this rail is on testnet — the client uses it to render the correct address\n form (e.g. TON's testnet-tagged user-friendly address). Only meaningful per rail; false\n for a mainnet rail." } }, "title": "DepositAddress", "additionalProperties": false }, "banking.v1.DepositList": { "type": "object", "properties": { "deposits": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Deposit" }, "title": "deposits" } }, "title": "DepositList", "additionalProperties": false }, "banking.v1.DepositScanCursor": { "type": "object", "properties": { "network": { "type": "string", "title": "network" }, "age_secs": { "type": [ "integer", "string" ], "title": "age_secs", "format": "int64" } }, "title": "DepositScanCursor", "additionalProperties": false, "description": "Seconds since a rail's deposit watcher last advanced/touched its per-network scan\n cursor (refreshed only by a completed scan cycle, so age ≈ time since the last\n healthy cycle; thresholds are the consumer's concern)." }, "banking.v1.DisableUserRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" } }, "title": "DisableUserRequest", "additionalProperties": false }, "banking.v1.DisableUserResponse": { "type": "object", "title": "DisableUserResponse", "additionalProperties": false }, "banking.v1.DispatchWithdrawalRequest": { "type": "object", "properties": { "withdrawal_id": { "type": "string", "title": "withdrawal_id" } }, "title": "DispatchWithdrawalRequest", "additionalProperties": false }, "banking.v1.DispatchWithdrawalResponse": { "type": "object", "title": "DispatchWithdrawalResponse", "additionalProperties": false }, "banking.v1.ExternalDestination": { "type": "object", "properties": { "network": { "type": "string", "title": "network", "description": "Rail the payment ships on (BEP20 / POLYGON / TRC20 / TON)." }, "address": { "type": "string", "title": "address", "description": "Destination address, rendered in FULL wherever a human approves it." } }, "title": "ExternalDestination", "additionalProperties": false }, "banking.v1.FailRedemptionRequest": { "type": "object", "properties": { "redemption_id": { "type": "string", "title": "redemption_id" } }, "title": "FailRedemptionRequest", "additionalProperties": false }, "banking.v1.FailWithdrawalRequest": { "type": "object", "properties": { "withdrawal_id": { "type": "string", "title": "withdrawal_id" }, "reason": { "type": "string", "title": "reason", "description": "operator note (audit only)" } }, "title": "FailWithdrawalRequest", "additionalProperties": false }, "banking.v1.FailWithdrawalResponse": { "type": "object", "title": "FailWithdrawalResponse", "additionalProperties": false }, "banking.v1.FeeAssessment": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "trigger": { "type": "string", "title": "trigger", "description": "period | redemption" }, "nav": { "type": "string", "title": "nav", "description": "the price the charge was measured and taken at" }, "management": { "type": "string", "title": "management" }, "performance": { "type": "string", "title": "performance" }, "debt_opening": { "type": "string", "title": "debt_opening", "description": "uncollected fee carried INTO this charge" }, "charged_units": { "type": "string", "title": "charged_units", "description": "units clawed back" }, "charged_cash": { "type": "string", "title": "charged_cash", "description": "their value at `nav`" }, "debt_carried": { "type": "string", "title": "debt_carried", "description": "what deferred to the next charge" }, "high_water_mark": { "type": "string", "title": "high_water_mark", "description": "the investor's mark AFTER this charge" }, "assessed_at": { "type": [ "integer", "string" ], "title": "assessed_at", "format": "int64", "description": "unix seconds" } }, "title": "FeeAssessment", "additionalProperties": false, "description": "One charge against one holding. `due` and `charged_cash` differ exactly when the\n holding could not cover the charge and the rest deferred into `debt_carried`." }, "banking.v1.FeeAssessmentList": { "type": "object", "properties": { "assessments": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.FeeAssessment" }, "title": "assessments" } }, "title": "FeeAssessmentList", "additionalProperties": false }, "banking.v1.FeePolicy": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "configured": { "type": "boolean", "title": "configured" }, "management_bps": { "type": "integer", "title": "management_bps", "description": "200 = 2% p.a." }, "performance_bps": { "type": "integer", "title": "performance_bps", "description": "2000 = 20% of the gain above the mark" }, "hurdle_bps": { "type": "integer", "title": "hurdle_bps", "description": "0 = no hurdle; else the p.a. rate the gain must clear first" }, "basis": { "type": "string", "title": "basis", "description": "invested_capital | market_value — what the management fee is charged on.\n `invested_capital` (the default) is the cash the investor actually put in: it does\n not swell with a mark the operator posted, which keeps the fee the operator earns\n independent of the input the operator supplies." }, "crystallization": { "type": "string", "title": "crystallization", "description": "monthly | quarterly | semi_annual | annual — how often the performance fee\n crystallizes and the mark ratchets. This is a price, not a detail: crystallizing\n more often measurably raises what an investor pays over a fund's life, because\n each reset locks in gains a later loss can no longer claw back." }, "updated_at": { "type": [ "integer", "string" ], "title": "updated_at", "format": "int64", "description": "unix seconds; 0 when unconfigured" }, "version": { "type": "integer", "title": "version", "description": "Which version of the fund's history these terms are; 0 when unconfigured." }, "effective_from": { "type": [ "integer", "string" ], "title": "effective_from", "format": "int64", "description": "Unix seconds since which these terms bind; 0 when unconfigured." }, "pending": { "title": "pending", "description": "The change on its way, if any — awaiting the owners or scheduled. Shown to holders\n and non-holders alike: the terms coming are part of deciding whether to stay in.", "$ref": "#/components/schemas/banking.v1.FeePolicyChange" } }, "title": "FeePolicy", "additionalProperties": false, "description": "One fund's fee terms. `configured` is false when the product has no policy at all,\n which is different from a policy whose rates happen to be zero." }, "banking.v1.FeePolicyChange": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "service": { "type": "string", "title": "service" }, "version": { "type": "integer", "title": "version" }, "state": { "type": "string", "title": "state" }, "management_bps": { "type": "integer", "title": "management_bps" }, "performance_bps": { "type": "integer", "title": "performance_bps" }, "hurdle_bps": { "type": "integer", "title": "hurdle_bps" }, "basis": { "type": "string", "title": "basis" }, "crystallization": { "type": "string", "title": "crystallization" }, "effective_from": { "type": [ "integer", "string" ], "title": "effective_from", "format": "int64", "description": "Unix seconds the terms bind from. Provisional while awaiting the owners; fixed when\n the change is scheduled." }, "requirement": { "type": "string", "title": "requirement" }, "consilium_id": { "type": "string", "title": "consilium_id", "description": "The consilium this change waits on (or waited on); empty for an administrator's change." }, "requested_by": { "type": "string", "title": "requested_by" }, "requested_at": { "type": [ "integer", "string" ], "title": "requested_at", "format": "int64" }, "scheduled_at": { "type": [ "integer", "string" ], "title": "scheduled_at", "format": "int64", "description": "Unix seconds the notice clock started; 0 while awaiting the owners." }, "applied_at": { "type": [ "integer", "string" ], "title": "applied_at", "format": "int64", "description": "Unix seconds the terms took effect; 0 until they did." }, "reason": { "type": "string", "title": "reason", "description": "Why, in the requester's words; empty when none was given." }, "notices_waived_by": { "type": "string", "title": "notices_waived_by", "description": "The operator's acknowledgement of holders who could not be told (see\n AcknowledgeUndeliveredNotices): who took responsibility — the latest to, when the\n record was extended — governance detail, shown to operators and blank for everyone\n else." }, "notices_waived_at": { "type": [ "integer", "string" ], "title": "notices_waived_at", "format": "int64", "description": "Unix seconds the (latest) acknowledgement was given; 0 when the notices were never\n waived. Public like every other moment on the change." }, "notices_waived_users": { "type": "array", "items": { "type": "string" }, "title": "notices_waived_users", "description": "The ids of the holders whose notice the mailer had given up on by that moment — the\n holders the change binds over untold. Operators only; empty for everyone else." }, "undelivered_notices": { "type": "integer", "title": "undelivered_notices", "description": "Notices of this change not yet delivered to a CURRENT holder, how many of those the\n mailer has given up on — the figures a tightening waits on — and how many of the\n given-up ones the acknowledgement does not cover (all of them while there is none):\n the holders a (further) AcknowledgeUndeliveredNotices would name, so it is worth\n offering exactly while this is non-zero. Counted only while `scheduled` (0 in every\n other state), and shown to operators only." }, "notices_given_up": { "type": "integer", "title": "notices_given_up" }, "notices_unacknowledged": { "type": "integer", "title": "notices_unacknowledged" } }, "title": "FeePolicyChange", "additionalProperties": false, "description": "One row of a fund's fee-policy history. `state` is one of awaiting_consilium |\n scheduled | active | superseded | rejected | cancelled; `requirement` is admin |\n owner_consilium. See docs/FEES.md § \"Changing the terms\"." }, "banking.v1.FeePolicyChangeList": { "type": "object", "properties": { "changes": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.FeePolicyChange" }, "title": "changes" } }, "title": "FeePolicyChangeList", "additionalProperties": false }, "banking.v1.FeePolicyList": { "type": "object", "properties": { "policies": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.FeePolicy" }, "title": "policies" } }, "title": "FeePolicyList", "additionalProperties": false }, "banking.v1.FeeSettlement": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "units": { "type": "string", "title": "units" }, "nav": { "type": "string", "title": "nav" }, "cash": { "type": "string", "title": "cash" } }, "title": "FeeSettlement", "additionalProperties": false }, "banking.v1.FeeShares": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "units": { "type": "string", "title": "units" }, "value": { "type": "string", "title": "value", "description": "units × current NAV" } }, "title": "FeeShares", "additionalProperties": false, "description": "The `fee` allocation's uncollected fee units in one fund — the product's fee class." }, "banking.v1.FundNav": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "nav": { "type": "string", "title": "nav", "description": "decimal USDT per share" }, "aum": { "type": "string", "title": "aum", "description": "last posted AUM (decimal USDT; empty if seed)" }, "units_outstanding": { "type": "string", "title": "units_outstanding", "description": "decimal units in circulation (the NAV denominator)" }, "posted_at": { "type": [ "integer", "string" ], "title": "posted_at", "format": "int64", "description": "unix seconds of the mark (0 = seed)" }, "stale": { "type": "boolean", "title": "stale" }, "unit_cap": { "type": "string", "title": "unit_cap", "description": "The allocation's authorised unit supply and what is left of it. `remaining_capacity`\n counts in-flight mints as issued, so a client that offers it can never offer more\n than Subscribe will accept. decimal units" }, "remaining_capacity": { "type": "string", "title": "remaining_capacity", "description": "decimal units still issuable (0 once at the cap)" } }, "title": "FundNav", "additionalProperties": false, "description": "The current price of a fund's share, derived (AUM / units_outstanding) and frozen\n between operator marks. `posted_at` is 0 when the fund has never been marked (seed\n NAV 1.0); `stale` is true when the latest mark is older than the dealing window." }, "banking.v1.FundNavHistory": { "type": "object", "properties": { "allocation": { "type": "string", "title": "allocation" }, "marks": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.NavMark" }, "title": "marks" }, "participation": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.ParticipationPoint" }, "title": "participation" }, "truncated": { "type": "boolean", "title": "truncated" } }, "title": "FundNavHistory", "additionalProperties": false, "description": "A fund's valuation log over the requested window (oldest first), and the caller's\n participation through it. `participation` steps at every mark and every change to the\n caller's units (subscribe, redeem, fee charge, in-kind issuance, book fill) and always\n ends at the window's end — \"now\" unless `to` was given — priced off the live holding,\n so the last point equals the position card. Empty `marks` means the fund is still on\n the seed NAV (or no mark fell in the window); it is not an error. `truncated` is true\n when more marks fell in the window than the cap allows and the OLDEST were dropped." }, "banking.v1.GetAccruedFeesRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "GetAccruedFeesRequest", "additionalProperties": false }, "banking.v1.GetAllocationRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "GetAllocationRequest", "additionalProperties": false }, "banking.v1.GetBookPolicyRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "GetBookPolicyRequest", "additionalProperties": false }, "banking.v1.GetBookRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "depth": { "type": "integer", "title": "depth", "description": "price levels a side; 0 = the server default (20); capped at 50" } }, "title": "GetBookRequest", "additionalProperties": false }, "banking.v1.GetConsentInvitationRequest": { "type": "object", "properties": { "token": { "type": "string", "title": "token", "description": "The opaque single-use token from the mail. Never the code." } }, "title": "GetConsentInvitationRequest", "additionalProperties": false }, "banking.v1.GetConsiliumRequest": { "type": "object", "properties": { "consilium_id": { "type": "string", "title": "consilium_id" } }, "title": "GetConsiliumRequest", "additionalProperties": false }, "banking.v1.GetDepositAddressRequest": { "type": "object", "properties": { "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton" } }, "title": "GetDepositAddressRequest", "additionalProperties": false }, "banking.v1.GetFeePolicyRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "GetFeePolicyRequest", "additionalProperties": false }, "banking.v1.GetFeeSharesRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "GetFeeSharesRequest", "additionalProperties": false }, "banking.v1.GetFundNavRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "GetFundNavRequest", "additionalProperties": false }, "banking.v1.GetFundRevenueRequest": { "type": "object", "title": "GetFundRevenueRequest", "additionalProperties": false }, "banking.v1.GetInvitationRequest": { "type": "object", "properties": { "token": { "type": "string", "title": "token", "description": "The opaque single-use token from the mail. Never the code." } }, "title": "GetInvitationRequest", "additionalProperties": false }, "banking.v1.GetMeRequest": { "type": "object", "title": "GetMeRequest", "additionalProperties": false }, "banking.v1.GetOperationsModeRequest": { "type": "object", "title": "GetOperationsModeRequest", "additionalProperties": false }, "banking.v1.GetPaymentRequest": { "type": "object", "properties": { "payment_id": { "type": "string", "title": "payment_id" } }, "title": "GetPaymentRequest", "additionalProperties": false }, "banking.v1.GetPositionRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "GetPositionRequest", "additionalProperties": false }, "banking.v1.GetTreasuryRequest": { "type": "object", "title": "GetTreasuryRequest", "additionalProperties": false }, "banking.v1.GetUserBalanceRequest": { "type": "object", "title": "GetUserBalanceRequest", "additionalProperties": false }, "banking.v1.GetWalletRequest": { "type": "object", "title": "GetWalletRequest", "additionalProperties": false }, "banking.v1.GrantAllocationAccessRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "user_id": { "type": "string", "title": "user_id", "description": "the investor's banking user id" }, "level": { "type": "string", "title": "level", "description": "view | invest (never hidden — a grant only ever adds)" } }, "title": "GrantAllocationAccessRequest", "additionalProperties": false }, "banking.v1.HolderGrantTerms": { "type": "object", "properties": { "allocation": { "type": "string", "title": "allocation", "description": "fee | fund — a reserved allocation only" }, "user_id": { "type": "string", "title": "user_id", "description": "On the request: a banking (or concierge) user id, resolved the way every admin RPC\n resolves a target. On a response: the money-plane id the terms stored." }, "units": { "type": "string", "title": "units", "description": "decimal units, \u003e 0" } }, "title": "HolderGrantTerms", "additionalProperties": false, "description": "The immutable subject of a HOLDER-GRANT consilium (#245): `units` of the reserved\n `allocation` minted to `user_id`, with no cash leg. The units are frozen, not a cash\n figure — what they are worth is the allocation's NAV at execution. Executing it records\n a `UnitIssuance` (`source = \"mint\"`, holder `user`) that `executed_issuance_id` names." }, "banking.v1.IssueUnitsRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "user_id": { "type": "string", "title": "user_id", "description": "Who receives the units: a banking (or concierge) user id, resolved the way every\n admin RPC resolves a target. Required — a mint to nobody is a malformed request.\n Only a person: the company is not a holder (#245), and a reserved allocation is\n seated by the owners' consilium (`ConsiliumService.OpenHolderGrant`) or by the fee\n accrual, never by an operator's mint — so there is deliberately no arm for either." }, "units": { "type": "string", "title": "units", "description": "decimal units, \u003e 0" }, "cost_basis": { "type": "string", "title": "cost_basis", "description": "Decimal USDT the holder is deemed to have paid. Empty means `units × NAV` at the\n dealing mark — what a subscription for these units would have cost right now. An\n explicit value may be anything, zero included: a stake in an asset the holder\n already owned cost them no cash. This is what lands in their position's cost basis,\n and so what their P\u0026L and management fee are measured from." }, "idempotency_key": { "type": "string", "title": "idempotency_key", "description": "required, 1..64 chars, unique per service" } }, "title": "IssueUnitsRequest", "additionalProperties": false }, "banking.v1.IssueUserTokenRequest": { "type": "object", "properties": { "concierge_user_id": { "type": "string", "title": "concierge_user_id", "description": "The concierge canonical user id (a UUID) of the already-authenticated user. Banking\n maps it to its local mirror row (provisioned by the cross-plane bridge) and mints the\n money-plane pair for that user. Banking never sees Google's `sub` — the bridge carries\n it; the BFF carries this concierge id, which it has from the concierge sign-in." }, "user_agent": { "type": "string", "title": "user_agent", "description": "Device metadata captured by the BFF at sign-in, stored on the refresh-token family\n for the \"sessions \u0026 devices\" surface. Best-effort, free-form." }, "ip": { "type": "string", "title": "ip" } }, "title": "IssueUserTokenRequest", "additionalProperties": false }, "banking.v1.Jwk": { "type": "object", "properties": { "kid": { "type": "string", "title": "kid" }, "kty": { "type": "string", "title": "kty" }, "crv": { "type": "string", "title": "crv" }, "x": { "type": "string", "title": "x" }, "alg": { "type": "string", "title": "alg" }, "use": { "type": "string", "title": "use" } }, "title": "Jwk", "additionalProperties": false, "description": "One JSON Web Key. Ed25519 keys are OKP: kty=\"OKP\", crv=\"Ed25519\", x=base64url\n public key, alg=\"EdDSA\". `kid` is a stable thumbprint of the public key." }, "banking.v1.JwksRequest": { "type": "object", "title": "JwksRequest", "additionalProperties": false }, "banking.v1.JwksResponse": { "type": "object", "properties": { "keys": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Jwk" }, "title": "keys" } }, "title": "JwksResponse", "additionalProperties": false }, "banking.v1.ListAllocationAccessGrantsRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "ListAllocationAccessGrantsRequest", "additionalProperties": false }, "banking.v1.ListAllocationsRequest": { "type": "object", "properties": { "include_unlisted": { "type": "boolean", "title": "include_unlisted", "description": "Include `draft`, `closed` and `hidden` allocations. Requires AllocationManage; a\n caller without it is refused rather than silently downgraded to the visible list." } }, "title": "ListAllocationsRequest", "additionalProperties": false }, "banking.v1.ListCandlesRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "resolution": { "type": "string", "title": "resolution", "description": "1m | 5m | 15m | 1h | 4h | 1d" }, "from": { "type": [ "integer", "string" ], "title": "from", "format": "int64", "description": "unix seconds, inclusive" }, "to": { "type": [ "integer", "string" ], "title": "to", "format": "int64", "description": "unix seconds, exclusive; 0 = now" } }, "title": "ListCandlesRequest", "additionalProperties": false }, "banking.v1.ListConsiliaRequest": { "type": "object", "properties": { "limit": { "type": "integer", "title": "limit", "description": "0 means the server default." } }, "title": "ListConsiliaRequest", "additionalProperties": false }, "banking.v1.ListDepositsRequest": { "type": "object", "title": "ListDepositsRequest", "additionalProperties": false }, "banking.v1.ListFeeAssessmentsRequest": { "type": "object", "title": "ListFeeAssessmentsRequest", "additionalProperties": false }, "banking.v1.ListFeePoliciesRequest": { "type": "object", "title": "ListFeePoliciesRequest", "additionalProperties": false }, "banking.v1.ListFeePolicyChangesRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "ListFeePolicyChangesRequest", "additionalProperties": false }, "banking.v1.ListFundFeeAssessmentsRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "ListFundFeeAssessmentsRequest", "additionalProperties": false }, "banking.v1.ListFundNavHistoryRequest": { "type": "object", "properties": { "allocation": { "type": "string", "title": "allocation" }, "from": { "type": [ "integer", "string" ], "title": "from", "format": "int64" }, "to": { "type": [ "integer", "string" ], "title": "to", "format": "int64" } }, "title": "ListFundNavHistoryRequest", "additionalProperties": false, "description": "Keyed by the ALLOCATION (the product's registry key — today equal to the service id)\n rather than the service, so a hidden allocation such as the fee fund can serve its\n holders' history later without a second route. `from`/`to` are unix seconds,\n inclusive; 0 means \"from the first mark\" / \"up to now\"." }, "banking.v1.ListOpenOrdersRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service", "description": "empty = every allocation" } }, "title": "ListOpenOrdersRequest", "additionalProperties": false }, "banking.v1.ListOperationsRequest": { "type": "object", "properties": { "limit": { "type": "integer", "title": "limit", "description": "Rows to return. 0 means the server default (100); the server caps it at 200." } }, "title": "ListOperationsRequest", "additionalProperties": false }, "banking.v1.ListOrderHistoryRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service", "description": "empty = every allocation" }, "limit": { "type": "integer", "title": "limit", "description": "0 = the server default (100); capped at 200" } }, "title": "ListOrderHistoryRequest", "additionalProperties": false }, "banking.v1.ListParkedEventsRequest": { "type": "object", "title": "ListParkedEventsRequest", "additionalProperties": false }, "banking.v1.ListPaymentsRequest": { "type": "object", "properties": { "limit": { "type": "integer", "title": "limit", "description": "0 means the server default." }, "state": { "title": "state", "description": "UNSPECIFIED means every state.", "$ref": "#/components/schemas/banking.v1.PaymentState" }, "party": { "title": "party", "description": "Either end. Unset means every party.", "$ref": "#/components/schemas/banking.v1.Party" }, "fund_owned_only": { "type": "boolean", "title": "fund_owned_only", "description": "Only orders whose source is an allocation's claim (`service:\u003cid\u003e`) — the ones the\n owners' consilium gates, i.e. the governance surface." } }, "title": "ListPaymentsRequest", "additionalProperties": false }, "banking.v1.ListPositionsRequest": { "type": "object", "title": "ListPositionsRequest", "additionalProperties": false }, "banking.v1.ListRailsRequest": { "type": "object", "title": "ListRailsRequest", "additionalProperties": false }, "banking.v1.ListRedemptionQueueRequest": { "type": "object", "title": "ListRedemptionQueueRequest", "additionalProperties": false }, "banking.v1.ListRedemptionsRequest": { "type": "object", "title": "ListRedemptionsRequest", "additionalProperties": false }, "banking.v1.ListSessionsRequest": { "type": "object", "properties": { "refresh_token": { "type": "string", "title": "refresh_token", "description": "The caller's current refresh token: proves identity and flags the current session." } }, "title": "ListSessionsRequest", "additionalProperties": false }, "banking.v1.ListSessionsResponse": { "type": "object", "properties": { "sessions": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Session" }, "title": "sessions" } }, "title": "ListSessionsResponse", "additionalProperties": false }, "banking.v1.ListTradesRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "limit": { "type": "integer", "title": "limit", "description": "0 = the server default (50); capped at 200" } }, "title": "ListTradesRequest", "additionalProperties": false }, "banking.v1.ListUnitHoldersRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" } }, "title": "ListUnitHoldersRequest", "additionalProperties": false }, "banking.v1.ListUserTradesRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service", "description": "empty = every allocation" }, "limit": { "type": "integer", "title": "limit", "description": "0 = the server default (100); capped at 200" } }, "title": "ListUserTradesRequest", "additionalProperties": false }, "banking.v1.ListWithdrawalQueueRequest": { "type": "object", "title": "ListWithdrawalQueueRequest", "additionalProperties": false }, "banking.v1.ListWithdrawalsRequest": { "type": "object", "title": "ListWithdrawalsRequest", "additionalProperties": false }, "banking.v1.LogoutRequest": { "type": "object", "properties": { "refresh_token": { "type": "string", "title": "refresh_token" }, "revoke_all": { "type": "boolean", "title": "revoke_all", "description": "When true, bump the user's token_version (coarse \"revoke all\"), not just this\n refresh family." } }, "title": "LogoutRequest", "additionalProperties": false }, "banking.v1.LogoutResponse": { "type": "object", "title": "LogoutResponse", "additionalProperties": false }, "banking.v1.MigrateDepositAddressToCustodianRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id", "description": "the affected user (UUID)" }, "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton" } }, "title": "MigrateDepositAddressToCustodianRequest", "additionalProperties": false }, "banking.v1.MigrateDepositAddressToCustodianResponse": { "type": "object", "properties": { "old_address": { "type": "string", "title": "old_address", "description": "the retired address — kept so the operator can watch it" }, "new_address": { "type": "string", "title": "new_address", "description": "the NEW fundable, custody-held deposit address" } }, "title": "MigrateDepositAddressToCustodianResponse", "additionalProperties": false }, "banking.v1.NavMark": { "type": "object", "properties": { "nav": { "type": "string", "title": "nav", "description": "decimal USDT per share" }, "aum": { "type": "string", "title": "aum", "description": "the posted AUM (decimal USDT)" }, "posted_at": { "type": [ "integer", "string" ], "title": "posted_at", "format": "int64", "description": "unix seconds" } }, "title": "NavMark", "additionalProperties": false, "description": "One operator valuation mark, as posted. Same figures as FundNav, without the live\n supply/capacity fields that only make sense for the current mark." }, "banking.v1.NetworkWithdrawable": { "type": "object", "properties": { "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton" }, "withdrawable": { "type": "string", "title": "withdrawable", "description": "max requestable on this rail (= available)" }, "instant": { "type": "string", "title": "instant", "description": "ships now without queueing" }, "min_withdrawal": { "type": "string", "title": "min_withdrawal", "description": "smallest gross withdrawal accepted" }, "withdrawal_fee": { "type": "string", "title": "withdrawal_fee", "description": "flat network fee retained on a withdrawal" } }, "title": "NetworkWithdrawable", "additionalProperties": false, "description": "Per-rail withdrawal options (the accept-and-queue UX). `withdrawable` is the whole\n available balance (a request beyond `instant` is accepted and queued); `instant` is\n the portion that ships without queueing = min(available, rail liquidity)." }, "banking.v1.OpenHolderGrantRequest": { "type": "object", "properties": { "terms": { "title": "terms", "$ref": "#/components/schemas/banking.v1.HolderGrantTerms" } }, "title": "OpenHolderGrantRequest", "additionalProperties": false }, "banking.v1.OpenPaymentRequest": { "type": "object", "properties": { "source": { "title": "source", "$ref": "#/components/schemas/banking.v1.Party" }, "destination": { "title": "destination", "$ref": "#/components/schemas/banking.v1.PaymentDestination" }, "amount": { "type": "string", "title": "amount", "description": "Decimal USDT string." }, "reason": { "type": "string", "title": "reason", "description": "Required. Bounded at 500 bytes, no control characters; it is INSIDE the hashed\n payload the approver signs." } }, "title": "OpenPaymentRequest", "additionalProperties": false }, "banking.v1.OpenValuationOverrideRequest": { "type": "object", "properties": { "terms": { "title": "terms", "$ref": "#/components/schemas/banking.v1.ValuationOverrideTerms" } }, "title": "OpenValuationOverrideRequest", "additionalProperties": false }, "banking.v1.Operation": { "type": "object", "properties": { "id": { "type": "string", "title": "id", "description": "Unique within the feed: the aggregate UUID for a withdrawal / subscription /\n redemption, the on-chain `tx_ref` for a deposit (which has no surrogate id)." }, "kind": { "type": "string", "title": "kind", "description": "deposit | withdrawal | subscription | redemption | fee" }, "state": { "type": "string", "title": "state", "description": "Lifecycle, per kind. deposit: always `credited` (the row exists only once the\n watcher has confirmed it). subscription: always `completed` (an immutable mint).\n withdrawal: queued | processing | completed | failed | cancelled.\n redemption: queued | completed | failed | cancelled.\n fee: `charged` when the whole charge was collected, `partly_deferred` when the\n holding could not cover it and the rest was carried as debt to the next charge." }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64", "description": "unix seconds the hub recorded the operation" }, "amount": { "type": "string", "title": "amount", "description": "Cash moved, as a magnitude — the sign is implied by `kind`, never encoded here.\n Empty for a redemption that has not settled yet (settle-time pricing)." }, "fee": { "type": "string", "title": "fee", "description": "withdrawal only — network fee retained" }, "net_amount": { "type": "string", "title": "net_amount", "description": "withdrawal only — amount − fee, what ships on-chain" }, "units": { "type": "string", "title": "units", "description": "fund kinds — units minted (subscription) or burned (redemption)" }, "nav": { "type": "string", "title": "nav", "description": "fund kinds — price dealt at (empty until a redemption settles)" }, "service": { "type": "string", "title": "service", "description": "fund kinds — the fund/service id" }, "network": { "type": "string", "title": "network", "description": "rail kinds — bep20 | polygon | trc20 | ton" }, "address": { "type": "string", "title": "address", "description": "withdrawal only — the destination address" }, "tx_ref": { "type": "string", "title": "tx_ref", "description": "rail kinds — the on-chain reference (empty until settled)" }, "management": { "type": "string", "title": "management", "description": "fee only — the two legs of the charge, so the row can say WHY it was taken rather\n than only how much. `management` is rent on parked capital and is charged whether\n the fund gained or not; `performance` is the share of the gain above this\n investor's own high-water mark, and is zero except at a crystallization." }, "performance": { "type": "string", "title": "performance" } }, "title": "Operation", "additionalProperties": false, "description": "One row of the timeline. `kind` is the discriminator — it decides which of the\n remaining fields carry a value; the rest are empty. Deliberately flat rather than a\n oneof: the whole surface is projected to TypeScript through OpenAPI, where a flat\n message with a documented discriminator survives the pipeline unambiguously.\n\n | field | deposit | withdrawal | subscription | redemption | fee |\n | ------------ | ------- | ---------- | ------------ | ---------- | ---------- |\n | amount | ✓ | ✓ (gross) | ✓ (cash in) | ✓ at settle| ✓ (taken) |\n | fee | | ✓ | | | |\n | net_amount | | ✓ | | | |\n | units / nav | | | ✓ | ✓ at settle| ✓ |\n | service | | | ✓ | ✓ | ✓ |\n | network | ✓ | ✓ | | | |\n | address | | ✓ | | | |\n | tx_ref | ✓ | ✓ at settle| | | |\n | management | | | | | ✓ |\n | performance | | | | | ✓ |\n\n The `fee` row is the one the investor did not initiate: the fund charging its own\n management and performance fee against the holding. It moves no cash and touches no\n chain — units are clawed back to the manager on the share ledger — so `amount` is what\n those units were WORTH at `nav`, not a transfer. Without this row an investor's units\n would simply shrink with nothing on the timeline to explain it." }, "banking.v1.OperationList": { "type": "object", "properties": { "operations": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Operation" }, "title": "operations" }, "truncated": { "type": "boolean", "title": "truncated", "description": "True when the caller's history is longer than `limit` — the client is looking at\n the newest page, not the whole record." } }, "title": "OperationList", "additionalProperties": false }, "banking.v1.OperationsMode": { "type": "object", "properties": { "read_only": { "type": "boolean", "title": "read_only" } }, "title": "OperationsMode", "additionalProperties": false }, "banking.v1.Order": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "service": { "type": "string", "title": "service" }, "user_id": { "type": "string", "title": "user_id" }, "side": { "type": "string", "title": "side", "description": "buy | sell" }, "kind": { "type": "string", "title": "kind", "description": "limit | market" }, "tif": { "type": "string", "title": "tif", "description": "gtc | ioc | alo" }, "price": { "type": "string", "title": "price", "description": "decimal USDT per unit" }, "size": { "type": "string", "title": "size", "description": "decimal units" }, "filled": { "type": "string", "title": "filled", "description": "decimal units" }, "remaining": { "type": "string", "title": "remaining", "description": "decimal units (size − filled)" }, "avg_fill_price": { "type": "string", "title": "avg_fill_price", "description": "decimal USDT per unit; empty until the first fill" }, "fee_paid": { "type": "string", "title": "fee_paid", "description": "decimal USDT the caller paid as taker on this order" }, "state": { "type": "string", "title": "state", "description": "open | partially_filled | filled | cancelled | rejected" }, "reject_reason": { "type": "string", "title": "reject_reason", "description": "free text; set exactly when state = rejected" }, "client_order_id": { "type": "string", "title": "client_order_id" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64", "description": "unix seconds" }, "updated_at": { "type": [ "integer", "string" ], "title": "updated_at", "format": "int64", "description": "unix seconds" }, "cancel_reason": { "type": "string", "title": "cancel_reason", "description": "Set exactly when state = cancelled: \"\" | user | ioc_remainder | market_remainder.\n `user` is the owner's own cancel; the other two are the hub cancelling what an IOC\n limit / a market order could not fill at once — such an order may still show\n `filled \u003e 0`, which is what makes the reason worth carrying." } }, "title": "Order", "additionalProperties": false, "description": "One order. `price` is the limit — for a market order, the limit the hub derived from\n the quote at placement. `filled`, `remaining`, `avg_fill_price` and `fee_paid` grow as\n fills land; `state` ends in `filled`, `cancelled` or `rejected` (`reject_reason` set —\n the ledger refused the escrow after the order was recorded, a raced over-spend the\n optimistic balance check could not see). `user_id` is populated only on the caller's\n own orders." }, "banking.v1.OrderList": { "type": "object", "properties": { "orders": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Order" }, "title": "orders" } }, "title": "OrderList", "additionalProperties": false }, "banking.v1.ParkedEvent": { "type": "object", "properties": { "seq": { "type": [ "integer", "string" ], "title": "seq", "format": "int64" }, "event_id": { "type": "string", "title": "event_id" }, "aggregate": { "type": "string", "title": "aggregate" }, "aggregate_id": { "type": "string", "title": "aggregate_id" }, "kind": { "type": "string", "title": "kind" }, "reason": { "type": "string", "title": "reason" }, "parked_at": { "type": [ "integer", "string" ], "title": "parked_at", "format": "int64" }, "compensated": { "type": "boolean", "title": "compensated" } }, "title": "ParkedEvent", "additionalProperties": false, "description": "One parked outbox row. `reason` is the relay's last error; `parked_at` is unix\n seconds; `compensated` marks a half-applied event that is owed compensation\n (never unparkable)." }, "banking.v1.ParkedEventList": { "type": "object", "properties": { "events": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.ParkedEvent" }, "title": "events" } }, "title": "ParkedEventList", "additionalProperties": false }, "banking.v1.ParticipationPoint": { "type": "object", "properties": { "at": { "type": [ "integer", "string" ], "title": "at", "format": "int64", "description": "unix seconds" }, "value": { "type": "string", "title": "value", "description": "decimal USDT" } }, "title": "ParticipationPoint", "additionalProperties": false, "description": "The value of the caller's holding at one instant: the units they held then × the\n NAV in force then (the seed NAV 1.0 before the first mark)." }, "banking.v1.Party": { "type": "object", "properties": { "kind": { "type": "string", "title": "kind", "description": "user | service. (`piggybank` and `revenue` are retired, #245 — the platform's money is\n the `fee` and `fund` allocations: `{kind: \"service\", id: \"fee\" | \"fund\"}`.)" }, "id": { "type": "string", "title": "id", "description": "A service slug for `service` (`fee` and `fund` included). For `user`, the CONCIERGE\n user id the console carries (resolved to the money-plane id here; a banking id is\n accepted as a fallback, the way UsersService.GetUserBalance resolves one)." } }, "title": "Party", "additionalProperties": false, "description": "One end of a payment, as a REQUEST names it." }, "banking.v1.Payment": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "state": { "title": "state", "$ref": "#/components/schemas/banking.v1.PaymentState" }, "tier": { "type": "string", "title": "tier", "description": "internal | service | external — DERIVED from the destination, never supplied." }, "source": { "title": "source", "$ref": "#/components/schemas/banking.v1.PaymentEnd" }, "destination": { "title": "destination", "$ref": "#/components/schemas/banking.v1.PaymentEnd" }, "amount": { "type": "string", "title": "amount", "description": "Decimal USDT string, as everywhere else on this wire." }, "reason": { "type": "string", "title": "reason", "description": "Why, in the initiator's words. Required, shown verbatim, never interpreted." }, "requirement": { "type": "string", "title": "requirement", "description": "owner_consilium | subject_consent — the one requirement, read off the source." }, "payload_hash": { "type": "string", "title": "payload_hash", "description": "Hex SHA-256 over the canonical terms, re-verified at execution." }, "initiator_email": { "type": "string", "title": "initiator_email" }, "consilium_id": { "type": "string", "title": "consilium_id", "description": "Set exactly when the requirement is the owner consilium." }, "consent": { "title": "consent", "description": "Set exactly when the requirement is the subject's consent.", "$ref": "#/components/schemas/banking.v1.PaymentConsent" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "decided_at": { "type": [ "integer", "string" ], "title": "decided_at", "format": "int64", "description": "Unix seconds; 0 while pending." }, "executed_withdrawal_id": { "type": "string", "title": "executed_withdrawal_id", "description": "Set on EXECUTED for an external order only: an internal one settled as a ledger\n transfer and records no id of its own." }, "failure_reason": { "type": "string", "title": "failure_reason" }, "version": { "type": [ "integer", "string" ], "title": "version", "format": "int64", "description": "Monotonic per order." } }, "title": "Payment", "additionalProperties": false }, "banking.v1.PaymentConsent": { "type": "object", "properties": { "subject_email": { "type": "string", "title": "subject_email", "description": "Masked (`a***@example.com`)." }, "decision": { "title": "decision", "$ref": "#/components/schemas/banking.v1.ConsentDecision" }, "notified": { "type": "boolean", "title": "notified", "description": "True once the consent mail has actually been handed to concierge." }, "attempts_remaining": { "type": "integer", "title": "attempts_remaining", "description": "Code attempts left before the token burns." }, "invalidated": { "type": "boolean", "title": "invalidated", "description": "True when one of the pins recorded at open (the subject's token version, their\n mailbox) has moved: the seat can no longer be answered or executed." }, "invalidation_reason": { "type": "string", "title": "invalidation_reason", "description": "Why, when `invalidated` is true." } }, "title": "PaymentConsent", "additionalProperties": false, "description": "The consent seat of an investor-sourced order, as the owner surface sees it." }, "banking.v1.PaymentConsentInvitation": { "type": "object", "properties": { "payment_id": { "type": "string", "title": "payment_id" }, "state": { "title": "state", "$ref": "#/components/schemas/banking.v1.PaymentState" }, "tier": { "type": "string", "title": "tier" }, "source": { "title": "source", "$ref": "#/components/schemas/banking.v1.PaymentEnd" }, "destination": { "title": "destination", "$ref": "#/components/schemas/banking.v1.PaymentEnd" }, "amount": { "type": "string", "title": "amount" }, "reason": { "type": "string", "title": "reason" }, "payload_hash": { "type": "string", "title": "payload_hash" }, "initiator_email": { "type": "string", "title": "initiator_email", "description": "Who opened it, masked." }, "subject_email": { "type": "string", "title": "subject_email", "description": "The recipient's own masked address, so they can confirm the mail reached the right\n mailbox before typing the code." }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "decision": { "title": "decision", "description": "This seat's own answer, so a reopened link shows what was already said.", "$ref": "#/components/schemas/banking.v1.ConsentDecision" }, "attempts_remaining": { "type": "integer", "title": "attempts_remaining", "description": "Code attempts left before the token burns." } }, "title": "PaymentConsentInvitation", "additionalProperties": false, "description": "What the emailed investor is shown BEFORE they answer. Deliberately narrower than\n `Payment`: the terms they are consenting to, and nothing about the operator beyond a\n masked address." }, "banking.v1.PaymentDestination": { "type": "object", "oneOf": [ { "type": "object", "properties": { "external": { "title": "external", "$ref": "#/components/schemas/banking.v1.ExternalDestination" } }, "title": "external", "required": [ "external" ] }, { "type": "object", "properties": { "internal": { "title": "internal", "$ref": "#/components/schemas/banking.v1.Party" } }, "title": "internal", "required": [ "internal" ] } ], "title": "PaymentDestination", "additionalProperties": false, "description": "Where a payment lands. An external SOURCE is unrepresentable on purpose: money cannot\n arrive from an address by anyone's say-so — that is a deposit, which a chain watcher\n attests." }, "banking.v1.PaymentEnd": { "type": "object", "properties": { "label": { "type": "string", "title": "label" }, "kind": { "type": "string", "title": "kind", "description": "service | user, or `external` for an address." }, "id": { "type": "string", "title": "id", "description": "The service slug, or the MONEY-PLANE user id (the request accepts a concierge id; the\n response carries what the order stored). Empty for addresses." }, "network": { "type": "string", "title": "network", "description": "Set only when `kind` is `external`." }, "address": { "type": "string", "title": "address" }, "detail": { "type": "string", "title": "detail", "description": "What a person recognises this end BY, beside the label: the receiving investor's\n MASKED mailbox for `user`, the product's title for `service`. Empty otherwise. Never\n part of the digest — the label is what an approval binds." } }, "title": "PaymentEnd", "additionalProperties": false, "description": "One end of a payment, as a RESPONSE describes it. `label` is the wording every approval\n surface (the owners' mail, the subject's mail, this screen) shares; the structured\n fields let a screen link to the account." }, "banking.v1.PaymentList": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Payment" }, "title": "items" } }, "title": "PaymentList", "additionalProperties": false }, "banking.v1.PaymentState": { "type": "string", "title": "PaymentState", "enum": [ "PAYMENT_STATE_UNSPECIFIED", "PAYMENT_STATE_PENDING", "PAYMENT_STATE_APPROVED", "PAYMENT_STATE_EXECUTED", "PAYMENT_STATE_EXECUTION_FAILED", "PAYMENT_STATE_REJECTED", "PAYMENT_STATE_EXPIRED", "PAYMENT_STATE_CANCELLED" ], "description": "Where an order stands. Terminal everywhere except PENDING and APPROVED." }, "banking.v1.PlaceOrderRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service", "description": "the allocation" }, "side": { "type": "string", "title": "side", "description": "buy | sell" }, "kind": { "type": "string", "title": "kind", "description": "limit | market" }, "tif": { "type": "string", "title": "tif", "description": "gtc | ioc | alo (post-only); market orders are always ioc" }, "price": { "type": "string", "title": "price", "description": "decimal USDT per unit, on the tick; EMPTY for market" }, "size": { "type": "string", "title": "size", "description": "decimal units, on the lot, \u003e 0" }, "client_order_id": { "type": "string", "title": "client_order_id", "description": "required, 1..64 chars, unique per caller (the retry key)" } }, "title": "PlaceOrderRequest", "additionalProperties": false }, "banking.v1.Position": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "units": { "type": "string", "title": "units", "description": "units held free in the holding (decimal)" }, "nav": { "type": "string", "title": "nav", "description": "current NAV per share (decimal USDT)" }, "value": { "type": "string", "title": "value", "description": "units × nav (decimal USDT)" }, "cost_basis": { "type": "string", "title": "cost_basis", "description": "net cash invested, average cost (decimal USDT)" }, "pnl": { "type": "string", "title": "pnl", "description": "value − cost_basis (signed decimal USDT)" }, "nav_as_of": { "type": [ "integer", "string" ], "title": "nav_as_of", "format": "int64", "description": "unix seconds of the NAV mark (0 = seed NAV)" }, "units_in_orders": { "type": "string", "title": "units_in_orders", "description": "Units committed to the holder's resting sell orders on the book (BookService).\n Still theirs — `value` and `pnl` price `units + units_in_orders` — but not free to\n redeem or sell again until the order fills or is cancelled." } }, "title": "Position", "additionalProperties": false, "description": "A user's holding in one fund. `value = (units + units_in_orders) × nav`; `pnl = value − cost_basis`\n (a signed decimal — losses are negative). `nav_as_of` is the unix-seconds timestamp\n of the NAV mark used (0 when the fund is on the bootstrap seed NAV)." }, "banking.v1.PositionList": { "type": "object", "properties": { "positions": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Position" }, "title": "positions" } }, "title": "PositionList", "additionalProperties": false }, "banking.v1.PostFundValuationRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service", "description": "the fund/service id" }, "aum": { "type": "string", "title": "aum", "description": "decimal USDT — the fund's total assets under management" } }, "title": "PostFundValuationRequest", "additionalProperties": false }, "banking.v1.Rail": { "type": "object", "properties": { "network": { "type": "string", "title": "network" }, "configured": { "type": "boolean", "title": "configured" }, "frozen": { "type": "boolean", "title": "frozen" }, "gas_coin": { "type": "string", "title": "gas_coin" } }, "title": "Rail", "additionalProperties": false }, "banking.v1.RailLiquidity": { "type": "object", "properties": { "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton" }, "custody": { "type": "string", "title": "custody", "description": "liquid on-chain USDT held in this rail's custody wallet" }, "treasury_address": { "type": "string", "title": "treasury_address", "description": "the rail's hot wallet — fund USDT (liquidity) + gas here" }, "onchain_usdt": { "type": "string", "title": "onchain_usdt", "description": "decimal USDT actually on-chain in the treasury wallet" }, "onchain_gas": { "type": "string", "title": "onchain_gas", "description": "decimal native units (BNB | TRX | TON) for gas" }, "gas_station_address": { "type": "string", "title": "gas_station_address", "description": "The rail's sweep GAS-STATION wallet — a separate account paying the gas drops\n that consolidate user deposits into the treasury. Fund the native coin here,\n never USDT. Empty when the rail has no gas-station view." }, "gas_station_gas": { "type": "string", "title": "gas_station_gas", "description": "the gas station's native-coin balance" }, "is_testnet": { "type": "boolean", "title": "is_testnet", "description": "Whether the addresses above are testnet-tagged, so a client can render them in the\n rail's user-facing form (e.g. TON's testnet-tagged friendly address). Only\n meaningful per rail; false where the rail's address form is network-agnostic." } }, "title": "RailLiquidity", "additionalProperties": false, "description": "Per-rail on-chain liquidity (the treasury / Layer 2). The `treasury_*`/`onchain_*`\n fields are the operator funding view, read best-effort from the chain — empty means\n the rail is unconfigured or the read was unavailable, never an error." }, "banking.v1.RailList": { "type": "object", "properties": { "rails": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Rail" }, "title": "rails" } }, "title": "RailList", "additionalProperties": false }, "banking.v1.ReadinessRequest": { "type": "object", "title": "ReadinessRequest", "additionalProperties": false }, "banking.v1.ReadinessResponse": { "type": "object", "properties": { "ready": { "type": "boolean", "title": "ready" }, "db_ok": { "type": "boolean", "title": "db_ok" }, "ledger_ok": { "type": "boolean", "title": "ledger_ok" }, "parked_rows": { "type": [ "integer", "string" ], "title": "parked_rows", "format": "int64" }, "backlog": { "type": [ "integer", "string" ], "title": "backlog", "format": "int64" }, "oldest_backlog_age_secs": { "type": [ "integer", "string" ], "title": "oldest_backlog_age_secs", "format": "int64" }, "scan_cursors": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.DepositScanCursor" }, "title": "scan_cursors", "description": "Per-rail deposit-scan diagnostics; only configured rails appear. A large age on\n a configured rail means the deposit scan is stalled — deposits confirm on-chain\n but are not credited. Diagnostics only: it does NOT gate `ready`." }, "unseal_failures": { "type": [ "integer", "string" ], "title": "unseal_failures", "format": "int64", "description": "Signer unseal failures seen on money-moving paths (sweep / withdrawal signing)\n since this instance booted. Any non-zero value means a PROVABLY DEAD key (the\n KEK-epoch bug class) was asked to sign — funds on its address cannot move.\n Diagnostics only: it does NOT gate `ready`." } }, "title": "ReadinessResponse", "additionalProperties": false, "description": "`ready` is the gate the orchestrator acts on; the rest are diagnostics so a\n not-ready response says *why* without scraping logs. `parked_rows` are outbox\n events the relay could not apply (need operator intervention); `backlog` is the\n count of undispatched rows and the age of the oldest, surfacing a wedged relay." }, "banking.v1.RecordDepositRequest": { "type": "object", "properties": { "tx_ref": { "type": "string", "title": "tx_ref", "description": "`txhash:logIndex` (EVM) | `txhash:recipient` (TON) — verified, and the idempotency key" }, "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton — the rail it arrived on" }, "expected_amount": { "type": "string", "title": "expected_amount", "description": "Optional operator assertion in decimal USDT. When set it must equal what the chain\n reports or the call is refused, so a mistyped reference fails loudly instead of\n silently crediting some other transfer." } }, "title": "RecordDepositRequest", "additionalProperties": false, "description": "Record an arrival that reached a rail out of band, PROVEN against the chain.\n\n The caller supplies only a pointer to a fact: the reference is read back from the chain\n and the amount and the credited party are taken from what is actually there. An operator\n therefore cannot mint a balance by typing one — the worst a wrong reference can do is\n name a transfer that does not exist, or one that did not land on an address of ours,\n and both are rejected." }, "banking.v1.RecordDepositResponse": { "type": "object", "properties": { "recorded": { "type": "boolean", "title": "recorded", "description": "false if `tx_ref` was already recorded (idempotent no-op)" }, "amount": { "type": "string", "title": "amount", "description": "what the CHAIN reported, decimal USDT — never the caller's number" }, "party_kind": { "type": "string", "title": "party_kind", "description": "always `user`" }, "party_id": { "type": "string", "title": "party_id", "description": "the banking user id" } }, "title": "RecordDepositResponse", "additionalProperties": false, "description": "The chain names the owner of the deposit address the transfer landed on, so the\n credited party is always a PERSON: `party_kind` is `user` and `party_id` their banking\n id. A transfer to the treasury address is nobody's until the owners say whose — it is\n refused here and attributed through `SeedCapital`." }, "banking.v1.RedeemRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service", "description": "the fund/service id" }, "units": { "type": "string", "title": "units", "description": "decimal units to redeem" } }, "title": "RedeemRequest", "additionalProperties": false }, "banking.v1.Redemption": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "service": { "type": "string", "title": "service" }, "units": { "type": "string", "title": "units" }, "nav": { "type": "string", "title": "nav", "description": "settle NAV (empty until settled)" }, "cash": { "type": "string", "title": "cash", "description": "cash paid out (empty until settled)" }, "state": { "type": "string", "title": "state" } }, "title": "Redemption", "additionalProperties": false, "description": "A redemption in the accept-and-queue saga. `units` are fixed at request; `nav`/`cash`\n are empty until settle (settle-time pricing). State ∈ {queued, completed, failed,\n cancelled}." }, "banking.v1.RedemptionList": { "type": "object", "properties": { "redemptions": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Redemption" }, "title": "redemptions" } }, "title": "RedemptionList", "additionalProperties": false }, "banking.v1.RedemptionQueue": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.RedemptionQueueItem" }, "title": "items" } }, "title": "RedemptionQueue", "additionalProperties": false }, "banking.v1.RedemptionQueueItem": { "type": "object", "properties": { "redemption_id": { "type": "string", "title": "redemption_id" }, "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email" }, "service": { "type": "string", "title": "service" }, "units": { "type": "string", "title": "units" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" } }, "title": "RedemptionQueueItem", "additionalProperties": false, "description": "One queued redemption for the operator queue. `email` is the mirrored identity email\n (may be empty if the bridge hasn't populated it). `created_at` is unix seconds." }, "banking.v1.RefreshRequest": { "type": "object", "properties": { "refresh_token": { "type": "string", "title": "refresh_token" } }, "title": "RefreshRequest", "additionalProperties": false }, "banking.v1.RegisterAllocationRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "title": { "type": "string", "title": "title" }, "summary": { "type": "string", "title": "summary" }, "icon": { "type": "string", "title": "icon", "description": "See `Allocation.icon`. Empty means \"not chosen\" and lands on `fund`; a value\n outside the set is refused rather than silently defaulted. Deliberately NOT\n `optional`, unlike the update request: a registration creates the row, so there is\n no earlier pick that \"unset\" could destroy — absent and empty both legitimately\n mean \"the operator chose nothing yet\", which is what the default is for." } }, "title": "RegisterAllocationRequest", "additionalProperties": false }, "banking.v1.RequestWithdrawalRequest": { "type": "object", "properties": { "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton — the rail to ship on" }, "address": { "type": "string", "title": "address", "description": "destination on-chain address (validated per network)" }, "amount": { "type": "string", "title": "amount", "description": "gross decimal USDT to debit (the fee is taken from this)" } }, "title": "RequestWithdrawalRequest", "additionalProperties": false }, "banking.v1.RetireUnitsRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "user_id": { "type": "string", "title": "user_id", "description": "Whose units are burnt: a banking (or concierge) user id, shaped as IssueUnits'\n holder is and for the same reason. Required — a burn of nobody's units is a\n malformed request." }, "units": { "type": "string", "title": "units", "description": "decimal units, \u003e 0, at most what the holder has available" }, "cost_basis": { "type": "string", "title": "cost_basis", "description": "Decimal USDT of book value written off, recorded on the row. Empty means\n `units × NAV` at the dealing mark, like IssueUnits. No cash moves either way." }, "idempotency_key": { "type": "string", "title": "idempotency_key", "description": "required, 1..64 chars, unique per service (shared with IssueUnits)" }, "force": { "type": "boolean", "title": "force", "description": "Retiring is allowed on a `closed` allocation only; `force = true` is the operator's\n explicit override to burn units out of a live (draft or open) product." } }, "title": "RetireUnitsRequest", "additionalProperties": false }, "banking.v1.RevokeAllocationAccessRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "user_id": { "type": "string", "title": "user_id" } }, "title": "RevokeAllocationAccessRequest", "additionalProperties": false }, "banking.v1.RevokeAllocationAccessResponse": { "type": "object", "title": "RevokeAllocationAccessResponse", "additionalProperties": false }, "banking.v1.RevokeSessionRequest": { "type": "object", "properties": { "refresh_token": { "type": "string", "title": "refresh_token", "description": "The caller's current refresh token (proves identity)." }, "session_id": { "type": "string", "title": "session_id", "description": "The session id to revoke (must belong to the same user)." } }, "title": "RevokeSessionRequest", "additionalProperties": false }, "banking.v1.RevokeSessionResponse": { "type": "object", "title": "RevokeSessionResponse", "additionalProperties": false }, "banking.v1.RevokeTokensRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" } }, "title": "RevokeTokensRequest", "additionalProperties": false }, "banking.v1.RevokeTokensResponse": { "type": "object", "properties": { "token_version": { "type": [ "integer", "string" ], "title": "token_version", "format": "int64" } }, "title": "RevokeTokensResponse", "additionalProperties": false }, "banking.v1.RotateDepositAddressRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id", "description": "the affected user (UUID)" }, "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton" } }, "title": "RotateDepositAddressRequest", "additionalProperties": false }, "banking.v1.RotateDepositAddressResponse": { "type": "object", "properties": { "address": { "type": "string", "title": "address", "description": "the NEW fundable deposit address" } }, "title": "RotateDepositAddressResponse", "additionalProperties": false }, "banking.v1.ScheduleFeePolicyRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "management_bps": { "type": "integer", "title": "management_bps" }, "performance_bps": { "type": "integer", "title": "performance_bps" }, "hurdle_bps": { "type": "integer", "title": "hurdle_bps" }, "basis": { "type": "string", "title": "basis" }, "crystallization": { "type": "string", "title": "crystallization" }, "effective_from": { "type": [ "integer", "string" ], "title": "effective_from", "format": "int64", "description": "Unix seconds the change should bind from; 0 = as soon as the notice period allows.\n An earlier request than the notice allows is lifted to the minimum, not refused." }, "reason": { "type": "string", "title": "reason", "description": "Why, in the requester's words. Required and non-empty when the owners must approve\n (the approval mail is refused without one); optional otherwise. Shown verbatim." } }, "title": "ScheduleFeePolicyRequest", "additionalProperties": false }, "banking.v1.SeedCapitalRequest": { "type": "object", "properties": { "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton — the rail the capital lands on" }, "tx_ref": { "type": "string", "title": "tx_ref", "description": "`txhash:logIndex` (EVM) | `txhash:recipient` (TON) — verified, and the idempotency key" }, "expected_amount": { "type": "string", "title": "expected_amount", "description": "REQUIRED, decimal USDT: what the chain must report for this reference. A seed is\n proposed at a figure the owners approve, not at \"whatever the chain says\" — a\n mistyped reference naming some other real transfer fails here, loudly." }, "depositor_user_id": { "type": "string", "title": "depositor_user_id", "description": "Whose money it is: the person booked as depositor and seated as a holder of `fund`.\n A banking (or concierge) user id, resolved the way every admin RPC resolves a\n target. Empty means the caller — an owner attributing their own transfer." } }, "title": "SeedCapitalRequest", "additionalProperties": false, "description": "Propose a seed: a transfer that reached a rail's treasury, PROVEN against the chain,\n as `depositor_user_id`'s deposit and subscription into `fund`.\n\n Like RecordDepositRequest the caller supplies only a pointer to a fact: the transfer\n must have landed on the rail's treasury address from a sender outside every wallet we\n control. A transfer to a user's deposit address is that user's deposit, not a seed —\n refused, use RecordDeposit. The sweep consolidating a user's address into the treasury\n is money already on the ledger — refused. Unlike RecordDeposit the amount is UNDER THE\n OWNERS' SIGNATURE: `expected_amount` is required, checked against the chain now, and\n frozen into the terms the owners vote over." }, "banking.v1.SeedCapitalResponse": { "type": "object", "properties": { "recorded": { "type": "boolean", "title": "recorded", "description": "always false: the booking is the consilium's execution" }, "amount": { "type": "string", "title": "amount", "description": "what the terms carry, decimal USDT — verified against the chain" }, "consilium_id": { "type": "string", "title": "consilium_id", "description": "the seed-capital consilium this opened" } }, "title": "SeedCapitalResponse", "additionalProperties": false, "description": "A seed is a consilium, not a write: `recorded` is always false here — nothing is\n booked until the owners' quorum executes it — and `consilium_id` is where the\n proposal lives (`ConsiliumService.GetConsilium`)." }, "banking.v1.SeedCapitalTerms": { "type": "object", "properties": { "tx_ref": { "type": "string", "title": "tx_ref", "description": "`txhash:logIndex` (EVM) | `txhash:recipient` (TON)" }, "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton" }, "amount": { "type": "string", "title": "amount", "description": "decimal USDT, as the chain reports it" }, "depositor_user_id": { "type": "string", "title": "depositor_user_id", "description": "the money-plane id the terms stored" } }, "title": "SeedCapitalTerms", "additionalProperties": false, "description": "The immutable subject of a SEED-CAPITAL consilium (#245): the transfer `tx_ref` names\n on `network`, which the chain must report as exactly `amount` USDT landing on the\n treasury from outside, is `depositor_user_id`'s — booked as their deposit and\n subscribed into `fund` at its price when the quorum executes. The amount is frozen\n into the terms (the owners approve \"this dollar is this person's\"); the units are\n not — they are what the cash buys at execution. Executing it records the fund\n subscription `executed_subscription_id` names. Opened through\n `BalanceService.SeedCapital`, never here." }, "banking.v1.Session": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "user_agent": { "type": "string", "title": "user_agent" }, "ip": { "type": "string", "title": "ip" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "last_seen": { "type": [ "integer", "string" ], "title": "last_seen", "format": "int64" }, "current": { "type": "boolean", "title": "current", "description": "True for the family that owns the refresh token presented on the listing call." } }, "title": "Session", "additionalProperties": false, "description": "One active session = one refresh-token family. Timestamps are unix SECONDS." }, "banking.v1.SetAllocationAccessRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "access": { "type": "string", "title": "access", "description": "hidden | view | invest" } }, "title": "SetAllocationAccessRequest", "additionalProperties": false }, "banking.v1.SetAllocationBackingRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "backing": { "type": "string", "title": "backing", "description": "cash | in_kind" } }, "title": "SetAllocationBackingRequest", "additionalProperties": false }, "banking.v1.SetAllocationStateRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "state": { "type": "string", "title": "state", "description": "open | closed (draft is entered only by RegisterAllocation)" } }, "title": "SetAllocationStateRequest", "additionalProperties": false }, "banking.v1.SetAllocationUnitCapRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "unit_cap": { "type": "string", "title": "unit_cap", "description": "decimal units, \u003e 0 (e.g. \"1000\" or \"100000000\")" } }, "title": "SetAllocationUnitCapRequest", "additionalProperties": false }, "banking.v1.SetBookPolicyRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "book_open": { "type": "boolean", "title": "book_open" }, "taker_fee_bps": { "type": "integer", "title": "taker_fee_bps", "description": "0..10000" }, "price_tick": { "type": "string", "title": "price_tick", "description": "decimal USDT, \u003e 0; empty = 0.01" }, "lot_size": { "type": "string", "title": "lot_size", "description": "decimal units, \u003e 0; empty = 0.0001" }, "market_slippage_bps": { "type": "integer", "title": "market_slippage_bps", "description": "0..10000; how far past the best quote a market order may fill" }, "allow_unbacked_trading": { "type": "boolean", "title": "allow_unbacked_trading", "description": "The operator's acknowledgement that the book may trade units the fund holds no cash\n for (`Allocation.backing = in_kind`): a buyer pays cash for a claim on an asset held in\n kind and cannot redeem it. Required to open the book on an in_kind product, and\n checked again on every order — the backing can flip after the book opened (the first\n in-kind mint). Harmless on a cash product. The terminal shows buyers a notice when set." } }, "title": "SetBookPolicyRequest", "additionalProperties": false }, "banking.v1.SetOperationsModeRequest": { "type": "object", "properties": { "read_only": { "type": "boolean", "title": "read_only" } }, "title": "SetOperationsModeRequest", "additionalProperties": false }, "banking.v1.SetRailFrozenRequest": { "type": "object", "properties": { "network": { "type": "string", "title": "network" }, "frozen": { "type": "boolean", "title": "frozen" } }, "title": "SetRailFrozenRequest", "additionalProperties": false }, "banking.v1.SettleFeeSharesRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "units": { "type": "string", "title": "units", "description": "decimal units; empty settles the whole accumulated balance" } }, "title": "SettleFeeSharesRequest", "additionalProperties": false }, "banking.v1.SettleRedemptionRequest": { "type": "object", "properties": { "redemption_id": { "type": "string", "title": "redemption_id" } }, "title": "SettleRedemptionRequest", "additionalProperties": false }, "banking.v1.SettleWithdrawalRequest": { "type": "object", "properties": { "withdrawal_id": { "type": "string", "title": "withdrawal_id" }, "tx_ref": { "type": "string", "title": "tx_ref", "description": "the on-chain transaction reference" } }, "title": "SettleWithdrawalRequest", "additionalProperties": false }, "banking.v1.SettleWithdrawalResponse": { "type": "object", "title": "SettleWithdrawalResponse", "additionalProperties": false }, "banking.v1.SubmitConsentRequest": { "type": "object", "properties": { "token": { "type": "string", "title": "token" }, "code": { "type": "string", "title": "code", "description": "The secret code from the same mail. Compared in constant time, as a hash." }, "decision": { "title": "decision", "description": "APPROVE or REJECT. PENDING is rejected as an invalid argument.", "$ref": "#/components/schemas/banking.v1.ConsentDecision" }, "client_ip": { "type": "string", "title": "client_ip", "description": "Audit only — the edge supplies these; they are never trusted for authorization." }, "user_agent": { "type": "string", "title": "user_agent" } }, "title": "SubmitConsentRequest", "additionalProperties": false }, "banking.v1.SubmitConsentResponse": { "type": "object", "properties": { "invitation": { "title": "invitation", "description": "The invitation as it stands after the answer.", "$ref": "#/components/schemas/banking.v1.PaymentConsentInvitation" }, "decided": { "type": "boolean", "title": "decided", "description": "True when this answer carried the order out of PENDING." } }, "title": "SubmitConsentResponse", "additionalProperties": false }, "banking.v1.SubmitDecisionRequest": { "type": "object", "properties": { "token": { "type": "string", "title": "token" }, "code": { "type": "string", "title": "code", "description": "The secret code from the same mail. Compared in constant time, as a hash." }, "decision": { "title": "decision", "description": "APPROVE or REJECT. PENDING is rejected as an invalid argument.", "$ref": "#/components/schemas/banking.v1.VoteDecision" }, "client_ip": { "type": "string", "title": "client_ip", "description": "Audit only — the edge supplies these; they are never trusted for authorization." }, "user_agent": { "type": "string", "title": "user_agent" } }, "title": "SubmitDecisionRequest", "additionalProperties": false }, "banking.v1.SubmitDecisionResponse": { "type": "object", "properties": { "invitation": { "title": "invitation", "description": "The invitation as it stands after the vote.", "$ref": "#/components/schemas/banking.v1.ConsiliumInvitation" }, "decided": { "type": "boolean", "title": "decided", "description": "True when this vote carried the consilium to its verdict." } }, "title": "SubmitDecisionResponse", "additionalProperties": false }, "banking.v1.SubscribeRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service", "description": "the fund/service id" }, "amount": { "type": "string", "title": "amount", "description": "decimal USDT to subscribe (cash in)" } }, "title": "SubscribeRequest", "additionalProperties": false }, "banking.v1.Subscription": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "service": { "type": "string", "title": "service" }, "cash": { "type": "string", "title": "cash" }, "nav": { "type": "string", "title": "nav" }, "units": { "type": "string", "title": "units" } }, "title": "Subscription", "additionalProperties": false, "description": "The receipt for one subscription (mint): `cash` of the user's balance bought `units`\n at `nav`. The position itself is read via GetPosition once the relay has applied it." }, "banking.v1.TokenResponse": { "type": "object", "properties": { "access_token": { "type": "string", "title": "access_token" }, "access_expires_at": { "type": [ "integer", "string" ], "title": "access_expires_at", "format": "int64" }, "refresh_token": { "type": "string", "title": "refresh_token" }, "refresh_expires_at": { "type": [ "integer", "string" ], "title": "refresh_expires_at", "format": "int64" }, "user": { "title": "user", "$ref": "#/components/schemas/banking.v1.UserSummary" } }, "title": "TokenResponse", "additionalProperties": false, "description": "A first-party token pair plus a snapshot of the principal. All expiries are\n unix SECONDS (matching the JWT `exp` claim); the BFF parses them with\n proto-loader `longs: String`." }, "banking.v1.Trade": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "service": { "type": "string", "title": "service" }, "price": { "type": "string", "title": "price", "description": "decimal USDT per unit" }, "size": { "type": "string", "title": "size", "description": "decimal units" }, "taker_side": { "type": "string", "title": "taker_side", "description": "buy | sell — the side that crossed the spread" }, "executed_at": { "type": [ "integer", "string" ], "title": "executed_at", "format": "int64", "description": "unix seconds" }, "user_side": { "type": "string", "title": "user_side", "description": "the caller's side; empty on the public tape" }, "order_id": { "type": "string", "title": "order_id", "description": "the caller's order; empty on the public tape" }, "fee": { "type": "string", "title": "fee", "description": "decimal USDT the caller paid; empty on the public tape" } }, "title": "Trade", "additionalProperties": false, "description": "One fill. On the public tape only `id`, `service`, `price`, `size`, `taker_side` and\n `executed_at` are populated. On the caller's own tape (ListUserTrades) `user_side` is\n the caller's side, `order_id` their order on it and `fee` what they paid (empty when\n they were the maker); the counterparty is never disclosed." }, "banking.v1.TradeList": { "type": "object", "properties": { "trades": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Trade" }, "title": "trades" } }, "title": "TradeList", "additionalProperties": false }, "banking.v1.Treasury": { "type": "object", "properties": { "rails": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.RailLiquidity" }, "title": "rails", "description": "per-rail on-chain liquidity (USDT)" }, "bank": { "type": "string", "title": "bank", "description": "mocked USD liquidity (separate ledger; off-ramp FX)" }, "total_custody": { "type": "string", "title": "total_custody", "description": "sum of rail custody — the asset side" }, "reserved_for_withdrawals": { "type": "string", "title": "reserved_for_withdrawals", "description": "locked by in-flight withdrawals and approved payments" }, "held_by_users": { "type": "string", "title": "held_by_users", "description": "Σ user claims — what people hold directly" }, "allocations": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.AllocationTreasury" }, "title": "allocations" } }, "title": "Treasury", "additionalProperties": false, "description": "The treasury picture: per-rail liquidity (Layer 2) and who the claims on it belong to\n (Layer 1). Under the unified-claim model the invariant is GLOBAL — `total_custody`\n (the asset side) equals the sum of all claims — and every claim is somebody's (#245):\n a person's directly (`held_by_users`, Σ `user:\u003cid\u003e` claims) or an allocation's, whose\n units people hold (`allocations`, the hidden `fee` and `fund` included). Nothing here\n is a remainder: each figure is read off its own accounts, and whether they add up to\n the custody is the reconciliation's finding, not this view's arithmetic." }, "banking.v1.UnitHolderRef": { "type": "object", "properties": { "kind": { "type": "string", "title": "kind", "description": "user | allocation" }, "id": { "type": "string", "title": "id" } }, "title": "UnitHolderRef", "additionalProperties": false, "description": "One holder of an allocation's units, as the cap table and the treasury name them.\n `kind` is `user` (`id` is the banking user id) or `allocation` (`id` is the holding\n allocation's slug — the reserved `fee` allocation holding a product's fee class). The\n reserved allocations' own holders are always people." }, "banking.v1.UnitHolders": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "units_outstanding": { "type": "string", "title": "units_outstanding" }, "queued_units": { "type": "string", "title": "queued_units", "description": "Decimal units of `mint` issuances still `queued` — recorded, not yet posted by the\n relay. Once they land, `units_outstanding` grows by this much, so an operator\n pinning the cap to what is issued must wait for it to read zero: a cap pinned to\n the settled figure alone leaves the queued mint to land above it.\n TODO(#271): retire (PR #278) shrinks supply — subtract queued retires once it lands." }, "holders": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.UnitHolding" }, "title": "holders" } }, "title": "UnitHolders", "additionalProperties": false, "description": "The cap table of one product: the settled supply and every holder of it, largest\n first (ties by the holder's stored identity, so the table reads the same on every\n refresh). Σ `holders[].units` = `units_outstanding` is the supply invariant the\n reconciliation checks — it is read, never derived, here. All units decimal." }, "banking.v1.UnitHolding": { "type": "object", "properties": { "holder": { "title": "holder", "$ref": "#/components/schemas/banking.v1.UnitHolderRef" }, "units": { "type": "string", "title": "units" } }, "title": "UnitHolding", "additionalProperties": false, "description": "One line of a cap table: who, and how many units (decimal). Holdings of zero are not\n listed." }, "banking.v1.UnitIssuance": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "service": { "type": "string", "title": "service" }, "holder_kind": { "type": "string", "title": "holder_kind", "description": "`user` | `allocation`. (The company stake's two historical rows never cross the\n wire: a lookup that lands on one is refused as a conflict, #245.)" }, "holder_id": { "type": "string", "title": "holder_id", "description": "The banking user id for `user`; the holding allocation's slug (`fee`) for\n `allocation`. A client must never resolve an `allocation` holder as a user." }, "units": { "type": "string", "title": "units", "description": "decimal units minted or retired (always positive)" }, "nav": { "type": "string", "title": "nav", "description": "decimal USDT per unit the issuance was recorded at" }, "cost_basis": { "type": "string", "title": "cost_basis", "description": "decimal USDT" }, "state": { "type": "string", "title": "state", "description": "`queued` until the relay posts the leg, then `applied`. A client that needs the\n units to be visible on the ledger polls for `applied`; a `queued` row is one the\n relay has not reached yet (or one it parked — see BalanceService.ListParkedEvents)." }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64", "description": "unix seconds" }, "source": { "type": "string", "title": "source", "description": "Where the units came from — or went: `mint` (IssueUnits or an executed holder\n grant — supply grew by `units`) or `retire` (RetireUnits — burnt out of the\n holder's account, supply shrank by `units`). `units` is always the magnitude; the\n source is the direction.\n Always populated; a row that predates the field reads as `mint`." } }, "title": "UnitIssuance", "additionalProperties": false, "description": "One in-kind issuance: a mint or a retirement (`source`).\n The holder is a flattened `UnitHolderRef`: a person, or the reserved allocation the\n fee accrual minted a product's fee class to." }, "banking.v1.UnparkEventRequest": { "type": "object", "properties": { "seq": { "type": [ "integer", "string" ], "title": "seq", "format": "int64" } }, "title": "UnparkEventRequest", "additionalProperties": false }, "banking.v1.UnparkEventResponse": { "type": "object", "title": "UnparkEventResponse", "additionalProperties": false }, "banking.v1.UpdateAllocationRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "title": { "type": "string", "title": "title" }, "summary": { "type": "string", "title": "summary" }, "icon": { "type": [ "string", "null" ], "title": "icon", "description": "See `Allocation.icon`. `optional` — and it is the ONLY field here that is, because\n it is the only one where \"the caller did not mention it\" has to be distinguishable\n from \"the caller cleared it\". Unset means LEAVE THE STORED ICON ALONE; empty string\n means reset to `fund`; an unknown value is refused.\n\n Without presence a scalar `string` cannot tell those apart, and every caller built\n before this field existed — a consumer repo on an older `contracts` pin, a browser\n tab holding a stale bundle, a pod mid-rolling-deploy — would silently wipe the\n operator's pick on the next title edit. `title` and `summary` need no such escape:\n they predate every live caller, so an omitted title is a client bug the boundary\n refuses outright rather than a field it has to guess about." } }, "title": "UpdateAllocationRequest", "additionalProperties": false }, "banking.v1.UpdateProfileRequest": { "type": "object", "properties": { "legal_name": { "type": "string", "title": "legal_name" }, "preferred_name": { "type": "string", "title": "preferred_name" }, "phone": { "type": "string", "title": "phone" }, "date_of_birth": { "type": "string", "title": "date_of_birth" }, "nationality": { "type": "string", "title": "nationality" }, "tax_residence": { "type": "string", "title": "tax_residence" }, "residential_address": { "type": "string", "title": "residential_address" }, "language": { "type": "string", "title": "language" }, "base_currency": { "type": "string", "title": "base_currency" }, "timezone": { "type": "string", "title": "timezone" } }, "title": "UpdateProfileRequest", "additionalProperties": false, "description": "The caller's editable profile, full-replace. Same 10 fields as the editable part of\n UserProfile; an empty string clears the field." }, "banking.v1.UserBalanceResponse": { "type": "object", "properties": { "amount": { "type": "string", "title": "amount" }, "pending": { "type": "string", "title": "pending" }, "authoritative": { "type": "boolean", "title": "authoritative" }, "as_of": { "type": [ "integer", "string" ], "title": "as_of", "format": "int64" } }, "title": "UserBalanceResponse", "additionalProperties": false, "description": "A live ledger balance for a user. `amount` and `pending` are u128 minor-unit\n decimal STRINGS (proto3 has no u128; a string is lossless and matches\n proto-loader's `longs: String`). An investor account is credit-normal, so\n `amount` = posted credits − posted debits is non-negative by invariant.\n `authoritative` is true when read directly from TigerBeetle; `as_of` is unix\n seconds. The `authoritative`/`as_of` pair is the forward-compat seam for a future\n read projection — a projection may later return `authoritative=false` rows with\n no breaking proto change. (Named for the users surface; the company-money\n `BalanceService` owns its own balance messages.)" }, "banking.v1.UserProfile": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email" }, "email_verified": { "type": "boolean", "title": "email_verified" }, "status": { "type": "string", "title": "status" }, "token_version": { "type": [ "integer", "string" ], "title": "token_version", "format": "int64" }, "legal_name": { "type": "string", "title": "legal_name", "description": "Editable profile fields (control plane; empty until the user sets them). email and\n status above stay read-only — email is the IdP's, status is admin-managed." }, "preferred_name": { "type": "string", "title": "preferred_name" }, "phone": { "type": "string", "title": "phone" }, "date_of_birth": { "type": "string", "title": "date_of_birth" }, "nationality": { "type": "string", "title": "nationality" }, "tax_residence": { "type": "string", "title": "tax_residence" }, "residential_address": { "type": "string", "title": "residential_address" }, "language": { "type": "string", "title": "language" }, "base_currency": { "type": "string", "title": "base_currency" }, "timezone": { "type": "string", "title": "timezone" }, "kyc_level": { "type": "integer", "title": "kyc_level", "description": "Kept wire-identical with concierge.v1.UserProfile (the cabinet TS is aliased to the\n concierge shape). The identity plane OWNS kyc/role; the money plane mirrors them for\n gating but does not re-serve them on its self-service GetMe, so these stay default\n here — the fields exist for cross-plane wire parity.\n\n The tier ladder, written down here because the money plane is what ENFORCES it and\n no authoritative range was stated in either plane before this:\n 0 — registered. Sign-up plus a confirmed email address; nothing else is verified.\n No deposit address is issued and no withdrawal is accepted.\n 1 — verified. Identity document, liveness, a face match against the document, and\n a passed sanctions/PEP screen. Deposits and withdrawals are permitted.\n 2 — enhanced. Everything in 1 plus proof of address and source of funds. Carries\n raised transaction limits (the limits themselves are not modelled yet).\n 3 — elevated. Enhanced due diligence; set only by a human reviewer, never\n automatically.\n Banking gates BOTH directions of money movement on \u003e= 1. The value is set by an\n admin in the identity plane and mirrored onto the money plane by the one-way\n lifecycle bridge; banking never authors it." }, "role": { "type": "string", "title": "role" }, "role_is_break_glass": { "type": "boolean", "title": "role_is_break_glass", "description": "True when `role` above came from concierge's OWNER_SUBJECTS emergency allowlist\n rather than from `users.role`. Carried here only for wire parity — the money plane\n has no allowlist of its own and never sets it." }, "suspended_by": { "type": "string", "title": "suspended_by", "description": "WHY the account is disabled, and therefore who may undo it — concierge splits the\n old blocking verb into a lapsing `admin_hold` and a ratified `governance` verdict,\n and an empty string is a THIRD case: an account suspended before the field existed,\n which keeps the one-act, never-lapsing semantics it was actually suspended under.\n\n Carried here only for wire parity, like `role_is_break_glass` above: the money plane\n learns of a freeze through the one-way lifecycle bridge's SUSPENDED/REINSTATED\n events, never by reading this, and never sets it. Absent them the parity round trip\n in `cabinet/backend/tests/concierge_parity.rs` re-encodes short and fails, which is\n exactly the drift that test exists to catch." }, "hold_expires_at": { "type": [ "integer", "string" ], "title": "hold_expires_at", "format": "int64", "description": "Unix SECONDS an \"admin_hold\" lapses; 0 when nothing lapses. Parity only, as above." }, "username": { "type": "string", "title": "username", "description": "Parity with concierge.v1.UserProfile.username, like the two above." } }, "title": "UserProfile", "additionalProperties": false }, "banking.v1.UserSummary": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id", "description": "The hub's canonical user id (a UUID) — this is the JWT `sub`, never Google's sub." }, "email": { "type": "string", "title": "email" }, "status": { "type": "string", "title": "status" }, "token_version": { "type": [ "integer", "string" ], "title": "token_version", "format": "int64" }, "role": { "type": "string", "title": "role", "description": "Kept wire-identical with concierge.v1.UserSummary (the cabinet TS is aliased to the\n concierge shape). The money plane doesn't serve the role here — the cabinet reads it\n from concierge's login summary — so this stays empty; the field exists for parity." }, "role_is_break_glass": { "type": "boolean", "title": "role_is_break_glass", "description": "Parity with concierge.v1.UserSummary.role_is_break_glass — the money plane does not\n serve it, but the field number must not be reused." }, "email_verified": { "type": "boolean", "title": "email_verified", "description": "Parity with concierge.v1.UserSummary, like `role` above." }, "username": { "type": "string", "title": "username" } }, "title": "UserSummary", "additionalProperties": false, "description": "Minimal principal snapshot returned with a freshly issued token pair, so the BFF\n can populate a session without a second round trip." }, "banking.v1.ValuationOverrideTerms": { "type": "object", "properties": { "service": { "type": "string", "title": "service", "description": "The fund/service id being marked." }, "aum": { "type": "string", "title": "aum", "description": "The fund's total AUM to mark it at — decimal USDT string, as everywhere on this wire." } }, "title": "ValuationOverrideTerms", "additionalProperties": false, "description": "The immutable subject of a VALUATION-OVERRIDE consilium — a NAV mark the move guard\n refuses (banking#232). The direct `PostFundValuation` caps a move at `MAX_NAV_MOVE_PCT`\n against the previous mark AND the mark anchoring a rolling window, and carries no flag\n to lift it; a genuine re-mark past the cap is put to the owners instead. Executing the\n consilium derives NAV from the LIVE unit supply at that moment and records the mark with\n the initiator as `posted_by`, so the redeem cooldown binds them exactly as a direct post\n would." }, "banking.v1.VoteDecision": { "type": "string", "title": "VoteDecision", "enum": [ "VOTE_DECISION_UNSPECIFIED", "VOTE_DECISION_PENDING", "VOTE_DECISION_APPROVE", "VOTE_DECISION_REJECT" ], "description": "How one voter answered." }, "banking.v1.Wallet": { "type": "object", "properties": { "balance": { "title": "balance", "$ref": "#/components/schemas/banking.v1.Balance" }, "deposit_addresses": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.DepositAddress" }, "title": "deposit_addresses", "description": "a rail to top up on (per network)" }, "withdrawable": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.NetworkWithdrawable" }, "title": "withdrawable", "description": "per-rail withdraw options" } }, "title": "Wallet", "additionalProperties": false }, "banking.v1.WatchBookRequest": { "type": "object", "properties": { "service": { "type": "string", "title": "service" }, "depth": { "type": "integer", "title": "depth", "description": "as GetBook" } }, "title": "WatchBookRequest", "additionalProperties": false }, "banking.v1.Withdrawal": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton" }, "address": { "type": "string", "title": "address", "description": "destination address" }, "amount": { "type": "string", "title": "amount", "description": "gross debited from the user (decimal USDT)" }, "fee": { "type": "string", "title": "fee", "description": "network fee retained (decimal USDT)" }, "net_amount": { "type": "string", "title": "net_amount", "description": "amount − fee, the amount sent on-chain" }, "state": { "type": "string", "title": "state", "description": "queued | processing | completed | failed | cancelled" }, "tx_ref": { "type": "string", "title": "tx_ref", "description": "on-chain reference once settled (empty otherwise)" } }, "title": "Withdrawal", "additionalProperties": false, "description": "A user withdrawal aggregate, projected. `state` advances queued → processing →\n completed (settled on confirmations) | failed (voided, refunded); a queued one may\n also be cancelled (voided, refunded)." }, "banking.v1.WithdrawalList": { "type": "object", "properties": { "withdrawals": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.Withdrawal" }, "title": "withdrawals" } }, "title": "WithdrawalList", "additionalProperties": false }, "banking.v1.WithdrawalQueue": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/banking.v1.WithdrawalQueueItem" }, "title": "items" } }, "title": "WithdrawalQueue", "additionalProperties": false }, "banking.v1.WithdrawalQueueItem": { "type": "object", "properties": { "withdrawal_id": { "type": "string", "title": "withdrawal_id" }, "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email" }, "network": { "type": "string", "title": "network", "description": "bep20 | polygon | trc20 | ton" }, "address": { "type": "string", "title": "address", "description": "destination on-chain address" }, "amount": { "type": "string", "title": "amount", "description": "gross decimal USDT debited from the source" }, "net_amount": { "type": "string", "title": "net_amount", "description": "amount − fee — what ships on-chain" }, "state": { "type": "string", "title": "state", "description": "queued | processing" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "source": { "type": "string", "title": "source", "description": "user — which claim funds it (always a person's since #245)" } }, "title": "WithdrawalQueueItem", "additionalProperties": false, "description": "One withdrawal awaiting operator action. `email` is the mirrored identity email\n (may be empty if the bridge hasn't populated it); `created_at` is unix seconds." }, "concierge.v1.AdminUserSummary": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email" }, "status": { "type": "string", "title": "status" }, "kyc_level": { "type": "integer", "title": "kyc_level" }, "role": { "type": "string", "title": "role" }, "token_version": { "type": [ "integer", "string" ], "title": "token_version", "format": "int64" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64", "description": "Unix SECONDS the user was provisioned (joined)." }, "role_is_break_glass": { "type": "boolean", "title": "role_is_break_glass", "description": "True when `role` above came from the OWNER_SUBJECTS emergency allowlist rather than\n from `users.role` — see UserProfile.role_is_break_glass. This is the field that\n stops the console listing an \"owner\" the consilium has never heard of." }, "suspended_by": { "type": "string", "title": "suspended_by", "description": "Why the account is disabled; see UserProfile.suspended_by. On the list because a\n held account and a suspended one need different action buttons, and a console that\n cannot tell them apart offers the wrong one." }, "hold_expires_at": { "type": [ "integer", "string" ], "title": "hold_expires_at", "format": "int64", "description": "Unix SECONDS an \"admin_hold\" lapses. 0 when nothing lapses." }, "username": { "type": "string", "title": "username", "description": "See UserProfile.username. ListUsers' query matches it as it matches the email." } }, "title": "AdminUserSummary", "additionalProperties": false, "description": "A lightweight user row for the operator console's user list (not the full profile).\n Named distinctly from auth.proto's login `UserSummary` (same package)." }, "concierge.v1.AdmissionPeer": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email" }, "vote": { "title": "vote", "$ref": "#/components/schemas/concierge.v1.AdmissionVote" }, "voted_at": { "type": [ "integer", "string" ], "title": "voted_at", "format": "int64" } }, "title": "AdmissionPeer", "additionalProperties": false }, "concierge.v1.AdmissionVote": { "type": "string", "title": "AdmissionVote", "enum": [ "ADMISSION_VOTE_UNSPECIFIED", "ADMISSION_VOTE_PENDING", "ADMISSION_VOTE_ADMIT", "ADMISSION_VOTE_REJECT" ], "description": "Deliberately its own enum rather than a reuse of RemovalVote: \"remove/keep\" and\n \"admit/reject\" are different questions, and a surface that renders the wrong verb on\n a governance vote is a surface that gets a vote cast by mistake." }, "concierge.v1.CancelOwnerAdmissionRequest": { "type": "object", "properties": { "admission_id": { "type": "string", "title": "admission_id" } }, "title": "CancelOwnerAdmissionRequest", "additionalProperties": false }, "concierge.v1.CancelOwnerRemovalRequest": { "type": "object", "properties": { "removal_id": { "type": "string", "title": "removal_id" } }, "title": "CancelOwnerRemovalRequest", "additionalProperties": false }, "concierge.v1.CancelUserProposalRequest": { "type": "object", "properties": { "proposal_id": { "type": "string", "title": "proposal_id" } }, "title": "CancelUserProposalRequest", "additionalProperties": false }, "concierge.v1.CatalogAlias": { "type": "object", "properties": { "name": { "type": "string", "title": "name", "description": "`\u003cnamespace\u003e:\u003cname\u003e`." }, "members": { "type": "array", "items": { "type": "string" }, "title": "members" }, "delegates": { "type": "array", "items": { "type": "string" }, "title": "delegates", "description": "Aliases of this catalog its holders may grant and revoke (GrantPermission)." } }, "title": "CatalogAlias", "additionalProperties": false }, "concierge.v1.ClientTokenResponse": { "type": "object", "properties": { "access_token": { "type": "string", "title": "access_token" }, "access_expires_at": { "type": [ "integer", "string" ], "title": "access_expires_at", "format": "int64" }, "refresh_token": { "type": "string", "title": "refresh_token" }, "refresh_expires_at": { "type": [ "integer", "string" ], "title": "refresh_expires_at", "format": "int64" }, "user_id": { "type": "string", "title": "user_id", "description": "The concierge user id — the access token's `sub`." } }, "title": "ClientTokenResponse", "additionalProperties": false, "description": "A relying party's token pair. Expiries are unix SECONDS. Deliberately carries no\n profile: the client reads that from `UserDirectory.GetMe` with the access token, and\n GetMe is also what it re-checks `permissions` against on every request." }, "concierge.v1.DisableUserRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" } }, "title": "DisableUserRequest", "additionalProperties": false }, "concierge.v1.DisableUserResponse": { "type": "object", "title": "DisableUserResponse", "additionalProperties": false }, "concierge.v1.ExchangeCodeRequest": { "type": "object", "properties": { "client_id": { "type": "string", "title": "client_id" }, "client_secret": { "type": "string", "title": "client_secret" }, "code": { "type": "string", "title": "code", "description": "The `code` query parameter the browser brought back to the redirect_uri." }, "redirect_uri": { "type": "string", "title": "redirect_uri", "description": "The redirect_uri sent to authorize, byte for byte." }, "code_verifier": { "type": "string", "title": "code_verifier", "description": "The PKCE verifier whose S256 challenge was sent to authorize." } }, "title": "ExchangeCodeRequest", "additionalProperties": false }, "concierge.v1.FeePolicyApprovalMail": { "type": "object", "properties": { "consilium_id": { "type": "string", "title": "consilium_id" }, "initiator_email": { "type": "string", "title": "initiator_email" }, "fund": { "type": "string", "title": "fund", "description": "The fund whose terms change, in words a person recognises (not a service id)." }, "current": { "title": "current", "description": "The terms in force today. Absent when the fund charges nothing yet — a product with\n no policy charges no fee, so \"none\" is a real current state, not a missing field.", "$ref": "#/components/schemas/concierge.v1.FeeTerms" }, "proposed": { "title": "proposed", "description": "The terms proposed. Required.", "$ref": "#/components/schemas/concierge.v1.FeeTerms" }, "reason": { "type": "string", "title": "reason", "description": "Why, in the operator's words. Required, and rendered attributed to them." }, "payload_hash": { "type": "string", "title": "payload_hash" }, "threshold": { "type": "integer", "title": "threshold" }, "owner_count": { "type": "integer", "title": "owner_count" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "approval_url": { "type": "string", "title": "approval_url", "description": "Absolute URL of the approval page, carrying the opaque token." }, "code": { "type": "string", "title": "code", "description": "The secret code the owner types on that page. Held only until the mail is sent,\n then cleared from the delivery row." } }, "title": "FeePolicyApprovalMail", "additionalProperties": false, "description": "An owner asked to approve new fee terms for a fund.\n\n Shaped like PaymentApprovalMail — a seated owner, a verified address, the operator's\n reason set apart as theirs, a link on our origin and the code that arms it — and it\n describes what an owner must actually be able to check: the terms in force NOW beside\n the terms PROPOSED, field by field. A fee change is a change to the price of every\n investor in the fund, and an approval mail that showed only the new number would have\n the owner approve a difference they cannot see." }, "concierge.v1.FeePolicyNoticeMail": { "type": "object", "properties": { "subject_user_id": { "type": "string", "title": "subject_user_id", "description": "Concierge canonical id of the investor. MUST equal the request's user_id; the relay\n refuses the mail otherwise." }, "fund": { "type": "string", "title": "fund", "description": "The fund whose terms change, in words a person recognises." }, "current": { "title": "current", "description": "The terms in force until `effective_at`. Absent when the fund charged nothing.", "$ref": "#/components/schemas/concierge.v1.FeeTerms" }, "proposed": { "title": "proposed", "description": "The terms that apply from `effective_at`. Required.", "$ref": "#/components/schemas/concierge.v1.FeeTerms" }, "effective_at": { "type": [ "integer", "string" ], "title": "effective_at", "format": "int64", "description": "Unix seconds the new terms take effect." }, "link": { "type": "string", "title": "link", "description": "Cabinet-relative path of the page showing the full terms, e.g. `/funds/qn/fees`.\n Must start with a single `/`; empty means the cabinet's front page." } }, "title": "FeePolicyNoticeMail", "additionalProperties": false, "description": "One investor told that the fee terms of a fund they hold are changing.\n\n `subject_user_id` exists beside SendGovernanceMailRequest.user_id for the reason\n PaymentConsentMail gives: no seat is involved, so the only fact this plane can hold\n the money plane to is that the person it is writing to IS the person the notice is\n about. A caller that fans one investor's notice out to a second mailbox has to\n contradict itself in the same message to do it.\n\n No code and no decision: the terms were set — by the operator within the house terms,\n or by the owners' consilium beyond them — and this is the investor being told before\n they take effect, with the same notice either way. `link` is a CABINET-RELATIVE path —\n the money plane names no host at all; this plane hangs it off its own cabinet origin." }, "concierge.v1.FeeTerms": { "type": "object", "properties": { "management_bps": { "type": "integer", "title": "management_bps", "description": "Annual management fee, in basis points of `basis`." }, "performance_bps": { "type": "integer", "title": "performance_bps", "description": "Performance fee over the high-water mark, in basis points of the gain." }, "hurdle_bps": { "type": "integer", "title": "hurdle_bps", "description": "Annual hurdle the gain must clear before the performance fee is due. 0 = none." }, "basis": { "type": "string", "title": "basis", "description": "invested_capital | market_value — what the management fee is charged on." }, "crystallization": { "type": "string", "title": "crystallization", "description": "monthly | quarterly | semi_annual | annual — how often the performance fee\n crystallizes." } }, "title": "FeeTerms", "additionalProperties": false, "description": "One set of fee terms, as the money plane's `FeePolicy` spells them: basis points and\n two closed vocabularies. Rendered HERE as percentages and words — the money plane\n never hands this plane a pre-rendered \"2.5%\", because a string it renders is a string\n it can make say anything. Every `_bps` is refused above 10 000 (100%), and `basis` and\n `crystallization` are refused outside their closed sets: an unknown word means the two\n planes disagree about what the terms ARE, which is a rejected call, not a line of mail." }, "concierge.v1.GetMeRequest": { "type": "object", "title": "GetMeRequest", "additionalProperties": false }, "concierge.v1.GetOwnerAdmissionRequest": { "type": "object", "properties": { "admission_id": { "type": "string", "title": "admission_id" } }, "title": "GetOwnerAdmissionRequest", "additionalProperties": false }, "concierge.v1.GetOwnerRemovalRequest": { "type": "object", "properties": { "removal_id": { "type": "string", "title": "removal_id" } }, "title": "GetOwnerRemovalRequest", "additionalProperties": false }, "concierge.v1.GetRemovalInvitationRequest": { "type": "object", "properties": { "token": { "type": "string", "title": "token" } }, "title": "GetRemovalInvitationRequest", "additionalProperties": false }, "concierge.v1.GetUserProposalRequest": { "type": "object", "properties": { "proposal_id": { "type": "string", "title": "proposal_id" } }, "title": "GetUserProposalRequest", "additionalProperties": false }, "concierge.v1.GetUserRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" } }, "title": "GetUserRequest", "additionalProperties": false }, "concierge.v1.GovernanceMailKind": { "type": "string", "title": "GovernanceMailKind", "enum": [ "GOVERNANCE_MAIL_KIND_UNSPECIFIED", "GOVERNANCE_MAIL_KIND_PAYOUT_APPROVAL", "GOVERNANCE_MAIL_KIND_PAYOUT_OUTCOME", "GOVERNANCE_MAIL_KIND_APPROVAL_TOKEN_BURNED", "GOVERNANCE_MAIL_KIND_PAYMENT_CONSENT", "GOVERNANCE_MAIL_KIND_PAYMENT_APPROVAL", "GOVERNANCE_MAIL_KIND_FEE_POLICY_APPROVAL", "GOVERNANCE_MAIL_KIND_FEE_POLICY_NOTICE", "GOVERNANCE_MAIL_KIND_PAYMENT_OUTCOME" ], "description": "The typed governance mails this plane knows how to render." }, "concierge.v1.GovernanceTick": { "type": "object", "properties": { "revision": { "type": [ "integer", "string" ], "title": "revision", "format": "int64", "description": "Monotonic across the whole governance surface. Refetch when it moves." }, "at": { "type": [ "integer", "string" ], "title": "at", "format": "int64", "description": "Unix seconds the tick was produced, so a client can tell a live stream from a\n wedged one." }, "heartbeat": { "type": "boolean", "title": "heartbeat", "description": "True for the periodic keepalive, which carries the current revision unchanged." } }, "title": "GovernanceTick", "additionalProperties": false }, "concierge.v1.GrantHolder": { "type": "object", "properties": { "grant": { "title": "grant", "$ref": "#/components/schemas/concierge.v1.PermissionGrant" }, "email": { "type": "string", "title": "email" }, "legal_name": { "type": "string", "title": "legal_name" }, "preferred_name": { "type": "string", "title": "preferred_name" }, "username": { "type": "string", "title": "username", "description": "The holder's handle; empty when they have none. A delegate sees it as it sees the email." } }, "title": "GrantHolder", "additionalProperties": false }, "concierge.v1.GrantPermissionRequest": { "type": "object", "allOf": [ { "properties": { "target": { "type": "string", "title": "target" }, "reason": { "type": "string", "title": "reason", "description": "Recorded on the grant and the audit row." } } }, { "oneOf": [ { "type": "object", "properties": { "account": { "type": "string", "title": "account", "description": "An email or a username: one handle, resolved the way a password sign-in resolves it." } }, "title": "account", "required": [ "account" ] }, { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" } }, "title": "user_id", "required": [ "user_id" ] } ] } ], "title": "GrantPermissionRequest", "additionalProperties": false }, "concierge.v1.GrantPermissionResponse": { "type": "object", "properties": { "grant": { "title": "grant", "$ref": "#/components/schemas/concierge.v1.PermissionGrant" } }, "title": "GrantPermissionResponse", "additionalProperties": false }, "concierge.v1.HoldUserRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "reason": { "type": "string", "title": "reason", "description": "REQUIRED. A brake that stops someone's money with no stated cause cannot be\n reviewed afterwards, and the owners asked to ratify it are reading exactly this." } }, "title": "HoldUserRequest", "additionalProperties": false }, "concierge.v1.HoldUserResponse": { "type": "object", "properties": { "hold_expires_at": { "type": [ "integer", "string" ], "title": "hold_expires_at", "format": "int64", "description": "Unix SECONDS the hold lapses unless the owners ratify it." } }, "title": "HoldUserResponse", "additionalProperties": false }, "concierge.v1.Jwk": { "type": "object", "properties": { "kid": { "type": "string", "title": "kid" }, "kty": { "type": "string", "title": "kty" }, "crv": { "type": "string", "title": "crv" }, "x": { "type": "string", "title": "x" }, "alg": { "type": "string", "title": "alg" }, "use": { "type": "string", "title": "use" } }, "title": "Jwk", "additionalProperties": false, "description": "One JSON Web Key. Ed25519 keys are OKP: kty=\"OKP\", crv=\"Ed25519\", x=base64url\n public key, alg=\"EdDSA\". `kid` is a stable thumbprint of the public key." }, "concierge.v1.JwksRequest": { "type": "object", "title": "JwksRequest", "additionalProperties": false }, "concierge.v1.JwksResponse": { "type": "object", "properties": { "keys": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.Jwk" }, "title": "keys" } }, "title": "JwksResponse", "additionalProperties": false }, "concierge.v1.ListGrantsRequest": { "type": "object", "properties": { "namespace": { "type": "string", "title": "namespace", "description": "The tenant namespace (`sa`)." } }, "title": "ListGrantsRequest", "additionalProperties": false }, "concierge.v1.ListGrantsResponse": { "type": "object", "properties": { "holders": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.GrantHolder" }, "title": "holders", "description": "Oldest grant first." } }, "title": "ListGrantsResponse", "additionalProperties": false }, "concierge.v1.ListOwnerAdmissionsRequest": { "type": "object", "properties": { "limit": { "type": "integer", "title": "limit", "description": "0 means the server default. Includes closed proposals — nothing is deleted." } }, "title": "ListOwnerAdmissionsRequest", "additionalProperties": false }, "concierge.v1.ListOwnerRemovalsRequest": { "type": "object", "properties": { "limit": { "type": "integer", "title": "limit", "description": "0 means the server default. Includes closed proposals — nothing is deleted." } }, "title": "ListOwnerRemovalsRequest", "additionalProperties": false }, "concierge.v1.ListOwnersRequest": { "type": "object", "title": "ListOwnersRequest", "additionalProperties": false }, "concierge.v1.ListSessionsRequest": { "type": "object", "properties": { "refresh_token": { "type": "string", "title": "refresh_token", "description": "The caller's current refresh token: proves identity and flags the current session." } }, "title": "ListSessionsRequest", "additionalProperties": false }, "concierge.v1.ListSessionsResponse": { "type": "object", "properties": { "sessions": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.Session" }, "title": "sessions" } }, "title": "ListSessionsResponse", "additionalProperties": false }, "concierge.v1.ListUserProposalsRequest": { "type": "object", "properties": { "limit": { "type": "integer", "title": "limit", "description": "0 means the server default. Includes closed proposals — nothing is deleted." }, "kind": { "title": "kind", "description": "UNSPECIFIED lists every kind.", "$ref": "#/components/schemas/concierge.v1.UserProposalKind" } }, "title": "ListUserProposalsRequest", "additionalProperties": false }, "concierge.v1.ListUsersRequest": { "type": "object", "properties": { "query": { "type": "string", "title": "query", "description": "Free-text match over email/user_id (empty = no text filter)." }, "role": { "type": "string", "title": "role", "description": "Optional exact filters (empty string = unfiltered)." }, "status": { "type": "string", "title": "status" }, "limit": { "type": "integer", "title": "limit", "description": "Page window. `limit` is clamped server-side; `offset` is a simple row offset." }, "offset": { "type": "integer", "title": "offset" } }, "title": "ListUsersRequest", "additionalProperties": false }, "concierge.v1.ListUsersResponse": { "type": "object", "properties": { "users": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.AdminUserSummary" }, "title": "users" }, "total": { "type": [ "integer", "string" ], "title": "total", "format": "int64", "description": "Total matching the filters (before the page window), for the list header count." } }, "title": "ListUsersResponse", "additionalProperties": false }, "concierge.v1.LogoutRequest": { "type": "object", "properties": { "refresh_token": { "type": "string", "title": "refresh_token" }, "revoke_all": { "type": "boolean", "title": "revoke_all", "description": "When true, bump the user's token_version (coarse \"revoke all\"), not just this\n refresh family." } }, "title": "LogoutRequest", "additionalProperties": false }, "concierge.v1.LogoutResponse": { "type": "object", "title": "LogoutResponse", "additionalProperties": false }, "concierge.v1.OpenAdminAdmissionRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "reason": { "type": "string", "title": "reason" } }, "title": "OpenAdminAdmissionRequest", "additionalProperties": false }, "concierge.v1.OpenOwnerAdmissionRequest": { "type": "object", "properties": { "candidate_user_id": { "type": "string", "title": "candidate_user_id", "description": "The user to seat. Must not already be an owner." }, "reason": { "type": "string", "title": "reason" } }, "title": "OpenOwnerAdmissionRequest", "additionalProperties": false }, "concierge.v1.OpenOwnerRemovalRequest": { "type": "object", "properties": { "target_user_id": { "type": "string", "title": "target_user_id" }, "reason": { "type": "string", "title": "reason" } }, "title": "OpenOwnerRemovalRequest", "additionalProperties": false }, "concierge.v1.OpenUserReinstatementRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "reason": { "type": "string", "title": "reason" } }, "title": "OpenUserReinstatementRequest", "additionalProperties": false }, "concierge.v1.OpenUserSuspensionRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "reason": { "type": "string", "title": "reason", "description": "REQUIRED — it is what the other owners are voting on." } }, "title": "OpenUserSuspensionRequest", "additionalProperties": false }, "concierge.v1.Owner": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email", "description": "Masked on every surface a non-owner can reach." }, "display_name": { "type": "string", "title": "display_name" }, "owner_since": { "type": [ "integer", "string" ], "title": "owner_since", "format": "int64" } }, "title": "Owner", "additionalProperties": false }, "concierge.v1.OwnerAdmission": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "state": { "title": "state", "$ref": "#/components/schemas/concierge.v1.OwnerAdmissionState" }, "candidate_user_id": { "type": "string", "title": "candidate_user_id" }, "candidate_email": { "type": "string", "title": "candidate_email" }, "initiator_user_id": { "type": "string", "title": "initiator_user_id" }, "initiator_email": { "type": "string", "title": "initiator_email" }, "reason": { "type": "string", "title": "reason", "description": "Why, in the initiator's words. Shown to every voter." }, "peers": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.AdmissionPeer" }, "title": "peers", "description": "Every owner except the initiator, with their answers. Never empty: an admission\n with nobody to agree is refused at open rather than left open and unpassable." }, "owner_count": { "type": "integer", "title": "owner_count", "description": "Owners at open. The initiator is counted but does not vote." }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "decided_at": { "type": [ "integer", "string" ], "title": "decided_at", "format": "int64" }, "void_reason": { "type": "string", "title": "void_reason" }, "version": { "type": [ "integer", "string" ], "title": "version", "format": "int64" } }, "title": "OwnerAdmission", "additionalProperties": false }, "concierge.v1.OwnerAdmissionList": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.OwnerAdmission" }, "title": "items" } }, "title": "OwnerAdmissionList", "additionalProperties": false }, "concierge.v1.OwnerAdmissionState": { "type": "string", "title": "OwnerAdmissionState", "enum": [ "OWNER_ADMISSION_STATE_UNSPECIFIED", "OWNER_ADMISSION_STATE_OPEN", "OWNER_ADMISSION_STATE_EXECUTED", "OWNER_ADMISSION_STATE_REJECTED", "OWNER_ADMISSION_STATE_EXPIRED", "OWNER_ADMISSION_STATE_CANCELLED", "OWNER_ADMISSION_STATE_VOID" ], "description": "The six states a proposal of either kind can be in. A separate enum from\n OwnerRemovalState only because proto enum VALUES share one namespace per package;\n the states themselves are identical, and the domain models them with one type." }, "concierge.v1.OwnerList": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.Owner" }, "title": "items" }, "below_payout_floor": { "type": "boolean", "title": "below_payout_floor", "description": "Below three, the money plane can no longer reach its payout threshold." } }, "title": "OwnerList", "additionalProperties": false }, "concierge.v1.OwnerRemoval": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "state": { "title": "state", "$ref": "#/components/schemas/concierge.v1.OwnerRemovalState" }, "target_user_id": { "type": "string", "title": "target_user_id" }, "target_email": { "type": "string", "title": "target_email" }, "initiator_user_id": { "type": "string", "title": "initiator_user_id" }, "initiator_email": { "type": "string", "title": "initiator_email" }, "reason": { "type": "string", "title": "reason", "description": "Why, in the initiator's words. Shown to the target and to every peer." }, "peers": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.RemovalPeer" }, "title": "peers", "description": "Every owner except the target and the initiator, with their answers. Empty means\n path (b) is unavailable and only the target's own acceptance can carry this." }, "target_decision": { "title": "target_decision", "description": "How the target answered from their mailbox.", "$ref": "#/components/schemas/concierge.v1.RemovalVote" }, "target_decided_at": { "type": [ "integer", "string" ], "title": "target_decided_at", "format": "int64" }, "target_notified": { "type": "boolean", "title": "target_notified" }, "owner_count": { "type": "integer", "title": "owner_count", "description": "Owners at open, and the count that would remain. The floor is checked at open AND\n at execution, because the roster can move underneath an open proposal." }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "decided_at": { "type": [ "integer", "string" ], "title": "decided_at", "format": "int64" }, "void_reason": { "type": "string", "title": "void_reason" }, "version": { "type": [ "integer", "string" ], "title": "version", "format": "int64" } }, "title": "OwnerRemoval", "additionalProperties": false }, "concierge.v1.OwnerRemovalInvitation": { "type": "object", "properties": { "removal_id": { "type": "string", "title": "removal_id" }, "state": { "title": "state", "$ref": "#/components/schemas/concierge.v1.OwnerRemovalState" }, "initiator_email": { "type": "string", "title": "initiator_email" }, "target_email": { "type": "string", "title": "target_email" }, "reason": { "type": "string", "title": "reason" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "decision": { "title": "decision", "$ref": "#/components/schemas/concierge.v1.RemovalVote" }, "attempts_remaining": { "type": "integer", "title": "attempts_remaining" } }, "title": "OwnerRemovalInvitation", "additionalProperties": false, "description": "What the TARGET is shown before answering. No peer identities, no vote breakdown —\n knowing exactly who voted to remove you, before you answer, is not information this\n flow needs to hand over." }, "concierge.v1.OwnerRemovalList": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.OwnerRemoval" }, "title": "items" } }, "title": "OwnerRemovalList", "additionalProperties": false }, "concierge.v1.OwnerRemovalState": { "type": "string", "title": "OwnerRemovalState", "enum": [ "OWNER_REMOVAL_STATE_UNSPECIFIED", "OWNER_REMOVAL_STATE_OPEN", "OWNER_REMOVAL_STATE_EXECUTED", "OWNER_REMOVAL_STATE_REJECTED", "OWNER_REMOVAL_STATE_EXPIRED", "OWNER_REMOVAL_STATE_CANCELLED", "OWNER_REMOVAL_STATE_VOID" ] }, "concierge.v1.PaymentApprovalMail": { "type": "object", "properties": { "consilium_id": { "type": "string", "title": "consilium_id" }, "payment_id": { "type": "string", "title": "payment_id" }, "initiator_email": { "type": "string", "title": "initiator_email" }, "tier": { "type": "string", "title": "tier", "description": "internal | service | external." }, "source": { "type": "string", "title": "source", "description": "Where the money leaves from, in words a person recognises (not an account id)." }, "destination": { "type": "string", "title": "destination", "description": "Where it lands, in words a person recognises." }, "amount": { "type": "string", "title": "amount" }, "reason": { "type": "string", "title": "reason", "description": "Why the payment was opened, in the operator's words. Required." }, "payload_hash": { "type": "string", "title": "payload_hash" }, "threshold": { "type": "integer", "title": "threshold" }, "owner_count": { "type": "integer", "title": "owner_count" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "approval_url": { "type": "string", "title": "approval_url", "description": "Absolute URL of the approval page, carrying the opaque token." }, "code": { "type": "string", "title": "code", "description": "The secret code the owner types on that page. Held only until the mail is sent,\n then cleared from the delivery row." } }, "title": "PaymentApprovalMail", "additionalProperties": false, "description": "An owner asked to approve a payment of fund-owned money.\n\n WHY NOT PayoutApprovalMail. That template opens with \"a request to pay fund revenue\n out on-chain\" and labels its middle rows Network and Destination address. A payment\n is a transfer between two claims the platform holds — `Piggybank → Revenue`, or into a\n service's pooled funds, or off the platform — and rendering it through the payout\n copy would mail the whole roster a sentence naming the wrong claim and the wrong rail\n on a money move they are being asked to authorize. The one thing an approval mail\n must do is describe correctly what is being approved, so a payment gets its own.\n\n The recipient rule is the payout one: a seated owner, resolved from the identity\n record, and nobody else. Field rules are PaymentConsentMail's — every string is\n bounded in bytes and refused if it carries a control character, `tier` is a closed\n set, and `reason` is required and rendered attributed to the operator who typed it." }, "concierge.v1.PaymentConsentMail": { "type": "object", "properties": { "payment_id": { "type": "string", "title": "payment_id" }, "subject_user_id": { "type": "string", "title": "subject_user_id", "description": "Concierge canonical id of the user whose money moves. MUST equal the request's\n user_id; the relay refuses the mail otherwise." }, "initiator_email": { "type": "string", "title": "initiator_email", "description": "The operator who opened the payment. Shown so the subject knows who is asking." }, "tier": { "type": "string", "title": "tier", "description": "internal | service | external. A closed set: an unknown tier is a bug in the money\n plane, not a string to render at a person deciding whether to part with money." }, "source": { "type": "string", "title": "source", "description": "Where the money leaves from, in words a person recognises (not an account id)." }, "destination": { "type": "string", "title": "destination", "description": "Where it lands, in words a person recognises." }, "amount": { "type": "string", "title": "amount" }, "reason": { "type": "string", "title": "reason", "description": "Why the payment was opened, written by the operator and shown to the subject\n VERBATIM. Required — a consent request with no stated reason is one nobody can\n judge. Rendered under its own label so it never reads as a platform statement, and\n refused outright if it carries a control character: the text part of a mail is not\n escaped, so a newline here would forge the Amount/To lines this mail exists to show." }, "payload_hash": { "type": "string", "title": "payload_hash" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "approval_url": { "type": "string", "title": "approval_url", "description": "Absolute URL of the consent page, carrying the opaque token." }, "code": { "type": "string", "title": "code", "description": "The secret code the subject types on that page." } }, "title": "PaymentConsentMail", "additionalProperties": false, "description": "One user's consent to a payment that moves their own money.\n\n WHY subject_user_id EXISTS BESIDE SendGovernanceMailRequest.user_id. Every other kind\n is addressed to a fund owner, and \"is this recipient an owner?\" is a fact this plane\n holds independently of anything the money plane says. This kind has no such fact to\n check against: any user may consent to their own transfer, so \"is this the right\n recipient?\" is unanswerable from the addressing field alone. So the money plane must\n state, in the TYPED payload, whose money is moving — and the relay refuses unless the\n user it is being asked to write to IS that person. A caller that fans one consent out\n to a second mailbox has to contradict itself in the same message to do it.\n\n It is a redundancy on purpose. The address is still resolved HERE from the identity\n record and never taken from either field." }, "concierge.v1.PaymentOutcomeMail": { "type": "object", "properties": { "subject_user_id": { "type": "string", "title": "subject_user_id", "description": "Concierge canonical id of the user whose money the payment would have moved." }, "outcome": { "type": "string", "title": "outcome", "description": "TOKEN_BURNED (five wrong codes on the consent page) or INVALIDATED (the consent was\n voided under the subject — sessions revoked, email changed). A closed set." }, "reason": { "type": "string", "title": "reason", "description": "Why the consent died, as a closed word this plane turns into its own phrase:\n WRONG_CODES (the only reason for TOKEN_BURNED), SESSIONS_REVOKED or EMAIL_CHANGED (the\n two reasons for INVALIDATED). Any other word, or a pair that does not match, is refused." }, "tier": { "type": "string", "title": "tier", "description": "internal | service | external — the consent kind's closed set." }, "source": { "type": "string", "title": "source", "description": "Where the money would have left from, in words a person recognises." }, "destination": { "type": "string", "title": "destination", "description": "Where it would have landed, in words a person recognises." }, "amount": { "type": "string", "title": "amount", "description": "The amount, spelled by the money plane (`1 200.00 USDT`): digits with the usual\n separators, one ASCII space, an upper-case currency code. Repeated in the subject line\n and in the subject's inbox, so anything else is refused." }, "payment_id": { "type": "string", "title": "payment_id", "description": "The payment's id, a UUID. Shown to staff so they can find the order; not to the subject." } }, "title": "PaymentOutcomeMail", "additionalProperties": false, "description": "A payment cancelled because its subject's consent could no longer be given.\n\n WHY NOT PayoutOutcomeMail. That one is the consilium's record and goes to seated owners\n only; the people this one is FOR are the payment's subject — whose consent link was\n attacked, or whose sessions were just revoked — and the staff member who opened the\n order, who is usually an admin. Neither holds a seat.\n\n `subject_user_id` exists for the reason PaymentConsentMail gives, with one widening: the\n relay accepts the request's user_id when it IS that subject, or when it names an admin or\n an owner. Which of the two it was decides the copy (the subject is told what to do about\n their mailbox; staff get the order's details) and whether an inbox trace is written (the\n subject only).\n\n Nothing here is a secret and nothing can be a link: no URL, no code. Why the consent\n died is a closed word the platform phrases itself, and the amount must read as money —\n no money-plane text reaches a sentence of ours." }, "concierge.v1.PayoutApprovalMail": { "type": "object", "properties": { "consilium_id": { "type": "string", "title": "consilium_id" }, "initiator_email": { "type": "string", "title": "initiator_email" }, "network": { "type": "string", "title": "network" }, "address": { "type": "string", "title": "address" }, "amount": { "type": "string", "title": "amount" }, "memo": { "type": "string", "title": "memo" }, "payload_hash": { "type": "string", "title": "payload_hash" }, "threshold": { "type": "integer", "title": "threshold" }, "owner_count": { "type": "integer", "title": "owner_count" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "approval_url": { "type": "string", "title": "approval_url", "description": "Absolute URL of the approval page, carrying the opaque token." }, "code": { "type": "string", "title": "code", "description": "The secret code the owner types on that page. Held only until the mail is sent,\n then cleared from the delivery row." } }, "title": "PayoutApprovalMail", "additionalProperties": false }, "concierge.v1.PayoutOutcomeMail": { "type": "object", "properties": { "consilium_id": { "type": "string", "title": "consilium_id" }, "outcome": { "type": "string", "title": "outcome", "description": "APPROVED / REJECTED / EXPIRED / CANCELLED / EXECUTED / EXECUTION_FAILED, or\n TOKEN_BURNED under the burn kind." }, "network": { "type": "string", "title": "network", "description": "The payout pair. Empty for a payment." }, "address": { "type": "string", "title": "address" }, "amount": { "type": "string", "title": "amount" }, "detail": { "type": "string", "title": "detail" }, "tier": { "type": "string", "title": "tier", "description": "The payment tuple. Empty for a payout. Same rules as PaymentApprovalMail: `tier`\n is the closed set, `source` and `destination` are words a person recognises, and\n `reason` is the operator's own text, shown attributed and refused if it carries a\n control character." }, "source": { "type": "string", "title": "source" }, "destination": { "type": "string", "title": "destination" }, "reason": { "type": "string", "title": "reason" }, "fund": { "type": "string", "title": "fund", "description": "The fee terms description. Empty for a payout and for a payment. Same rules as\n FeePolicyApprovalMail: `fund` is words a person recognises and may not carry a\n link, `current` is absent when the fund charged nothing (a real state, not a\n missing field), `proposed` is required, and `reason` — the operator's words, shown\n attributed — is empty under the burn kind." }, "current": { "title": "current", "$ref": "#/components/schemas/concierge.v1.FeeTerms" }, "proposed": { "title": "proposed", "$ref": "#/components/schemas/concierge.v1.FeeTerms" }, "mark": { "type": "string", "title": "mark", "description": "The NAV mark description: `fund` as above, and the value the consilium was asked to\n mark it at, spelled by the money plane as an amount is (`5 000.00 USDT`). Empty for\n the other three. A mark used to ride the payment tuple (`Amount: 5000`, `To: AUM\n 5000 USDT`, `Type: service`), which told the owners money had moved when a mark\n moves none; with this field filled the relay renders it as the value it is. Same\n rules as an amount: one line, and it may not carry a link." } }, "title": "PayoutOutcomeMail", "additionalProperties": false, "description": "How a consilium ended — over a revenue payout, over a payment, over a fund's fee\n terms, or over a fund's NAV mark — and, under APPROVAL_TOKEN_BURNED, that one of its\n tokens burned.\n\n ONE message for four subjects, additively. The burn notice already rides this shape\n under its own kind, so a payment consilium's outcome and burn ride it too, and so do a\n fee-policy consilium's and a valuation override's, rather than each growing a message\n of their own: `network` + `address` describe a payout, `source` + `destination`\n (+ `tier`, `reason`) describe a payment, `fund` + `proposed` (+ `current`, `reason`)\n describe fee terms, `fund` + `mark` (+ `reason`) describe a NAV mark, and the renderer\n switches on which description is filled. A caller fills exactly one and leaves the\n others empty." }, "concierge.v1.PermissionGrant": { "type": "object", "properties": { "id": { "type": [ "integer", "string" ], "title": "id", "format": "int64" }, "user_id": { "type": "string", "title": "user_id" }, "target": { "type": "string", "title": "target" }, "granted_by": { "type": "string", "title": "granted_by" }, "granted_at": { "type": [ "integer", "string" ], "title": "granted_at", "format": "int64", "description": "Unix SECONDS." }, "reason": { "type": "string", "title": "reason" }, "orphaned": { "type": "boolean", "title": "orphaned", "description": "The tenant's current catalog defines nothing this target names: it grants nothing." } }, "title": "PermissionGrant", "additionalProperties": false, "description": "One grant of a target inside a tenant's namespace." }, "concierge.v1.ProposalVote": { "type": "string", "title": "ProposalVote", "enum": [ "PROPOSAL_VOTE_UNSPECIFIED", "PROPOSAL_VOTE_PENDING", "PROPOSAL_VOTE_FOR", "PROPOSAL_VOTE_AGAINST" ], "description": "Deliberately NEUTRAL verbs, where the owner consilia use remove/keep and\n admit/reject. Three kinds share this vote, so a kind-specific verb would only mean\n something read against UserProposal.kind — and a vocabulary that is correct only when\n cross-referenced is one that eventually gets rendered wrong. The kind-specific verb\n belongs on the SURFACE, which knows the kind; this is which way the voter pushed." }, "concierge.v1.PublishCatalogRequest": { "type": "object", "properties": { "client_id": { "type": "string", "title": "client_id" }, "client_secret": { "type": "string", "title": "client_secret" }, "version": { "type": [ "integer", "string" ], "title": "version", "format": "int64", "description": "Unix SECONDS of the commit the client was built from (nix `self.lastModified`):\n build time, not boot time, so a restarting older replica never supersedes a newer one." }, "permissions": { "type": "array", "items": { "type": "string" }, "title": "permissions" }, "aliases": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.CatalogAlias" }, "title": "aliases" } }, "title": "PublishCatalogRequest", "additionalProperties": false }, "concierge.v1.PublishCatalogResponse": { "type": "object", "title": "PublishCatalogResponse", "additionalProperties": false }, "concierge.v1.RefreshClientTokenRequest": { "type": "object", "properties": { "client_id": { "type": "string", "title": "client_id" }, "client_secret": { "type": "string", "title": "client_secret" }, "refresh_token": { "type": "string", "title": "refresh_token" } }, "title": "RefreshClientTokenRequest", "additionalProperties": false }, "concierge.v1.RefreshRequest": { "type": "object", "properties": { "refresh_token": { "type": "string", "title": "refresh_token" } }, "title": "RefreshRequest", "additionalProperties": false }, "concierge.v1.ReinstateUserRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "reason": { "type": "string", "title": "reason", "description": "Recorded verbatim on the audit row." } }, "title": "ReinstateUserRequest", "additionalProperties": false }, "concierge.v1.ReinstateUserResponse": { "type": "object", "title": "ReinstateUserResponse", "additionalProperties": false }, "concierge.v1.RemovalPeer": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email" }, "vote": { "title": "vote", "$ref": "#/components/schemas/concierge.v1.RemovalVote" }, "voted_at": { "type": [ "integer", "string" ], "title": "voted_at", "format": "int64" } }, "title": "RemovalPeer", "additionalProperties": false }, "concierge.v1.RemovalVote": { "type": "string", "title": "RemovalVote", "enum": [ "REMOVAL_VOTE_UNSPECIFIED", "REMOVAL_VOTE_PENDING", "REMOVAL_VOTE_REMOVE", "REMOVAL_VOTE_KEEP" ] }, "concierge.v1.ResignOwnershipRequest": { "type": "object", "properties": { "confirm_email": { "type": "string", "title": "confirm_email", "description": "Typed confirmation, so a resignation cannot be a stray click. The server checks it\n equals the caller's own email." } }, "title": "ResignOwnershipRequest", "additionalProperties": false }, "concierge.v1.RevokePermissionRequest": { "type": "object", "allOf": [ { "properties": { "target": { "type": "string", "title": "target" }, "reason": { "type": "string", "title": "reason", "description": "Recorded on the audit row." } } }, { "oneOf": [ { "type": "object", "properties": { "account": { "type": "string", "title": "account", "description": "An email or a username, as in GrantPermissionRequest." } }, "title": "account", "required": [ "account" ] }, { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" } }, "title": "user_id", "required": [ "user_id" ] } ] } ], "title": "RevokePermissionRequest", "additionalProperties": false }, "concierge.v1.RevokePermissionResponse": { "type": "object", "title": "RevokePermissionResponse", "additionalProperties": false }, "concierge.v1.RevokeSessionRequest": { "type": "object", "properties": { "refresh_token": { "type": "string", "title": "refresh_token", "description": "The caller's current refresh token (proves identity)." }, "session_id": { "type": "string", "title": "session_id", "description": "The session id to revoke (must belong to the same user)." } }, "title": "RevokeSessionRequest", "additionalProperties": false }, "concierge.v1.RevokeSessionResponse": { "type": "object", "title": "RevokeSessionResponse", "additionalProperties": false }, "concierge.v1.RevokeTokensRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "reason": { "type": "string", "title": "reason", "description": "Recorded verbatim on the audit row. Optional here: revoking sessions is the\n reflex you want an operator to reach for without composing a sentence first." } }, "title": "RevokeTokensRequest", "additionalProperties": false }, "concierge.v1.RevokeTokensResponse": { "type": "object", "properties": { "token_version": { "type": [ "integer", "string" ], "title": "token_version", "format": "int64" } }, "title": "RevokeTokensResponse", "additionalProperties": false }, "concierge.v1.SendGovernanceMailRequest": { "type": "object", "properties": { "kind": { "title": "kind", "$ref": "#/components/schemas/concierge.v1.GovernanceMailKind" }, "user_id": { "type": "string", "title": "user_id", "description": "Concierge canonical user id of the recipient. The address is resolved HERE, from\n the identity record, so the money plane cannot redirect a governance mail." }, "dedupe_key": { "type": "string", "title": "dedupe_key", "description": "Idempotency key. The same key never sends twice.\n\n A key names ONE mail: one kind, to one recipient. Reusing a key for the same mail is a\n retry and answers `enqueued: false`; reusing it for a different recipient or kind is\n refused ALREADY_EXISTS, because the key is unique across the whole queue. So a kind\n told to several people — PAYMENT_OUTCOME to the subject and to each staff member —\n needs a key per copy." }, "payout_approval": { "title": "payout_approval", "description": "Typed fields the template consumes. Escaped at render; never interpreted as markup.", "$ref": "#/components/schemas/concierge.v1.PayoutApprovalMail" }, "payout_outcome": { "title": "payout_outcome", "$ref": "#/components/schemas/concierge.v1.PayoutOutcomeMail" }, "payment_consent": { "title": "payment_consent", "$ref": "#/components/schemas/concierge.v1.PaymentConsentMail" }, "payment_approval": { "title": "payment_approval", "$ref": "#/components/schemas/concierge.v1.PaymentApprovalMail" }, "fee_policy_approval": { "title": "fee_policy_approval", "$ref": "#/components/schemas/concierge.v1.FeePolicyApprovalMail" }, "fee_policy_notice": { "title": "fee_policy_notice", "$ref": "#/components/schemas/concierge.v1.FeePolicyNoticeMail" }, "payment_outcome": { "title": "payment_outcome", "$ref": "#/components/schemas/concierge.v1.PaymentOutcomeMail" } }, "title": "SendGovernanceMailRequest", "additionalProperties": false }, "concierge.v1.SendGovernanceMailResponse": { "type": "object", "properties": { "enqueued": { "type": "boolean", "title": "enqueued", "description": "False when `dedupe_key` had already been accepted." } }, "title": "SendGovernanceMailResponse", "additionalProperties": false }, "concierge.v1.Session": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "user_agent": { "type": "string", "title": "user_agent" }, "ip": { "type": "string", "title": "ip" }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "last_seen": { "type": [ "integer", "string" ], "title": "last_seen", "format": "int64" }, "current": { "type": "boolean", "title": "current", "description": "True for the family that owns the refresh token presented on the listing call." } }, "title": "Session", "additionalProperties": false, "description": "One active session = one refresh-token family. Timestamps are unix SECONDS." }, "concierge.v1.SetKycLevelRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "kyc_level": { "type": "integer", "title": "kyc_level" }, "reason": { "type": "string", "title": "reason", "description": "Recorded verbatim on the audit row." } }, "title": "SetKycLevelRequest", "additionalProperties": false }, "concierge.v1.SetKycLevelResponse": { "type": "object", "properties": { "kyc_level": { "type": "integer", "title": "kyc_level", "description": "The user's KYC level now in effect (echoes the applied level)." } }, "title": "SetKycLevelResponse", "additionalProperties": false }, "concierge.v1.SetRoleRequest": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "role": { "type": "string", "title": "role", "description": "The role to grant (snake_case: investor/operator/admin/owner).\n\n `owner` is refused in both directions and `admin` in the GRANTING direction, each\n naming the proposal that does it instead. Taking `admin` away is still one act:\n containing a rogue operator must never be the slower path." }, "reason": { "type": "string", "title": "reason", "description": "Recorded verbatim on the audit row." } }, "title": "SetRoleRequest", "additionalProperties": false }, "concierge.v1.SetRoleResponse": { "type": "object", "properties": { "role": { "type": "string", "title": "role", "description": "The role now in effect (echoes the applied role)." } }, "title": "SetRoleResponse", "additionalProperties": false }, "concierge.v1.SubmitAdmissionVoteRequest": { "type": "object", "properties": { "admission_id": { "type": "string", "title": "admission_id" }, "vote": { "title": "vote", "$ref": "#/components/schemas/concierge.v1.AdmissionVote" } }, "title": "SubmitAdmissionVoteRequest", "additionalProperties": false }, "concierge.v1.SubmitPeerVoteRequest": { "type": "object", "properties": { "removal_id": { "type": "string", "title": "removal_id" }, "vote": { "title": "vote", "$ref": "#/components/schemas/concierge.v1.RemovalVote" } }, "title": "SubmitPeerVoteRequest", "additionalProperties": false }, "concierge.v1.SubmitSelfDecisionRequest": { "type": "object", "properties": { "token": { "type": "string", "title": "token" }, "code": { "type": "string", "title": "code" }, "vote": { "title": "vote", "description": "REMOVE accepts the expulsion; KEEP refuses it.", "$ref": "#/components/schemas/concierge.v1.RemovalVote" }, "client_ip": { "type": "string", "title": "client_ip" }, "user_agent": { "type": "string", "title": "user_agent" } }, "title": "SubmitSelfDecisionRequest", "additionalProperties": false }, "concierge.v1.SubmitSelfDecisionResponse": { "type": "object", "properties": { "invitation": { "title": "invitation", "$ref": "#/components/schemas/concierge.v1.OwnerRemovalInvitation" }, "decided": { "type": "boolean", "title": "decided" } }, "title": "SubmitSelfDecisionResponse", "additionalProperties": false }, "concierge.v1.SubmitUserProposalVoteRequest": { "type": "object", "properties": { "proposal_id": { "type": "string", "title": "proposal_id" }, "vote": { "title": "vote", "$ref": "#/components/schemas/concierge.v1.ProposalVote" } }, "title": "SubmitUserProposalVoteRequest", "additionalProperties": false }, "concierge.v1.TokenResponse": { "type": "object", "properties": { "access_token": { "type": "string", "title": "access_token" }, "access_expires_at": { "type": [ "integer", "string" ], "title": "access_expires_at", "format": "int64" }, "refresh_token": { "type": "string", "title": "refresh_token" }, "refresh_expires_at": { "type": [ "integer", "string" ], "title": "refresh_expires_at", "format": "int64" }, "user": { "title": "user", "$ref": "#/components/schemas/concierge.v1.UserSummary" } }, "title": "TokenResponse", "additionalProperties": false, "description": "A first-party token pair plus a snapshot of the principal. All expiries are\n unix SECONDS (matching the JWT `exp` claim); the BFF parses them with\n proto-loader `longs: String`." }, "concierge.v1.UpdateProfileRequest": { "type": "object", "properties": { "legal_name": { "type": "string", "title": "legal_name" }, "preferred_name": { "type": "string", "title": "preferred_name" }, "phone": { "type": "string", "title": "phone" }, "date_of_birth": { "type": "string", "title": "date_of_birth" }, "nationality": { "type": "string", "title": "nationality" }, "tax_residence": { "type": "string", "title": "tax_residence" }, "residential_address": { "type": "string", "title": "residential_address" }, "language": { "type": "string", "title": "language" }, "base_currency": { "type": "string", "title": "base_currency" }, "timezone": { "type": "string", "title": "timezone" } }, "title": "UpdateProfileRequest", "additionalProperties": false, "description": "The caller's editable profile, full-replace. Same 10 fields as the editable part of\n UserProfile; an empty string clears the field." }, "concierge.v1.UserProfile": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email" }, "email_verified": { "type": "boolean", "title": "email_verified" }, "status": { "type": "string", "title": "status" }, "token_version": { "type": [ "integer", "string" ], "title": "token_version", "format": "int64" }, "legal_name": { "type": "string", "title": "legal_name", "description": "Editable profile fields (control plane; empty until the user sets them). email and\n status above stay read-only — email is the IdP's, status is admin-managed." }, "preferred_name": { "type": "string", "title": "preferred_name" }, "phone": { "type": "string", "title": "phone" }, "date_of_birth": { "type": "string", "title": "date_of_birth" }, "nationality": { "type": "string", "title": "nationality" }, "tax_residence": { "type": "string", "title": "tax_residence" }, "residential_address": { "type": "string", "title": "residential_address" }, "language": { "type": "string", "title": "language" }, "base_currency": { "type": "string", "title": "base_currency" }, "timezone": { "type": "string", "title": "timezone" }, "kyc_level": { "type": "integer", "title": "kyc_level", "description": "The user's KYC level (admin-managed; mirrored to the money plane)." }, "role": { "type": "string", "title": "role", "description": "The user's platform access role (snake_case: investor/operator/admin/owner).\n Admin-managed via SetRole; read-only here." }, "role_is_break_glass": { "type": "boolean", "title": "role_is_break_glass", "description": "True when `role` above came from the OWNER_SUBJECTS emergency allowlist rather than\n from `users.role`. See UserSummary.role_is_break_glass in auth.proto — same flag,\n same meaning: real authority, granted by the environment while the fund has no\n persisted owner, seating nobody. Render it as a warning, never as ownership." }, "suspended_by": { "type": "string", "title": "suspended_by", "description": "WHY the account is disabled — and therefore who may undo it. Empty on an active\n user, and also on one suspended before this field existed (those keep the old\n one-act, never-lapsing semantics they were actually suspended under).\n \"admin_hold\" — one operator's brake; lapses at hold_expires_at; ReinstateUser\n lifts it in one act.\n \"governance\" — the owners' ratified verdict; never lapses; ReinstateUser\n refuses and names OpenUserReinstatement." }, "hold_expires_at": { "type": [ "integer", "string" ], "title": "hold_expires_at", "format": "int64", "description": "Unix SECONDS an \"admin_hold\" lapses. 0 when nothing lapses." }, "permissions": { "type": "array", "items": { "type": "string" }, "title": "permissions", "description": "What the caller may do, concrete: no alias, no wildcard. Filled by GetMe only. To a\n relying party, its tenant's namespace and nothing else; to a first-party session, the\n seat's permissions plus every tenant's. A relying party gates on this alone." }, "username": { "type": "string", "title": "username", "description": "A handle beside the email, interchangeable with it wherever an account is named.\n Empty when the account has none." } }, "title": "UserProfile", "additionalProperties": false }, "concierge.v1.UserProposal": { "type": "object", "properties": { "id": { "type": "string", "title": "id" }, "kind": { "title": "kind", "$ref": "#/components/schemas/concierge.v1.UserProposalKind" }, "state": { "title": "state", "$ref": "#/components/schemas/concierge.v1.UserProposalState" }, "subject_user_id": { "type": "string", "title": "subject_user_id", "description": "Any user — NOT necessarily an owner. That is the difference from OwnerAdmission,\n and the reason none of its roster checks have an analogue here." }, "subject_email": { "type": "string", "title": "subject_email" }, "initiator_user_id": { "type": "string", "title": "initiator_user_id" }, "initiator_email": { "type": "string", "title": "initiator_email" }, "reason": { "type": "string", "title": "reason", "description": "Why, in the initiator's words. Required, and shown to every voter." }, "peers": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.UserProposalPeer" }, "title": "peers", "description": "Every owner except the initiator, with their answers. Never empty: a proposal with\n nobody to agree is refused at open rather than left open and unpassable." }, "owner_count": { "type": "integer", "title": "owner_count", "description": "Owners at open. The initiator is counted but does not vote." }, "threshold": { "type": "integer", "title": "threshold", "description": "How many of `peers` must vote FOR, frozen at open — so a surface shows the bar this\n proposal is actually measured against, not one re-derived from a roster that moved." }, "created_at": { "type": [ "integer", "string" ], "title": "created_at", "format": "int64" }, "expires_at": { "type": [ "integer", "string" ], "title": "expires_at", "format": "int64" }, "decided_at": { "type": [ "integer", "string" ], "title": "decided_at", "format": "int64" }, "void_reason": { "type": "string", "title": "void_reason" }, "version": { "type": [ "integer", "string" ], "title": "version", "format": "int64" } }, "title": "UserProposal", "additionalProperties": false, "description": "The owners' verdict over one PERSON's standing.\n\n It passes on a MAJORITY of the snapshotted voters, not the unanimity the OWNER\n consilia demand, and the difference is deliberate. Unanimity guards the owner roster\n because a minority able to add owners by majority grows itself into a majority.\n Neither thing decided here has that property: `admin` cannot vote in any consilium\n and cannot be granted `owner`, and a suspension is defensive and reversible by the\n same body. Against that, unanimity here would COST safety — a hold lapses in 24h, so\n ratifying one races a clock, and under unanimity one unreachable owner does not delay\n the verdict, they decide it by releasing a compromised account at the deadline.\n\n What is preserved is the property that matters: the initiator is excluded from the\n voter set and the threshold is at least one, so no single actor ever acts alone." }, "concierge.v1.UserProposalKind": { "type": "string", "title": "UserProposalKind", "enum": [ "USER_PROPOSAL_KIND_UNSPECIFIED", "USER_PROPOSAL_KIND_SUSPENSION", "USER_PROPOSAL_KIND_REINSTATEMENT", "USER_PROPOSAL_KIND_ADMIN_ADMISSION" ], "description": "What a UserProposal decides. Three kinds share one message because all three are the\n same question — \"do the owners agree to change this person's standing?\" — differing\n only in what the verdict writes." }, "concierge.v1.UserProposalList": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/concierge.v1.UserProposal" }, "title": "items" } }, "title": "UserProposalList", "additionalProperties": false }, "concierge.v1.UserProposalPeer": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id" }, "email": { "type": "string", "title": "email" }, "vote": { "title": "vote", "$ref": "#/components/schemas/concierge.v1.ProposalVote" }, "voted_at": { "type": [ "integer", "string" ], "title": "voted_at", "format": "int64" } }, "title": "UserProposalPeer", "additionalProperties": false }, "concierge.v1.UserProposalState": { "type": "string", "title": "UserProposalState", "enum": [ "USER_PROPOSAL_STATE_UNSPECIFIED", "USER_PROPOSAL_STATE_OPEN", "USER_PROPOSAL_STATE_EXECUTED", "USER_PROPOSAL_STATE_REJECTED", "USER_PROPOSAL_STATE_EXPIRED", "USER_PROPOSAL_STATE_CANCELLED", "USER_PROPOSAL_STATE_VOID" ], "description": "The six states, again as their own enum: proto enum VALUES share one namespace per\n package, so the identical states have to be spelled three times even though the\n domain models them with one type." }, "concierge.v1.UserSummary": { "type": "object", "properties": { "user_id": { "type": "string", "title": "user_id", "description": "The concierge canonical user id (a UUID) — this is the JWT `sub`, never Google's sub." }, "email": { "type": "string", "title": "email" }, "status": { "type": "string", "title": "status" }, "token_version": { "type": [ "integer", "string" ], "title": "token_version", "format": "int64" }, "role": { "type": "string", "title": "role", "description": "The user's platform access role (snake_case: investor/operator/admin/owner), so the\n BFF can gate the admin console at sign-in without a second round trip. Read-only." }, "role_is_break_glass": { "type": "boolean", "title": "role_is_break_glass", "description": "True when `role` above came from the OWNER_SUBJECTS emergency allowlist rather than\n from `users.role`. It is real authority, but it is the environment's and not the\n register's: it disappears the moment the fund has its first persisted owner, and it\n seats nobody. A client MUST render it as a warning, never as ownership." }, "email_verified": { "type": "boolean", "title": "email_verified" }, "username": { "type": "string", "title": "username", "description": "Empty when the account has no handle." } }, "title": "UserSummary", "additionalProperties": false, "description": "Minimal principal snapshot returned with a freshly issued token pair, so the BFF\n can populate a session without a second round trip." }, "concierge.v1.WatchGovernanceRequest": { "type": "object", "title": "WatchGovernanceRequest", "additionalProperties": false }, "connect-protocol-version": { "type": "number", "title": "Connect-Protocol-Version", "enum": [ 1 ], "description": "Define the version of the Connect protocol", "const": 1 }, "connect-timeout-header": { "type": "number", "title": "Connect-Timeout-Ms", "description": "Define the timeout, in ms" }, "connect.error": { "type": "object", "properties": { "code": { "type": "string", "examples": [ "not_found" ], "enum": [ "canceled", "unknown", "invalid_argument", "deadline_exceeded", "not_found", "already_exists", "permission_denied", "resource_exhausted", "failed_precondition", "aborted", "out_of_range", "unimplemented", "internal", "unavailable", "data_loss", "unauthenticated" ], "description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]." }, "message": { "type": "string", "description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client." }, "details": { "type": "array", "items": { "$ref": "#/components/schemas/connect.error_details.Any" }, "description": "A list of messages that carry the error details. There is no limit on the number of messages." } }, "title": "Connect Error", "additionalProperties": true, "description": "Error type returned by Connect: https://connectrpc.com/docs/go/errors/#http-representation" }, "connect.error_details.Any": { "type": "object", "properties": { "type": { "type": "string", "description": "A URL that acts as a globally unique identifier for the type of the serialized message. For example: `type.googleapis.com/google.rpc.ErrorInfo`. This is used to determine the schema of the data in the `value` field and is the discriminator for the `debug` field." }, "value": { "type": "string", "format": "binary", "description": "The Protobuf message, serialized as bytes and base64-encoded. The specific message type is identified by the `type` field." }, "debug": { "oneOf": [ { "type": "object", "title": "Any", "additionalProperties": true, "description": "Detailed error information." } ], "discriminator": { "propertyName": "type" }, "title": "Debug", "description": "Deserialized error detail payload. The 'type' field indicates the schema. This field is for easier debugging and should not be relied upon for application logic." } }, "additionalProperties": true, "description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message, with an additional debug field for ConnectRPC error details." } } }, "security": [], "tags": [ { "name": "banking.v1.AllocationsService", "description": "AllocationsService — the registry of investable products (the Allocation primitive).\n\n An allocation is the control-plane record that makes a service id investable. It is\n the ONLY way one comes into existence: `FundsService.Subscribe` refuses a service\n with no registered, open allocation, so a user can never mint a fund by typing an\n unknown slug. Money never flows through this service — amounts, units and NAV stay\n on FundsService/BalanceService; here live identity, presentation, lifecycle and\n access only.\n\n Lifecycle: `draft` (registered, not yet accepting money) → `open` (subscribe +\n redeem) → `closed` (redeem only, so a closed product never traps an investor).\n `closed` → `open` re-opens. Registration and every transition require\n `AllocationManage` (Admin/Owner) — the same trust seam as posting a valuation.\n\n Access is a second axis, orthogonal to the lifecycle. `state` says whether the\n product takes money at all; `access` says WHO may see it and who may put money in.\n Every allocation carries a default level — `hidden` | `view` | `invest` — and an\n operator may raise one investor above it with a per-user grant (`view` | `invest`).\n The level a caller effectively holds is the higher of the two. A registration lands\n on `view`: visible, but locked until an operator opens it or grants the investor.\n\n Reads are open to any authenticated user, filtered by that effective level:\n `ListAllocations` returns only `open` allocations the caller may at least view, and\n `GetAllocation` answers NOT_FOUND for one the caller may not — unless the caller\n holds `AllocationManage`, who sees everything in every state. `Subscribe` refuses\n (FAILED_PRECONDITION) unless the caller's effective level is `invest`; `Redeem` is\n never gated on access, so locking a product cannot trap an investor. See\n docs/ARCHITECTURE.md.\n\n The one place this service touches supply is `IssueUnits`: an operator minting units\n IN KIND — to an investor — with no cash behind them, for a product registered against\n an asset that already exists and already has owners. It lives here rather than on\n FundsService because it is a registry decision about who holds what, made by the same\n `AllocationManage` holder who sizes the product, not an investor dealing at NAV. The\n holder is always a PERSON: the company is not a holder (#245 — every unit of value is\n somebody's), and a reserved allocation (`fee`) comes to hold a product's fee class\n only through the fee accrual, never through this surface. `RetireUnits` is the mirror\n of `IssueUnits`: a holder's units burnt with no cash leg, supply shrinking by exactly\n that. It is Read-First on what the holder has AVAILABLE (units resting on the book or\n reserved by a redemption cannot be retired), and the burn shows in `ListUnitHolders`\n like any other supply change.\n\n Backing is the third axis. Units minted in kind have no cash in the fund's claim\n behind them, so `Redeem` — which pays cash out of that claim — is refused on a product\n whose `backing` is `in_kind` (FAILED_PRECONDITION); holders exit through the book. The\n first `IssueUnits` flips a product from `cash` to `in_kind` on its own; an operator\n flips it back with `SetAllocationBacking` once the fund does hold cash for the units." }, { "name": "banking.v1.AuthService", "description": "AuthService — the money plane's token issuance and authorization surface.\n\n This is the MONEY plane: it does NOT do third-party (Google) OAuth — identity and\n sign-in live wholly in the concierge plane. Users are mirrored here by the one-way\n cross-plane bridge (concierge `CREATED` → a local row keyed by `auth_subject`).\n This service only issues/rotates the hub's OWN first-party asymmetric JWTs\n (EdDSA/Ed25519, `aud=banking-core`) for those already-identified users, and\n publishes verification keys. Services do NOT call this per request to authorize:\n they verify access tokens locally against the cached JWKS via the shared\n `evbanking_auth` flow (no round trip, no per-service token storage). They DO call\n `Jwks` periodically to refresh that cache, since the hub speaks only gRPC (no HTTP\n `.well-known` endpoint).\n\n `IssueUserToken` is the concierge→banking token-exchange seam: after the cabinet\n BFF authenticates a user against concierge, it calls this server-to-server (with the\n shared bridge issuance token, NOT a user token) to mint the money-plane pair for that\n user. Banking trusts its OWN service credential, never concierge's issuer — so a\n leaked concierge token can't move money. See docs/ARCHITECTURE.md." }, { "name": "banking.v1.FundsService", "description": "FundsService — a user's investment in funds via the service currency (units/shares).\n\n Subscribing buys units at the current NAV; a holding's value is units × NAV, so\n profit comes from NAV rising, not from extra units. Redeeming is accept-and-queue:\n units are reserved immediately and the cash is priced + paid at settle (settle-time\n NAV). Every amount/unit/price is a decimal STRING (proto3 has no u128; a string is\n lossless and matches proto-loader's `longs: String`). Self-service RPCs act on the\n caller's own access-token `sub`. See docs/ARCHITECTURE.md." }, { "name": "banking.v1.BalanceService", "description": "BalanceService — the bank's treasury and the platform's own allocations (operator\n surface).\n\n Reads authoritative balances from the TigerBeetle ledger; metadata and events from\n Postgres. Every amount is a decimal USDT STRING (proto3 has no u128; a string is\n lossless and matches proto-loader's `longs: String`). All RPCs are admin-gated\n (allowlist) at the boundary. See docs/ARCHITECTURE.md.\n\n The platform holds no money of its own (#245): what it earns is the `fee` allocation's\n and what it was seeded with is the `fund` allocation's, and both are held by PEOPLE\n through units — so the treasury lists every allocation with its holders, and nothing\n here pays \"the fund\" out. Cash leaves a reserved allocation by a holder's redemption\n or by a payment the owners' consilium approved (`PaymentsService`)." }, { "name": "banking.v1.BookService", "description": "BookService — the secondary market in an allocation's units: holders trading with\n each other on a central limit order book, price-time priority, in the shape of a spot\n exchange.\n\n It sits BESIDE the fund's own dealing, never instead of it. FundsService.Subscribe and\n Redeem are dealings with the fund at NAV; the book is holders dealing with holders at\n whatever they agree. NAV stays the accounting price — a position, its P\u0026L and the fee\n high-water mark are measured at it — and the book's last trade is a second, market\n quote shown next to it (`BookSnapshot.nav` carries the mark so a ticker can show both).\n\n Money never leaves the ledger's custody: a resting order is an ESCROW inside it. A sell\n moves its units from the holder's `shares` account into a per-user book escrow, a buy\n moves its worst-case cash — size × price plus the taker fee it might owe — from the\n user's claim into a per-user cash escrow. A fill is ONE linked TigerBeetle batch (units\n to the buyer, cash to the seller, the taker's fee to the fund): delivery versus payment\n or nothing. Whatever the escrow still holds when an order ends is handed back, so a buy\n that filled below its limit, an IOC remainder and a cancel all release the difference.\n The hub records the order and its fills first (Postgres, under one lock per book) and\n the ledger moves follow through the same outbox relay as every other money event, so\n the balances a client reads lag a placement by the relay's latency, exactly as after a\n Subscribe.\n\n Who may trade: any signed-in investor whose effective access on the allocation is\n `invest` — the same gate as Subscribe, EXCEPT that the allocation's `state` does not\n apply (a `closed` product's holders may still trade among themselves; only `book_open`\n on the policy, `hidden` and `view` refuse). Placing is also refused while the money\n plane is in read-only mode or the caller is frozen; cancelling never is, so a frozen\n user can still unwind. The policy (fees, tick, lot, slippage, whether the book is open\n at all) is set by an `AllocationManage` holder; a product with no policy row has a\n closed book.\n\n Every amount, size and price is a decimal STRING (proto3 has no u128; a string is\n lossless and matches proto-loader's `longs: String`). Enumerations are strings too,\n pinned in `evbanking_contracts::book`. See piggybank/core/PATTERNS.md." }, { "name": "banking.v1.ConsiliumService", "description": "ConsiliumService — multi-owner authorization over the platform's own money and its\n price: a payment out of a service claim (opened inside `PaymentsService.OpenPayment`),\n a NAV mark past the move guard, a change of fee terms beyond the house envelope, a new\n holder of a reserved allocation (`OpenHolderGrant`), and a seed of the platform's\n capital (`BalanceService.SeedCapital`). One owner opens a request; strictly more than\n half of ALL owners must each confirm it from their mailbox before anything happens.\n\n The kinds, as the `Consilium` message tells them apart (exactly one terms sibling is\n set): `payment`, `valuation_override`, `fee_policy`, `holder_grant`, `seed_capital`.\n (`revenue_payout` was retired by #245 and left the contract with C-9; field 3 of\n `Consilium` and `ConsiliumInvitation` is reserved for it.)\n\n WHY THE MONEY PLANE OWNS THIS. docs/ARCHITECTURE.md rejects letting a\n concierge-signed artifact authorize money movement, and a consilium verdict is\n exactly such an artifact. So the tally is computed, stored and verified here, against\n the owner roster this plane already mirrors (`0016_user_role.sql`). Concierge is used\n only to DELIVER the mail, over a typed payload it renders itself.\n\n QUORUM. `threshold = floor(N / 2) + 1` where N is the owner count at open. The\n initiator is in the denominator but gets NO vote and is never minted a token — so\n opening a request can never lower the bar the initiator has to clear. N \u003c 3 makes\n the threshold unreachable and is refused at open rather than parked forever.\n\n IMMUTABILITY. There is no edit RPC. `payload_hash` binds every approval to the exact\n terms shown in the mail; changing anything means cancel and reopen, and votes are not\n carried over. See docs/CONSILIUM.md for the full policy and threat model." }, { "name": "banking.v1.ConsiliumApprovalService", "description": "ConsiliumApprovalService — the surface an emailed owner reaches. Mounted OUTSIDE the\n user-auth layer, exactly as AuthService is: the emailed token IS the credential, and\n the owner clicking it may not be signed in.\n\n The GET is strictly read-only because mail scanners (Gmail, Outlook SafeLinks,\n corporate gateways) issue automatic requests for every URL in a message. The vote is\n a separate call carrying the secret code from the same mail — that is what turns a\n scanned link into a deliberate human act." }, { "name": "banking.v1.FeesService", "description": "FeesService — a fund's management and performance fee (\"2 and 20\").\n\n Two charges, answering different questions. **Management** (2% p.a. by default) is\n rent on parked capital: it accrues continuously with elapsed time and is charged\n whether the fund made money or not. **Performance** (20% by default) is a share of\n profit above the investor's OWN high-water mark, crystallized at the end of a\n period. A product with no policy charges nothing — the fee is opt-in per product.\n\n The mark is PER INVESTOR, not per fund. That is what stops one investor from paying\n for another's timing: somebody who subscribed at the top pays only on gains above\n the price they actually paid, and somebody who subscribed after a drawdown does not\n ride the recovery fee-free. (A fund-level mark, which a tokenized vault is forced\n into, mutualizes both.)\n\n A fee is collected by clawing back UNITS — the holder's fund units move to the\n product's fee class, held by the reserved `fee` allocation (#245: what the platform\n earns is that allocation's, and its holders are people) — never by moving cash. So: no chain\n fee is ever paid to collect a fee, an investor's cash balance is untouched and\n cannot be driven negative, and because total units outstanding do not change, NAV\n per unit does not move and no other investor pays for the charge. What cannot be\n collected (units locked by a queued redemption, or a residue below one base unit)\n is carried as debt and taken next time; it is never written off.\n\n SettleFeeShares is the one operation that crosses into cash, converting a whole\n fund's accumulated fee units in one go rather than once per investor — at the NAV of\n the day, out of the product's claim into the `fee` allocation's. Amounts and prices\n are exact decimal strings. See piggybank/core/PATTERNS.md and docs/FEES.md." }, { "name": "banking.v1.HealthService", "description": "Health surface for the hub's gRPC service plane.\n\n Check — liveness: is the process up? Trivial, unauthenticated; backs the\n `cabinet` BFF smoke path (browser -\u003e BFF -\u003e gRPC) and service checks.\n Readiness — can this instance actually move money? Pings Postgres + TigerBeetle\n and inspects the outbox (parked rows / dispatch backlog). An\n orchestrator/LB drains an instance that is up but not ready instead of\n routing money-moving traffic to it." }, { "name": "banking.v1.OperationsService", "description": "OperationsService — the caller's activity timeline: every money event that touched\n their account, in one time-ordered stream.\n\n A pure CQRS **read model**. The four things a user does — deposit, withdraw,\n subscribe, redeem — are separate aggregates written through their own services\n (WalletService, FundsService); each already exposes its own list. What none of them\n can answer is \"what happened, in order\", because interleaving four lists client-side\n needs a timestamp every one of them must agree on. This service is that join, done\n once in the hub over the Postgres projections.\n\n Read-only: it moves no money and owns no state. Every RPC acts on the caller's own\n access-token `sub`. Amounts are decimal USDT STRINGS (proto3 has no u128; a string is\n lossless and matches proto-loader's `longs: String`).\n See docs/ARCHITECTURE.md and piggybank/core/PATTERNS.md." }, { "name": "banking.v1.PaymentsService", "description": "PaymentsService — the ORDER that moves money between two named ends of the platform.\n\n Three tiers on one order, DERIVED from the destination and never supplied: an external\n wallet address (L1, settled by the withdrawal saga), a product's pooled claim\n `service:\u003cid\u003e` (L2, one posted transfer), any other internal claim (L3, one posted\n transfer). See domain/src/payments.rs for the aggregate and docs/CONSILIUM.md § Payments\n for the policy.\n\n AUTHORIZATION IS A FUNCTION OF THE SOURCE. A payment out of an allocation's pooled\n claim (`service:\u003cid\u003e` — a product's, or the platform's own `fee` / `fund`) needs the\n owners' consilium at every tier — the consilium is opened INSIDE OpenPayment, there is\n no separate RPC. A payment out of an investor's own claim (`user:\u003cid\u003e`) needs THAT\n investor's emailed consent at every tier. There is deliberately no cell in which one\n admin moves pooled money alone. The platform has no money of its own outside an\n allocation (#245): the singleton `piggybank` / `revenue` sources are retired, and a\n request naming them is refused.\n\n IMMUTABILITY. There is no edit RPC. `payload_hash` binds the approval to the exact terms\n shown in the mail; changing anything means cancel and reopen." }, { "name": "banking.v1.PaymentConsentService", "description": "PaymentConsentService — the surface an emailed investor reaches. Mounted OUTSIDE the\n user-auth layer, exactly as ConsiliumApprovalService is: the emailed token IS the\n credential, and the investor clicking it may not be signed in.\n\n The GET is strictly read-only because mail scanners issue automatic requests for every\n URL in a message. The consent is a separate call carrying the secret code from the same\n mail — that is what turns a scanned link into a deliberate human act." }, { "name": "banking.v1.UsersService", "description": "UsersService — investor accounts and their investments.\n\n Identity metadata is the Postgres control plane; money is read live from the\n authoritative TigerBeetle ledger and is NEVER re-bookkept in Postgres. Every\n RPC is authorized from the verified access-token Claims injected by core's\n inbound auth layer; self-service RPCs act on the caller's own `sub`, admin RPCs\n are gated by the hub's admin allowlist (config). See docs/ARCHITECTURE.md." }, { "name": "banking.v1.WalletService", "description": "WalletService — a user's own crypto wallet: one unified USDT balance, deposit\n addresses, and withdrawals. Networks (BEP20/Polygon/TRC20/TON) are a transaction attribute\n (where you deposit / where a withdrawal ships), never a balance dimension — the user\n holds a single fungible USDT balance, segmented by lifecycle.\n\n Every RPC acts on the caller's own access-token `sub`. Balances are read live from the\n authoritative TigerBeetle ledger (Read-First); amounts are decimal USDT STRINGS\n (proto3 has no u128; a string is lossless and matches proto-loader's `longs: String`).\n A withdrawal is a queued saga (reserve → dispatch → settle/void): it is accepted even\n when the chosen rail is short on liquidity and queued until the treasury tops it up.\n The operator-driven dispatch/settle/fail RPCs live on BalanceService; the custody\n broadcast and deposit-address derivation sit behind ports (a stub in this scaffold).\n See docs/ARCHITECTURE.md and piggybank/core/PATTERNS.md." }, { "name": "concierge.v1.UserDirectory", "description": "UserDirectory — the authoritative user/identity control plane.\n\n Owns investor accounts and their profile metadata. This is the identity plane:\n money lives in the separate banking plane and is NEVER mirrored here. Every RPC\n is authorized from the verified access-token Claims injected by the inbound auth\n layer; self-service RPCs act on the caller's own `sub`, admin RPCs are gated by\n the admin allowlist (config)." }, { "name": "concierge.v1.AuthService", "description": "AuthService — the concierge plane's token issuance and authorization surface.\n\n Issues first-party asymmetric JWTs (EdDSA/Ed25519), rotates refresh tokens, and\n publishes verification keys. Services do NOT call this per request to authorize:\n they verify access tokens locally against the cached JWKS via the shared\n `evconcierge_auth` flow (no round trip, no per-service token storage). They DO call\n `Jwks` periodically to refresh that cache, since concierge speaks only gRPC (no HTTP\n `.well-known` endpoint).\n\n Sign-in itself (Google, GitHub, emailed code, password) is the plane's own HTTP\n surface (`/auth/*`, reached as `evinvest.ltd/api/auth/*`), which opens the session\n in process; no RPC signs anybody in." }, { "name": "concierge.v1.GovernanceService", "description": "GovernanceService — the fund's OWNERSHIP plane: who holds `Role::Owner`, and the\n consilium that must agree before a seat is taken away.\n\n WHY OWNERSHIP LIVES HERE. A seat is `users.role`, a concierge-owned fact, and the\n bridge to the money plane is one-way. Only this plane may mutate it, so only this\n plane can authorize the mutation. The money plane runs its own, separate consilium\n over its own mirrored roster — neither plane trusts the other's verdict.\n\n THE RULE. A removal passes when EITHER\n (a) the target accepts it from their own mailbox, OR\n (b) every owner except the target and the initiator votes to remove.\n\n Path (b) is unanimity over `owners \\ {target, initiator}`. With exactly two owners\n that set is EMPTY and unanimity over it is vacuously true — which would let either\n owner expel the other unilaterally. Path (b) therefore requires at least ONE eligible\n peer voter; with two owners only path (a) exists.\n\n FLOOR. A removal may not leave fewer than TWO owners. Two suspends payouts — the\n money plane's `floor(N/2)+1` threshold is unreachable below three — but that is\n recoverable, because two owners can still admit a third. A floor of three was the\n earlier draft and it was wrong: at exactly three owners it made a bad actor\n unremovable forever, and a permanent deadlock is worse than a recoverable pause.\n\n ADMISSION IS GOVERNED TOO, and it is the reason the rest of this holds. Granting a\n seat is its own consilium: unanimity of `owners \\ {initiator}`, with at least one such\n peer. Without it a bad actor mints sock puppets BEFORE opening an invoice and then\n reaches quorum legitimately — 2 honest owners plus 4 puppets is N=7, threshold 4,\n voters 6 — and snapshotting the roster cannot help, because the stuffing already\n happened. Unanimity rather than a majority, because a minority must never be able to\n grow itself into a majority.\n\n See banking's docs/CONSILIUM.md for the whole policy." }, { "name": "concierge.v1.OwnerRemovalApprovalService", "description": "OwnerRemovalApprovalService — the surface the TARGET of a removal reaches from their\n mailbox. Mounted outside the user-auth layer, like AuthService: the emailed token is\n the credential, and the person clicking may not be signed in.\n\n The read is side-effect free because mail scanners issue automatic requests for every\n URL in a message; accepting requires the secret code from the same mail." }, { "name": "concierge.v1.MailRelayService", "description": "MailRelayService — the one seam over which the MONEY plane asks this plane to send a\n governance mail, because this plane owns the only mailer (lettre + the delivery queue\n + backoff + the daily budget) and standing up a second one would duplicate all of it.\n\n Authenticated by the shared banking↔concierge service secret, compared in constant\n time, and mounted outside the user-auth layer exactly as the lifecycle bridge is.\n\n The payload is TYPED, never rendered HTML: this plane renders it. A compromised money\n plane must not be able to put arbitrary markup into an owner's mailbox.\n\n WHO MAY RECEIVE ONE is decided per KIND, and the default is the strict one. The\n consilium kinds — the three payout kinds and PAYMENT_APPROVAL — speak to the\n consilium, so they go to a seated owner and to nobody else — that rule is what stops a\n compromised money plane aiming a concierge-branded security mail at any address on\n the platform. PAYMENT_CONSENT cannot use it: consenting to a\n transfer of your own money has nothing to do with holding a seat. It gets its own rule,\n narrower in the dimension that matters — the recipient must BE the payment's subject,\n named in the typed payload — so the surface widens by exactly one person per message\n rather than to everyone. The fee policy pair follows the same split: FEE_POLICY_APPROVAL\n is a consilium kind (a seated owner, verified address), FEE_POLICY_NOTICE is addressed by\n identity to the one investor it is about.\n\n PAYMENT_OUTCOME — a payment that died while waiting for its subject's consent (the\n consent link burned on wrong codes, or was invalidated when the subject's sessions were\n revoked or their address changed) — speaks to two audiences at once, so it has the one\n two-armed rule: the recipient must BE the payment's subject, or hold a staff role\n (admin or owner) — the person who opened the order is usually an admin and holds no\n seat. It carries no link and no code: there is nothing left to decide.\n\n This path deliberately bypasses notification preferences. `NotificationService.Emit`\n is opt-out on both channels, and a security mail that a subscriber can silently\n switch off is not a security mail." } ] }