Trading API
Endpoints, signing, agents, nonces, request weight, and examples.
Endpoints
| Route | Use |
|---|---|
POST /info | Public market data: exchangeStatus, meta, metaAndAssetCtxs, allMids, l2Book, candleSnapshot, recentTrades, fundingHistory, predictedFundings, perpsAtOpenInterestCap, spotMeta, spotMetaAndAssetCtxs, tokenDetails, vaultDetails, insuranceFund, liquidationStats. Account reads such as clearinghouseState, openOrders, orderStatus, userFills, and userFees when signed by the owner or an agent. Every type is listed under Info reads |
POST /exchange | Signed actions, each listed with its schema under Action schemas |
GET /ws | Book, trades, candles, and the account's own orders, fills, and positions |
All three routes are served from one API host. An asset's id is its index in the meta response: BTC 0, ETH 1, SOL 2, SUB 3. The SUB / USDC spot market is asset 10000. exchangeStatus returns, in its signing field, the chain id and custody address that trading actions and signed reads are bound to, with the network’s source and subliquidChain values. Owner actions are bound to the network by subliquidChain instead.
Signing
| Item | Scheme |
|---|---|
| Keys | secp256k1 |
| Trading actions and signed reads | EIP-712 typed data over a hash of the msgpack-encoded action, bound to the chain and custody contract |
Owner typed data: approveAgent, withdraw3, usdSend, spotSend, usdClassTransfer, cDeposit, cWithdraw, linkStakingUser | EIP-712 typed data signed by the owner |
Other owner-only actions: vaultTransfer, createSubAccount, subAccountTransfer, oiCommit, oiRelease, cDeposit2, subVest, reserveFund | The trading-action scheme, signed by the owner’s own key; an agent’s signature is refused |
| Signature | { r, s, v }: 32-byte hex r and s, v of 27 or 28; high-s signatures are refused |
| Authorization | Signer recovered from the signature and checked by the engine against the account's owner and approved agents |
Trading actions
| Item | Value |
|---|---|
| Domain | EIP712Domain(string name,string version,uint256 chainId,address verifyingContract) with name Subliquid, version 1, no salt |
| chainId, verifyingContract | The settlement chain and the custody contract, both returned by exchangeStatus in its signing field |
| Primary type | Agent(string source,bytes32 connectionId), where source is the network letter exchangeStatus returns |
| connectionId | keccak256(msgpack(action) ‖ nonce ‖ vault ‖ expiry) |
| nonce | 8 bytes, big-endian |
| vault | 0x00 without vaultAddress; otherwise 0x01 followed by its 20 address bytes |
| expiry | Nothing without expiresAfter; otherwise 0x00 followed by it as 8 bytes, big-endian |
| msgpack | Smallest encoding of every value; map keys in each action’s schema order, the order the examples on this page use; optional keys omitted, never null; floats, binary, and extension types refused |
With agentType the Agent type string above, the digest is keccak256(0x19 0x01 ‖ domainSeparator ‖ keccak256(keccak256(agentType) ‖ keccak256(source) ‖ connectionId)). The server rebuilds each action in its schema order before hashing, so JSON keys may arrive in any order, while a client must hash in schema order to recover its own address. An unknown key, a missing required key, or an optional key sent as null is refused. A signed read hashes the request without nonce and signature, in the order type, user, its own fields, then an optional dex of "" last; any other dex is refused. The websocket sign-in hashes { type: "wsAuth", user, challenge }.
Owner actions
| Item | Value |
|---|---|
| Domain | Name SubliquidSignTransaction, version 1, chainId from the action’s signatureChainId (the wallet’s chain, lowercase hex), verifyingContract the zero address |
| Network check | subliquidChain must name the exchange’s network as exchangeStatus returns it |
| Agent approval | SubliquidTransaction:ApproveAgent(string subliquidChain,address agentAddress,string agentName,uint64 nonce) |
Withdrawal (withdraw3) | SubliquidTransaction:Withdraw(string subliquidChain,string destination,string amount,uint64 time) |
| USDC transfer | SubliquidTransaction:UsdSend(string subliquidChain,string destination,string amount,uint64 time) |
| Spot transfer | SubliquidTransaction:SpotSend(string subliquidChain,string destination,string token,string amount,uint64 time) |
| Perp and spot balance move | SubliquidTransaction:UsdClassTransfer(string subliquidChain,string amount,bool toPerp,uint64 nonce); every account is unified, with perps and spot drawing on one USDC balance, so it is accepted and checked against what the account could move but moves nothing |
| Stake, unstake | SubliquidTransaction:CDeposit(string subliquidChain,uint64 wei,uint64 nonce), SubliquidTransaction:CWithdraw(string subliquidChain,uint64 wei,uint64 nonce), with wei in 10−8 SUB |
| Staking link | SubliquidTransaction:LinkStakingUser(string subliquidChain,address user,bool isFinalize,uint64 nonce) |
The request’s nonce must equal the struct’s time or nonce field. Owner actions carry no vaultAddress or expiresAfter. agentName may be left out when approving the unnamed agent; it is then signed as the empty string "". An agent’s expiry is optional. It rides in its name as "<name> valid_until <ms>", or "valid_until <ms>" for the unnamed agent, at most 180 days ahead. An agent approved without one stays until it is replaced. A withdrawal’s destination must be the owner’s own address.
Action schemas
Every action is a JSON object whose keys a client hashes in the order shown. A key marked ? is optional and is left out when unused, never sent as null. int is a JSON integer, bool a JSON boolean, and string a JSON string; prices, sizes, and token amounts are decimal strings. An agent may sign only the actions marked owner or agent; any other action an agent signs is refused with Action requires the account owner's signature.
| Action | Keys in hashing order | Scheme | Signed by |
|---|---|---|---|
order | type, orders: [order], grouping: string | Trading | Owner or agent |
cancel | type, cancels: [{ a: int, o: int }] | Trading | Owner or agent |
cancelByCloid | type, cancels: [{ asset: int, cloid: string }] | Trading | Owner or agent |
cancelAll | type, asset?: int | Trading | Owner or agent |
modify | type, oid: int or string, order: order | Trading | Owner or agent |
batchModify | type, modifies: [{ oid: int or string, order: order }] | Trading | Owner or agent |
scheduleCancel | type, time?: int | Trading | Owner or agent |
updateLeverage | type, asset: int, isCross: bool, leverage: int | Trading | Owner or agent |
updateIsolatedMargin | type, asset: int, isBuy: bool, ntli: int | Trading | Owner or agent |
updatePositionMode | type, hedge: bool | Trading | Owner or agent |
twapOrder | type, twap: { a: int, b: bool, s: string, r: bool, m: int, t: bool } | Trading | Owner or agent |
twapCancel | type, a: int, t: int | Trading | Owner or agent |
trailingStop | type, a: int, b: bool, s: string, r: bool, retracement: { pct: string } or { px: string }, activationPx?: string, c?: string | Trading | Owner or agent |
reserveRequestWeight | type, weight: int | Trading | Owner or agent |
noop | type | Trading | Owner or agent |
createSubAccount | type, name: string | Trading | Owner of a master account |
subAccountTransfer | type, subAccountUser: string, isDeposit: bool, usd: int | Trading | Owner of a master account |
vaultTransfer | type, vaultAddress: string, isDeposit: bool, usd: int | Trading | Owner |
oiCommit | type, asset: int, sz: string, until: int | Trading | Owner |
oiRelease | type | Trading | Owner |
cDeposit2 | type, wei: int | Trading | Owner |
subVest | type, allocation: int | Trading | Owner named as the grant’s beneficiary |
reserveFund | type, usd: int | Trading | Owner |
approveAgent | type, signatureChainId: string, subliquidChain: string, agentAddress: string, agentName?: string, nonce: int; agentName left out means the unnamed agent, signed as "" | Owner typed data | Owner |
withdraw3 | type, signatureChainId: string, subliquidChain: string, destination: string, amount: string, time: int | Owner typed data | Owner |
usdSend | type, signatureChainId: string, subliquidChain: string, destination: string, amount: string, time: int | Owner typed data | Owner |
spotSend | type, signatureChainId: string, subliquidChain: string, destination: string, token: string, amount: string, time: int | Owner typed data | Owner |
usdClassTransfer | type, signatureChainId: string, subliquidChain: string, amount: string, toPerp: bool, nonce: int | Owner typed data | Owner |
cDeposit | type, signatureChainId: string, subliquidChain: string, wei: int, nonce: int | Owner typed data | Owner |
cWithdraw | type, signatureChainId: string, subliquidChain: string, wei: int, nonce: int | Owner typed data | Owner |
linkStakingUser | type, signatureChainId: string, subliquidChain: string, user: string, isFinalize: bool, nonce: int | Owner typed data | Owner |
| Field | Content |
|---|---|
| Order element | { a: int, b: bool, p: string, s: string, r: bool, t: object, c?: string, ps?: string }: asset, buy, price, size, reduce-only, type, client order id, hedge leg |
t | { limit: { tif: string } } with Gtc, Ioc, or Alo (post-only), or { trigger: { isMarket: bool, triggerPx: string, tpsl: string } } with tpsl tp or sl |
c, cloid | 0x and 32 hex digits |
ps | long or short, in hedge mode only |
grouping | na, normalTpsl, or positionTpsl |
oid in a modify | An order id, or a client order id string |
scheduleCancel.time | Milliseconds, at least 5 s ahead; leaving it out clears the schedule |
ntli | Signed, nonzero, in 10−6 USDC: positive adds isolated margin, negative removes it; isBuy names the long leg in hedge mode and is ignored in one-way mode |
twap.m, twap.t | Duration in minutes; randomize slice sizes |
twapCancel.t | The TWAP id from the twapOrder reply |
retracement | pct a fraction such as "0.02" with up to six decimals, or px a price distance on the market’s tick grid |
usd | Integer amounts in 10−6 USDC |
wei | Integer amounts in 10−8 SUB |
until, time, nonce | Milliseconds |
A request is { action, nonce, signature, vaultAddress?, expiresAfter? }. vaultAddress names a sub-account of the signer’s owner; it is refused on owner typed data, createSubAccount, and subAccountTransfer. An order carrying builder is refused, as are sendAsset, approveBuilderFee, setReferrer, convertToMultiSigUser, multiSig, and tokenDelegate. subVest releases vested SUB from an in-engine grant to its beneficiary. reserveFund moves USDC from the signer’s own flat balance into the insurance fund.
Agents and API wallets
Each account has one unnamed agent and up to three named API wallets; approving a new agent in a slot replaces the old one immediately. Run bots on a named API wallet, since each terminal login replaces the unnamed agent. Never reuse an agent address. Order lifecycle lists what agents can and cannot sign.
Sub-accounts and transfers
| Action | Who signs | Effect |
|---|---|---|
createSubAccount with a name | Owner | Opens a sub-account with its own address, balance, positions, and request allowance; no count limit. Its 10,000-request buffer starts once it trades or a deposit credits it |
Orders and cancels with vaultAddress set to the sub-account | Owner or its agents | Trade the sub-account; reads of it take the same signatures |
subAccountTransfer with subAccountUser, isDeposit, and usd | Owner | Moves USDC between the owner and its sub-account |
usdSend, spotSend | Owner | Sends USDC, or SUB, to any address on the exchange, opening its account if needed, free. An account opened this way gets its 10,000-request buffer once it trades or a deposit credits it |
vaultTransfer with vaultAddress, isDeposit, and usd | Owner | Deposits to or withdraws from the AMM vault |
createSubAccount, subAccountTransfer, and vaultTransfer use the trading-action scheme, signed by the owner’s own key, as do oiCommit, oiRelease, and cDeposit2. usdSend and spotSend use the owner’s typed data above.
Nonces and expiry
A nonce is a millisecond timestamp, unique per signer, from 2 days back to 1 day ahead. Signed reads use no nonce and stay valid for 5 s. Trading actions can carry an optional expiry. An exact retry returns the original receipt.
Place an order
A buy of 0.01 BTC at 84,750, good till canceled, signed by an API wallet:
POST /exchange
{
"action": {
"type": "order",
"orders": [{ "a": 0, "b": true, "p": "84750", "s": "0.01", "r": false,
"t": { "limit": { "tif": "Gtc" } } }],
"grouping": "na"
},
"nonce": 1793232000000,
"signature": { "r": "0x...", "s": "0x...", "v": 27 }
}Each order in the batch gets its own status: resting with its order id, filled with total size and average price, or error with a message. With grouping normalTpsl, the TP and SL children reply waitingForFill.
{ "status": "ok", "response": { "type": "order", "data": { "statuses": [
{ "filled": { "totalSz": "0.01", "avgPx": "84731", "oid": 77738308 } }
] } } }The order fields are asset a, buy b, price p, size s, reduce-only r, type t (limit with Gtc, Ioc, or Alo for post-only, or trigger with isMarket, triggerPx, and tpsl), an optional client order id c, and, in hedge mode, the leg ps.
Cancel an order
POST /exchange
{
"action": { "type": "cancel", "cancels": [{ "a": 0, "o": 77738308 }] },
"nonce": 1793232000500,
"signature": { "r": "0x...", "s": "0x...", "v": 28 }
}{ "status": "ok", "response": { "type": "cancel", "data": { "statuses": ["success"] } } }cancelByCloid takes { "asset", "cloid" } elements instead.
Read account state
A signed read carries the owner’s address and a nonce within 5 s of the engine clock; the signature comes from the owner or one of its agents.
POST /info
{
"type": "clearinghouseState",
"user": "0x...",
"nonce": 1793232001000,
"signature": { "r": "0x...", "s": "0x...", "v": 27 }
}{
"assetPositions": [{ "type": "oneWay", "position": {
"coin": "BTC", "szi": "0.01", "entryPx": "84731", "positionValue": "847.31",
"unrealizedPnl": "0", "liquidationPx": "55462.40911", "marginUsed": "42.3655",
"leverage": { "type": "cross", "value": 20 }, "maxLeverage": 40 } }],
"marginSummary": { "accountValue": "299.61871", "totalNtlPos": "847.31",
"totalRawUsd": "-547.69129", "totalMarginUsed": "42.3655" },
"crossMaintenanceMarginUsed": "10.591375",
"withdrawable": "214.88771",
"positionMode": "oneWay",
"time": 1793232001000
}Abbreviated: replies also carry crossMarginSummary, funding since open, and return on equity. A read that fails authorization gets Unauthorized read., whether or not the account exists.
Info reads
Every read is POST /info with a JSON body carrying type. Public reads need no signature. Account reads add user, then their own fields, then an optional dex of "", then nonce and signature. They need a signature from the owner or one of its agents. Times are milliseconds and endTime defaults to now.
Public reads
| Type | Request fields | Reply |
|---|---|---|
exchangeStatus | None | time, halted, degraded, signing { chainId, verifyingContract, source, subliquidChain }, … |
meta | None | universe [{ name, szDecimals, maxLeverage, marginTableId, onlyIsolated?, isDelisted? }], marginTables [[id, { description, marginTiers [{ lowerBound, maxLeverage }] }]] |
metaAndAssetCtxs | None | [meta, [{ funding, openInterest, prevDayPx, dayNtlVlm, premium, oraclePx, markPx, midPx, impactPxs, dayBaseVlm }]], one context per perp in meta order |
allMids | None | { coin: mid } for every perp and spot market |
l2Book | coin, nSigFigs? (2 to 5), mantissa? (1, 2, or 5, with nSigFigs 5) | { coin, time, levels [bids, asks] }, each level { px, sz, n }, 20 levels a side |
candleSnapshot | req { coin, interval, startTime, endTime? } | [{ t, T, s, i, o, c, h, l, v, n }], the latest 5,000 candles in the range; intervals 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 8h, 12h, 1d, 3d, 1w, 1M |
recentTrades | coin | The latest 20 trades, newest first: [{ coin, side, px, sz, time, tid }] |
fundingHistory | coin, startTime, endTime? | Up to 500 payments from startTime, oldest first: [{ coin, fundingRate, premium, time }] |
predictedFundings | None | [[coin, [[venue, { fundingRate, nextFundingTime }]]]] |
perpsAtOpenInterestCap | None | [coin], the markets at their open interest cap |
spotMeta | None | tokens [{ name, szDecimals, weiDecimals, index, tokenId, isCanonical, evmContract, fullName }], universe [{ tokens, name, index, isCanonical }] |
spotMetaAndAssetCtxs | None | [spotMeta, [{ coin, dayNtlVlm, markPx, midPx, prevDayPx, dayBaseVlm }]] |
tokenDetails | tokenId (id or name) | { name, maxSupply, totalSupply, circulatingSupply, szDecimals, weiDecimals, midPx, markPx, prevDayPx, … } |
vaultDetails | vaultAddress? | { name, vaultAddress, nav, shareSupply, sharePrice, lockupMs, allowDeposits, isClosed, … }, aggregates only |
insuranceFund | None | { balance } |
liquidationStats | startTime?, endTime? (default the last 24 hours) | [{ startTime, endTime, count, longNtl, shortNtl, backstopNtl, adlNtl }], buckets of at least 5 liquidations |
Account reads
| Type | Fields after user | Reply |
|---|---|---|
clearinghouseState | None | assetPositions, marginSummary, crossMarginSummary, crossMaintenanceMarginUsed, withdrawable, positionMode, time (example above) |
spotClearinghouseState | None | { balances [{ coin, token, total, hold, entryNtl }] } |
openOrders | None | [{ coin, side, limitPx, sz, oid, timestamp, origSz, cloid? }], newest first |
frontendOpenOrders | None | openOrders plus orderType, reduceOnly, isTrigger, triggerPx, triggerCondition, isPositionTpsl, tif, children |
orderStatus | oid (an order id or client order id) | { status: "order", order { order, status, statusTimestamp } } or { status: "unknownOid" } |
userFills | aggregateByTime? | The latest 2,000 fills, newest first: [{ coin, px, sz, side, time, startPosition, dir, closedPnl, hash, oid, crossed, fee, feeToken, tid, liquidation? }] |
userFillsByTime | startTime, endTime?, aggregateByTime? | Up to 2,000 fills from startTime, oldest first |
userFunding | startTime, endTime? | Up to 500 entries from startTime, oldest first: [{ time, hash, delta { type, coin, usdc, szi, fundingRate, nSamples } }] |
historicalOrders | None | Up to 2,000: open orders, then closed ones newest first, each { order, status, statusTimestamp } |
userNonFundingLedgerUpdates | startTime, endTime? | Up to 2,000 entries from startTime, oldest first: [{ time, hash, delta }] with delta types deposit, withdraw, send, spotTransfer, spotDeposit, spotWithdraw, subAccountTransfer, accountClassTransfer, reserveRequestWeight, and liquidation |
userRateLimit | None | { cumVlm, nRequestsUsed, nRequestsCap, nRequestsSurplus } |
userFees | None | { dailyUserVlm, feeSchedule, userCrossRate, userAddRate, userSpotCrossRate, userSpotAddRate, activeStakingDiscount, feeTier, makerRebateTier, … } |
activeAssetData | coin | { user, coin, leverage, maxTradeSzs, availableToTrade, markPx } |
subAccounts | None | [{ name, subAccountUser, master, clearinghouseState, spotState }] or null |
userVaultEquities | None | [{ vaultAddress, equity, lockedUntilTimestamp }] |
delegatorSummary | None | { delegated, undelegated, totalPendingWithdrawal, nPendingWithdrawals } |
userRewards | None | { points, sub { held, released }, holderPaid, oiCommitment, allocations, … } |
userClaims | None | The owner’s claimable SUB and USDC with the proofs each claim needs |
userTwapSliceFills, twapHistory | None | The latest 2,000, newest first |
portfolio, userRole, userAbstraction, referral, approvedBuilders, maxBuilderFee | maxBuilderFee takes builder | Compatibility reads: account value history, the account’s role, unifiedAccount, and empty referral and builder data |
No read takes a page token. A time-range read returns at most its stated number of rows, oldest first from startTime; to page, send the next request with startTime just past the last row’s time. A read without a range returns the newest rows. These numbers bound one reply and never what is kept, so every row stays readable by time range.
Websocket
| Channel set | Subscriptions |
|---|---|
| Public | allMids, l2Book, l2Delta, trades, bbo, candle, activeAssetCtx, fastAssetCtxs (every market’s context in one frame) |
| Account, after one signed auth message | orderUpdates, userFills, userFundings, userNonFundingLedgerUpdates, userEvents, notification, clearinghouseState, openOrders, activeAssetData, webData3, twapStates, userTwapSliceFills, userTwapHistory, spotState |
{ "method": "subscribe", "subscription": { "type": "l2Book", "coin": "BTC" } }| Channel | Content and cadence |
|---|---|
l2Book | The full book to 20 levels a side on every push, sent when it changed and at most every 500 ms; optional nSigFigs (2 to 5) and mantissa aggregate levels; no sequence number |
l2Delta | The whole book at every price level, unaggregated and with no depth limit. A first frame with isSnapshot: true carries every level. Each later frame carries only the levels that changed, with U, u, and pu; a level of size "0" is gone; a client has missed nothing while each pu equals its last u |
bbo, trades, other public channels | Sent on the next feed tick after a change or print; ticks are at least 10 ms apart |
userFills | A snapshot with isSnapshot: true on subscribe, then each fill; fill ids (tid) rise with engine order |
orderUpdates, userEvents, notification | No snapshot; read openOrders once after subscribing |
Every frame derived from engine state is sent only after that state is committed to disk. Frames leave in the order the engine computed them. On one connection, an account’s fills and order updates arrive in commit order. A client that reconnects rebuilds from a fresh snapshot. A post message carries an /info or /exchange request over the socket. Trades on the public tape carry no account or hash and do not mark liquidations; the liquidated account’s own fill carries a liquidation field. liquidationStats publishes liquidations in buckets of at least 5. Limits per IP address: 10 connections, 30 new connections a minute, 1,000 subscriptions, 10 authenticated users, 2,000 messages a minute and 100 posts in flight; an idle connection closes after 60 s, so send a ping.
Request weight
| Request | Weight |
|---|---|
| Signed action | 1, or 1 + ⌊n / 40⌋ for a batch of n orders, cancels, or modifies |
Light reads: l2Book, allMids, clearinghouseState, orderStatus, exchangeStatus, spotClearinghouseState, insuranceFund | 2 |
userRole | 60 |
| Other reads | 20 |
| Per-item extra | +1 per 20 items returned by fills, funding, order history, trades, and ledger reads; +1 per 60 candles |
1,200 units per IP address over any 60 s. Every reply carries the weight used in the x-used-weight-1m header; above the limit the reply is HTTP 429 with Retry-After. Cancels, scheduled cancels, and reduce-only orders are charged weight but never refused for it. They still count against the account’s own request allowance, where cancels get extra room and reduce-only orders do not. An account can buy request allowance beyond its traded volume with reserveRequestWeight { weight } at 0.0005 USDC per request; that fee splits 50/20/10/10/10 like trading fees (Fees and payouts). Market making sets out the per-account limits.
Load shedding
The API gateway counts the exchange requests it has received and not yet answered. Once that count reaches its overload threshold, it refuses every new request outside the exit lane before any signature work. The refusal reads Server is overloaded; new orders are shed. Cancels, reduce-only and closing orders still run. with HTTP 200. Meanwhile exchangeStatus reports degraded: true until the count falls back.
| Request | Under load shedding |
|---|---|
cancel, cancelByCloid, cancelAll, twapCancel, scheduleCancel | Always runs |
| Orders, modifies, TWAPs, and trailing stops whose every element is reduce-only or closes its hedge leg | Always runs |
| Post-only orders and every other order that adds risk | Refused |
| Non-order actions such as leverage changes, transfers, and withdrawals | Refused |
The exit lane is also exempt from IP request weight refusals. Load shedding is the one case where traffic from other accounts can refuse an account’s request. A full matching cycle never does: requests past 8,192 wait for the next cycle. No order is refused or evicted because of the orders other accounts hold on the book.
Size, price, and amount precision
Sizes are whole size steps. Prices are whole ticks with at most 5 significant figures, or any whole dollar; a perp tick is 10−(6 − size decimals) USDC and a spot tick 10−(8 − size decimals) USDC (Markets and pricing). Numbers travel as decimal strings. A value finer than its unit is refused for that order alone. USDC amounts carry six decimals.
Errors
| Message | Meaning |
|---|---|
Price must be divisible by tick size. | Price is off the tick or has more than 5 significant figures |
Insufficient margin to place order. | Initial margin not met |
Post only order would have immediately matched, bbo was bid@ask. | Post-only order crossed the book |
Order price too far from mark. | Outside the 10% price band around the mark |
Order must have minimum value of $10. | Below the 10 USDC minimum; reduce-only orders are exempt |
Cannot increase position when open interest is at cap. | The market’s open interest cap is reached; orders that reduce still run |
Insufficient margin to remove from isolated position. | The removal would leave the isolated position short of its margin requirement |
Too many open orders. | Open order limit reached |
Invalid nonce: duplicate nonce | Nonce already used by this signer |
Withdrawal must be larger than the 1 USDC fee. | Withdrawal amount at or below the fee |
Withdrawals are paused while settlement is halted. | Withdrawals are temporarily paused; trading continues |
The exchange is restarting; retry. | The exchange is restarting; every signed action is refused until it is back |
Server is overloaded; new orders are shed. Cancels, reduce-only and closing orders still run. | Load shedding refused a request that adds risk; cancels, reduce-only, and closing orders still run |
Action requires the account owner's signature. | An agent signed an action only the owner may sign |
Unknown outcome. | The reply was lost after the request reached the engine; orderStatus by order id or client order id resolves it |
Each element of a batch fails on its own with its own message. Engine refusals, load shedding included, arrive with HTTP 200 and "status": "err". Other HTTP status codes: 400 for an invalid request, 404 for an unknown route, 413 above the 1 MiB body limit, 415 for a body that is not application/json, 429 above the weight limit, and 503 when the service is unavailable.
Response semantics
- An acknowledgement is sent after the request is committed, state-dependent refusals included.
- Malformed actions and bad signatures are refused immediately.
- A refused request changes nothing and does not count against the account’s request allowance; it still counts toward IP request weight.