Skip to main content
Subaccounts let a Direct account partition its balance and positions into independent buckets under one set of API credentials. Every account has a primary subaccount (number 0) and may use numbered subaccounts 1–63.
Subaccounts are currently an API-only feature — they are not yet supported in the Kalshi web or mobile app. Numbered-subaccount balances and positions are managed through the trade API.

Requirements

Creating a numbered subaccount with Create Subaccount requires the Advanced API tier or above. On the Basic tier the request returns 403 with code subaccount_creation_requires_advanced_api_usage_level. Intra Account Transfer returns the same error when a Basic-tier account names a numbered subaccount. The demo environment does not enforce the tier requirement, so a client that works in demo can still receive this 403 in production. Creating a subaccount needs an API key with the write scope, and transferring between subaccounts needs write::transfer. See Scopes.

Numbering

Transfers

You can move cash between your own subaccounts with POST /portfolio/subaccounts/transfer (amounts in cents). Transfers net to zero at the account level — nothing leaves your account. Transfers are idempotent on a client-supplied client_transfer_id: retrying with the same value returns 409 instead of applying the transfer twice.

Listing transfers

GET /portfolio/subaccounts/transfers returns your subaccount transfers, paginated.

Restricted API keys

When generating an API key you can restrict it to a single subaccount. A restricted key can read and trade on that subaccount: order placement and management, portfolio reads (balance, positions, fills, settlements), order groups, and the full REST RFQ lifecycle — creating combo markets in multivariate event collections, creating and cancelling RFQs, posting, confirming, and cancelling quotes, and accepting quotes. Requests that omit subaccount act on the key’s locked subaccount, and naming any other subaccount is rejected. GET /portfolio/subaccounts/balances also accepts restricted keys. It returns only the key’s locked subaccount, with separate balances per exchange index. To move funds between exchange indices, call POST /portfolio/intra_exchange_instance_transfer with source_subaccount and destination_subaccount both set to the key’s subaccount. Transfers to or from margin are not allowed. On perps, a restricted key can place, amend, decrease, and cancel orders (including cancel-all), manage order groups, and manage cross-margin exit triggers on its locked subaccount. It can also list that subaccount’s orders (GET /margin/orders; naming any other subaccount is rejected), read them individually (GET /margin/orders/{order_id} returns 404 for orders in any other subaccount), and read that subaccount’s positions, fills, and funding payments (GET /margin/positions, GET /margin/fills, and GET /margin/funding_history, on the same terms as the order list). GET /margin/balance returns only the locked subaccount’s balance and omits the account-wide settled_funds total. Other authenticated perps endpoints, including risk (GET /margin/risk), are not yet available to restricted keys. Self-trade prevention applies across all subaccounts of an account. When an order from a restricted key would trade against an order resting in another subaccount, its self_trade_prevention_type decides the outcome: taker_at_cross cancels the restricted key’s order, and maker cancels the resting order in the other subaccount. A restricted key cannot transfer funds between subaccounts, manage subaccounts or API keys, or act on RFQs and quotes belonging to a different subaccount of the same account. Subaccount-scoped requests match rows created through the API with an explicit subaccount identity; RFQs created in the web app are not addressable per subaccount. Endpoints outside its allowed set return 403 this API key is restricted to a single sub-account and cannot access this endpoint. On FIX, restricted keys support order entry and the maker quote lifecycle only — RFQ creation (35=R) and quote acceptance (35=UA) are not available to restricted FIX sessions.