Skip to content
BuildBuild on HyperCore16 pages
Architecture: info, exchange, WebSocketFoundationHyperliquid's API has three surfaces: an unsigned read endpoint, a signed write endpoint, and a WebSocket that streams data and can carry both.Your first requestFoundationReading Hyperliquid needs no key, no account and no risk: three unsigned POST requests return the list of markets, an order book and any address's positions.Asset ids and namingPractitionerOrders name a market by an integer asset id and info requests by a coin string, and perps, spot, HIP-3 and outcomes each derive both by a different rule.Precision: tick size, lot size, significant figuresPractitionerA HyperCore price has at most 5 significant figures and a decimal cap set by szDecimals, a size at most szDecimals decimals, and outcomes use a 0.00001 grid.Signing from first principlesExpertL1 actions sign a keccak hash of their msgpack bytes, user-signed actions sign readable EIP-712 data, and one wrong byte in either recovers a stranger's address.Nonces, expiry and API walletsPractitionerHyperCore keeps each signer's 100 highest nonces and accepts a new one only if unused, above the smallest, and within 2 days before and 1 day after block time.Orders: place, modify, cancel, batch, dead man's switchPractitionerAn order is a signed action carrying a batch of compact orders; modify, cancel, TWAP and the dead man's switch are separate actions, each with its own response.Transfers and withdrawalsPractitionerEvery HyperCore transfer is a signed action: sends and withdrawals need the account's own key, and an API wallet's transfer actions keep value inside the account.Multi-sig actionsExpertA multi-sig action carries enough authorised users' signatures over one nonce and one named leader, in an envelope only the leader signs and submits.WebSocket: subscriptions, post requests, heartbeatsPractitionerOne WebSocket streams book, trade and account updates as blocks execute and carries signed actions, but drops without warning and forgets every subscription.Rate limits and user limitsPractitionerHyperliquid meters each IP by request weight, 1200 per minute, and each address by actions: 10,000 plus one per USDC traded.Priority fees and the activation feeExpertHyperliquid sells latency in two burned auctions, read priority per IP and write priority per order, and charges 1 quote token to activate a new account.Error responsesPractitionerHyperliquid reports errors at four layers, from HTTP status to a string inside a successful response, and several name a cause other than the real one.Debugging signatures and wire shapesExpertA signature over wrong bytes still verifies, so HyperCore recovers a stranger's address and says it does not exist; the fix is almost always the encoding.Optimising latencyExpertMost of an order's round trip is consensus; code wins by streaming reads, cutting serial round trips, using the fast order class and never stalling orders.Data: historical, node and explorerPractitionerThe API keeps only recent history; a full record needs pagination, archived node data or your own node, and each trade counted once by its trade id.
BuildBuild on the HyperEVM9 pages
What the HyperEVM is, and is notFoundationThe HyperEVM is Hyperliquid's smart contract environment: it reads HyperCore state and queues HyperCore actions, but never executes them atomically.Blocks, gas and RPCPractitionerThe HyperEVM produces small blocks every second and big blocks every minute, prices gas with EIP-1559 in HYPE, and serves a JSON-RPC with no historical state.Moving assets between HyperCore and the HyperEVMPractitionerLinked tokens cross between HyperCore and the HyperEVM via per-token system addresses, with a decimal offset and a 200k-gas fee when leaving HyperCore.Linking a tokenExpertLinking binds a HyperCore token to one ERC20 through the spot deployer's request and the contract deployer's finalisation; the protocol checks almost nothing else.Reading HyperCore: precompilesExpertRead precompiles are 21 fixed addresses, 0x800 to 0x814, that return HyperCore state as of the EVM block's construction, and only at the latest block.Writing to HyperCore: CoreWriterExpertCoreWriter turns a contract call into a HyperCore action for the caller's own account, run after the EVM block, with no result returned and no revert on refusal.Execution order and timingExpertEach L1 block runs the EVM block, then EVM to HyperCore transfers, then CoreWriter actions; on mainnet most actions land within half a second, vault transfers in about 4 s.PatternsExpertA contract that touches HyperCore stays solvent by recording an intent, sending the action, and settling only on HyperCore state that visibly moved.Footguns, measuredExpertTwelve ways a HyperEVM contract loses money or silently does nothing when it touches HyperCore, each with the on-chain evidence and the fix.

Error responses

Practitioner

Hyperliquid reports errors at four layers, from HTTP status to a string inside a successful response, and several name a cause other than the real one.

A client that reads only one layer treats real rejections as success. A reply can be HTTP 200 with "status": "ok" and still reject every order.

Say you send 3 orders in one batch and margin runs out. The reply is still "status": "ok", and one of the 3 statuses is {"error": "Insufficient margin to place order."}. Stop at the status and you’d think all 3 are live.

Several errors name the wrong cause: a serialisation bug arrives as an account that “does not exist”, a trailing zero as a tick-size error.

Layer Shape Example
HTTP status 422 with a body that may be plain text, not JSON Failed to deserialize ...
HTTP status 429 when the IP’s weight budget is spent no Retry-After header
Whole action {"status": "err", "response": "<string>"} Price would cross book on a modify
Whole batch one error for the batch, from pre-validation an empty batch of orders
Per order "statuses": [{"error": "<string>"}] inside "status": "ok" Insufficient margin to place order.
WebSocket post "response": {"type": "error", "payload": "<string>"} mirrors the HTTP status and description
From the HyperEVM nothing: the EVM transaction succeeds read the L1 record (data)

Order and cancel errors normally return a list as long as the batch. Payload-only errors fail pre-validation with one error for the whole request (an empty batch, a TP/SL order that is not reduce-only, an order too far from the reference price, some tick-size checks); the docs recommend copying it to every order before your callbacks.

A CoreWriter failure leaves the money where it was; its only record is the typed L1 action’s error field from the explorer’s userDetails (footguns).

Shape: the payload isn’t what the server expects

Section titled “Shape: the payload isn’t what the server expects”
Error Cause and fix
HTTP 422 Failed to deserialize Wrong wire shape. A catch-all: a missing key, a wrong type, an extra key. Read the body as text before parsing it as JSON
a rejection of f: false or a: false Cancels and modifies hashed with the flag set to false are refused. Omit the key
a 422 on a missing nullable key Some actions need an explicit null rather than an absent key, for example the nullable fields of HIP-3 registerAsset2
Invalid token sendAsset to the HyperEVM with dex ""; use "spot"
frame on WebSocket channel error the subscription type is dead, for example webData2

The server parses before checking the signature, so a deliberately wrong signature probes a shape: a 422 means it does not parse, a signer error means it does (the probe).

Signature: the server recovered someone else’s address

Section titled “Signature: the server recovered someone else’s address”
Error Cause and fix
L1 error: User or API Wallet 0x... does not exist. The signed bytes differ from what the server rebuilt: key order, trailing zeros, an uppercase address, or the wrong signing scheme. The address in the message changes with the input
Must deposit before performing actions. User: 0x... Either the same recovery failure, or the address genuinely holds nothing. If the address in the message is not yours, it is a signing bug
Price must be divisible by tick size. Usually precision, but a price string signed with trailing zeros has produced it too
Invalid multi-sig outer signer Inner r and s sent with leading zeros; about 1 in 4 submissions failed before stripping them (multi-sig actions)

The docs warn that recovering the signer locally proves nothing: your local payload may be what is wrong (signing). In multi-sig actions, a checksummed address recovers the wrong signer and the error blames the outer signer.

Account state: valid, but not possible now

Section titled “Account state: valid, but not possible now”
Error Meaning
Insufficient margin to place order. not enough margin for the new order
Reduce only order would increase position. the reduce-only order would increase the position
Order has insufficient spot balance to trade spot only: not enough balance of the token the order spends
Order would cause position to exceed margin tier limit at current leverage lower leverage or size (margin)
Order was never placed, already canceled, or filled. the cancel lost a race with a fill or an earlier cancel
TWAP was never placed, already canceled, or filled. the same, for twapCancel
Insufficient USDC or HYPE balance for token transfer gas a transfer to the HyperEVM left nothing to pay its gas
Borrow/Lend error: Insufficient spot balance for operation a supply larger than the spot balance; measured on testnet

Precision: a number the market won’t accept

Section titled “Precision: a number the market won’t accept”

The rules are on precision.

Error Meaning
Price must be divisible by tick size. price off the market’s tick grid
Order must have minimum value of $10. perp order below the minimum notional
Order must have minimum value of 10 {quote_token}. spot order below the minimum, in the quote token
Invalid number of decimals: 9599.79902008 an amount the destination cannot represent, such as USDC to the HyperEVM not in whole 1e-6 units (5 of 5 measured)
Invalid TWAP duration: 1 min(s) a TWAP duration outside the allowed range, here 1 minute

Limits: the book, a price band, a cap or a rate limit

Section titled “Limits: the book, a price band, a cap or a rate limit”
Error Meaning
Post only order would have immediately matched, bbo was {bbo}. an Alo order would have crossed
Order could not immediately match against any resting orders. an Ioc order found nothing to fill
No liquidity available for market order. a market order found an empty book
Order price too far from oracle the limit price is too far from the oracle price
Invalid TP/SL price. the trigger price was rejected
Order would increase open interest while open interest is capped the asset is at its open interest cap; two error types share this string
Order rejected due to price more aggressive than oracle while at open interest cap at the cap, an order priced more aggressively than the oracle is refused
Order would increase open interest too quickly open interest is growing faster than allowed
Price would cross book a modify whose new price would execute
HTTP 429 IP weight exhausted (rate limits)
too many pending post requests id=N WebSocket posts backed up; keep under 100 in flight

Two limits have no documented string: the address action budget and the 1000-open-order cap on reduce-only and trigger orders (values in the numbers). Historical statuses tell apart the two causes sharing the open interest cap string: positionIncreaseAtOpenInterestCapRejected and positionFlipAtOpenInterestCapRejected.

Error Meaning
Action disabled when unified account is active usdSend, spotSend or usdClassTransfer on a unified or portfolio margin account; use sendAsset (transfers)
Manual borrow/lend not allowed with portfolio margin a manual borrow/lend operation on a portfolio margin account; observed on mainnet for withdraws sent through CoreWriter
Portfolio margin requires account value of $10000 or total volume of $5000000 the account is not eligible for portfolio margin
Abstraction transition not allowed a mode switch refused; observed leaving unified mode, cause unresolved

One mode rule has no documented string: a builder address must be in standard mode to accrue builder fees (account modes).

orderStatus and historical orders record each outcome as a status string:

Kind Statuses
Rejections, mirroring the errors above tickRejected, minTradeNtlRejected, perpMarginRejected, badAloPxRejected, iocCancelRejected, oracleRejected, and so on
Cancellations the protocol made for you marginCanceled, selfTradeCanceled, reduceOnlyCanceled, siblingFilledCanceled, openInterestCapCanceled, liquidatedCanceled, delistedCanceled, scheduledCancel
Threshold behind an error Value
Minimum perp order $10
Minimum spot order 10 units of the quote token
scheduleCancel lead time at least 5 s
Minimum TWAP duration 5 minutes
Open orders before reduce-only and trigger orders are refused 1000
WebSocket posts in flight 100
Unified and portfolio margin actions 50k per day
Rate-limited address 1 action per 10 s

Handling a response and deciding on a retry

Section titled “Handling a response and deciding on a retry”

Handle a response in this order: HTTP status, body as text, JSON parse, top-level status, every element of statuses. Then decide on a retry:

Cause Retry unchanged? What to do
Shape never fix the payload; probe with a dummy signature
Signature never compare your bytes with a reference SDK
Account state after the state changes add margin, reduce size, refresh positions
Precision never round to the market’s rules before signing
Limits after backoff or a price change back off on 429; reprice on band and cap errors
Mode never change the action or the account mode
Timeout, 5xx unknown outcome reconcile by cloid first; never resend blindly

A blind retry after a timeout can double an order or transfer: check orderStatus by cloid, or the ledger for transfers, first. A successful modify can return a bare {"status": "ok"} with no statuses: treat it as success and look up the new oid by cloid.

For every string in one table, see the error catalogue. To turn a signer error into a fix, see Debugging signatures and wire shapes.