DocsMarket makers

Trading API

Endpoints, signing, agents, nonces, request weight, and examples.

Endpoints

RouteUse
POST /infoPublic 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 /exchangeSigned actions, each listed with its schema under Action schemas
GET /wsBook, 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

ItemScheme
Keyssecp256k1
Trading actions and signed readsEIP-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, linkStakingUserEIP-712 typed data signed by the owner
Other owner-only actions: vaultTransfer, createSubAccount, subAccountTransfer, oiCommit, oiRelease, cDeposit2, subVest, reserveFundThe 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
AuthorizationSigner recovered from the signature and checked by the engine against the account's owner and approved agents

Trading actions

ItemValue
DomainEIP712Domain(string name,string version,uint256 chainId,address verifyingContract) with name Subliquid, version 1, no salt
chainId, verifyingContractThe settlement chain and the custody contract, both returned by exchangeStatus in its signing field
Primary typeAgent(string source,bytes32 connectionId), where source is the network letter exchangeStatus returns
connectionIdkeccak256(msgpack(action) ‖ nonce ‖ vault ‖ expiry)
nonce8 bytes, big-endian
vault0x00 without vaultAddress; otherwise 0x01 followed by its 20 address bytes
expiryNothing without expiresAfter; otherwise 0x00 followed by it as 8 bytes, big-endian
msgpackSmallest 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

ItemValue
DomainName SubliquidSignTransaction, version 1, chainId from the action’s signatureChainId (the wallet’s chain, lowercase hex), verifyingContract the zero address
Network checksubliquidChain must name the exchange’s network as exchangeStatus returns it
Agent approvalSubliquidTransaction:ApproveAgent(string subliquidChain,address agentAddress,string agentName,uint64 nonce)
Withdrawal (withdraw3)SubliquidTransaction:Withdraw(string subliquidChain,string destination,string amount,uint64 time)
USDC transferSubliquidTransaction:UsdSend(string subliquidChain,string destination,string amount,uint64 time)
Spot transferSubliquidTransaction:SpotSend(string subliquidChain,string destination,string token,string amount,uint64 time)
Perp and spot balance moveSubliquidTransaction: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, unstakeSubliquidTransaction:CDeposit(string subliquidChain,uint64 wei,uint64 nonce), SubliquidTransaction:CWithdraw(string subliquidChain,uint64 wei,uint64 nonce), with wei in 10−8 SUB
Staking linkSubliquidTransaction: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.

ActionKeys in hashing orderSchemeSigned by
ordertype, orders: [order], grouping: stringTradingOwner or agent
canceltype, cancels: [{ a: int, o: int }]TradingOwner or agent
cancelByCloidtype, cancels: [{ asset: int, cloid: string }]TradingOwner or agent
cancelAlltype, asset?: intTradingOwner or agent
modifytype, oid: int or string, order: orderTradingOwner or agent
batchModifytype, modifies: [{ oid: int or string, order: order }]TradingOwner or agent
scheduleCanceltype, time?: intTradingOwner or agent
updateLeveragetype, asset: int, isCross: bool, leverage: intTradingOwner or agent
updateIsolatedMargintype, asset: int, isBuy: bool, ntli: intTradingOwner or agent
updatePositionModetype, hedge: boolTradingOwner or agent
twapOrdertype, twap: { a: int, b: bool, s: string, r: bool, m: int, t: bool }TradingOwner or agent
twapCanceltype, a: int, t: intTradingOwner or agent
trailingStoptype, a: int, b: bool, s: string, r: bool, retracement: { pct: string } or { px: string }, activationPx?: string, c?: stringTradingOwner or agent
reserveRequestWeighttype, weight: intTradingOwner or agent
nooptypeTradingOwner or agent
createSubAccounttype, name: stringTradingOwner of a master account
subAccountTransfertype, subAccountUser: string, isDeposit: bool, usd: intTradingOwner of a master account
vaultTransfertype, vaultAddress: string, isDeposit: bool, usd: intTradingOwner
oiCommittype, asset: int, sz: string, until: intTradingOwner
oiReleasetypeTradingOwner
cDeposit2type, wei: intTradingOwner
subVesttype, allocation: intTradingOwner named as the grant’s beneficiary
reserveFundtype, usd: intTradingOwner
approveAgenttype, signatureChainId: string, subliquidChain: string, agentAddress: string, agentName?: string, nonce: int; agentName left out means the unnamed agent, signed as ""Owner typed dataOwner
withdraw3type, signatureChainId: string, subliquidChain: string, destination: string, amount: string, time: intOwner typed dataOwner
usdSendtype, signatureChainId: string, subliquidChain: string, destination: string, amount: string, time: intOwner typed dataOwner
spotSendtype, signatureChainId: string, subliquidChain: string, destination: string, token: string, amount: string, time: intOwner typed dataOwner
usdClassTransfertype, signatureChainId: string, subliquidChain: string, amount: string, toPerp: bool, nonce: intOwner typed dataOwner
cDeposittype, signatureChainId: string, subliquidChain: string, wei: int, nonce: intOwner typed dataOwner
cWithdrawtype, signatureChainId: string, subliquidChain: string, wei: int, nonce: intOwner typed dataOwner
linkStakingUsertype, signatureChainId: string, subliquidChain: string, user: string, isFinalize: bool, nonce: intOwner typed dataOwner
FieldContent
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, cloid0x and 32 hex digits
pslong or short, in hedge mode only
groupingna, normalTpsl, or positionTpsl
oid in a modifyAn order id, or a client order id string
scheduleCancel.timeMilliseconds, at least 5 s ahead; leaving it out clears the schedule
ntliSigned, 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.tDuration in minutes; randomize slice sizes
twapCancel.tThe TWAP id from the twapOrder reply
retracementpct a fraction such as "0.02" with up to six decimals, or px a price distance on the market’s tick grid
usdInteger amounts in 10−6 USDC
weiInteger amounts in 10−8 SUB
until, time, nonceMilliseconds

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

ActionWho signsEffect
createSubAccount with a nameOwnerOpens 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-accountOwner or its agentsTrade the sub-account; reads of it take the same signatures
subAccountTransfer with subAccountUser, isDeposit, and usdOwnerMoves USDC between the owner and its sub-account
usdSend, spotSendOwnerSends 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 usdOwnerDeposits 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

TypeRequest fieldsReply
exchangeStatusNonetime, halted, degraded, signing { chainId, verifyingContract, source, subliquidChain }, …
metaNoneuniverse [{ name, szDecimals, maxLeverage, marginTableId, onlyIsolated?, isDelisted? }], marginTables [[id, { description, marginTiers [{ lowerBound, maxLeverage }] }]]
metaAndAssetCtxsNone[meta, [{ funding, openInterest, prevDayPx, dayNtlVlm, premium, oraclePx, markPx, midPx, impactPxs, dayBaseVlm }]], one context per perp in meta order
allMidsNone{ coin: mid } for every perp and spot market
l2Bookcoin, 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
candleSnapshotreq { 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
recentTradescoinThe latest 20 trades, newest first: [{ coin, side, px, sz, time, tid }]
fundingHistorycoin, startTime, endTime?Up to 500 payments from startTime, oldest first: [{ coin, fundingRate, premium, time }]
predictedFundingsNone[[coin, [[venue, { fundingRate, nextFundingTime }]]]]
perpsAtOpenInterestCapNone[coin], the markets at their open interest cap
spotMetaNonetokens [{ name, szDecimals, weiDecimals, index, tokenId, isCanonical, evmContract, fullName }], universe [{ tokens, name, index, isCanonical }]
spotMetaAndAssetCtxsNone[spotMeta, [{ coin, dayNtlVlm, markPx, midPx, prevDayPx, dayBaseVlm }]]
tokenDetailstokenId (id or name){ name, maxSupply, totalSupply, circulatingSupply, szDecimals, weiDecimals, midPx, markPx, prevDayPx, … }
vaultDetailsvaultAddress?{ name, vaultAddress, nav, shareSupply, sharePrice, lockupMs, allowDeposits, isClosed, … }, aggregates only
insuranceFundNone{ balance }
liquidationStatsstartTime?, endTime? (default the last 24 hours)[{ startTime, endTime, count, longNtl, shortNtl, backstopNtl, adlNtl }], buckets of at least 5 liquidations

Account reads

TypeFields after userReply
clearinghouseStateNoneassetPositions, marginSummary, crossMarginSummary, crossMaintenanceMarginUsed, withdrawable, positionMode, time (example above)
spotClearinghouseStateNone{ balances [{ coin, token, total, hold, entryNtl }] }
openOrdersNone[{ coin, side, limitPx, sz, oid, timestamp, origSz, cloid? }], newest first
frontendOpenOrdersNoneopenOrders plus orderType, reduceOnly, isTrigger, triggerPx, triggerCondition, isPositionTpsl, tif, children
orderStatusoid (an order id or client order id){ status: "order", order { order, status, statusTimestamp } } or { status: "unknownOid" }
userFillsaggregateByTime?The latest 2,000 fills, newest first: [{ coin, px, sz, side, time, startPosition, dir, closedPnl, hash, oid, crossed, fee, feeToken, tid, liquidation? }]
userFillsByTimestartTime, endTime?, aggregateByTime?Up to 2,000 fills from startTime, oldest first
userFundingstartTime, endTime?Up to 500 entries from startTime, oldest first: [{ time, hash, delta { type, coin, usdc, szi, fundingRate, nSamples } }]
historicalOrdersNoneUp to 2,000: open orders, then closed ones newest first, each { order, status, statusTimestamp }
userNonFundingLedgerUpdatesstartTime, 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
userRateLimitNone{ cumVlm, nRequestsUsed, nRequestsCap, nRequestsSurplus }
userFeesNone{ dailyUserVlm, feeSchedule, userCrossRate, userAddRate, userSpotCrossRate, userSpotAddRate, activeStakingDiscount, feeTier, makerRebateTier, … }
activeAssetDatacoin{ user, coin, leverage, maxTradeSzs, availableToTrade, markPx }
subAccountsNone[{ name, subAccountUser, master, clearinghouseState, spotState }] or null
userVaultEquitiesNone[{ vaultAddress, equity, lockedUntilTimestamp }]
delegatorSummaryNone{ delegated, undelegated, totalPendingWithdrawal, nPendingWithdrawals }
userRewardsNone{ points, sub { held, released }, holderPaid, oiCommitment, allocations, … }
userClaimsNoneThe owner’s claimable SUB and USDC with the proofs each claim needs
userTwapSliceFills, twapHistoryNoneThe latest 2,000, newest first
portfolio, userRole, userAbstraction, referral, approvedBuilders, maxBuilderFeemaxBuilderFee takes builderCompatibility 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 setSubscriptions
PublicallMids, l2Book, l2Delta, trades, bbo, candle, activeAssetCtx, fastAssetCtxs (every market’s context in one frame)
Account, after one signed auth messageorderUpdates, userFills, userFundings, userNonFundingLedgerUpdates, userEvents, notification, clearinghouseState, openOrders, activeAssetData, webData3, twapStates, userTwapSliceFills, userTwapHistory, spotState
{ "method": "subscribe", "subscription": { "type": "l2Book", "coin": "BTC" } }
ChannelContent and cadence
l2BookThe 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
l2DeltaThe 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 channelsSent on the next feed tick after a change or print; ticks are at least 10 ms apart
userFillsA snapshot with isSnapshot: true on subscribe, then each fill; fill ids (tid) rise with engine order
orderUpdates, userEvents, notificationNo 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

RequestWeight
Signed action1, or 1 + ⌊n / 40⌋ for a batch of n orders, cancels, or modifies
Light reads: l2Book, allMids, clearinghouseState, orderStatus, exchangeStatus, spotClearinghouseState, insuranceFund2
userRole60
Other reads20
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.

RequestUnder load shedding
cancel, cancelByCloid, cancelAll, twapCancel, scheduleCancelAlways runs
Orders, modifies, TWAPs, and trailing stops whose every element is reduce-only or closes its hedge legAlways runs
Post-only orders and every other order that adds riskRefused
Non-order actions such as leverage changes, transfers, and withdrawalsRefused

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

MessageMeaning
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 nonceNonce 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.
Subliquid docs · Last changed October 28, 2026