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. Pay on Base, where 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/intervals | Supported candle interval labels, 1m through 1d. |
GET/v1/dexes | Every dex (main, HIP-3 perps and HIP-4 outcome markets) with first/last seen. |
GET/v1/dexes/{dex}/coins | The active universe on a dex. |
GET/v1/dexes/history | Full HIP-3 dex appearance log: listed / delisted / deployer-changed, oldest first. |
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 and outcome id you use to buy candles, ctx (asset context: funding, mark, oracle and similar fields) or OI (open interest). |
GET/v1/availability/{coin} | Per-dex first/last for ctx and candles. |
GET/v1/coverage/{coin}?start=&end=&dex= | Gap manifest for OI / ctx over a window. dex defaults to main. |
GET/v1/candles/{coin}/coverage?start=&end=&dex= | Gap manifest for candles over a window (≤31 days). dex defaults to main. |
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, about 2 hours' lag, window cap, pricing; ?coin= adds dex and 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. |
POST/v1/mailing/unsubscribe | JSON unsubscribe for agents (body {"email", "token"}, the same token subscribe returned). Wrong token or unknown email → 404. |
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 scheme in accepts (alongside exact).
Instead of settling on-chain every request, you deposit USDC into an escrow once.
After that you pay per request with a cumulative off-chain voucher. Each voucher
is verified off-chain, so there's no per-request on-chain transaction and the reply is almost
instant. Verification includes our own check of its signature against your
payerAuthorizer, the address of the key that signs your vouchers (see below).
After your purchase, our keyless channel manager claims your latest voucher on-chain. Because each voucher is cumulative (it carries your running total), you never over-pay. The manager stays keyless, because Coinbase Developer Platform (CDP) holds the claiming key and pays the gas. It is opt-in, and 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. That multiple is what lets one deposit cover 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. It's verified off-chain and the data comes back immediately, with no on-chain round-trip. - We claim your voucher. After your purchase, our keyless channel manager
claims your latest voucher on-chain, paying it to
payTo. Because the voucher is cumulative, you never over-pay. CDP pays the gas. - Refund the remainder. Spent less than you deposited? Ask for a cooperative
refund with the client's
refundcall. Or start a withdrawal from the escrow contract yourself: the withdrawal completes after the channel's withdrawal delay (24 hours). 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 and 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")
# A private-key wallet needs nothing extra: payerAuthorizer defaults to this signer's address.
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())
For a private-key wallet, 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.
Set a non-zero payerAuthorizer before you use batch settlement
A batch-settlement channel must name a non-zero payerAuthorizer:
the address of the key that signs your vouchers. Vouchers from a channel whose
payerAuthorizer is the zero address are refused with a 402.
- Private-key (EOA) wallet: nothing to do. The x402 client sets
payerAuthorizerto your signing key's address by default, so the example above works as it is. - Smart-contract wallet: pass a separate plain signing key you control as the
voucher signer. In Python that's
BatchSettlementEvmSchemeOptions(voucher_signer=...); in TypeScript,{ voucherSigner }. Its address becomes thepayerAuthorizer.
The payerAuthorizer must be the address of your own key, never hyperextend's. If
you can't or won't set one, the exact scheme on Base and on HyperCore stays open to
you. Upstream details:
wallet compatibility
(the "Batch-settlement vouchers" section) and the
TypeScript batch-settlement client
(the "Voucher Signer Delegation" section).
Endpoints
| Endpoint | Notes |
|---|---|
GET/v1/candles/{coin}/{interval}?start=&end=&dex= | Historical OHLCV (open, high, low, close, volume) candles for a coin & interval over a time window. dex defaults to main; set spot, a HIP-3 dex name (e.g. xyz), or outcome for HIP-4. Base rate on main & spot, premium elsewhere. |
GET/v1/candles/{coin}/{interval}/latest?n=&dex= | The most recent n candles, a cheap recent-window convenience. dex as above. |
GET/v1/asset_ctx/{coin}?start=&end=&dex= | Open interest / funding / mark / oracle / mid / volumes. Premium rate. dex defaults to main; set spot or a HIP-3 dex name. |
GET/v1/asset_ctx/{coin}/latest?n=&dex= | The most recent n OI / ctx snapshots, a cheap recent-window convenience. Premium rate. dex as above. |
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 and the gaps. Warms the cache. Priced floor plus $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 Hyperliquid feed; about 2 hours' lag). Priced per asset-hour at a third of trades; plus $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 and the gaps. Warms the cache. Floor plus $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 Hyperliquid'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 plus 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]). Each row also carries 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 plus cold-pull) | $0.056 |
Archive-derived: there's no live tier (no public feed exists), so
liquidations are available about 2 hours 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
Here a rail is the network you pay on, and a scheme is how you
pay on it (exact or batch-settlement). The accepts array
advertises what this deployment takes: the Base and Hyperliquid rails, with Base offering both
the per-request exact scheme 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 · scheme | Identifier | USDC |
|---|---|---|
Base (EVM) · exact | eip155:8453 | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
Base (EVM) · batch-settlement | eip155:8453 · scheme batch-settlement | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
Hyperliquid (HyperCore) · exact | 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. We merge that store transparently 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. We reconstruct the forced-liquidation tape from the node-fills archive, and it is available about 2 hours behind. A request clamps to that horizon. Same 24-asset-hour cap and per-hour cold-pull as trades.