CaptainAhab

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

RouteReturns
GET /v1/coverageObserved periods, nulls, gaps, symbols, source receipts
GET /v1/hlp/capitalCapital snapshots (JSON, limit 1–1000)
GET /v1/hlp/fillsHLP 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/usageYour key's status and request/row allowances
GET /v1/analytics/capitalDaily observed capital and utilization statistics
GET /v1/analytics/fillsCounts, notional and VWAP by symbol, leg and side
GET /v1/analytics/activityObserved inter-arrival and burst statistics by symbol and leg
  • Timestamps are Unix milliseconds, UTC. start_ms is inclusive, end_ms exclusive, at most 31 days apart.
  • JSON includes data, count, next_cursor and snapshot provenance. JSON null and 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 /health and /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: 1 without 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_ms is our poll time, not a block time. vault_equity_usd comes from the upstream maxDistributable value. Equity changes include PnL and are not deposits or withdrawals.
  • Fill id is an archive row id for paging, not an exchange execution id. side is the aggressor (B/A); hlp_side is 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)