Practical knowledge about Hyperliquid (HL): API, SDK, accounts, balances, orders, TWAP, WebSocket, limits, fees, risk, historical data, backtesting limits, and API operational facts. This is hands-on HL API practice: mechanics, formulas, thresholds, and pitfalls. Every rule has a reason, and every fact verified live has a verification date.
The facts were checked with this stack: @nktkas/hyperliquid 0.27.1, viem 2.5x, ws 8.x, Node ≥ 20, and TypeScript. Freshness: most material was checked through 2026-09-14; later checks carry their own dates.
How to read annotations inside the files:
- “verified” with a date (in the text or brackets, for example
[verified 2026-09-23]) means the fact was checked with live requests or observation; do not simplify such rules; - “according to documentation, not verified” means the statement comes from public HL documentation and was not checked live;
- “Open questions / not verified” is the final section of every file; a combined summary appears at the end of this page.
Files
| File | Contents | When to open it |
|---|---|---|
| sdk-and-api.md | Mainnet/testnet endpoints, /info and /exchange formats, the @nktkas/hyperliquid SDK and viem, SDK error classes, EIP-712 signing, egress-IP binding | First HL code, choosing the SDK or raw fetch, interpreting SDK exceptions |
| accounts.md | Master, agent/API wallet, sub-accounts, vault, builder address, userRole, collateral modes (manual / Unified Account / portfolio margin), agentEnableDexAbstraction | Connecting a key, trading from a sub-account, the does not exist error, HIP-3 through an agent |
| balance-and-equity.md | clearinghouseState per dex, spotClearinghouseState, portfolio, ledger; capital and margin-ratio formulas; phantom reads and their filtering | Displaying balances, equity-based sizing, risk caps, drawdown safeguards |
| orders.md | Order payload, tif, “market” through IoC, reduceOnly, native TP/SL, price and size rounding, the $10 minimum, responses and errors, cancellations, retries, reading open orders | Any placement, cancellation, or order reconciliation |
| twap.md | twapOrder / twapCancel, the userTwapSliceFills feed, verification procedure | Placing TWAP, account PnL from both feeds, “the position shrinks but there are no fills” |
| market-data.md | meta, precision (szDecimals, tick), HIP-3 dex and asset id, allMids, l2Book, candleSnapshot, spot, equity-market hours on xyz, delisted assets | Market metadata, prices, order book, candles, xyz: markets |
| fills-and-history.md | userFills / userFillsByTime and pagination, fill fields, grouping partials, position and PnL reconstruction, historicalOrders, ledger, leaderboard, builder-fills dump | Account trade history, PnL, builder-fee accounting |
| websocket.md | Subscriptions and frame formats, snapshot vs update, user-tracking limits, ping/pong, reconnect, ghost slots, self-healing | Any WS client, market-data recording, live positions |
| rate-limits.md | IP weight and request weights, address limit, short 429 window, limiter architecture, retry policy, egress IP, bulk-request pace | Load design, 429 storms, bulk reads and backfills |
| fees.md | Maker/taker tiers, userFees, fee calculation from fills, builder fee and approveBuilderFee, builder-revenue accounting, fee effects on strategies | Strategy economics, builder code, backtest fees |
| risk-and-margin.md | updateLeverage, cross/isolated, ROE, liquidation, utilization ceiling and rejection loop, portfolio drawdown, “naked” positions, native and software stops, reliable closing and exit priority, preflight | Leverage, stops, closing positions, preparing for a live launch |
| backtest-and-data.md | Historical data available from the public API (candles, account fills, funding) and its limits, data the API does not provide, caching and reproducibility, why backtesting on HL is hard and where it lies, recording your own data (one-second candles) | Any backtest, recording your own data |
| ops-and-deploy.md | API latency, per-IP limits, safe client shutdown, REST/WS telemetry, and open limit questions | API operational properties |
| pitfalls.md | JS numeric precision, “not read” ≠ “empty,” replica lag, races, caches, remembered state, closing as a critical path, duplicate processes, network, misleading instruments | Trading-code review, diagnosing strange behavior |
Nado and Lighter are documented by their dedicated skills and knowledge bases.
Quick answers
1. How do I obtain account balance and equity?
Call clearinghouseState for every perp dex (without dex, only the main dex is returned; obtain the dex list from perpDexs) → sum marginSummary.accountValue. Add free spot stablecoins from spotClearinghouseState: max(0, total − (spotHold ?? hold)) for USDC/USDT/USDT0/USDH/USDE. Read perp and spot in one Promise.all. Do not add all spot balances: on Unified Account that double-counts them. Do not trust a single read. → balance-and-equity.md §3, §6
2. What account types exist?
Master (funds, withdrawals, approveAgent, approveBuilderFee); agent/API wallet (signs trading actions, holds no funds, cannot withdraw, lifetime up to 180 days, limit of 1 unnamed + 3 named + 2 per sub-account); sub-account (its own funds, margin, and address limit); vault. userRole (weight 60) identifies the address type. → accounts.md §1–4
3. How does an agent wallet work?
ExchangeClient signs with the agent key, but user in info requests is the account address, not the agent address. User or API Wallet 0x… does not exist means the agent is unauthorized, expired, or revoked; retries are useless. Verify the binding with a signed updateLeverage: extraAgents does not show unnamed agents. → accounts.md §2
4. How do I trade from a sub-account?
The main account's agent signs, while defaultVaultAddress in the client is the sub-account address. The sub-account does not need a separate key. reserveRequestWeight does not credit purchased capacity to the sub-account. → accounts.md §3
5. How do I place and cancel a TWAP?
twapOrder { a, b, s, r, m, t }, where m is minutes and t is randomize. The response contains running.twapId. Cancel with twapCancel { a, t: twapId }. According to documentation, a slice runs about every 30 seconds with slippage ≤3%. Live placement was not verified: smoke-test it first. Slices appear neither in userFills nor in frontendOpenOrders, only in userTwapSliceFills. → twap.md §2, §7
6. How do I round price and size?
A perp price has at most 5 significant digits and at most 6 − szDecimals decimal places; an integer price is always valid. Floor size to 10^-szDecimals with an epsilon (Math.floor(sz*f + 1e-9)/f). Send both values as strings, and make the planner and executor call the same function. When price crosses a power of ten, the tick changes tenfold. → orders.md §5, market-data.md §3
7. What is the minimum order?
$10 notional at the rounded order price: Order must have minimum value of $10. Skip openings and partial reductions below the minimum. Do not constrain a full reduceOnly close by the minimum: ceil and lift it to the minimum; the exchange caps it at the position. → orders.md §6
8. Which tif values exist, and how do I make a “market” order?
Gtc rests on the book. Ioc executes what it can and discards the remainder. Alo is post-only: a crossing order is rejected (badAloPxRejected). HL has no market-order type: use an IoC limit at mid ± slippage; exactly at mid it will not execute. TP/SL orders are trigger orders activated by mark price. → orders.md §2, §4
9. What are the weights and limits?
IP: approximately 1200 weight/min across /info + /exchange. Weights: 2 for l2Book, allMids, clearinghouseState, spotClearinghouseState; 60 for userRole; 20 for nearly everything else, with a response-volume surcharge on history downloads. Exchange IP weight is 1 + floor(n/40) per batch. Address capacity is 10,000 + 1 request per $1 of volume; after exhaustion, one request per 10 seconds remains. The limit window is shorter than one minute; configure limiter sustained rate, burst, and concurrency explicitly for the actual workload. → rate-limits.md §1–4, §9
10. What should I do on 429 and 5xx?
A 429 is rejected before the matching engine, so retrying it is safe. A 5xx, timeout, or disconnect means the outcome is unknown: do not repeat OPEN/INCREASE, partial reduceOnly, or transfers; reconcile against the book first. Cancel, updateLeverage, agentEnableDexAbstraction, and a full reduceOnly close are idempotent. → orders.md §10, rate-limits.md §5
11. Which WS subscriptions exist, and what are their limits?
Use wss://api.hyperliquid.xyz/ws; ping every 30 seconds because the server disconnects after 60 seconds of silence. For user subscriptions (userFills, orderUpdates, allDexsClearinghouseState, webData3), documentation states 10 unique addresses per IP, while about 20 total across all connections was measured. New connections from the same IP add no slots. Rejection arrives on channel:"error". There are about 1000 total subscriptions per IP. WS does not provide spot balances. → websocket.md §2, §4
12. What are the candle limitations?
candleSnapshot returns at most about 5000 candles per call; if the window is wider, it returns the newest candles. Depth: 5m ≈ 18 days, 15m ≈ 52 days. The minimum interval is 1m; there are no one-second candles, so record them yourself from WS trades. The final bar is open. For HIP-3, use coin: 'xyz:SP500' without a dex field. → market-data.md §8, backtest-and-data.md §2, §8
13. How much are fees, and how does builder fee work?
Base perp tier: maker 1.5 bps, taker 4.5 bps, with the tier based on 14-day volume. userFees returns the account's rates; actual fees are in each fill's fee field. Builder fee uses builder: { b, f } in the order, with lowercase b and f in tenths of a basis point; the perp cap is 100 (0.1%). It requires approveBuilderFee signed by the master wallet. If f exceeds the approved value, the entire order is rejected. → fees.md §1, §3
14. What is the liquidation formula?
Approximately ROE_liq = leverage / (2 × maxLeverage) − 1; the price move to liquidation is 1/leverage − 1/(2·maxLeverage). At maximum leverage, liquidation occurs at −50% ROE. This is the base tier without other cross collateral or funding. → risk-and-margin.md §5
15. How do I set leverage?
Call updateLeverage({ asset, isCross: !onlyIsolated, leverage }), where leverage = max(1, min(floor(x), maxLeverage)). Set it before the entry order. Most xyz pairs are isolated-only. Per-coin leverage is visible only when a position is open. → risk-and-margin.md §2
16. Why are orders and positions on xyz: missing?
Each HIP-3 dex is a separate universe: request clearinghouseState, frontendOpenOrders, meta, and allMids with dex: 'xyz'. Asset id is 100000 + perpDexIndex × 10000 + index. The agent needs agentEnableDexAbstraction. Exception: userFills/userFillsByTime ignore the dex parameter. → market-data.md §4–5, accounts.md §5.3
17. How do I export trade history?
userFills returns up to 2000 latest fills. userFillsByTime returns up to 2000 oldest fills from startTime, so page forward with startTime = max(time) from the page (without + 1: a page can end inside a millisecond; corrected 2026-09-23), deduplicate by tid, and do not pass dex. Group partials by oid. Fetch TWAP slices separately from userTwapSliceFills. → fills-and-history.md §2–5
18. Why is backtesting on HL hard?
Fine candle intervals are available only for the latest ~5000 bars (5m ≈ 18 days), and the public API provides neither one-second candles nor historical order books. Intrabar price order and book queue position are invisible, and funding is included in neither candles nor closedPnl. Therefore an HL backtest is, at best, a relative comparison of alternatives; absolute return figures are almost always optimistic. Missing data can be obtained only through your own recording started in advance. → backtest-and-data.md §5, §7, §8
19. How do I test code without real orders? Use isolated tests with a stubbed network interface and representative response fixtures. Test partial batch success and ambiguous outcomes separately: “the exchange applied it, but the client timed out” requires reconciliation against the book, not a blind retry. A test fixture is not evidence that an exact error string was observed on the exchange. → orders.md §7, §10, §11
Open questions (summary)
Everything below is either not verified live or contradictory. Details and adopted working assumptions are in the “Open questions” section of the named file.
SDK, signing, accounts
- Whether
fetchOptions.dispatcherreaches the SDK transport orsetGlobalDispatcheris required: verify with an echo request. → sdk-and-api.md agentEnableDexAbstraction: exact signature and idempotency; a call throughvaultAddresson a sub-account and on a freshdisabledaccount was not verified with a live key. → sdk-and-api.md, accounts.md- The asset-id formula was verified only for
xyz; other HIP-3 dexes were not checked. → sdk-and-api.md hyperliquidChain: 'Testnet'for user-signed actions,usdSendon a non-unified account, the 0.27.x SDK call forapproveBuilderFee. → sdk-and-api.md, fees.md- Agents: semantics of
validUntil = 0(assumed “no expiry”), weight ofextraAgents(assumed 20), error text when the agent limit is exceeded, repeatedapproveAgentbehavior, expiration of an agent created in the UI. → accounts.md - Relationship between portfolio margin and Unified Account;
usdunits insubAccountTransfer. → accounts.md
Balance and margin
- A jump in
accountValueon a unified account without fills after placing orders (double-countedholdor reads taken at different moments). → balance-and-equity.md - Capital with borrowing (
borrowed,ltv); USDC under isolated positions outsideaccountValue; meaning ofspotState.totalRawUsd;withdrawablesemantics on unified/PM. → balance-and-equity.md - HIP-3 dex collateral isolation in different account modes: shared pool or separate funds. → balance-and-equity.md, risk-and-margin.md
- Whether selected leverage affects liquidation price on cross; liquidation formula without margin tiers; ADL, partial liquidation,
updateIsolatedMargin. → risk-and-margin.md
Orders and TWAP
- Whether HL accepts a reduceOnly IoC below $10 without lifting the size (the reliable approach remains lifting it). → orders.md
- Weight of
openOrders(assumed 20) and its fields. → orders.md, rate-limits.md modify/batchModify(whether oid and queue position are preserved),cancelByCloid,scheduleCancel, how longorderStatusis retained beforeunknownOid. → orders.md- Exact Alo and other rejection strings,
orderTypeon trigger orders, spot price rule. → orders.md twapOrder/twapCancelwere not verified live:randomizesemantics, minimum TWAP and slice notional,reduceOnlyafter the position closes, boundaries form. → twap.md- Slice pace (5–9 per minute observed versus one per 30 seconds in documentation); whether
userTwapSliceFillshonorsstartTime;userTwapSliceFillsByTime,twapHistory, WSuserTwapHistory. → twap.md
Data and history
- Exact
candleSnapshotweight and response-volume surcharge;1mhistory depth; weekly and monthly intervals. → market-data.md, rate-limits.md userFillsByTimedepth (documentation says only about the latest 10,000 fills for an address);aggregateByTimeand pagination; shapes ofuserFundingand theliquidationfill field. → fills-and-history.md, backtest-and-data.md- WS
trades,candle,bbo, andactiveAssetCtxwere not checked on a live socket; whether a trade snapshot is sent on reconnect. → websocket.md - Trading hours for HIP-3 dexes other than
xyz; funding and OI fields inmetaAndAssetCtxs. → market-data.md
Limits and WebSocket
- User tracking: 10 (documentation), 15 (error text), ~20 (measurement)—what exactly each number counts; WS connections per IP: 10 or 100 (plan for 10). → websocket.md, rate-limits.md
- Length of the short IP-limit window; sustained ~200–300 info requests/min during bulk sequential requests from one IP versus the theoretical 600. → rate-limits.md
- How
nRequestsCap/nRequestsSurpluschange afterreserveRequestWeight; address-limit error text; “429 on exchange = not executed” was verified live but not in documentation. → rate-limits.md - Built-in SDK retries and whether the WS transport's
maxRetries=3can be removed. → rate-limits.md, websocket.md
Fees
- Tiers above the base tier and rebates have medium confidence; spot and HIP-3 dex rates; whether builder fee is included in the
feefield; whetherbuildermay be attached to trigger orders. → fees.md
Historical data and backtesting limitations
- The one-second-candle recording recipe in this knowledge base was not verified live; the effect of one-second resolution on stops was not measured. → backtest-and-data.md
- Candles do not reveal book queue, actual latency, or slippage; the effect of look-ahead on the last bar was not measured. The
userFundingresponse cap (500 rows in one measurement) was not checked separately. → backtest-and-data.md
Operations and other topics
- Exact limits for user-specific addresses and total WS connections per IP conflict and require another check. → ops-and-deploy.md §4
- oid and the 2^53 boundary: at what value precision loss becomes real (store it as a string already). → pitfalls.md
- A safe interval for REST fallback position reads during WS degradation is unknown. → pitfalls.md
Disclaimer
This is not financial advice or a recommendation to trade. Numbers from backtests and observations describe particular periods and do not guarantee results. The Hyperliquid API, limits, fees, and response shapes change without notice: before use, verify facts against current official HL documentation and live requests, especially anything marked “not verified.” Run code snippets in dry-run mode and with minimal capital first. You are responsible for how you use them.
Code: the @markpaper/hl-kit package
The rules in this knowledge base are implemented in the packages/hl-kit library in the markpaper repository (npm @markpaper/hl-kit, Apache-2.0): price and size rounding and the $10 minimum, asset ids and metadata registry, /info and /exchange throttling, equity across all dexes, fills with TWAP, candles, fees and liquidation, a WS client, and safe order placement. Documentation and examples are on the hl-kit SDK page. Functions tagged @experimental correspond to “according to documentation, not verified” notes.
License
The hyperliquid knowledge base and skill are distributed under CC BY 4.0. You may copy, adapt, and use them, including commercially, but every publication must credit “markpaper — Hyperliquid knowledge base,” link to the original and the license, and indicate changes. See LICENSE.md for the terms.
© markpaper authors. Licensed under CC BY 4.0: when publishing or adapting the material, credit “markpaper — Hyperliquid knowledge base” and link to the original and the license.