FlowscopeDocs

GET /v1/hl/footprint

Hyperliquid open-interest, net-long and net-short footprint minutes of one coin over a time range.

Returns per minute and price row what Hyperliquid trades did to positions: the change in open interest, longs opened minus closed, and shorts opened minus closed. Flowscope draws these as the Hyperliquid positioning footprints.

Request

Text
GET /v1/hl/footprint/<COIN>?from=<ms>&to=<ms>
HEAD /v1/hl/footprint/<COIN>?from=<ms>&to=<ms>
ParameterInTypeDescription
COINPathstringA coin from /v1/hl/coins, case-sensitive
fromQueryinteger, msStart of the range; rounded down to the minute
toQueryinteger, msEnd of the range; rounded up to the minute, exclusive

The range rules are the same as for /v1/hl/levels: to greater than from, at most 60 days, and always pass both.

Response

HeaderValue
Content-Typeapplication/octet-stream
Cache-Controlno-cache

The body is one footprint payload in the positions codec: the coin, the row size, the newest sample time and the start of the range answered, then the minutes, then a checksum.

The payload holds every recorded minute that starts in the range, in time order. Each minute has:

FieldUnitMeaning
minuteminutes since the epochms / 60 000
oicoinsHyperliquid’s open interest at the end of the minute
markpriceMark price at the end of the minute
tracked_long, tracked_shortcoinsLong and short size of the tracked accounts at the end of the minute
volumecoinsTraded volume in the minute
taker_knowncoinsVolume whose aggressor was tracked: covered by net long and net short
both_knowncoinsVolume with both sides tracked: covered by Δ OI

and a list of price cells:

FieldUnitMeaning
row—Prices [row × row_px, (row + 1) × row_px)
d_oicoinsΔ open interest: buyer’s plus seller’s change of long size
nlcoinsΔ net long: longs opened minus closed by the aggressor
nscoinsΔ net short: shorts opened minus closed by the aggressor
volumecoinsTraded volume in the row, all trades

NaN means unknown: oi, mark, tracked_long and tracked_short are NaN in a minute where they were not seen.

Coverage per minute is taker_known / volume for net long and net short, and both_known / volume for Δ OI. Show it next to the figures; a chart without coverage overstates what it knows.

The payload’s from is the start of the requested range, or later when nothing is recorded before that point.

Status codes

StatusBodyWhen
200Footprint payloadThe coin has samples
400bad rangeto <= from, or the range is longer than 60 days
404coin not recordedThe coin is not in --hl-coins
404hyperliquid positions not recordedHyperliquid recording is off
404not foundAnything other than levels or footprint after /v1/hl/
503no sample yetThe coin is recorded but has not been sampled yet

Example

The last hour of ETH footprints:

Terminal
TO=$(( $(date +%s) * 1000 ))
FROM=$(( TO - 3600000 ))
curl -fsS -o eth.fp "http://127.0.0.1:8787/v1/hl/footprint/ETH?from=$FROM&to=$TO"

An hour is typically 2–4 kB per coin.

Decoding in Rust

Rust
use flowscope_engine::positions::codec::decode_footprint;

let bytes = std::fs::read("eth.fp")?;
let p = decode_footprint(&bytes)?;
for m in &p.minutes {
    let taker_cov = if m.volume > 0.0 { m.taker_known / m.volume } else { 0.0 };
    let nl: f32 = m.cells.iter().map(|c| c.nl).sum();
    let ns: f32 = m.cells.iter().map(|c| c.ns).sum();
    println!("{} oi {} net long {nl:+.2} net short {ns:+.2} coverage {:.0} %", m.minute * 60_000, m.oi, taker_cov * 100.0);
}

How answers are built

Minutes that memory no longer holds completely come from the coin’s .fp day files; the rest come from memory. A minute is appended to its day file once it has closed. Payloads written with a different row size are skipped.

Footprints exist only on a recorder, because they need the complete trade stream. Flowscope clients get them from the data hub, which runs one; without a hub they have no Hyperliquid footprints.