API reference · schema v1
Docs
Read-only HLP history and reproducible analytics from versioned snapshots. Generate a key on your account page and send it as a bearer token.
History by symbol and leg
The dated October 10 baseline contains 58 observed symbol/leg pairs. VINE's last observation on both legs is August 25, 2026; the other 56 pairs span more than 89 days between their first and last observations. Those spans and gaps do not establish uninterrupted collection, and missing observations do not establish zero market activity.
Download the dated symbol/leg coverage CSV for row counts, first/last timestamps and largest observed inter-arrival gaps. This is the initial baseline; use authenticated queries and /v1/coverage for the current rolling dataset.
Endpoints
| Route | Returns |
|---|---|
| GET /v1/coverage | Observed periods, nulls, gaps, symbols, source receipts |
| GET /v1/hlp/capital | Capital snapshots (JSON, limit 1–1000) |
| GET /v1/hlp/fills | HLP fills (JSON, limit 1–1000, optional exact coin) |
| GET /v1/exports/capital GET /v1/exports/fills | CSV pages, limit 1–10000; next page in X-Next-Cursor header |
| GET /v1/usage | Your key's status and request/row allowances |
| GET /v1/analytics/capital | Daily observed capital and utilization statistics |
| GET /v1/analytics/fills | Counts, notional and VWAP by symbol, leg and side |
| GET /v1/analytics/activity | Observed inter-arrival and burst statistics by symbol and leg |
- Timestamps are Unix milliseconds, UTC.
start_msis inclusive,end_msexclusive, at most 31 days apart. - JSON includes
data,count,next_cursorand snapshot provenance. JSONnulland empty CSV fields mean unknown, not zero. - Cursors are tied to the snapshot version. If the version changes, discard the cursor and start again.
- Errors: 401 bad key, 403 inactive account, 422 invalid range, 400 mismatched cursor, 429 over limit. Rate limits include
Retry-After; insufficient row allowance requires a smaller query or allowance reset. - Limits: 10,000 requests and 1,000,000 rows per UTC month, 60 requests per minute.
- Retention target: 90 days. Queries span at most 31 days; split longer studies into windows. Hourly refresh and at most two hours of observed lag are pilot targets. Check
/healthand/v1/coverage; reliability measurement is in progress.
curl
Queries below use the bounds of the dated initial sample: capital 2026-09-10 to 2026-10-10, fills 2026-10-09 to 2026-10-10. Set your key in the environment; nothing here runs automatically.
export AHAB_KEY="paste-your-key-here"
curl -s -H "Authorization: Bearer $AHAB_KEY" \
"{ORIGIN}/v1/coverage"
curl -s -H "Authorization: Bearer $AHAB_KEY" \
"{ORIGIN}/v1/hlp/capital?start_ms=1789052384233&end_ms=1791641106949&limit=3"
curl -s -H "Authorization: Bearer $AHAB_KEY" \
"{ORIGIN}/v1/hlp/fills?start_ms=1791557418974&end_ms=1791643739699&coin=MORPHO&limit=3"
curl -s -H "Authorization: Bearer $AHAB_KEY" \
"{ORIGIN}/v1/usage"
Read current bounds from /v1/coverage (oldest_ts_ms, newest_ts_ms + 1). The dated free sample is separate from the refreshed paid history.
Python
Pages through up to seven observed days of BTC fills. Requires httpx.
import os
import httpx
headers = {"Authorization": "Bearer " + os.environ["AHAB_KEY"]}
with httpx.Client(base_url="{ORIGIN}", headers=headers, timeout=30) as c:
coverage = c.get("/v1/coverage").raise_for_status().json()
cov = coverage["coverage"]["fills"]
end = cov["newest_ts_ms"] + 1
params = {"start_ms": max(cov["oldest_ts_ms"], end - 7*86400000),
"end_ms": end, "limit": 1000, "coin": "BTC"}
rows = []
for _ in range(100):
page = c.get("/v1/hlp/fills", params=params).raise_for_status().json()
if page["snapshot"]["version"] != coverage["snapshot"]["version"]:
raise RuntimeError("Snapshot refreshed; rerun the study")
rows.extend(page["data"])
if not page["next_cursor"]:
break
params["cursor"] = page["next_cursor"]
else:
raise RuntimeError("Query bound reached; choose a shorter window")
print(len(rows), "fills")
Analytics definitions
All three use start_ms and end_ms, at most 31 days apart. Fills and activity also accept coin. Responses identify analytics-v1, the snapshot version, exact formulas, freshness and the number of underlying rows examined.
- Capital: UTC-day buckets report first/last observed equity, their difference, sample counts and utilization mean/min/max. Means are sample-weighted; nulls are excluded. Partial query days and backfill counts are marked. Equity differences are not PnL or wallet flows. Gaps are measured within each day; consult coverage for gaps crossing midnight.
- Fills: each symbol/leg/side group reports observation count, sum of recorded USD notional, sum of size and VWAP = sum(price × size) / sum(size). Exact duplicates are reported and included. These groups do not establish exchange market volume.
- Activity: per symbol/leg, exact duplicate observations are removed when trade IDs are known. Gaps between consecutive observations produce nearest-rank percentiles and a burst fraction: gaps ≤1,000 ms / gap count. No gaps yields null; fewer than 30 gaps is marked low sample. Collector outages can lengthen observed gaps.
- Analytics charge one request and the returned aggregate rows. A window above 100,000 underlying rows returns 413; above 5,000 result rows returns 422. Insufficient remaining row allowance returns 429. Narrow the dates or filter by coin; partial aggregates are never substituted.
- If analytics capacity is busy, the API returns 429 with
Retry-After: 1without charging a request or rows.
Download the runnable Python notebook. It answers a concrete utilization/activity question and independently reconciles all three analytics against raw API data. Set AHAB_DATA_API_KEY in the environment; it uses your normal allowance.
Field notes
snapshot_ts_msis our poll time, not a block time.vault_equity_usdcomes from the upstreammaxDistributablevalue. Equity changes include PnL and are not deposits or withdrawals.- Fill
idis an archive row id for paging, not an exchange execution id.sideis the aggressor (B/A);hlp_sideis that HLP leg's side. - Rows from different HLP addresses may describe the same trade. Do not sum them as market volume.
- CSV text beginning with a formula character is prefixed with an apostrophe; JSON keeps the source text.
- Values are collector-observed floats, not an accounting ledger.
Sample JSON · capital.csv (initial sample, 719 rows) · fills.csv (initial sample, 2,293 fills from 24 hours)