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.

EndpointAnswers
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: GET402 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)

python · exact
# 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.

  1. 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_multiplier below, so it covers a run of calls). CDP broadcasts and gasses it; you sign, you don't pay gas.
  2. 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.
  3. 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.
  4. 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:

python · batch-settlement
# 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

EndpointNotes
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.

Floor
$0.001 / request

Charged on every request, before any rows.

Base · per row
$0.00001

Main-perp & spot candles.

Premium · per row
$0.000025

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.

RequestCost
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):

tariff · trades
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)
RequestCost
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:

tariff · liquidations
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)
RequestCost
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.

RailIdentifierUSDC
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 end to the cutoff; responses carry an X-Data-Cutoff-Ts header.
  • GET /v1/discovery reports the current availability_lag_minutes (candles) and asset_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.