Lifecycle
Parent margin account creation is handled internally. UsetransferCollateralToParentMarginAccount for first-time margin funding; it does not take a tradingPairId and does not open a risk bucket. Orders and risk simulation can use the accountless methods below without storing a marginAccountId.
(params?: ListMarginAccountsParams) => Promise<ListMarginAccountsResponse>
Paginated list of the user’s margin accounts. The result includes the parent account row plus a separate row per risk bucket (risk bucket rows carry
riskBucketId, marginMode, and tradingPairId).Parameters:params?:ListMarginAccountsParamspage?: number — defaults to 1pageSize?: number — defaults to 20, max 100state?: string — filter byaccountStatetradingPairId?: string — filter to bucket rows scoped to a specific trading pair
ListMarginAccountsResponse:accounts:MarginAccountSummary[]total: numberpage: numberpageSize: number
(params?: GetMarginAccountSummaryParams) => Promise<MarginAccountSummary>
Live state of the authenticated wallet’s parent margin account. Monaco resolves the parent account from the wallet and application scope; no
marginAccountId lookup is required. Passing tradingPairId returns the summary for that pair’s risk bucket under the parent — the risk bucket fields (riskBucketId, marginMode, tradingPairId) are populated on risk bucket summaries and left unset on the parent.Parameters:params?:GetMarginAccountSummaryParamstradingPairId?: string — return the bucket summary scoped to this trading pair
MarginAccountSummary:marginAccountId: stringlabel?: stringriskBucketId?: string — set on risk bucket summaries; unset on the parentmarginMode?:"ISOLATED" | "CROSS"— set on risk bucket summaries; unset on the parenttradingPairId?: string — trading pair this risk bucket is scoped to, if setselectedTradingPairIds?: string[] — on the cross risk-bucket row only: the bucket’s recorded scope. A pair joins when a cross order on it succeeds. After its positions close, removal is lazy: it remains listed until a later successful cross order on a different pair reconciles the bucket. Pairs declared before scope became derived follow the same delayed pruning after they trade and close. Omitted on the parent row and isolated rows; it may also be omitted when a cross bucket has no recorded scopestrategyKey?: string — strategy tag, if setaccountState: string —"NORMAL"|"PENDING_LIQUIDATION"|"BAD_DEBT"equity: stringinitialMarginRequired: stringmaintenanceMarginRequired: stringfreeCollateral: string — trading-margin headroom for existing cross exposurewithdrawableCollateral: string — the largest amount the withdrawal gate will accept (capped by unearmarked principal as well as margin requirements, funding, and PnL; an unrealized gain does not raise it). Size transfers — and new isolated/first-use positions, which allocate principal through the same gate — from this field, notfreeCollateraltotalPositionNotional: stringunrealizedPnl: stringrealizedPnl: stringupdatedAt: string — ISO 8601availableOrderCollateral?: string — the collateral still available to open new orders in this risk bucket: the largest increase in the bucket’s worst-case order reserve the risk engine’s admission gate accepts, automatic top-up from the parent’s unallocated capacity included. UnlikewithdrawableCollateralit credits an unrealized gain in full, and it already contains the bucket’s live free collateral — don’t addfreeCollateralorunrealizedPnlon top (it can legitimately differ from this row’sfreeCollateral, a persisted reconstruction that can’t see resting-order reserves). Not additive across rows: every bucket’s figure includes the same parent headroom. A requirement budget, not an order size — a reducing, reduce-only, or opposite-side order sheltered by a larger resting ladder needs less or none of it (and can be admitted when this is zero). Collateral, not notional (divide by the market’s initial margin rate). Present only on risk-bucket rows served from a live risk engine snapshot — absent on parent rows and fallback reads, so handleundefined; the per-order authority remainssimulateRiskBucketOrderRisk
(marginAccountId: string, params?: GetMarginAccountSummaryParams) => Promise<MarginAccountSummary>
Legacy compatibility method for callers that already store a
marginAccountId. Prefer getParentMarginAccountSummary for new integrations.Funding
(marginAccountId: string, request: TransferCollateralRequest) => Promise<TransferCollateralResponse>
deprecated
Deprecated. This endpoint overloads two unrelated operations: with
tradingPairId it allocates into that pair’s isolated risk bucket (crediting the sole open position’s stored margin), without it it performs a wallet-debiting deposit to the parent. Use transferCollateralToRiskBucket for bucket funding — which now applies the same position-margin credit — and transferCollateralToParentMarginAccount for wallet-to-margin deposits. Kept for backward compatibility; no removal date scheduled.When tradingPairId is omitted the transfer is scoped to the parent account, even if an active cross-risk bucket exists. Previously omitting tradingPairId could route the transfer into an active cross-risk bucket — this is now fixed.Parameters:marginAccountId: stringrequest:TransferCollateralRequestasset: string — e.g."USDC"amount: string — decimal string in collateral unitstradingPairId?: string — target a specific bucket under the parent; omit to target the parentstrategyKey?: string — strategy tag for the bucket
TransferCollateralResponse:movementId: stringmarginAccountId: stringstrategyKey?: string — the bucket’s strategy tag, if setasset: stringamount: stringstatus: stringnewEquity: string — equity after the transfernewTotalCollateralValue: string — total collateral value in the account after the transfernewWithdrawableCollateral: string — amount available to withdraw after the transfer
newTotalCollateralValue and newWithdrawableCollateral to update the UI immediately without a separate read.(marginAccountId: string, request: TransferCollateralRequest) => Promise<TransferCollateralResponse>
Release collateral from a risk bucket, or move it from a known margin account back to the wallet.Which of those happens depends on how the bucket is named (0XM-2414):
tradingPairId— releases that pair’s isolated bucket. The collateral returns to the parent margin account, where it can be redeployed; it does not reach the wallet.marginMode: "CROSS"— releases the account’s cross bucket, which has no trading pair and cannot be named any other way. Also returns to the parent. The two are mutually exclusive.- neither — a parent-scoped transfer to the wallet. Prefer
transferCollateralFromParentMarginAccountfor new integrations.
withdrawableCollateral. Trying to withdraw more will fail with a 400.Parameters:marginAccountId: stringrequest:TransferCollateralRequestasset: string — e.g."USDC"amount: string — decimal string in collateral unitstradingPairId?: string — release that pair’s isolated risk bucket to the parent; omit to target the parentmarginMode?:"ISOLATED" | "CROSS"— pass"CROSS"to select the account’s cross risk bucket, which has no trading pair and cannot be named bytradingPairId; the released collateral returns to the parent margin account. Mutually exclusive withtradingPairId— passing both is rejected client-sidestrategyKey?: string — strategy tag for the bucket
transferCollateralToMarginAccount, including newTotalCollateralValue and newWithdrawableCollateral.(request: TransferCollateralToParentMarginAccountRequest) => Promise<TransferCollateralResponse>
Move collateral from the user’s wallet into the parent margin account without specifying a
marginAccountId. This endpoint does not accept tradingPairId and does not open a risk bucket.Parameters:request:TransferCollateralToParentMarginAccountRequestasset: string — e.g."USDC"amount: string — decimal string
TransferCollateralResponse shape as transferCollateralToMarginAccount.Example:(request: TransferCollateralToRiskBucketRequest) => Promise<TransferCollateralResponse>
Move collateral into a specific risk bucket without specifying a
marginAccountId. Monaco resolves the parent account and ensures the risk bucket exists automatically.What the money becomes when the isolated bucket holds an open position is stated by applyToPositionMargin — the two intents want opposite fates for the same dollars, and either way the liquidation cushion improves identically:- Omitted or
true(the default is the human “Adjust Margin” gesture): the amount is committed to the position’s stored margin. Effective leverage drops and stays down, initial margin required rises by the amount, and free collateral is unchanged — new orders cannot spend it. false: a plain allocation. Free collateral rises and the next order can spend it. Programmatic funding loops that top a bucket up to a free-collateral target must passfalse— under the default, each top-up converts into requirement and the loop never converges.
TransferCollateralToCrossRiskBucketRequest types it never and the request validator rejects it even as false; omit it entirely on a cross transfer. (The raw REST and gRPC bodies are laxer, rejecting only an explicit true.) The response’s positionMarginCredited reports what actually happened: true — the credit landed; false — it degraded to a plain allocation because the persisted position row was stale (close/reopen race; re-issue the Adjust Margin once the new row lands); absent — no credit was in play.Parameters:request:TransferCollateralToRiskBucketRequest— a union onmarginMode:- Isolated (
marginModeomitted or"ISOLATED"):asset: string — e.g."USDC"amount: string — decimal stringtradingPairId: string — UUID of the trading pairstrategyKey?: string — omit to target the default risk bucket for the pairapplyToPositionMargin?: boolean — see above; omitted meanstrue(commit to the open position’s stored margin),falsekeeps the amount as spendable free collateral
- Cross (
marginMode: "CROSS"):asset: stringamount: string- nothing else. A cross transfer names no pairs: the cross bucket’s scope is derived from trading — a pair joins the bucket when a cross order on it succeeds — so funding has nothing to declare. After that pair’s positions close, removal is lazy: it remains listed until a later successful cross order on a different pair reconciles the bucket. Read the current scope from the cross bucket’s row in
listMarginAccounts()(selectedTradingPairIds) or from this call’s response; the parent summary row carries no scope. Pairs declared before scope became derived follow the same delayed pruning after they trade and close. Because scope no longer needs declaring,simulateParentMarginOrderRiskand the pair-filtered summaries resolve a never-traded pair to the account’s cross bucket instead of refusing it.
- Isolated (
TransferCollateralResponse shape as transferCollateralToMarginAccount.Example:(request: TransferCollateralFromParentMarginAccountRequest) => Promise<TransferCollateralResponse>
Move collateral from the parent margin account back to the user’s wallet without specifying a
marginAccountId.Parameters:request:TransferCollateralFromParentMarginAccountRequestasset: string — e.g."USDC"amount: string — decimal string
TransferCollateralResponse shape as transferCollateralFromMarginAccount.(params?: GetAvailableCollateralParams) => Promise<GetAvailableCollateralResponse>
Check what’s actually movable from the user’s wallet into a margin account, and what can come back out. The two directions are separate fields:
marginTransferable is wallet-to-margin capacity, marginAvailableCollateral is the largest amount that can currently leave the parent margin account.Parameters:params?:GetAvailableCollateralParamsasset?: string — defaults to USDC
GetAvailableCollateralResponse:asset: stringwalletAvailable: string — unlocked spot balancewalletLocked: string — locked by spot orders / pending withdrawalsmarginTransferable?: string — eligible to transfer inmarginAvailableCollateral?: string — the largest amount that can currently leave the parent margin account, matchingMarginAccountSummary.withdrawableCollateral. Not trading headroom for existing cross exposure: it is capped by unearmarked principal as well as by margin requirements, and an unrealized gain does not raise it. The summary’sfreeCollateralremains the trading-margin headroom for existing cross exposure — but a new isolated or first-use position allocates principal through the same gate this field measures, so size those from this field (orwithdrawableCollateral), not fromfreeCollateral.
Activity
(params?: GetMarginAccountMovementsParams) => Promise<GetMarginAccountMovementsResponse>
Collateral movements (transfers in / out) recorded against the authenticated wallet’s parent margin account. PnL, funding, and fees are tracked through other endpoints (
getPaginatedUserMovements and GET /api/v1/accounts/funding-payments).Parameters:params?:GetMarginAccountMovementsParamsmovementType?:"TRANSFER_IN"|"TRANSFER_OUT"page?: number — at most 10,000; a larger page is rejectedpageSize?: number
GetMarginAccountMovementsResponse:movements:MarginAccountMovement[]— each withmovementId,movementType,asset,amount,createdAttotal: number — bounded by the pagination reach: exact up topageSize× 10,000 rows and saturating there, so a caller with more movements than page-number mode can page through reads the cap, not its lifetime totalpage: numberpageSize: number
(marginAccountId: string, params?: GetMarginAccountMovementsParams) => Promise<GetMarginAccountMovementsResponse>
Legacy compatibility method for callers that already store a
marginAccountId. Prefer getParentMarginAccountMovements for new integrations.Pre-trade simulation
(request: SimulateOrderRiskRequest) => Promise<SimulateOrderRiskResponse>
Preflight a perp order against the authenticated wallet’s parent margin account without placing it. Monaco resolves the parent account from the wallet and application scope.Parameters:Common pattern: run on every order-form change with debouncing, and disable the place-order button when
request:SimulateOrderRiskRequesttradingPairId: stringside:"BUY" | "SELL"positionSide?:"LONG" | "SHORT" | "NONE"— deprecated compatibility field; if supplied, it must agree withsideorderType:"LIMIT" | "MARKET"price?: string — required for LIMITquantity: stringleverage: string — decimal string, e.g."10"reduceOnly?: booleanslippageToleranceBps?: number — MARKET only,0–1000, the rule the server applies to a placed MARKET order (a LIMIT preview carrying it is rejected with the placement’s message). Tightens the previewed walk to the band the real order will run under, soexpectedMatchResultandestimatedFeeprice under it. Omit for the placement default; it never widens the band. To carry a previewed value into placement, note thatplaceMarketOrderand the batch helpers takeslippageToleranceas a ratio (0.05= 500 bps): passslippageToleranceBps / 10_000— aslippageToleranceBpskey on those calls is not forwarded. On a first-use isolated preview the value is also forwarded to the bucket’s auto-funding for parity with placement; that path floors it at 1,000 bps, so today it does not change the funded figure.
SimulateOrderRiskResponse:accepted: booleanrejectReason?: string — human-readable whenaccepted: falsemarginAccountId: string — the resolved margin account the simulation ran againststrategyKey?: string — the bucket’s strategy tag, if setmarginMode?:"ISOLATED" | "CROSS"— the resolved risk-bucket mode, if setriskBucketId?: string — the risk bucket the simulation resolved against, if anyselectedTradingPairIds?: string[] — cross previews only, never a caller’s list: fromsimulateRiskBucketOrderRiskthe derived scope the preview ran against (the cross bucket’s recorded pairs — including any still listed after their positions closed — every pair with an open position in it, and the previewed pair; the previewed pair alone before the first cross order); fromsimulateOrderRiskandsimulateParentMarginOrderRisk, the recorded pairs plus the previewed pairequityAfter: stringinitialMarginRequiredAfter: stringmaintenanceMarginRequiredAfter: stringfreeCollateralAfter: stringestimatedFee?: string — what the order pays in fees once its whole size has executed: the taker rate (plus the application’s additional taker fee) on the quantity that would cross immediately, the maker rate on the quantity that would rest. One figure whether the order fills, rests, or splits between the two. Signed — negative is a net rebate, which is what a resting order earns on a pair whose maker fee is negative. Populated even whenaccepted: false, and for reduce-only orders. Assumes the resting part eventually fills. Absent — never0— when the engine could not price the order; treat absence as unknown, not free.estimatedLiquidationPrice?: string — isolated simulated position/risk-bucket threshold; cross conditional per-target-position estimate, not a whole-account scalar. Absent or blank means unavailable, never0.expectedMatchResult?: MatchResult — the simulated match the engine ran to admit the order: the sameMatchResultshape a placement’smatchResultcarries, from the same walk over the live book at the moment of the preview, underslippageToleranceBpsmerged tighter-wins with the 1,000 bps protective band and your wallet’s self-trade-prevention default (the preview runs under your wallet, as placement does). Not a client-side re-walk, so preflight and placement read the same numbers.totalFilledis what would execute;remainingQuantitywhat the band or the depth leaves unfilled — the partial-fill indicator, a MARKET preview with a non-zero remainder is a warning that the size does not clear the previewed book — placement runs against a later book, so read the placement’s own status and quantities rather than treating this as the fill it will get;averageFillPriceandexecutionPriceRange.worstPriceare the fill levels (highest ask a BUY takes, lowest bid a SELL hits),nullwhen nothing crosses;statusis the status placement would end in —FILLEDfor a full fill,CANCELLEDfor a MARKET order the band or the depth cuts short (a MARKET remainder cannot rest, so the fills execute and the rest is cancelled; readremainingQuantityfor the partial fill),SUBMITTEDfor a LIMIT that rests,PARTIALLY_FILLEDfor a LIMIT that crosses partly and rests the remainder;actualSlippageBpsis the realized slippage againstreferencePrice— for a LIMIT or IOC preview, against the limit price,nullwhen every fill improved on it;maxSlippageBpsechoes your tolerance. A preview cannot carrypostOnly, TP/SL legs or a per-order self-trade-prevention override, so a post-only order that would cross is refused by placement, not here. Present only whenacceptedis true;nullon every refused preview (accepted: falsewith arejectReason), including the post-match maker-risk rejection — treat absence as unknown, not as a zero fill.referencePrice?: string — the touch on the taking side when a MARKET preview ran (best ask for a BUY, best bid for a SELL), whichexpectedMatchResultand itsactualSlippageBpsare measured from. Present only whenacceptedis true and the preview is a MARKET order; a LIMIT or IOC preview is measured against its own limit price and publishes nothing here.
expectedMatchResult.actualSlippageBps to your trigger price as an impact figure, rather than displaying this call’s absolute expectedMatchResult.averageFillPrice. The fee tier the preview reads can lag the engine’s own copy by one refresh interval, so estimatedFee and the fee settled moments later can differ by a tier step in that window.Example:accepted === false.(marginAccountId: string, request: SimulateOrderRiskRequest) => Promise<SimulateOrderRiskResponse>
Legacy compatibility method for callers that already store a
marginAccountId. Prefer simulateParentMarginOrderRisk for new integrations.(request: SimulateRiskBucketOrderRiskRequest) => Promise<SimulateOrderRiskResponse>
Preflight an order against a risk bucket without storing a Cross example:
marginAccountId. Accepts both isolated and cross modes via a discriminated union on marginMode.Isolated (marginMode?: "ISOLATED"):tradingPairId: stringmarginMode?:"ISOLATED"— default when omittedstrategyKey?: string — omit for the default risk bucketside,orderType,price?,quantity,leverage,reduceOnly?
marginMode: "CROSS"):tradingPairId: string — the pair being previewedmarginMode:"CROSS"— requiredside,orderType,price?,quantity,leverage,reduceOnly?- nothing else. A cross preview names no pairs: the cross bucket’s scope is derived from trading — a pair joins the bucket when a cross order on it succeeds; after its positions close, removal is lazy: it remains listed until a later successful cross order on a different pair reconciles the bucket — so the previewed pair is in scope by construction and there is nothing to declare. The response’s
selectedTradingPairIdsreports the derived scope the preview ran against: the active cross bucket’s recorded pairs (including any still listed after their positions closed), every pair with an open position in it, and the previewed pair (the previewed pair alone before the first cross order).
estimatedLiquidationPrice is conditional per target position, not a whole-account scalar: it varies only the target position’s mark while all other marks in the cross risk bucket remain unchanged. Other position marks, funding, realized PnL, fees/reserves, and collateral can change it. Render it as a conditional liquidation price; an absent or blank value is unavailable, never 0.Returns: Same SimulateOrderRiskResponse shape as simulateOrderRisk.Isolated example:Errors
400ontransferCollateralFromParentMarginAccountortransferCollateralFromMarginAccountwhenamountexceedswithdrawableCollateral400onsimulateParentMarginOrderRisk,simulateRiskBucketOrderRisk,simulateOrderRisk, and order placement:accepted: falsewithrejectReason(e.g., “Requested leverage exceeds max leverage for trading pair”). Market-order simulations apply the same 1,000 bps price band as placement and can return arejectReasonfor no liquidity inside the band or no usable reference price400onsimulateParentMarginOrderRisk,simulateRiskBucketOrderRiskandsimulateOrderRiskwhenslippageToleranceBpsis sent on a non-MARKET preview or falls outside0–1000(it is an integer bps value; a negative tolerance is refused by the same schema as one above1000) — the SDK raisesValidationErrorbefore the request is sent; a raw REST or gRPC caller gets placement’s own message (gRPCINVALID_ARGUMENT)403when the account belongs to a different user404when themarginAccountIddoes not exist429onsimulateParentMarginOrderRisk,simulateRiskBucketOrderRiskandsimulateOrderRisk— every authenticated read draws one request from the account’s read budget. Enforcement is gated per environment by theread_rate_limit_enforcedflag, which is off by default: until it is enabled the budget is measured and over-budget reads are admitted, so treat the429as a contract to handle rather than one you can rely on observing. When enforced, REST carries the retry horizon indetails.retryAfterwhile gRPC returnsRESOURCE_EXHAUSTEDwith agoogle.rpc.RetryInfodetail — the hint is transport-specific, so a gRPC caller readsRetryInforather than looking for aretryAfterfield. See Rate limits

