For buyers
API documentation
Free endpoints (coverage, discovery, availability) let you decide what to buy. Data endpoints return HTTP 402 Payment Required (x402 v2) until you pay with a signed authorisation, in USDC, on Base (the facilitator pays the gas) or directly on Hyperliquid with the same USDC you trade with (gasless).
Base URL: https://api.hyperextend.xyz
Discover before you pay
All free, all unauthenticated: check what's available and how deep before spending anything.
| Endpoint | Answers |
|---|---|
GET/v1/discovery | What's available at a glance: dex/coin counts, intervals, availability lag. |
GET/v1/dexes | Every dex (main, HIP-3 and HIP-4) with first/last seen. |
GET/v1/dexes/{dex}/coins | The active universe on a dex. |
GET/v1/coins/{coin} | Which dexes a coin trades on. |
GET/v1/coins/{coin}/history | Listing / delisting / leverage-change log over time. |
GET/v1/outcome_markets?start=&end= | HIP-4 outcome markets trading in a window (epoch-ms, both optional). Each market's name plus the side coins & outcome id to buy candles / ctx / OI with. |
GET/v1/availability/{coin} | Per-dex first/last for ctx + candles. |
GET/v1/coverage/{coin}?start=&end= | Gap manifest for OI / ctx over a window. |
GET/v1/candles/{coin}/coverage?start=&end= | Gap manifest for candles over a window (≤31 days). |
GET/v1/trades/discovery?coin= | Trades model: served-live, archive floor, window cap, pricing; ?coin= adds hot first/last. |
GET/v1/trades/cache | Archive hours already warm in the cold cache, as coalesced windows; read inside them and the cold-pull fee never applies (trades and liquidations share the cache). |
GET/v1/liquidations/discovery?coin= | Liquidations model: archive floor, ~2h lag, window cap, pricing; ?coin= adds dex + rate. |
POST/v1/mailing/subscribe | JSON mailing signup for agents (body {"email"}); returns a confirm token inline (POST /v1/mailing/confirm with it to activate). Double-opt-in archive updates. |
The payment flow
We speak x402 v2, so use Coinbase's official
x402 client. It
does the whole dance for you: GET → 402 challenge (in the
PAYMENT-REQUIRED header) → sign an EIP-3009 authorisation → retry with the
PAYMENT-SIGNATURE header → 200. You only need USDC on Base; the
facilitator pays gas and the receipt returns in PAYMENT-RESPONSE.
Python (official x402 client)
# pip install "x402[evm]" (Coinbase's official x402 client; handles 402 -> pay -> retry)
import asyncio
from eth_account import Account
from x402 import x402Client
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
from x402.http.clients import x402HttpxClient
async def main():
client = x402Client()
register_exact_evm_client(client, EthAccountSigner(Account.from_key(MY_PRIVATE_KEY)))
url = "https://api.hyperextend.xyz/v1/candles/BTC/1m?start=1748736000000&end=1748822400000" # a 1-day window with data
async with x402HttpxClient(client) as http:
r = await http.get(url) # pays automatically; needs USDC on Base
candles = (await r.aread()) and r.json()
asyncio.run(main()) x402HttpxClient reads the challenge, signs with your key, and retries
automatically, with no protocol code to hand-roll. There's a matching JS/TS client too.
Or pay on Hyperliquid (HyperCore)
The 402's accepts also offers a hyperliquid:mainnet
rail: pay directly with the same USDC you trade and open positions with on
Hyperliquid: no bridging, no second wallet, no gas. There's no facilitator; you
sign a HyperliquidTransaction:SendAsset with the
hyperliquid SDK,
echo the quoted amount verbatim, and retry with PAYMENT-SIGNATURE;
HyperCore settles it gaslessly. Pay from your spot or perps balance; Hyperliquid's
unified account means one USDC funds both.
Or pay once, then stream (batch settlement)
For high-throughput use (many small calls in a row), Base also offers a
batch-settlement rail in accepts (alongside exact).
Instead of settling on-chain every request, you deposit USDC into an escrow once,
then pay per request with a cumulative off-chain voucher the server verifies
locally (no per-request on-chain tx, ~instant). A keyless channel manager periodically
redeems the accumulated vouchers in a single on-chain claim, so N requests
cost one deposit + ⌈N/batch⌉ claims instead of N settles. It stays keyless on our side
(Coinbase's CDP holds the claiming key and pays the gas), and it's opt-in:
you only need USDC on Base (no ETH), since CDP gasses the deposit and claim.
- Deposit once (request 1). The first paid call opens a payment channel:
the client deposits USDC into the escrow on Base (a multiple of the request price, set by the
deposit_multiplierbelow, so it covers a run of calls). CDP broadcasts and gasses it; you sign, you don't pay gas. - Stream vouchers (requests 2…N). Each subsequent call is a purely
off-chain signed voucher carrying the growing cumulative
maxClaimableAmount. The server verifies it locally and returns data immediately, with no on-chain round-trip. - We claim, in batches. Our keyless channel manager periodically redeems the
latest cumulative voucher in a single on-chain claim to
payTo. You never over-pay, since the voucher is cumulative rather than per-call. - Refund the remainder (optional). Spent less than you deposited? Cooperatively refund the unused balance at the end (a fully-spent channel simply has nothing to return).
Register only the batch-settlement scheme and the official
x402[evm] client selects it from the 402's accepts and
handles the deposit + vouchers for you:
# pip install "x402[evm]" (register ONLY batch-settlement so the client picks it over exact)
import asyncio, httpx
from eth_account import Account
from x402 import x402Client
from x402.http.clients import x402_httpx_transport
from x402.mechanisms.evm import EthAccountSignerWithRPC
from x402.mechanisms.evm.batch_settlement.client import (
BatchSettlementEvmScheme, BatchSettlementEvmSchemeOptions,
BatchSettlementDepositPolicy, InMemoryClientChannelStorage,
)
async def main():
signer = EthAccountSignerWithRPC(Account.from_key(MY_PRIVATE_KEY), rpc_url="https://mainnet.base.org")
scheme = BatchSettlementEvmScheme(signer, BatchSettlementEvmSchemeOptions(
deposit_policy=BatchSettlementDepositPolicy(deposit_multiplier=5), # escrow = 5x the request price
storage=InMemoryClientChannelStorage(),
))
client = x402Client().register("eip155:*", scheme) # batch-settlement only -> chosen over exact
url = "https://api.hyperextend.xyz/v1/candles/BTC/1m?start=1748736000000&end=1748822400000" # a 1-day window with data
async with httpx.AsyncClient(transport=x402_httpx_transport(client)) as http:
for _ in range(100): # request 1 opens the channel (on-chain deposit); the rest are vouchers
r = await http.get(url) # ~instant, no per-request on-chain tx
candles = (await r.aread()) and r.json()
asyncio.run(main())
The snippet above is the whole integration: the official x402[evm] client opens
the channel and signs the vouchers for you. Best when you'd otherwise make hundreds of
per-request settles; for the occasional call, plain exact is simpler.
Endpoints
| Endpoint | Notes |
|---|---|
GET/v1/candles/{coin}/{interval}?start=&end= | Historical OHLCV for a coin & interval over a time window. Base rate on main & spot; premium on HIP-3 and HIP-4 outcome dexes. |
GET/v1/candles/{coin}/{interval}/latest?n= | The most recent n candles, a cheap recent-window convenience. |
GET/v1/asset_ctx/{coin}?start=&end= | Open interest / funding / mark / oracle / mid / volumes. Premium rate. |
GET/v1/asset_ctx/{coin}/latest?n= | The most recent n OI / ctx snapshots, a cheap recent-window convenience. Premium rate. |
GET/v1/outcome_ctx/{coin}?start=&end= | HIP-4 outcome-side mark / mid / circulating supply / volumes. Premium rate; served live (no lag). |
GET/v1/outcome_ctx/{coin}/latest?n= | The most recent n outcome-side snapshots. Premium rate; served live. |
GET/v1/outcome/{outcome}/oi?start=&end= | Derived two-sided open interest for a HIP-4 outcome market, per minute. Premium rate; served live. |
GET/v1/trades/{coin}?start=&end= | Raw trade tape, mirroring Hyperliquid's WsTrade verbatim: coin, side, px, sz, time, hash, tid and users:[buyer, seller]. Priced per asset-hour (not per row); HIP-3 / HIP-4 premium. Each uncached archive hour pulled adds a $0.05 cold-pull charge and warms the cache for everyone after. |
GET/v1/trades/coverage?coin=&start=&end= | Archive coverage for a coin over a window (≤7 days): which hours have trades + the gaps. Warms the cache. Priced floor + $0.05 per archived hour examined. |
GET/v1/liquidations/{coin}?start=&end= | Forced-liquidation tape: a trade row (coin, side, px, sz, time, hash, tid, users:[buyer, seller]) plus the liquidation markers (method, markPx, liquidatedUser, dir) over a window. Archive-derived (no public HL feed; ~2h lag). Priced per asset-hour at a third of trades; +$0.05 per uncached archive hour pulled (warms the cache). |
GET/v1/liquidations/coverage?coin=&start=&end= | Archive coverage for a coin's liquidations over a window (≤7 days): which hours have liquidations + the gaps. Warms the cache. Floor + $0.05 per archived hour examined. |
Pricing
Two-part tariff: cost = floor + rows × per_row, billed per row returned. The per-row rate is tiered by what the data is.
Charged on every request, before any rows.
Main-perp & spot candles.
Open interest, HIP-3 perps, HIP-4 outcome markets.
Premium is the data Hyperliquid keeps no history of. Responses are
paginated: walk wider ranges with the X-Next-Start cursor returned in the
response headers.
| Request | Cost |
|---|---|
| 100 main / spot candles (base) | $0.002 |
| 1 day of 1m candles (1,440 rows, base) | $0.0154 |
| 100 rows of OI / outcome data (premium) | $0.0035 |
| 1 day of 1m candles on a HIP-3 / outcome dex (premium) | $0.037 |
Trades
Each trade row mirrors Hyperliquid's WsTrade verbatim:
coin, side, px, sz, time, hash, tid and users:[buyer, seller] (the
counterparty addresses HL's own feed carries). The raw tape is priced per
asset-hour (one (coin, hour) bucket, which can hold thousands of fills)
rather than per row. HIP-3 / HIP-4 are premium. Each
uncached archive hour a request pulls adds a per-hour cold-pull charge (it
reconstructs that hour from the archive and warms the cache, so already-cached hours don't
re-charge):
cost = floor + asset_hours × per_asset_hour (+ cold-pull × uncached_hours)
floor = $0.001 per request
per_asset_hour = $0.015 base (main & spot)
= $0.03 premium (HIP-3 perps & HIP-4 outcomes)
cold-pull = $0.05 per uncached archive hour pulled (warms the cache for everyone after) | Request | Cost |
|---|---|
| 1 hour of BTC trades (base, cached) | $0.016 |
| 1 day of BTC trades (24 asset-hours, base, cached) | $0.361 |
| 1 hour of a HIP-3 / outcome coin (premium, cached) | $0.031 |
| 1 uncached archive hour (base + cold-pull) | $0.066 |
Archive coverage: GET /v1/trades/coverage?coin=&start=&end=
(≤7-day window) reports which archived hours hold a coin's trades and where the gaps are, and
warms the cache for everyone after. Priced $0.001 + $0.05 × archived
hours examined (the same per-hour cold rate as a read's cold-pull).
See what's already warm for free: GET /v1/trades/cache lists the
cached archive hours as coalesced windows; a read wholly inside them pays only the
per-asset-hour rate, never the cold-pull. Warm hours are exchange-wide (every coin) and shared
with liquidations.
Liquidations
The forced-liquidation tape (GET /v1/liquidations/…) is the same
per asset-hour model as trades but a third of the rate:
liquidations are sparse, so an hour holds far fewer rows. Each row is a
full trade row (coin, side, px, sz, time, hash, tid,
users:[buyer, seller]) plus the liquidation markers
(method market | backstop, markPx, liquidatedUser,
which of the two users was force-closed, and dir). Hyperliquid
publishes no liquidations feed at all, so this is reconstructed from the
node-fills archive:
cost = floor + asset_hours × per_asset_hour (+ cold-pull × uncached_hours)
floor = $0.001 per request
per_asset_hour = $0.005 base (main & spot)
= $0.01 premium (HIP-3 perps & HIP-4 outcomes)
cold-pull = $0.05 per uncached archive hour pulled (warms the cache for everyone after) | Request | Cost |
|---|---|
| 1 hour of BTC liquidations (base, cached) | $0.006 |
| 1 day of BTC liquidations (24 asset-hours, base, cached) | $0.121 |
| 1 hour of a HIP-3 / outcome coin (premium, cached) | $0.011 |
| 1 uncached archive hour (base + cold-pull) | $0.056 |
Archive-derived: there's no live tier (no public feed exists), so
liquidations are available ~2h after the hour closes.
GET /v1/liquidations/coverage?coin=&start=&end= reports which archived
hours hold a coin's liquidations and where the gaps are, and warms the cache for everyone after.
Network & USDC
The accepts array advertises what this deployment takes: Base and Hyperliquid,
with Base offering both per-request exact and the opt-in
batch-settlement scheme. Always confirm the exact asset and (for Base) the
EIP-712 domain from accepts[].asset / accepts[].extra rather than
hardcoding them.
| Rail | Identifier | USDC |
|---|---|---|
Base (EVM) · exact | eip155:8453 | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
Base (EVM) · batch-settlement | eip155:8453 · scheme batch-settlement | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Hyperliquid (HyperCore) | hyperliquid:mainnet | USDC:0x6d1e7cde53ba9467b783cb7c530ce054 |
Data freshness
Candles are served up to roughly 2 days ago, the archive's freshness horizon. For more-recent candles, go straight to the source: Hyperliquid's own API natively serves the latest candles.
Need anything fresher than a product's window? Query Hyperliquid's info endpoint directly. It serves recent candles and live state. hyperextend keeps the deep, per-minute history.
- Candle reads clip
endto the cutoff; responses carry anX-Data-Cutoff-Tsheader. GET /v1/discoveryreports the currentavailability_lag_minutes(candles) andasset_ctx_availability_lag_minutes(OI, 0 = live).- Newer candles → Hyperliquid's info endpoint.
Open interest / asset-context is served live, with no 2-day lag. Hyperliquid
exposes no OI history endpoint, so our per-minute archive is the only source;
we serve it right up to the captured edge, and /v1/coverage shows exactly which
minutes are present. Same posture as the HIP-4 outcome series.
Trades are served live too, with no 2-day lag. The raw tape is served live: a hot store holds roughly the last 24 hours as fills are captured, transparently merged with an S3 archive reaching back to the start of our trade history (mid-2025). You don't pick a tier: a single request spans both, so trades cover everything from moments-old to the archive floor.
- Each request is capped to a 24-asset-hour window (one asset-day for a single coin); for longer spans, paginate by day; a wider window returns
400. - Each uncached archived hour a request pulls adds the $0.05 cold-pull charge (see Pricing) and warms the cache for everyone after.
GET /v1/trades/cache(free) shows which archive hours are already warm: windows you can read with no cold-pull charge at all.
Liquidations, by contrast, are archive-derived. Hyperliquid exposes no liquidations feed of any kind, so there's no live tier: the forced-liquidation tape is reconstructed from the node-fills archive and is available ~2 hours behind (a request clamps to that horizon). Same 24-asset-hour cap and per-hour cold-pull as trades.