Short answer:Hyperliquid's public POST /info endpoint gives you funding with no API key: metaAndAssetCtxs returns the current hourly rate for every perp, predictedFundings returns the predicted rate on Hyperliquid, Binance and Bybit, and fundingHistory returns past hourly prints. This recipe builds a read-only Python monitor that annualizes those rates, flags any above your threshold and sends alerts to the console or a webhook, on mainnet or testnet.
Everything is a public POST /info call: mainnet https://api.hyperliquid.xyz, testnet https://api.hyperliquid-testnet.xyz. No key, no wallet.
metaAndAssetCtxs returns [meta, assetCtxs]; universe[i] pairs with assetCtxs[i], and funding is the current hourly rate.
predictedFundings returns predicted rates for HlPerp, BinPerp and BybitPerp, each with fundingIntervalHours (1 on Hyperliquid, often 4 or 8 on the others). Entries can be null.
fundingHistory takes {coin, startTime, endTime} in ms and returns at most 500 rows per call, so paginate.
Funding is paid every hour at one-eighth of an 8-hour formula rate and is capped at 4% per hour. The baseline is 0.00125% per hour (10.95% a year simple, 11.6% compounded).
Asset IDs differ between mainnet and testnet (we saw BTC = 0 on mainnet and 3 on testnet). Join data by coin name, never by index.
DifficultyBeginner
Time30–45 min
Cost$0 (public endpoints, no account)
Works withClaude Code, Cursor, ChatGPT / Codex, Grok
What will you build?
A Python CLI that shows current and predicted funding for every Hyperliquid perp, annualized and clearly labelled, prints funding history, and watches for any asset whose funding crosses a threshold you set, with deduplicated alerts to the console or an optional webhook. It never signs anything and never touches the exchange endpoint.
Who is it for?
Builders who want funding data in their own tools, dashboards or research notebooks, and anyone starting on Hyperliquid who wants a first project that can't lose money.
Not for:Placing trades, funding-arbitrage execution or anything that needs a wallet. This monitor only reads public data and reports numbers. It doesn't tell you what to do with them.
How Hyperliquid Funding Works, and What the API Gives You
Funding is what keeps a perpetual's price near the spot price. When the perp trades above the oracle, longs pay shorts; when it trades below, shorts pay longs. On Hyperliquid this happens every hour. The rate is computed with the same 8-hour formula that centralised exchanges use, and one-eighth of it is paid each hour. The formula includes a fixed interest component of 0.01% per 8 hours, so a quiet market sits at 0.00125% per hour, which is why so many perps show the same number at once.
The API gives you three views:
Now:metaAndAssetCtxs returns every perp's metadata plus a context object with funding, premium, markPx, oraclePx and openInterest.
Predicted:predictedFundings returns Hyperliquid's predicted rate next to Binance's and Bybit's for the same coin. Each venue has its own interval. If Binance or Bybit omits the interval (we saw 21 Binance entries without it, all for coins already delisted on Hyperliquid), the monitor shows "interval unknown" instead of guessing an APR.
History:fundingHistory returns one row per hour for a coin, with fundingRate and premium.
On annualizing: multiplying an hourly rate by 24 × 365 is a convention that makes venues comparable. It isn't a forecast: funding changes every hour and can flip sign. This monitor labels every annualized number as such and never turns a rate into a "do this" message. For the API basics (endpoints, asset IDs, rate limits), start with the Hyperliquid API starter. To see large trades and public positions instead, use the read-only whale and large-trade tracker. More Hyperliquid recipes are on the Hyperliquid platform page.
What prompt do you paste into your AI coding tool?
Works in Claude Code, Cursor, Codex/ChatGPT, Grok or any agent that can write files. Paste it into an empty folder. Read what it builds before you run anything.
You are building a READ-ONLY Hyperliquid funding-rate monitor in Python.
It only calls the public POST /info endpoint. It must never import a
signing library, read a private key, or call /exchange. Use only what is
documented at https://hyperliquid.gitbook.io/hyperliquid-docs (Info
endpoint > Perpetuals; Trading > Funding). If unsure, stop and ask me.
Project: hl-funding/
- Python 3.10+ (run with `python3`), `requests`, `pytest`. If
`python3 -m venv` fails (Debian/Ubuntu), install `python3-venv` or
`pip install requests pytest` directly. No SDK needed:
the official SDK has no helper for predictedFundings, so use raw POSTs.
- hl_funding.py
- MAINNET https://api.hyperliquid.xyz, TESTNET
https://api.hyperliquid-testnet.xyz. post_info(body, testnet) POSTs JSON
to {base}/info, backs off and retries on HTTP 429. Each of these calls
weighs 20 of the 1200/min per-IP budget; fundingHistory adds weight
per 20 rows returned.
- annualize(rate, interval_hours=1) = rate * (24 / interval_hours) * 365
(SIMPLE, a comparison convention, not a forecast). Also
annualize_compounded() = (1+rate)**(8760/interval_hours) - 1, and label
which one you show (the baseline 0.00125%/h is 10.95% simple, 11.6%
compounded).
- current_funding(testnet): {"type":"metaAndAssetCtxs"} returns
[meta, assetCtxs]; zip meta["universe"][i] with assetCtxs[i]. Row per
perp: coin, asset_id (= index; it DIFFERS between mainnet and testnet,
so never hardcode it and never join on it), funding_1h = float(funding)
(an HOURLY rate), apr, premium, markPx, oraclePx, openInterest,
dayNtlVlm. Skip universe entries with "isDelisted": true by default,
filtering AFTER zipping so indexes stay aligned. premium and midPx can
be null.
- predicted_funding(testnet): {"type":"predictedFundings"} returns
[[coin, [[venue, info_or_null], ...]], ...]; venues are "HlPerp",
"BinPerp", "BybitPerp". info = {fundingRate, nextFundingTime,
fundingIntervalHours}. Skip null entries (coin not listed on that
venue). Annualize EACH venue with its own fundingIntervalHours (HL is
1, Binance/Bybit are often 4 or 8). Some rows omit
fundingIntervalHours (on 2026-10-22, 21 BinPerp entries did, all for
coins delisted on Hyperliquid; HlPerp and BybitPerp always had it). If HlPerp lacks it, default to 1 (HL pays
hourly). If ANY OTHER venue lacks it, do NOT guess: set interval and
apr to None, show "interval unknown", and keep it out of threshold
alerts (a 1h guess would overstate a 4h or 8h venue's APR 4-8x).
Don't build countdowns on
nextFundingTime: for HlPerp we saw it equal the top of the CURRENT hour.
- funding_history(coin, start_ms, end_ms): {"type":"fundingHistory",
"coin","startTime","endTime"} returns [{coin, fundingRate, premium,
time}]. Responses cap at 500 rows: if a page has 500 rows, request
again from last time + 1. Cap the number of pages.
- snapshot(testnet): current rows joined with predicted data BY COIN
NAME: predicted_1h / predicted_apr from HlPerp, plus other_venues
{venue: apr, or None when the interval is unknown}.
- over_threshold(rows, threshold_apr, field="apr"): |value| >= threshold,
either sign; ignore None.
- alerts.py: Alerter(webhook_url=None, cooldown_s=3600). Always prints to
the console; if a webhook URL is set, POST {"text": msg, "content": msg}
(works for Slack- and Discord-style hooks). Fire once when a coin
crosses, stay quiet during the cooldown, re-arm when it drops back
below. Wrap the webhook POST in `except Exception`: log the error and
keep looping; a webhook failure must never crash the monitor. The
message is descriptive only: coin, hourly rate, simple APR, predicted
APR, which side pays ("longs pay shorts" / "shorts pay longs"), the
threshold, and the words "Informational only". No buy/sell/long/short
suggestions.
- monitor.py (argparse subcommands; --testnet on EACH subcommand parser):
- snapshot [--coins BTC,ETH] [--top 20] [--threshold PCT]: table sorted
by |APR| with coin, asset id, hourly %, APR, predicted APR, Binance APR,
Bybit APR ("interval unknown" when that venue omits the interval),
and a neutral "over threshold" marker. Header states that
APR is hourly x24x365, simple, not a forecast.
- history COIN [--hours 72] [--last 24]: hourly prints in UTC plus the
mean, labelled "past data, not a forecast".
- watch --threshold PCT [--interval 60 (min 30)] [--cooldown 3600]
[--webhook URL or env HLF_WEBHOOK_URL] [--use-predicted] [--once]
[--max-loops N].
- tests/conftest.py that inserts the project root into sys.path, so
`pytest` works from any directory without installing the package.
- tests/ (pytest, mock HTTP with a fake session, no network): annualize
(incl. a 8h venue), delisted skipped with asset ids kept, null venue
skipped, join by coin name, testnet vs mainnet URL, pagination past 500
rows, threshold either sign, alert dedupe/re-arm + webhook payload, a
webhook that raises (loop continues), a missing fundingIntervalHours
(HlPerp -> 1; BinPerp -> apr None, "interval unknown", never alerted),
and a grep test that the APP MODULES (hl_funding.py, alerts.py,
monitor.py; not tests/, which quote these strings) contain no
"/exchange", "private_key", "eth_account" or "Exchange(".
- .gitignore (.env, __pycache__/, .venv/), README with the commands.
Testnet funding comes from thin testnet books and is NOT realistic; say so
in the README. Show me the file plan first. After writing, tell me exactly
what to run.
How do you build it, step by step?
Set up a clean folder (hl-funding) with the Safety Pack rules file, then paste the prompt into your AI coding tool. Approve the file plan before it writes code.
Check that each perp's hourly rate times 8,760 matches its APR column, and that most quiet perps sit at +0.00125% per hour (+10.95% APR).
Compare with testnet:python3 monitor.py snapshot --coins BTC,ETH,SOL --testnet. The asset IDs differ from mainnet and the funding numbers will look wild, because testnet books are thin. Testnet is for plumbing, not for reading the market.
Pull history:python3 monitor.py history ETH --hours 600. That's more than 500 hourly rows, so it proves the pagination works.
Run one alert pass:python3 monitor.py watch --threshold 50 --once. To test a webhook, point --webhook at a Slack or Discord incoming webhook you own, or at a local receiver. Then run watch with --max-loops 2 --interval 30 and confirm the second loop doesn't repeat the same alerts.
Leave it running if you want: python3 monitor.py watch --threshold 50 --interval 120. Keep the interval at 60 seconds or more. Funding only settles hourly, and each poll costs rate-limit weight.
How do you test it in paper or demo mode first?
This recipe is read-only from start to finish, so there's nothing to paper-trade: it never holds a key and can't place an order. Testnet support is there so you can test your plumbing (URLs, parsing, alerts) against a second network with different asset IDs.
What safety checks does it need before real money?
Tick every box before the bot touches real money. The full rules file, .gitignore and pre-commit hook are in the Safety Pack.
Key handling: API keys and private-key files live in environment variables or a secrets manager. Never in code, prompts, chat logs, screenshots or git. .env and *.pem are in .gitignore, and your AI tool is blocked from reading them (see the Safety Pack).
Position limits: hard caps in config (max contracts per order, max total exposure, max daily loss). The bot refuses any order above them, and the caps are checked in code, not just in the prompt.
Kill switch: one command or one file (touch KILL) stops new orders immediately, and a second command cancels every resting order through the venue's cancel-all endpoint.
Paper first: paper or demo mode is the default. Live trading needs an explicit --live flag and a typed confirmation, and you only flip it after days of clean paper logs.
The monitor has no key, no wallet and no signing library. A test fails the build if any app module (not the tests) mentions /exchange, private_key, eth_account or Exchange(.
If an AI tool suggests adding a private key "to read your positions", refuse. Positions for any address are public through clearinghouseState; only the address is needed.
Treat webhook URLs as secrets: keep them in .env or an environment variable (HLF_WEBHOOK_URL), never in the repo.
Alerts are descriptive ("shorts pay longs, 92% APR, informational only"), never "go short" or "go long". Annualized numbers are a convention, not a forecast.
Poll at 60 seconds or more and back off on HTTP 429. The info endpoint shares a 1,200-weight-per-minute budget per IP.
Endpoints and rules were checked against these pages on Oct 22, 2026. APIs change, so if something here disagrees with the official docs, trust the docs and tell us.
Frequently asked questions
How do I get Hyperliquid funding rates from the API?
POST {"type":"metaAndAssetCtxs"} to https://api.hyperliquid.xyz/info. The response is [meta, assetCtxs]; pair meta.universe[i] with assetCtxs[i] and read funding, which is the current hourly rate as a string. No API key is needed.
How often is funding paid on Hyperliquid?
Every hour. The rate comes from an 8-hour formula (average premium plus a clamped interest component), and one-eighth of it is paid each hour. Funding is capped at 4% per hour, and the payment is position size × oracle price × funding rate.
How do I annualize a Hyperliquid funding rate?
Multiply the hourly rate by 24 × 365 (8,760) for a simple APR. For venues with 8-hour funding, multiply by 3 × 365 instead. That's a comparison convention, not a forecast: rates change every hour and can flip sign. Compounding gives a slightly higher figure (the 0.00125%-per-hour baseline is 10.95% simple and about 11.6% compounded).
What does predictedFundings return?
For each coin, a list of venues (HlPerp, BinPerp, BybitPerp) with fundingRate, nextFundingTime and fundingIntervalHours. A venue's entry is null if the coin isn't listed there. Some Binance entries omit fundingIntervalHours (21 on 2026-10-22, all for coins delisted on Hyperliquid); don't assume 1h for them, since Binance and Bybit usually settle every 4 or 8 hours. It only covers the first perp dex, not HIP-3 builder-deployed dexes.
How do I get historical funding rates on Hyperliquid?
POST {"type":"fundingHistory","coin":"ETH","startTime":<ms>} with an optional endTime. Each row has coin, fundingRate, premium and time. Responses cap at 500 rows, so to go further back, request again starting from the last row's time plus one.
Why is testnet funding so different from mainnet?
Testnet books are thin, so the premium, and with it the funding rate, swings far more than on mainnet. Testnet APRs can be many times the mainnet figure for the same coin. Asset IDs differ too. Use testnet to test code, not to read the market.
Is a high funding rate a trading signal?
Not on its own, and this recipe doesn't treat it as one. The monitor reports who pays whom and how much, annualized by convention. It doesn't suggest trades. BotCookery doesn't give financial advice.
Get new recipes by email
When a new bot recipe passes its model tests, we'll send it to you. Free. No picks, no signals, ever.
An AI prompt that builds a Hyperliquid API starter in Python: public info reads on mainnet and testnet, then testnet-only orders signed by an API (agent) wallet, with tick rounding, a $10 minimum and a dead-man switch.
An AI prompt that builds a read-only Hyperliquid whale and large-trade tracker in Python: websocket trade alerts above a USD threshold, plus position and fill views for public addresses. No keys, no copy trading, informational only.
An AI prompt that builds four small wallet-safety tools for crypto and prediction-market bots: a secret scanner pre-commit hook, an env-file guard, a kill switch and a read-only wallet audit that flags balances and unlimited approvals.